diff --git a/Package.resolved b/Package.resolved index 85fb565..c78cb35 100644 --- a/Package.resolved +++ b/Package.resolved @@ -23,8 +23,8 @@ "package": "curvelib.swift", "repositoryURL": "https://github.com/tkey/curvelib.swift", "state": { - "branch": "refactor", - "revision": "3477abff071170d005f05397c6049478fa6ecaf3", + "branch": "extension", + "revision": "d5acae05bfd832393524ec8e0bf8820a745e5331", "version": null } }, diff --git a/Package.swift b/Package.swift index 1776997..2dca5d3 100644 --- a/Package.swift +++ b/Package.swift @@ -12,7 +12,7 @@ let package = Package( dependencies: [ .package(name: "BigInt", url: "https://github.com/attaswift/BigInt.git", from: "5.3.0"), .package(name: "CryptoSwift", url: "https://github.com/krzyzanowskim/CryptoSwift.git",from: "1.7.2"), - .package(name: "curvelib.swift", url: "https://github.com/tkey/curvelib.swift", .branch("refactor")), + .package(name: "curvelib.swift", url: "https://github.com/tkey/curvelib.swift", .branch("extension")), .package(name: "SocketIO", url: "https://github.com/socketio/socket.io-client-swift", .upToNextMajor(from: "16.0.1")), ], targets: [ diff --git a/Sources/tss-client-swift/CurveSecp256k1.swift b/Sources/tss-client-swift/CurveSecp256k1.swift deleted file mode 100644 index 4baf1cf..0000000 --- a/Sources/tss-client-swift/CurveSecp256k1.swift +++ /dev/null @@ -1,116 +0,0 @@ -import CryptoSwift -import Foundation -import BigInt -import curvelib_swift - -public struct CurveSecp256k1 {} - -extension CurveSecp256k1 { - public static func ecdh(pubKey: PublicKey, privateKey: SecretKey) throws -> PublicKey { - return try pubKey.mul(key: privateKey) - } - - public static func signForRecovery(hash: String, privateKey: SecretKey) throws -> curvelib_swift.Signature { - return try ECDSA.sign_recoverable(key: privateKey, hash: hash) - } - - public static func privateToPublic(privateKey: SecretKey, compressed: Bool = false) throws -> String { - let publicKey = try privateKey.to_public() - return try publicKey.serialize(compressed: compressed) - } - - public static func combineSerializedPublicKeys(keys: PublicKeyCollection, outputCompressed: Bool = false) throws -> String { - let combined = try PublicKey.combine(collection: keys) - return try combined.serialize(compressed: outputCompressed) - } - - internal static func recoverPublicKey(hash: String, recoverableSignature: curvelib_swift.Signature) throws -> PublicKey { - return try ECDSA.recover(signature: recoverableSignature, hash: hash) - } - - internal static func privateKeyToPublicKey(privateKey: String) throws -> PublicKey { - let sk = try SecretKey(hex: privateKey) - return try sk.to_public() - } - - public static func serializePublicKey(publicKey: PublicKey, compressed: Bool = false) throws -> String { - return try publicKey.serialize(compressed: compressed) - } - - static func parsePublicKey(serializedKey: String) throws -> PublicKey { - return try PublicKey(hex: serializedKey) - } - - public static func parseSignature(signature: String) throws -> curvelib_swift.Signature { - return try Signature(hex: signature) - } - - internal static func serializeSignature(recoverableSignature: curvelib_swift.Signature) throws -> String { - return try recoverableSignature.serialize() - } - - internal static func recoverableSign(hash: String, privateKey: String) throws -> curvelib_swift.Signature { - let sk = try SecretKey(hex: privateKey) - return try ECDSA.sign_recoverable(key: sk, hash: hash) - } - - public static func recoverPublicKey(hash: String, signature: String, compressed: Bool = false) throws -> String { - let sig = try Signature(hex: signature) - debugPrint(try sig.serialize()) - return try ECDSA.recover(signature: sig, hash: hash).serialize(compressed: compressed) - } - - public static func verifyPrivateKey(privateKey: String) -> Bool { - do { - _ = try SecretKey(hex: privateKey) - return true; - } catch (_) { - return false; - } - } - - public static func generatePrivateKey() throws -> String { - let sk = SecretKey() - return try sk.serialize() - } - - internal static func randomBytes(length: Int) -> Data? { - for _ in 0 ... 1024 { - var data = Data(repeating: 0, count: length) - let result = data.withUnsafeMutableBytes { mutableRBBytes -> Int32? in - if let mutableRBytes = mutableRBBytes.baseAddress, mutableRBBytes.count > 0 { - let mutableBytes = mutableRBytes.assumingMemoryBound(to: UInt8.self) - return SecRandomCopyBytes(kSecRandomDefault, 32, mutableBytes) - } else { - return nil - } - } - if let res = result, res == errSecSuccess { - return data - } else { - continue - } - } - return nil - } - - internal static func toByteArray(_ value: T) -> [UInt8] { - var value = value - return withUnsafeBytes(of: &value) { Array($0) } - } - - internal static func fromByteArray(_ value: [UInt8], _: T.Type) -> T { - return value.withUnsafeBytes { - $0.baseAddress!.load(as: T.self) - } - } - - internal static func constantTimeComparison(_ lhs: Data, _ rhs: Data) -> Bool { - guard lhs.count == rhs.count else { return false } - var difference = UInt8(0x00) - for i in 0 ..< lhs.count { // compare full length - difference |= lhs[i] ^ rhs[i] // constant time - } - return difference == UInt8(0x00) - } -} diff --git a/Sources/tss-client-swift/Helpers.swift b/Sources/tss-client-swift/Helpers.swift index 867c51a..08b7e72 100644 --- a/Sources/tss-client-swift/Helpers.swift +++ b/Sources/tss-client-swift/Helpers.swift @@ -1,6 +1,7 @@ import BigInt import curvelib_swift import CryptoKit +import CryptoSwift import Foundation public class TSSHelpers { @@ -78,7 +79,8 @@ public class TSSHelpers { throw TSSClientError("Invalid base64 encoded hash") } do { - let pk = try CurveSecp256k1.recoverPublicKey(hash: msgB64.hexString, signature: sigString, compressed: false) + let signature = try Signature(hex: sigString) + let pk = try ECDSA.recover(signature: signature, hash: msgB64.hexString).serialize(compressed: false) return pk } catch (_) { throw TSSClientError("Public key recover failed") @@ -241,8 +243,8 @@ public class TSSHelpers { let serverLagrangeCoeff = try TSSHelpers.getLagrangeCoefficient(parties: [BigInt(1), userTssIndex], party: BigInt(1)) let userLagrangeCoeff = try TSSHelpers.getLagrangeCoefficient(parties: [BigInt(1), userTssIndex], party: userTssIndex) - let serverTermUnprocessed = try CurveSecp256k1.parsePublicKey(serializedKey: dkgPubKey.toHexString()) - let userTermUnprocessed = try CurveSecp256k1.parsePublicKey(serializedKey: userSharePubKey.toHexString()) + let serverTermUnprocessed = try PublicKey(hex: dkgPubKey.toHexString()) + let userTermUnprocessed = try PublicKey(hex: userSharePubKey.toHexString()) var serverTerm = serverTermUnprocessed var userTerm = userTermUnprocessed @@ -250,9 +252,9 @@ public class TSSHelpers { let serverLagrangeCoeffData = try Data.ensureDataLengthIs32Bytes(serverLagrangeCoeff.serialize()) let userLagrangeCoeffData = try Data.ensureDataLengthIs32Bytes(userLagrangeCoeff.serialize()) - let serverTermProcessed = try CurveSecp256k1.ecdh(pubKey: serverTerm, privateKey: try SecretKey(hex: serverLagrangeCoeffData.toHexString())) + let serverTermProcessed = try PublicKey(hex: ECDH.ecdhStandard(sk: SecretKey(hex: serverLagrangeCoeffData.toHexString()), pk: serverTerm)) - let userTermProcessed = try CurveSecp256k1.ecdh(pubKey: userTerm, privateKey: SecretKey(hex: userLagrangeCoeffData.toHexString())) + let userTermProcessed = try PublicKey(hex: ECDH.ecdhStandard(sk: SecretKey(hex: userLagrangeCoeffData.toHexString()), pk: userTerm)) serverTerm = serverTermProcessed userTerm = userTermProcessed @@ -261,9 +263,9 @@ public class TSSHelpers { try collection.insert(key: serverTermProcessed) try collection.insert(key: userTermProcessed) - let combination = try CurveSecp256k1.combineSerializedPublicKeys(keys: collection) + let combination = try PublicKey.combine(collection: collection) - return Data(hexString: combination)! + return Data(hexString: try combination.serialize(compressed: false))! } internal static func getAdditiveCoefficient(isUser: Bool, participatingServerIndexes: [BigInt], userTSSIndex: BigInt, serverIndex: BigInt?) throws -> BigInt { diff --git a/Sources/tss-client-swift/dkls/ChaChaRng.swift b/Sources/tss-client-swift/dkls/ChaChaRng.swift index 5f27fb9..b1c5632 100644 --- a/Sources/tss-client-swift/dkls/ChaChaRng.swift +++ b/Sources/tss-client-swift/dkls/ChaChaRng.swift @@ -1,4 +1,5 @@ import Foundation +import curvelib_swift #if canImport(dkls) import dkls #endif @@ -7,7 +8,7 @@ internal final class ChaChaRng { private(set) var pointer: OpaquePointer? public init() throws { - let stateBytes = try CurveSecp256k1.generatePrivateKey() + let stateBytes = try SecretKey().serialize() let state = Data(hexString: stateBytes)!.base64EncodedString() var errorCode: Int32 = -1 diff --git a/Tests/tss-client-swiftTests/tss_client_swiftTests.swift b/Tests/tss-client-swiftTests/tss_client_swiftTests.swift index 54aa92e..7092175 100644 --- a/Tests/tss-client-swiftTests/tss_client_swiftTests.swift +++ b/Tests/tss-client-swiftTests/tss_client_swiftTests.swift @@ -38,7 +38,7 @@ final class tss_client_swiftTests: XCTestCase { let hash = TSSHelpers.hashMessage(message: token) let data = hash.data(using: .utf8)! let msgB64 = Data(base64Encoded: data)! - let serializedNodeSig = try CurveSecp256k1.signForRecovery(hash: msgB64.hexString, privateKey: SecretKey(hex: item)).serialize() + let serializedNodeSig = try ECDSA.signRecoverable(key: SecretKey(hex: item), hash: msgB64.hexString).serialize() let msg: [String: Any] = [ "data": token, "sig": serializedNodeSig, @@ -75,7 +75,7 @@ final class tss_client_swiftTests: XCTestCase { var additiveShares: [BigInt] = [] var shareSum = BigInt.zero for _ in 0 ..< (parties.count - 1) { - let shareBigUint = BigUInt(try CurveSecp256k1.generatePrivateKey(), radix: 16) + let shareBigUint = BigUInt(try SecretKey().serialize(), radix: 16) let shareBigInt = BigInt(sign: .plus, magnitude: shareBigUint!) additiveShares.append(shareBigInt) shareSum += shareBigInt @@ -144,12 +144,12 @@ final class tss_client_swiftTests: XCTestCase { private func setupMockShares(endpoints: [String?], parties: [Int32], localClientIndex: Int32, session: String) throws -> (Data, Data) { - let privKey = try CurveSecp256k1.generatePrivateKey() - let privKeyBigUInt = BigUInt(privKey, radix: 16) + let privKey = SecretKey() + let privKeyBigUInt = BigUInt(try privKey.serialize(), radix: 16) let privKeyBigInt = BigInt(sign: .plus, magnitude: privKeyBigUInt!) - let publicKey = try CurveSecp256k1.privateToPublic(privateKey: SecretKey(hex: privKey), compressed: false) + let publicKey = try privKey.toPublic() try distributeShares(privKey: privKeyBigInt, parties: parties, endpoints: endpoints, localClientIndex: localClientIndex, session: session) - return (Data(hexString: privKey)!, Data(hexString: publicKey)!) + return (Data(hexString: try privKey.serialize())!, Data(hexString: try publicKey.serialize(compressed: false))!) } private func generateEndpoints(parties: Int, clientIndex: Int32) -> ([String?], [String?], [Int32]) { @@ -177,7 +177,7 @@ final class tss_client_swiftTests: XCTestCase { let msg = "hello world" let msgHash = TSSHelpers.hashMessage(message: msg) let clientIndex = Int32(parties - 1) - let randomKey = BigUInt(try CurveSecp256k1.generatePrivateKey(), radix: 16) + let randomKey = BigUInt(try SecretKey().serialize(), radix: 16) let random = BigInt(sign: .plus, magnitude: randomKey!) + BigInt(Date().timeIntervalSince1970) let randomNonce = TSSHelpers.hashMessage(message: String(random)) let testingRouteIdentifier = "testingShares" @@ -207,7 +207,7 @@ final class tss_client_swiftTests: XCTestCase { let pk = try! TSSHelpers.recoverPublicKey(msgHash: msgHash, s: s, r: r, v: v) _ = try! TSSHelpers.hexUncompressedPublicKey(pubKey: Data(hexString:pk)!, return64Bytes: true) let pkHex65 = try! TSSHelpers.hexUncompressedPublicKey(pubKey: Data(hexString:pk)!, return64Bytes: false) - let skToPkHex = try CurveSecp256k1.privateToPublic(privateKey: SecretKey(hex: privateKey.hexString)) + let skToPkHex = try SecretKey(hex: privateKey.hexString).toPublic().serialize(compressed: false) XCTAssert(pkHex65 == skToPkHex) print(try! TSSHelpers.hexSignature(s: s, r: r, v: v))