Skip to content

Commit bd062d9

Browse files
committed
chore: update source secp256k1 dependency
1 parent 4f666ea commit bd062d9

File tree

4 files changed

+47
-123
lines changed

4 files changed

+47
-123
lines changed

Package.resolved

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ let package = Package(
1515
dependencies: [
1616
.package(name: "BigInt", url: "https://github.com/attaswift/BigInt", from: "5.3.0"),
1717
.package(name: "GenericJSON", url: "https://github.com/iwill/generic-json-swift", .upToNextMajor(from: "2.0.0")),
18-
.package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", .upToNextMajor(from: "0.6.0")),
18+
.package(name: "swift-secp256k1", url: "https://github.com/21-DOT-DEV/swift-secp256k1", from: "0.21.1"),
1919
.package(url: "https://github.com/vapor/websocket-kit.git", from: "2.0.0"),
2020
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0")
2121
],
@@ -29,7 +29,7 @@ let package = Package(
2929
.target(name: "Internal_CryptoSwift_PBDKF2"),
3030
"BigInt",
3131
"GenericJSON",
32-
.product(name: "secp256k1", package: "secp256k1.swift"),
32+
.product(name: "P256K", package: "swift-secp256k1"),
3333
.product(name: "WebSocketKit", package: "websocket-kit"),
3434
.product(name: "Logging", package: "swift-log")
3535
],

web3sTests/Account/EthereumKeyStorageTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class EthereumKeyStorageTests: XCTestCase {
4242
}
4343

4444
func testEncryptAndStorePrivateKey() {
45-
let randomData = Data.randomOfLength(256)!
45+
let randomData = Data.randomOfLength(32)!
4646
let keyStorage = EthereumKeyLocalStorage() as EthereumSingleKeyStorageProtocol
4747
let password = "myP4ssw0rD"
4848

@@ -56,7 +56,7 @@ class EthereumKeyStorageTests: XCTestCase {
5656
}
5757

5858
func testEncryptAndStorePrivateKeyMultiple() {
59-
let randomData = Data.randomOfLength(256)!
59+
let randomData = Data.randomOfLength(32)!
6060
let keyStorage = EthereumKeyLocalStorage() as EthereumMultipleKeyStorageProtocol
6161
let password = "myP4ssw0rD"
6262

web3swift/src/Utils/KeyUtil.swift

Lines changed: 34 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//
55

66
import Logging
7-
import secp256k1
7+
import P256K
88
import Foundation
99

1010
public enum KeyUtilError: Error {
@@ -26,40 +26,12 @@ public class KeyUtil {
2626
}
2727

2828
public static func generatePublicKey(from privateKey: Data) throws -> Data {
29-
guard let ctx = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)) else {
30-
logger.warning("Failed to generate a public key: invalid context.")
31-
throw KeyUtilError.invalidContext
32-
}
33-
34-
defer {
35-
secp256k1_context_destroy(ctx)
36-
}
37-
38-
let privateKeyPtr = (privateKey as NSData).bytes.assumingMemoryBound(to: UInt8.self)
39-
guard secp256k1_ec_seckey_verify(ctx, privateKeyPtr) == 1 else {
40-
logger.warning("Failed to generate a public key: private key is not valid.")
41-
throw KeyUtilError.privateKeyInvalid
42-
}
43-
44-
let publicKeyPtr = UnsafeMutablePointer<secp256k1_pubkey>.allocate(capacity: 1)
45-
defer {
46-
publicKeyPtr.deallocate()
47-
}
48-
guard secp256k1_ec_pubkey_create(ctx, publicKeyPtr, privateKeyPtr) == 1 else {
49-
logger.warning("Failed to generate a public key: public key could not be created.")
50-
throw KeyUtilError.unknownError
51-
}
52-
53-
var publicKeyLength = 65
54-
let outputPtr = UnsafeMutablePointer<UInt8>.allocate(capacity: publicKeyLength)
55-
defer {
56-
outputPtr.deallocate()
57-
}
58-
secp256k1_ec_pubkey_serialize(ctx, outputPtr, &publicKeyLength, publicKeyPtr, UInt32(SECP256K1_EC_UNCOMPRESSED))
59-
60-
let publicKey = Data(bytes: outputPtr, count: publicKeyLength).subdata(in: 1 ..< publicKeyLength)
61-
62-
return publicKey
29+
let privateKey = try P256K.Recovery.PrivateKey(dataRepresentation: privateKey, format: .uncompressed)
30+
31+
let publicKey = privateKey.publicKey.dataRepresentation
32+
let publicKeyLength = publicKey.count
33+
let finalPublicKey = publicKey.subdata(in: 1 ..< publicKeyLength)
34+
return finalPublicKey
6335
}
6436

6537
public static func generateAddress(from publicKey: Data) -> EthereumAddress {
@@ -69,90 +41,42 @@ public class KeyUtil {
6941
}
7042

7143
public static func sign(message: Data, with privateKey: Data, hashing: Bool) throws -> Data {
72-
guard let ctx = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)) else {
73-
logger.warning("Failed to sign message: invalid context.")
74-
throw KeyUtilError.invalidContext
75-
}
76-
77-
defer {
78-
secp256k1_context_destroy(ctx)
79-
}
80-
44+
let privateKey = try P256K.Recovery.PrivateKey(dataRepresentation: privateKey)
8145
let msgData = hashing ? message.web3.keccak256 : message
82-
let msg = (msgData as NSData).bytes.assumingMemoryBound(to: UInt8.self)
83-
let privateKeyPtr = (privateKey as NSData).bytes.assumingMemoryBound(to: UInt8.self)
84-
let signaturePtr = UnsafeMutablePointer<secp256k1_ecdsa_recoverable_signature>.allocate(capacity: 1)
85-
defer {
86-
signaturePtr.deallocate()
87-
}
88-
guard secp256k1_ecdsa_sign_recoverable(ctx, signaturePtr, msg, privateKeyPtr, nil, nil) == 1 else {
89-
logger.warning("Failed to sign message: recoverable ECDSA signature creation failed.")
90-
throw KeyUtilError.signatureFailure
91-
}
92-
93-
let outputPtr = UnsafeMutablePointer<UInt8>.allocate(capacity: 64)
94-
defer {
95-
outputPtr.deallocate()
96-
}
97-
var recid: Int32 = 0
98-
secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, outputPtr, &recid, signaturePtr)
46+
let digest = HashDigest(msgData.bytes)
47+
let signature = try privateKey.signature(for: digest)
9948

100-
let outputWithRecidPtr = UnsafeMutablePointer<UInt8>.allocate(capacity: 65)
101-
defer {
102-
outputWithRecidPtr.deallocate()
103-
}
104-
outputWithRecidPtr.assign(from: outputPtr, count: 64)
105-
outputWithRecidPtr.advanced(by: 64).pointee = UInt8(recid)
106-
107-
let signature = Data(bytes: outputWithRecidPtr, count: 65)
49+
let compactSignature = try signature.compactRepresentation.signature
50+
let recoveryId = try signature.compactRepresentation.recoveryId
10851

109-
return signature
52+
var resultSignature = Data(compactSignature)
53+
let v = UInt8(recoveryId & 0xFF)
54+
resultSignature.append(v)
55+
return resultSignature
11056
}
11157

