Posts

Post not yet marked as solved
2 Replies
1.5k Views
I am using the ecdsa python library to generate keys and signatures for messages, but I am unable to verify those signatures in Swift.I'm trying to simply verify a signature of the text "S". I've been able to successfully create a public SecKey, but no matter what I do, I cannot seem to get SecKeyVerifySignature to pass. The payload is hashed using SHA-1, and I've been able to verify the digest in Swift matches the digest in python. The failing code below should run in xCode.// ecdsaVerify import Foundation import CommonCrypto extension Data { struct HexEncodingOptions: OptionSet { let rawValue: Int static let upperCase = HexEncodingOptions(rawValue: 1 << 0) } func hexEncodedString(options: HexEncodingOptions = []) -> String { let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx" return map { String(format: format, $0) }.joined() } } extension String{ func sha1() -> String { let data = Data(self.utf8) var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH)) data.withUnsafeBytes { _ = CC_SHA1($0.baseAddress, CC_LONG(data.count), &digest) } let hexBytes = digest.map { String(format: "%02hhx", $0) } return hexBytes.joined() } var hexadecimalStringToData: Data? { // Convert a hexstring to data var data = Data(capacity: self.count / 2) let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive) regex.enumerateMatches(in: self, range: NSRange(startIndex..., in: self)) { match, _, _ in let byteString = (self as NSString).substring(with: match!.range) let num = UInt8(byteString, radix: 16)! data.append(num) } guard data.count > 0 else { return nil } return data } } //prime256v1, a.k.a kSecECCurveSecp256r1 // .der with first 26 bits removed let EC_PUBLIC_KEY = """ -----BEGIN BARE KEY----- BOptLvuuwPYOaQC6v7hDh36fTqsuwFTCyHVg3uYvfdbPtV5c3urT8HeS/UaGgaO8tMFfpz1sljTnwWTPb8gQcD8= -----END BARE KEY----- """ // Here for example purposes - to help others generate signatures. let PRIVATE_KEY = """ -----BEGIN EC PRIVATE KEY----- MHcCAQEEINxdvHX9q9PGrJBWHcmvXGe3poOc0Qc1/C4HnScp6cP7oAoGCCqGSM49 AwEHoUQDQgAE6m0u+67A9g5pALq/uEOHfp9Oqy7AVMLIdWDe5i991s+1Xlze6tPw d5L9RoaBo7y0wV+nPWyWNOfBZM9vyBBwPw== -----END EC PRIVATE KEY----- """ class ecdsaVerifier{ var publicKeyData:Data var publicKey: SecKey? init(_ pemPublicKey: String){ let pemPublicKeyNoComments = pemPublicKey.replacingOccurrences( of: #"(?m)^----.*"#, with: "", options: .regularExpression ).trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences(of: "\n", with: "") self.publicKeyData = Data(base64Encoded:pemPublicKeyNoComments)! var error: Unmanaged<CFError>? = nil self.publicKey = SecKeyCreateWithData(self.publicKeyData as NSData, [ kSecAttrKeyType: kSecAttrKeyTypeECDSA, kSecAttrKeyClass: kSecAttrKeyClassPublic, kSecAttrKeySizeInBits: 256 ] as NSDictionary, &error) print(self.publicKey) } func verifyFromHexString(content: String, hexSignature: String) -> Bool{ let cleanSignature = hexSignature.trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences(of: "\n", with: "").replacingOccurrences(of: " ", with: "") print("verify from", cleanSignature, content) let cleanSignatureData = cleanSignature.hexadecimalStringToData! let digest = content.sha1().hexadecimalStringToData! //let digest = content.data(using: .utf8)! print("Digest", digest.count, digest.hexEncodedString()) return self.verifyFromDigest(digest, signature: cleanSignatureData) } func verifyFromDigest(_ digest: Data, signature: Data) -> Bool{ var error: Unmanaged<CFError>? = nil guard SecKeyVerifySignature(publicKey!, SecKeyAlgorithm.ecdsaSignatureDigestX962SHA1, digest as CFData, signature as CFData, &error) else { print("error", error) return false } print("true!") return true } } let verifier = ecdsaVerifier(EC_PUBLIC_KEY) let signature = """ 30 44 02 20 14 08 69 ac 3a 39 29 78 c2 fd e1 0a c2 6d 87 4e 66 57 fd bf 1a 01 b8 4c b2 13 63 fc f6 e8 0b 64 02 20 42 88 2e a0 c8 4a ca 04 a1 0a 59 be e3 c7 50 d6 53 d4 14 d3 a6 f7 e6 07 0d e2 e5 6b 8f 44 47 52 """ let content = "S" verifier.verifyFromHexString(content: content, hexSignature: signature)Any help would be appriciated.
Posted
by scml.
Last updated
.