From ce7514ac23c5475b9047b53ffc309618bb96d1ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Da=CC=A8browski?= Date: Fri, 10 Oct 2025 11:21:55 +0200 Subject: [PATCH 1/7] chore: bump bigint and secp256k1 to new versions --- Package.resolved | 87 +++++++++++++++++++++++-------- Package.swift | 6 +-- Package@swift-6.1.swift | 6 +-- web3swift/src/Utils/KeyUtil.swift | 2 +- 4 files changed, 73 insertions(+), 28 deletions(-) diff --git a/Package.resolved b/Package.resolved index 38ae8640..ee6dfc0b 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,13 +1,13 @@ { - "originHash" : "6a7b6f94e12ad64740435b6a1f32724d65be46fe7a993e5ced1b75ca71949624", + "originHash" : "05067935d9be918d55a72afa4a7d59f1dfa450ae67d031dba3f3f2477737dd37", "pins" : [ { "identity" : "bigint", "kind" : "remoteSourceControl", "location" : "https://github.com/attaswift/BigInt", "state" : { - "revision" : "0ed110f7555c34ff468e72e1686e59721f2b0da6", - "version" : "5.3.0" + "revision" : "e07e00fa1fd435143a2dcf8b7eec9a7710b2fdfe", + "version" : "5.7.0" } }, { @@ -24,8 +24,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/GigaBitcoin/secp256k1.swift.git", "state" : { - "revision" : "1a14e189def5eaa92f839afdd2faad8e43b61a6e", - "version" : "0.12.2" + "revision" : "8c62aba8a3011c9bcea232e5ee007fb0b34a15e2", + "version" : "0.21.1" } }, { @@ -37,6 +37,24 @@ "version" : "1.2.1" } }, + { + "identity" : "swift-asn1", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-asn1.git", + "state" : { + "revision" : "f70225981241859eb4aa1a18a75531d26637c8cc", + "version" : "1.4.0" + } + }, + { + "identity" : "swift-async-algorithms", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-async-algorithms.git", + "state" : { + "revision" : "042e1c4d9d19748c9c228f8d4ebc97bb1e339b0b", + "version" : "1.0.4" + } + }, { "identity" : "swift-atomics", "kind" : "remoteSourceControl", @@ -46,13 +64,31 @@ "version" : "1.3.0" } }, + { + "identity" : "swift-certificates", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-certificates.git", + "state" : { + "revision" : "4b092f15164144c24554e0a75e080a960c5190a6", + "version" : "1.14.0" + } + }, { "identity" : "swift-collections", "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-collections.git", "state" : { - "revision" : "8c0c0a8b49e080e54e5e328cc552821ff07cd341", - "version" : "1.2.1" + "revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-crypto", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-crypto.git", + "state" : { + "revision" : "95ba0316a9b733e92bb6b071255ff46263bbe7dc", + "version" : "3.15.1" } }, { @@ -60,8 +96,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-http-structured-headers.git", "state" : { - "revision" : "db6eea3692638a65e2124990155cd220c2915903", - "version" : "1.3.0" + "revision" : "1625f271afb04375bf48737a5572613248d0e7a0", + "version" : "1.4.0" } }, { @@ -87,8 +123,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio.git", "state" : { - "revision" : "a5fea865badcb1c993c85b0f0e8d05a4bd2270fb", - "version" : "2.85.0" + "revision" : "a18bddb0acf7a40d982b2f128ce73ce4ee31f352", + "version" : "2.86.2" } }, { @@ -96,8 +132,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-extras.git", "state" : { - "revision" : "f1f6f772198bee35d99dd145f1513d8581a54f2c", - "version" : "1.26.0" + "revision" : "a55c3dd3a81d035af8a20ce5718889c0dcab073d", + "version" : "1.29.0" } }, { @@ -114,8 +150,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-ssl.git", "state" : { - "revision" : "385f5bd783ffbfff46b246a7db7be8e4f04c53bd", - "version" : "2.33.0" + "revision" : "b2b043a8810ab6d51b3ff4df17f057d87ef1ec7c", + "version" : "2.34.1" } }, { @@ -123,8 +159,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-nio-transport-services.git", "state" : { - "revision" : "decfd235996bc163b44e10b8a24997a3d2104b90", - "version" : "1.25.0" + "revision" : "df6c28355051c72c884574a6c858bc54f7311ff9", + "version" : "1.25.2" } }, { @@ -132,8 +168,17 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-numerics.git", "state" : { - "revision" : "e0ec0f5f3af6f3e4d5e7a19d2af26b481acb6ba8", - "version" : "1.0.3" + "revision" : "0c0290ff6b24942dadb83a929ffaaa1481df04a2", + "version" : "1.1.1" + } + }, + { + "identity" : "swift-service-lifecycle", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swift-server/swift-service-lifecycle.git", + "state" : { + "revision" : "0fcc4c9c2d58dd98504c06f7308c86de775396ff", + "version" : "2.9.0" } }, { @@ -141,8 +186,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-system.git", "state" : { - "revision" : "b63d24d465e237966c3f59f47dcac6c70fb0bca3", - "version" : "1.6.1" + "revision" : "395a77f0aa927f0ff73941d7ac35f2b46d47c9db", + "version" : "1.6.3" } }, { diff --git a/Package.swift b/Package.swift index bd4a0e03..c17cfd67 100644 --- a/Package.swift +++ b/Package.swift @@ -13,9 +13,9 @@ let package = Package( .library(name: "web3-zksync.swift", targets: ["web3-zksync"]) ], dependencies: [ - .package(url: "https://github.com/attaswift/BigInt", from: "5.3.0"), + .package(url: "https://github.com/attaswift/BigInt", from: "5.7.0"), .package(url: "https://github.com/iwill/generic-json-swift", .upToNextMajor(from: "2.0.2")), - .package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", .upToNextMajor(from: "0.6.0")), + .package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", exact: "0.21.1"), .package(url: "https://github.com/vapor/websocket-kit.git", from: "2.16.1"), .package(url: "https://github.com/apple/swift-log.git", from: "1.6.4") ], @@ -29,7 +29,7 @@ let package = Package( .target(name: "Internal_CryptoSwift_PBDKF2"), "BigInt", .product(name: "GenericJSON", package: "generic-json-swift"), - .product(name: "secp256k1", package: "secp256k1.swift"), + .product(name: "libsecp256k1", package: "secp256k1.swift"), .product(name: "WebSocketKit", package: "websocket-kit"), .product(name: "Logging", package: "swift-log") ], diff --git a/Package@swift-6.1.swift b/Package@swift-6.1.swift index 7362ba50..3a3a4de4 100644 --- a/Package@swift-6.1.swift +++ b/Package@swift-6.1.swift @@ -13,9 +13,9 @@ let package = Package( .library(name: "web3-zksync.swift", targets: ["web3-zksync"]) ], dependencies: [ - .package(url: "https://github.com/attaswift/BigInt", from: "5.3.0"), + .package(url: "https://github.com/attaswift/BigInt", from: "5.7.0"), .package(url: "https://github.com/iwill/generic-json-swift", .upToNextMajor(from: "2.0.2")), - .package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", .upToNextMajor(from: "0.6.0")), + .package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", exact: "0.21.1"), .package(url: "https://github.com/vapor/websocket-kit.git", from: "2.16.1"), .package(url: "https://github.com/apple/swift-log.git", from: "1.6.4") ], @@ -29,7 +29,7 @@ let package = Package( .target(name: "Internal_CryptoSwift_PBDKF2"), "BigInt", .product(name: "GenericJSON", package: "generic-json-swift"), - .product(name: "secp256k1", package: "secp256k1.swift"), + .product(name: "libsecp256k1", package: "secp256k1.swift"), .product(name: "WebSocketKit", package: "websocket-kit"), .product(name: "Logging", package: "swift-log") ], diff --git a/web3swift/src/Utils/KeyUtil.swift b/web3swift/src/Utils/KeyUtil.swift index a9d1ac6e..464404f6 100644 --- a/web3swift/src/Utils/KeyUtil.swift +++ b/web3swift/src/Utils/KeyUtil.swift @@ -4,7 +4,7 @@ // import Logging -import secp256k1 +import libsecp256k1 import Foundation public enum KeyUtilError: Error { From 9734e8f761c24c7e15220a87557cce93050a2770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Da=CC=A8browski?= Date: Fri, 10 Oct 2025 11:31:46 +0200 Subject: [PATCH 2/7] chore: remove redundant bigint conformance --- .../src/Contract/Statically Typed/ABIRawType+Static.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/web3swift/src/Contract/Statically Typed/ABIRawType+Static.swift b/web3swift/src/Contract/Statically Typed/ABIRawType+Static.swift index f21571cf..f417bde6 100644 --- a/web3swift/src/Contract/Statically Typed/ABIRawType+Static.swift +++ b/web3swift/src/Contract/Statically Typed/ABIRawType+Static.swift @@ -44,9 +44,6 @@ extension EthereumAddress: ABIType { } } -extension BigInt: @unchecked Sendable {} -extension BigUInt: @unchecked Sendable {} - extension BigInt: ABIType { public static var rawType: ABIRawType { .FixedInt(256) } public static var parser: ParserFunction { From 0659da35701f987d485c251313678a04cb09efd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Da=CC=A8browski?= Date: Fri, 10 Oct 2025 11:41:45 +0200 Subject: [PATCH 3/7] chore: resolve deprecation warnings --- .../src/Account/EthereumKeyStorage.swift | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/web3swift/src/Account/EthereumKeyStorage.swift b/web3swift/src/Account/EthereumKeyStorage.swift index 0a4db78d..157e6f18 100644 --- a/web3swift/src/Account/EthereumKeyStorage.swift +++ b/web3swift/src/Account/EthereumKeyStorage.swift @@ -31,16 +31,18 @@ public class EthereumKeyLocalStorage: EthereumSingleKeyStorageProtocol, @uncheck private let address: ThreadSafeBox = ThreadSafeBox(nil) private let localFileName = "ethereumkey" - private var addressPath: String? { + private var addressURL: URL? { guard let address = address.value else { return nil } if let url = folderPath { - return url.appendingPathComponent(address.asString()).path + return url.appendingPathComponent(address.asString()) } return nil } + private var addressPath: String? { addressURL?.path } + private var folderPath: URL? { if let url = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first { return url @@ -48,33 +50,40 @@ public class EthereumKeyLocalStorage: EthereumSingleKeyStorageProtocol, @uncheck return nil } + private var localURL: URL? { + fileManager + .urls(for: .cachesDirectory, in: .userDomainMask) + .first? + .appendingPathComponent(localFileName) + } + private var localPath: String? { - if let url = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first { - return url.appendingPathComponent(localFileName).path - } - return nil + localURL?.path } private let fileManager = FileManager.default public func storePrivateKey(key: Data) throws { - guard let localPath else { + guard let localURL else { throw EthereumKeyStorageError.failedToSave } - let success = NSKeyedArchiver.archiveRootObject(key, toFile: localPath) - - if !success { + do { + try NSKeyedArchiver + .archivedData(withRootObject: key, requiringSecureCoding: false) + .write(to: localURL) + } catch { throw EthereumKeyStorageError.failedToSave } } public func loadPrivateKey() throws -> Data { - guard let localPath else { + guard let localURL else { throw EthereumKeyStorageError.failedToLoad } - guard let data = NSKeyedUnarchiver.unarchiveObject(withFile: localPath) as? Data else { + guard let archivedData = try? Data(contentsOf: localURL), + let data = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSData.self, from: archivedData) as? Data else { throw EthereumKeyStorageError.failedToLoad } @@ -112,13 +121,15 @@ extension EthereumKeyLocalStorage: EthereumMultipleKeyStorageProtocol { } } - guard let localPath = self.addressPath else { + guard let localURL = self.addressURL else { throw EthereumKeyStorageError.failedToSave } - let success = NSKeyedArchiver.archiveRootObject(key, toFile: localPath) - - if !success { + do { + try NSKeyedArchiver + .archivedData(withRootObject: key, requiringSecureCoding: false) + .write(to: localURL) + } catch { throw EthereumKeyStorageError.failedToSave } } @@ -134,11 +145,12 @@ extension EthereumKeyLocalStorage: EthereumMultipleKeyStorageProtocol { } } - guard let localPath = self.addressPath else { + guard let localURL = self.addressURL else { throw EthereumKeyStorageError.failedToLoad } - guard let data = NSKeyedUnarchiver.unarchiveObject(withFile: localPath) as? Data else { + guard let archivedData = try? Data(contentsOf: localURL), + let data = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSData.self, from: archivedData) as? Data else { throw EthereumKeyStorageError.failedToLoad } From d42c851172cafc96d829d622ca76747c3a1072b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Da=CC=A8browski?= Date: Fri, 10 Oct 2025 13:46:15 +0200 Subject: [PATCH 4/7] fix: adjust to failing bigint initializer in new version, that does not default to 0 when initializing from empty string --- web3swift/src/Extensions/HexExtensions.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/web3swift/src/Extensions/HexExtensions.swift b/web3swift/src/Extensions/HexExtensions.swift index a07537a2..99fd74a5 100644 --- a/web3swift/src/Extensions/HexExtensions.swift +++ b/web3swift/src/Extensions/HexExtensions.swift @@ -8,7 +8,7 @@ import Foundation public extension BigUInt { init?(hex: String) { - self.init(hex.web3.noHexPrefix.lowercased(), radix: 16) + self.init(hex.web3.noHexPrefix.web3.orZero.lowercased(), radix: 16) } } @@ -24,7 +24,7 @@ public extension Web3Extensions where Base == BigUInt { public extension BigInt { init?(hex: String) { - self.init(hex.web3.noHexPrefix.lowercased(), radix: 16) + self.init(hex.web3.noHexPrefix.web3.orZero.lowercased(), radix: 16) } } @@ -79,6 +79,11 @@ public extension Web3Extensions where Base == String { return base } + var orZero: String { + if base.isEmpty { return "0" } + return base + } + var stringValue: String { if let byteArray = try? HexUtil.byteArray(fromHex: base.web3.noHexPrefix), let str = String(bytes: byteArray, encoding: .utf8) { return str From f668107ddb802623272919b09a02e52fdcf1b255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Da=CC=A8browski?= Date: Fri, 10 Oct 2025 14:15:51 +0200 Subject: [PATCH 5/7] chore: apply lint --- web3swift/src/Extensions/HexExtensions.swift | 4 +++- web3swift/src/Utils/KeyUtil.swift | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/web3swift/src/Extensions/HexExtensions.swift b/web3swift/src/Extensions/HexExtensions.swift index 99fd74a5..92cc66fb 100644 --- a/web3swift/src/Extensions/HexExtensions.swift +++ b/web3swift/src/Extensions/HexExtensions.swift @@ -80,7 +80,9 @@ public extension Web3Extensions where Base == String { } var orZero: String { - if base.isEmpty { return "0" } + if base.isEmpty { + return "0" + } return base } diff --git a/web3swift/src/Utils/KeyUtil.swift b/web3swift/src/Utils/KeyUtil.swift index 464404f6..1d1a8594 100644 --- a/web3swift/src/Utils/KeyUtil.swift +++ b/web3swift/src/Utils/KeyUtil.swift @@ -4,8 +4,8 @@ // import Logging -import libsecp256k1 import Foundation +import libsecp256k1 public enum KeyUtilError: Error { case invalidContext From 2844188bd266283419257e65b33893bbba9cc19e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Da=CC=A8browski?= Date: Fri, 10 Oct 2025 14:39:42 +0200 Subject: [PATCH 6/7] chore: update upgraded dependency name --- Package.resolved | 20 ++++++++++---------- Package.swift | 4 ++-- Package@swift-6.1.swift | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Package.resolved b/Package.resolved index ee6dfc0b..11cb6742 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "05067935d9be918d55a72afa4a7d59f1dfa450ae67d031dba3f3f2477737dd37", + "originHash" : "36ca63937bf49388c5b25ea5b3bd0742efb93e124ed013969d14ff142714af43", "pins" : [ { "identity" : "bigint", @@ -19,15 +19,6 @@ "version" : "2.0.2" } }, - { - "identity" : "secp256k1.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/GigaBitcoin/secp256k1.swift.git", - "state" : { - "revision" : "8c62aba8a3011c9bcea232e5ee007fb0b34a15e2", - "version" : "0.21.1" - } - }, { "identity" : "swift-algorithms", "kind" : "remoteSourceControl", @@ -172,6 +163,15 @@ "version" : "1.1.1" } }, + { + "identity" : "swift-secp256k1", + "kind" : "remoteSourceControl", + "location" : "https://github.com/21-DOT-DEV/swift-secp256k1", + "state" : { + "revision" : "8c62aba8a3011c9bcea232e5ee007fb0b34a15e2", + "version" : "0.21.1" + } + }, { "identity" : "swift-service-lifecycle", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index c17cfd67..7543a29e 100644 --- a/Package.swift +++ b/Package.swift @@ -15,7 +15,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/attaswift/BigInt", from: "5.7.0"), .package(url: "https://github.com/iwill/generic-json-swift", .upToNextMajor(from: "2.0.2")), - .package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", exact: "0.21.1"), + .package(url: "https://github.com/21-DOT-DEV/swift-secp256k1", exact: "0.21.1"), .package(url: "https://github.com/vapor/websocket-kit.git", from: "2.16.1"), .package(url: "https://github.com/apple/swift-log.git", from: "1.6.4") ], @@ -29,7 +29,7 @@ let package = Package( .target(name: "Internal_CryptoSwift_PBDKF2"), "BigInt", .product(name: "GenericJSON", package: "generic-json-swift"), - .product(name: "libsecp256k1", package: "secp256k1.swift"), + .product(name: "libsecp256k1", package: "swift-secp256k1"), .product(name: "WebSocketKit", package: "websocket-kit"), .product(name: "Logging", package: "swift-log") ], diff --git a/Package@swift-6.1.swift b/Package@swift-6.1.swift index 3a3a4de4..66324398 100644 --- a/Package@swift-6.1.swift +++ b/Package@swift-6.1.swift @@ -15,7 +15,7 @@ let package = Package( dependencies: [ .package(url: "https://github.com/attaswift/BigInt", from: "5.7.0"), .package(url: "https://github.com/iwill/generic-json-swift", .upToNextMajor(from: "2.0.2")), - .package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", exact: "0.21.1"), + .package(url: "https://github.com/21-DOT-DEV/swift-secp256k1", exact: "0.21.1"), .package(url: "https://github.com/vapor/websocket-kit.git", from: "2.16.1"), .package(url: "https://github.com/apple/swift-log.git", from: "1.6.4") ], @@ -29,7 +29,7 @@ let package = Package( .target(name: "Internal_CryptoSwift_PBDKF2"), "BigInt", .product(name: "GenericJSON", package: "generic-json-swift"), - .product(name: "libsecp256k1", package: "secp256k1.swift"), + .product(name: "libsecp256k1", package: "swift-secp256k1"), .product(name: "WebSocketKit", package: "websocket-kit"), .product(name: "Logging", package: "swift-log") ], From 3939e604a7f6809cf1f0b6059cc5cedd7c52c813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Da=CC=A8browski?= Date: Fri, 10 Oct 2025 14:56:45 +0200 Subject: [PATCH 7/7] chore: update source secp256k1 dependency --- Package.resolved | 2 +- Package.swift | 2 +- Package@swift-6.1.swift | 2 +- .../Account/EthereumKeyStorageTests.swift | 4 +- web3swift/src/Utils/KeyUtil.swift | 140 ++++-------------- 5 files changed, 37 insertions(+), 113 deletions(-) diff --git a/Package.resolved b/Package.resolved index 11cb6742..fe965630 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "36ca63937bf49388c5b25ea5b3bd0742efb93e124ed013969d14ff142714af43", + "originHash" : "b32ba4976231931ba232922d2a9641335f577e4e7cbe50182cb15282578b0c9a", "pins" : [ { "identity" : "bigint", diff --git a/Package.swift b/Package.swift index 7543a29e..de75a8bf 100644 --- a/Package.swift +++ b/Package.swift @@ -29,7 +29,7 @@ let package = Package( .target(name: "Internal_CryptoSwift_PBDKF2"), "BigInt", .product(name: "GenericJSON", package: "generic-json-swift"), - .product(name: "libsecp256k1", package: "swift-secp256k1"), + .product(name: "P256K", package: "swift-secp256k1"), .product(name: "WebSocketKit", package: "websocket-kit"), .product(name: "Logging", package: "swift-log") ], diff --git a/Package@swift-6.1.swift b/Package@swift-6.1.swift index 66324398..c4790339 100644 --- a/Package@swift-6.1.swift +++ b/Package@swift-6.1.swift @@ -29,7 +29,7 @@ let package = Package( .target(name: "Internal_CryptoSwift_PBDKF2"), "BigInt", .product(name: "GenericJSON", package: "generic-json-swift"), - .product(name: "libsecp256k1", package: "swift-secp256k1"), + .product(name: "P256K", package: "swift-secp256k1"), .product(name: "WebSocketKit", package: "websocket-kit"), .product(name: "Logging", package: "swift-log") ], diff --git a/web3sTests/Account/EthereumKeyStorageTests.swift b/web3sTests/Account/EthereumKeyStorageTests.swift index 92b5f824..828d9848 100644 --- a/web3sTests/Account/EthereumKeyStorageTests.swift +++ b/web3sTests/Account/EthereumKeyStorageTests.swift @@ -17,7 +17,7 @@ class EthereumKeyStorageTests: XCTestCase { } func testStoreLocalPrivateKey() { - let randomData = Data.randomOfLength(256)! + let randomData = Data.randomOfLength(32)! let keyStorage = EthereumKeyLocalStorage() do { @@ -29,7 +29,7 @@ class EthereumKeyStorageTests: XCTestCase { } func testStoreAndLoadLocalPrivateKey() { - let randomData = Data.randomOfLength(256)! + let randomData = Data.randomOfLength(32)! let keyStorage = EthereumKeyLocalStorage() let ethereumAddress = EthereumAddress(TestConfig.publicKey) do { diff --git a/web3swift/src/Utils/KeyUtil.swift b/web3swift/src/Utils/KeyUtil.swift index 1d1a8594..34735786 100644 --- a/web3swift/src/Utils/KeyUtil.swift +++ b/web3swift/src/Utils/KeyUtil.swift @@ -3,9 +3,9 @@ // Copyright © Argent Labs Limited. All rights reserved. // +import P256K import Logging import Foundation -import libsecp256k1 public enum KeyUtilError: Error { case invalidContext @@ -26,40 +26,12 @@ public class KeyUtil { } public static func generatePublicKey(from privateKey: Data) throws -> Data { - guard let ctx = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)) else { - logger.warning("Failed to generate a public key: invalid context.") - throw KeyUtilError.invalidContext - } - - defer { - secp256k1_context_destroy(ctx) - } - - let privateKeyPtr = (privateKey as NSData).bytes.assumingMemoryBound(to: UInt8.self) - guard secp256k1_ec_seckey_verify(ctx, privateKeyPtr) == 1 else { - logger.warning("Failed to generate a public key: private key is not valid.") - throw KeyUtilError.privateKeyInvalid - } - - let publicKeyPtr = UnsafeMutablePointer.allocate(capacity: 1) - defer { - publicKeyPtr.deallocate() - } - guard secp256k1_ec_pubkey_create(ctx, publicKeyPtr, privateKeyPtr) == 1 else { - logger.warning("Failed to generate a public key: public key could not be created.") - throw KeyUtilError.unknownError - } + let privateKey = try P256K.Recovery.PrivateKey(dataRepresentation: privateKey, format: .uncompressed) - var publicKeyLength = 65 - let outputPtr = UnsafeMutablePointer.allocate(capacity: publicKeyLength) - defer { - outputPtr.deallocate() - } - secp256k1_ec_pubkey_serialize(ctx, outputPtr, &publicKeyLength, publicKeyPtr, UInt32(SECP256K1_EC_UNCOMPRESSED)) - - let publicKey = Data(bytes: outputPtr, count: publicKeyLength).subdata(in: 1 ..< publicKeyLength) - - return publicKey + let publicKey = privateKey.publicKey.dataRepresentation + let publicKeyLength = publicKey.count + let finalPublicKey = publicKey.subdata(in: 1 ..< publicKeyLength) + return finalPublicKey } public static func generateAddress(from publicKey: Data) -> EthereumAddress { @@ -69,44 +41,18 @@ public class KeyUtil { } public static func sign(message: Data, with privateKey: Data, hashing: Bool) throws -> Data { - guard let ctx = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)) else { - logger.warning("Failed to sign message: invalid context.") - throw KeyUtilError.invalidContext - } - - defer { - secp256k1_context_destroy(ctx) - } - + let privateKey = try P256K.Recovery.PrivateKey(dataRepresentation: privateKey) let msgData = hashing ? message.web3.keccak256 : message - let msg = (msgData as NSData).bytes.assumingMemoryBound(to: UInt8.self) - let privateKeyPtr = (privateKey as NSData).bytes.assumingMemoryBound(to: UInt8.self) - let signaturePtr = UnsafeMutablePointer.allocate(capacity: 1) - defer { - signaturePtr.deallocate() - } - guard secp256k1_ecdsa_sign_recoverable(ctx, signaturePtr, msg, privateKeyPtr, nil, nil) == 1 else { - logger.warning("Failed to sign message: recoverable ECDSA signature creation failed.") - throw KeyUtilError.signatureFailure - } - - let outputPtr = UnsafeMutablePointer.allocate(capacity: 64) - defer { - outputPtr.deallocate() - } - var recid: Int32 = 0 - secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, outputPtr, &recid, signaturePtr) + let digest = HashDigest(msgData.bytes) + let signature = try privateKey.signature(for: digest) - let outputWithRecidPtr = UnsafeMutablePointer.allocate(capacity: 65) - defer { - outputWithRecidPtr.deallocate() - } - outputWithRecidPtr.update(from: outputPtr, count: 64) - outputWithRecidPtr.advanced(by: 64).pointee = UInt8(recid) - - let signature = Data(bytes: outputWithRecidPtr, count: 65) + let compactSignature = try signature.compactRepresentation.signature + let recoveryId = try signature.compactRepresentation.recoveryId - return signature + var resultSignature = Data(compactSignature) + let v = UInt8(recoveryId & 0xFF) + resultSignature.append(v) + return resultSignature } public static func recoverPublicKey(message: Data, signature: Data) throws -> String { @@ -114,45 +60,23 @@ public class KeyUtil { throw KeyUtilError.badArguments } - guard let ctx = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)) else { - logger.warning("Failed to sign message: invalid context.") - throw KeyUtilError.invalidContext - } - defer { secp256k1_context_destroy(ctx) } - - // get recoverable signature - let signaturePtr = UnsafeMutablePointer.allocate(capacity: 1) - defer { signaturePtr.deallocate() } - let serializedSignature = Data(signature[0 ..< 64]) - var v = Int32(signature[64]) - if v >= 27, v <= 30 { - v -= 27 - } else if v >= 31, v <= 34 { - v -= 31 - } else if v >= 35, v <= 38 { - v -= 35 - } - - try serializedSignature.withUnsafeBytes { - guard secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, signaturePtr, $0.bindMemory(to: UInt8.self).baseAddress!, v) == 1 else { - logger.warning("Failed to parse signature: recoverable ECDSA signature parse failed.") - throw KeyUtilError.signatureParseFailure - } - } - let pubkey = UnsafeMutablePointer.allocate(capacity: 1) - defer { pubkey.deallocate() } - - try message.withUnsafeBytes { - guard secp256k1_ecdsa_recover(ctx, pubkey, signaturePtr, $0.bindMemory(to: UInt8.self).baseAddress!) == 1 else { - throw KeyUtilError.signatureFailure - } - } - var size = 65 - var rv = Data(count: size) - _ = rv.withUnsafeMutableBytes { - secp256k1_ec_pubkey_serialize(ctx, $0.bindMemory(to: UInt8.self).baseAddress!, &size, pubkey, UInt32(SECP256K1_EC_UNCOMPRESSED)) - } - return "0x\(rv[1...].web3.keccak256.web3.hexString.suffix(40))" + var recoveryId = Int32(signature[64]) + if recoveryId >= 27, recoveryId <= 30 { + recoveryId -= 27 + } else if recoveryId >= 31, recoveryId <= 34 { + recoveryId -= 31 + } else if recoveryId >= 35, recoveryId <= 38 { + recoveryId -= 35 + } + + let digest = HashDigest(message.bytes) + let publicKey = try P256K.Recovery.PublicKey( + digest, + signature: P256K.Recovery.ECDSASignature(compactRepresentation: serializedSignature, recoveryId: recoveryId), + format: .uncompressed + ) + + return "0x\(publicKey.dataRepresentation[1...].web3.keccak256.web3.hexString.suffix(40))" } }