11258
public static func recoverPublicKey(message: Data, signature: Data) throws -> String {
11359
if signature.count != 65 || message.count != 32 {
11460
throw KeyUtilError.badArguments
11561
}
116-
117-
guard let ctx = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)) else {
118-
logger.warning("Failed to sign message: invalid context.")
119-
throw KeyUtilError.invalidContext
120-
}
121-
defer { secp256k1_context_destroy(ctx) }
122-
123-
// get recoverable signature
124-
let signaturePtr = UnsafeMutablePointer<secp256k1_ecdsa_recoverable_signature>.allocate(capacity: 1)
125-
defer { signaturePtr.deallocate() }
126-
62+
12763
let serializedSignature = Data(signature[0 ..< 64])
128-
var v = Int32(signature[64])
129-
if v >= 27, v <= 30 {
130-
v -= 27
131-
} else if v >= 31, v <= 34 {
132-
v -= 31
133-
} else if v >= 35, v <= 38 {
134-
v -= 35
135-
}
136-
137-
try serializedSignature.withUnsafeBytes {
138-
guard secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, signaturePtr, $0.bindMemory(to: UInt8.self).baseAddress!, v) == 1 else {
139-
logger.warning("Failed to parse signature: recoverable ECDSA signature parse failed.")
140-
throw KeyUtilError.signatureParseFailure
141-
}
142-
}
143-
let pubkey = UnsafeMutablePointer<secp256k1_pubkey>.allocate(capacity: 1)
144-
defer { pubkey.deallocate() }
145-
146-
try message.withUnsafeBytes {
147-
guard secp256k1_ecdsa_recover(ctx, pubkey, signaturePtr, $0.bindMemory(to: UInt8.self).baseAddress!) == 1 else {
148-
throw KeyUtilError.signatureFailure
149-
}
150-
}
151-
var size = 65
152-
var rv = Data(count: size)
153-
rv.withUnsafeMutableBytes {
154-
secp256k1_ec_pubkey_serialize(ctx, $0.bindMemory(to: UInt8.self).baseAddress!, &size, pubkey, UInt32(SECP256K1_EC_UNCOMPRESSED))
155-
}
156-
return "0x\(rv[1...].web3.keccak256.web3.hexString.suffix(40))"
64+
var recoveryId = Int32(signature[64])
65+
if recoveryId >= 27, recoveryId <= 30 {
66+
recoveryId -= 27
67+
} else if recoveryId >= 31, recoveryId <= 34 {
68+
recoveryId -= 31
69+
} else if recoveryId >= 35, recoveryId <= 38 {
70+
recoveryId -= 35
71+
}
72+
73+
let digest = HashDigest(message.bytes)
74+
let publicKey = try P256K.Recovery.PublicKey(
75+
digest,
76+
signature: P256K.Recovery.ECDSASignature(compactRepresentation: serializedSignature, recoveryId: recoveryId),
77+
format: .uncompressed
78+
)
79+
80+
return "0x\(publicKey.dataRepresentation[1...].web3.keccak256.web3.hexString.suffix(40))"
15781
}
15882
}

0 commit comments

Comments
 (0)