p256 signature using cryptokit fails verification on openssl

I've went through all the posts with similar info about signature or keys used not working with openssll. But I haven't been able to patch it all together. I will use some sample keys for what I tried,

let privPem = """
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgIUSrwhllMSminPZZ
Gx0YHUsL12IWIGI+4yhejpq90HihRANCAAT6pxKtIKm4VbfXeKpQ7rxITlC6b18Q
0X+Iz1UVDolyjx79bt5vUp0mPJ6hHBnK/Ap5gXpv89wmLPp7/O2NconE
-----END PRIVATE KEY-----
"""

let privKey = try! P256.Signing.PrivateKey(pemRepresentation: privPem)

let pubKey = privKey.publicKey

let challengeDev = "1122334455667788"

let dataToSignDev = challengeDev.hexadecimal

let digest = SHA256.hash(data: dataToSignDev!)
let signatureForDigest = try! privKey.signature(
    for: digest)


let signature1 = try! P256.Signing.ECDSASignature(derRepresentation: signatureForDigest.derRepresentation)

let isValidSignature = pubKey.isValidSignature(signatureForDigest, for: digest)

I have tried the same using Security framework also to no avail. What I tried is a direct application of what the openssl part does, So I have a device that will verify the signature that the iOS app will be sending. The public key is taken from a certificate I would share with the device. All data sent to the device including signature is in DER format.


openssl dgst -sha256 -sign app_private.key -out %OUT_RESOURCES_DIR%\signature.der -binary device_challenge.hex

openssl x509 -inform der -in cert.der -out cert.pem
openssl x509 -pubkey -noout -in cert.pem > public_key.pem
openssl dgst -sha256 -verify public_key.pem -signature signature.der challenge.hex

Here on the iOS side If I were to sign and verify everything is fine. But if the same signature is verified on OpenSSL it fails.

I tried to create a DER file on the terminal but asn1parse fails on it,

Test % echo 30450220198944e2a8352941036f227225940392cbd1bc720358ce29db29a2a85f2b2a30022100b4e75ceb0335e4b1955aab01edc8e7347f78dc627f8d02a78103cd9165571d57 > signature1.der

Test % openssl asn1parse -inform DER -in signature1.der
    0:d=0  hl=2 l=  48 cons: PRINTABLESTRING   
Error in encoding
140704639042368:error:0DFFF09B:asn1 encoding routines:CRYPTO_internal:too long:/AppleInternal/Library/BuildRoots/97f6331a-ba75-11ed-a4bc-863efbbaf80d/Library/Caches/com.apple.xbs/Sources/libressl/libressl-3.3/crypto/asn1/asn1_lib.c:143:

I'm assuming I need to manually do some changes to make them inter compatible? Like this post Can't export EC kSecAttrTokenIDSecureEnclave public key

Not sure how to get there though. All help appreciated.

  • @eskimo please check

Add a Comment

Replies

This is working for me. To start, I built this program with Xcode 14.3:

import Foundation
import CryptoKit

let privateKeyPEM = """
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgIUSrwhllMSminPZZ
Gx0YHUsL12IWIGI+4yhejpq90HihRANCAAT6pxKtIKm4VbfXeKpQ7rxITlC6b18Q
0X+Iz1UVDolyjx79bt5vUp0mPJ6hHBnK/Ap5gXpv89wmLPp7/O2NconE
-----END PRIVATE KEY-----
"""

let message = Data("Hello Cruel World!\n".utf8)

func main() {
    let privateKey = try! P256.Signing.PrivateKey(pemRepresentation: privateKeyPEM)
    let publicKey = privateKey.publicKey
    let digest = SHA256.hash(data: message)
    let signature = try! privateKey.signature(for: digest)
    print("public key:")
    print(publicKey.pemRepresentation)
    print("signature:")
    print((signature.derRepresentation as NSData).debugDescription)
}

main()

Running on macOS 13.5 it prints:

public key:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+qcSrSCpuFW313iqUO68SE5Qum9f
ENF/iM9VFQ6Jco8e/W7eb1KdJjyeoRwZyvwKeYF6b/PcJiz6e/ztjXKJxA==
-----END PUBLIC KEY-----
signature:
<30450221 00aa0c2e 0d56cac8 c8eec31c bb066ee0 565d8355 fb6ff133 6e537601 f79fd69f fd022048 fb636022 f613fba5 07a15c46 c4de88a1 583418dc 4d49c55d 02422f99 b7e428>

IMPORTANT You’ll get a different signature each time because X9.62 signatures are non-deterministic.

I then transferred that to the shell:

% cat public_key.pem                                                         
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+qcSrSCpuFW313iqUO68SE5Qum9f
ENF/iM9VFQ6Jco8e/W7eb1KdJjyeoRwZyvwKeYF6b/PcJiz6e/ztjXKJxA==
-----END PUBLIC KEY-----
% xxd signature.dat     
00000000: 3045 0221 00aa 0c2e 0d56 cac8 c8ee c31c  0E.!.....V......
00000010: bb06 6ee0 565d 8355 fb6f f133 6e53 7601  ..n.V].U.o.3nSv.
00000020: f79f d69f fd02 2048 fb63 6022 f613 fba5  ...... H.c`"....
00000030: 07a1 5c46 c4de 88a1 5834 18dc 4d49 c55d  ..\F....X4..MI.]
00000040: 0242 2f99 b7e4 28                        .B/...(
% xxd message.txt
00000000: 4865 6c6c 6f20 4372 7565 6c20 576f 726c  Hello Cruel Worl
00000010: 6421 0a                                  d!.

It verifies as expected:

% openssl dgst -sha256 -verify public_key.pem -signature signature.dat message.txt
Verified OK

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for checking @eskimo , you're right it's working.