I generated an elliptic curve private/public key pair on iOS, and store them to keychain inside secure enclave.
I want to sign/verify a message with those keys.
So, here is my code to sign a message using SecKeyCreateSignature.
var error: Unmanaged<CFError>?
let signature = SecKeyCreateSignature(myPrivateKey,
.ecdsaSignatureMessageX962SHA512,
plainData as CFData,
&error)
It works well, but SecKeyCreateSignature is only available in iOS 10.
I would like to maintain compatibility with iOS 9 at least. So I searched the alternative way to sign a message, and I found SecKeyRawSign that look similar to the function above.
However SecKeyRawSign doesn't look like to support elliptic curve key.
How can I use SecKeyRawSign or alternative ways to sign/verify a message that is equivalent or similar to the code above?
For compatibility you can use SecKeyRawSign similarly to SecKeyCreateSignature.
In this case, they are not equivalent because the algorithm to create the signature is different. But they can sign/verify as usual.
func signCompat(privateKey: SecKey, rawData: Data) -> Data? {
if #available(iOS 10.0, *) {
return sign_iOS_10(privateKey: privateKey, rawData: rawData)
} else {
return sign_iOS_9(privateKey: privateKey, rawData: rawData)
}
}
@available(iOS 10.0, *)
func sign_iOS_10(privateKey: SecKey, rawData: Data) -> Data? {
let algorithm = SecKeyAlgorithm.ecdsaSignatureMessageX962SHA512
return SecKeyCreateSignature(privateKey, algorithm, rawData as CFData, nil) as Data?
}
func sign_iOS_9(privateKey: SecKey, rawData: Data) -> Data? {
let sha512digestedData = rawData.sha512()
var raw_signature_length = 512
let raw_signature_bytes = UnsafeMutablePointer<UInt8>.allocate(capacity: 512)
let osStatus = SecKeyRawSign(privateKey,
.PKCS1SHA512,
[UInt8](sha512digestedData),
Int(CC_SHA512_DIGEST_LENGTH),
raw_signature_bytes,
&raw_signature_length)
guard osStatus == errSecSuccess else { return nil }
return Data(bytes: raw_signature_bytes, count: raw_signature_length)
}
// The same logic is applied to verify
//
func verifyCompat(privateKey: SecKey, rawData: Data) -> Data? { ... }
@available(iOS 10.0, *)
func verify_iOS_10(privateKey: SecKey, rawData: Data) -> Data? { ... }
func verify_iOS_9(privateKey: SecKey, rawData: Data) -> Data? { ... }
You can check for correctness with these openssl commands.
// Sign
openssl dgst -sha512 -sign private.pem < test.pdf > signature.bin
// Verify
openssl dgst -sha512 -verify public.pem -signature signature.bin test.pdf
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With