Platform SSO - Device Signing Key and Device Encryption Key Format

We are trying to get Platform SSO working on our extension and are facing difficulties in getting the Device Signing and Device Encryption keys in the correct format.

The relevant code fragments are pasted below:

// Getting the Device Signing and Device Encryption Key from the Login Manager
let cde = loginManager.key(for: ASAuthorizationProviderExtensionKeyType.currentDeviceEncryption) // Seckey Object
let cds = loginManager.key(for: ASAuthorizationProviderExtensionKeyType.currentDeviceSigning) // Seckey Object

// Call the method to convert them to PEM format. generatePEMKey is defined below
cde_pem = generatePEMKey(cde)
cds_pem = generatePEMKey(cds)

// Generating PEM data from the keys
func generatePEMKey(secKey: SecKey) -> String {
    guard let publicKey = SecKeyCopyPublicKey(secKey) else {
        print("Failed to copy public key")
        return ""
    }

    var error: Unmanaged<CFError>?
    guard let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, &error) as Data? else {
        print("Failed to copy external representation: \(error!.takeRetainedValue() as Error)")
        return ""
    }

    let pemKey = publicKeyData.base64EncodedString(options: [.lineLength64Characters, .endLineWithLineFeed])
    return """
    -----BEGIN PUBLIC KEY-----
    \(pemKey)
    -----END PUBLIC KEY-----
    """
}

However, when we try to use the keys obtained using the code fragments above, we get errors stating that these are invalid keys.

I saved the PEM output to a file (key1.pem) and tried to inspect it using OpenSSL:

openssl ec -in key1.pem -pubin -text -noout

This command results in the following errors:

read EC key
unable to load Key
8337280000:error:10FFF06B:elliptic curve routines:CRYPTO_internal:point is not on curve:/AppleInternal/Library/BuildRoots/91a344b1-f985-11ee-b563-fe8bc7981bff/Library/Caches/com.apple.xbs/Sources/libressl/libressl-3.3/crypto/ec/ec_lib.c:970:
8337280000:error:10FFF010:elliptic curve routines:CRYPTO_internal:EC lib:/AppleInternal/Library/BuildRoots/91a344b1-f985-11ee-b563-fe8bc7981bff/Library/Caches/com.apple.xbs/Sources/libressl/libressl-3.3/crypto/ec/ec_asn1.c:1581:
8337280000:error:10FFF08E:elliptic curve routines:CRYPTO_internal:decode error:/AppleInternal/Library/BuildRoots/91a344b1-f985-11ee-b563-fe8bc7981bff/Library/Caches/com.apple.xbs/Sources/libressl/libressl-3.3/crypto/ec/ec_ameth.c:212:
8337280000:error:0BFFF07D:x509 certificate routines:CRYPTO_internal:public key decode error:/AppleInternal/Library/BuildRoots/91a344b1-f985-11ee-b563-fe8bc7981bff/Library/Caches/com.apple.xbs/Sources/libressl/libressl-3.3/crypto/asn1/x_pubkey.c:203:
8337280000:error:09FFF00D:PEM routines:CRYPTO_internal:ASN1 lib:/AppleInternal/Library/BuildRoots/91a344b1-f985-11ee-b563-fe8bc7981bff/Library/Caches/com.apple.xbs/Sources/libressl/libressl-3.3/crypto/pem/pem_oth.c:84:

Questions:

  1. Is there an issue with how I am generating or formatting the PEM file in Swift?
  2. Why might OpenSSL be unable to load the key, and how can I resolve these errors?
  3. Is there a way to validate the key data before encoding it to base64 and writing it to a PEM file?

Any insights or suggestions would be greatly appreciated!

Answered by DTS Engineer in 798708022

The issue here is almost certainly that SecKeyCopyExternalRepresentation does not add the SubjectPublicKeyInfo wrapper. I talk about this in some detail in On Cryptographic Key Formats.

I believe you’ll be able to get the PEM you need using Apple CryptoKit:

func pemForPublicKey(_ publicKey: SecKey) throws -> String {
    let keyBytes = try secCall { SecKeyCopyExternalRepresentation(publicKey, $0) } as Data
    let k = try P256.Signing.PublicKey(x963Representation: keyBytes)
    return k.pemRepresentation
}

This is using the helpers from this post.

Share and Enjoy

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

The issue here is almost certainly that SecKeyCopyExternalRepresentation does not add the SubjectPublicKeyInfo wrapper. I talk about this in some detail in On Cryptographic Key Formats.

I believe you’ll be able to get the PEM you need using Apple CryptoKit:

func pemForPublicKey(_ publicKey: SecKey) throws -> String {
    let keyBytes = try secCall { SecKeyCopyExternalRepresentation(publicKey, $0) } as Data
    let k = try P256.Signing.PublicKey(x963Representation: keyBytes)
    return k.pemRepresentation
}

This is using the helpers from this post.

Share and Enjoy

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

Platform SSO - Device Signing Key and Device Encryption Key Format
 
 
Q