CryptoKit - generate Curve25519 public key from a long base 64 string given from server

Hi,
I'm using Curve25519 to generate the public-private key pair that's to be used for creating the shared Secret. The public key received from the server is but a very long message(base64 encoded string), which is about 309 bytes when converted to Data.

When I try to create the shared secret key using this data, CryptoKit throws the error "CryptoKit.CryptoKitError.incorrectKeySize" at this line:

Code Block swift
     let serverPublicKey = try! Curve25519.KeyAgreement.PublicKey(rawRepresentation: serverPublicKeyData)


I need the output of this line(serverPublicKey) for generating the shared secret.
Here's the rest of the code:
Code Block swift
     let clientPrivateKey = Curve25519.KeyAgreement.PrivateKey()
     let clientSharedSecret = try! clientPrivateKey.sharedSecretFromKeyAgreement(with: serverPublicKey)
     let clientSharedSecretyKey = clientSharedSecret.x963DerivedSymmetricKey(using: SHA256.self, sharedInfo: Data(), outputByteCount: 32)


and I'm encrypting using AES.GCM

Code Block swift
     let clientSealedBoxData = try! AES.GCM.seal(messageData, using: clientSharedSecretyKey).combined!
     let clientSealedBox = try! AES.GCM.SealedBox(combined: clientSealedBoxData)

where messageData is the data to be encrypted


Is there any way to compress the received public key to 32 bytes to pass it to the KeyAgreement line? (Also, is this the right method to generate the public key for encrypting?)

I've referred a lot of sites but couldn't arrive at a solution. Please help.

Accepted Reply

here's the original string without any tampering :)

Ta.

Decoding that I get this ASN.1:

Code Block
% dumpasn1 -a public-key.asn1
0 305: SEQUENCE {
4 234: SEQUENCE {
7 7: OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
16 222: SEQUENCE {
19 1: INTEGER 1
22 43: SEQUENCE {
24 7: OBJECT IDENTIFIER prime-field (1 2 840 10045 1 1)
33 32: INTEGER
: 7F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ED
: }
67 68: SEQUENCE {
69 32: OCTET STRING
: 2A AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA
: AA AA AA AA AA AA AA AA AA AA AA 98 49 14 A1 44
103 32: OCTET STRING
: 7B 42 5E D0 97 B4 25 ED 09 7B 42 5E D0 97 B4 25
: ED 09 7B 42 5E D0 97 B4 26 0B 5E 9C 77 10 C8 64
: }
137 65: OCTET STRING
: 04 2A AA AA AA AA AA AA AA AA AA AA AA AA AA AA
: AA AA AA AA AA AA AA AA AA AA AA AA AA AA AD 24
: 5A 20 AE 19 A1 B8 A0 86 B4 E0 1E DD 2C 77 48 D1
: 4C 92 3D 4D 7E 6D 7C 61 B2 29 E9 C5 A2 7E CE D3
: D9
204 32: INTEGER
: 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
: 14 DE F9 DE A2 F7 9C D6 58 12 63 1A 5C F5 D3 ED
238 1: INTEGER 8
: }
: }
241 66: BIT STRING
: 04 5A 26 73 A7 F9 8F 7D 04 79 D5 93 4E A4 47 9F
: C9 16 01 23 C1 6C 14 DD 58 FE 55 E1 C6 C9 01 F2
: 2C 6B 3C 0E A8 1E 55 FE 1A D8 67 DA CC 5F A3 F4
: 72 8C 5A D4 B7 0C 21 D0 58 A8 DA 46 1A E0 E6 A6
: 72
: }
0 warnings, 0 errors.


and this hex dump:

Code Block
% xxd public-key.asn1
00000000: 3082 0131 3081 ea06 072a 8648 ce3d 0201 0..10....*.H.=..
00000010: 3081 de02 0101 302b 0607 2a86 48ce 3d01 0.....0+..*.H.=.
00000020: 0102 207f ffff ffff ffff ffff ffff ffff .. .............
00000030: ffff ffff ffff ffff ffff ffff ffff ffff ................
00000040: ffff ed30 4404 202a aaaa aaaa aaaa aaaa ...0D. *........
00000050: aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa ................
00000060: aaaa 9849 14a1 4404 207b 425e d097 b425 ...I..D. {B^...%
00000070: ed09 7b42 5ed0 97b4 25ed 097b 425e d097 ..{B^...%..{B^..
00000080: b426 0b5e 9c77 10c8 6404 4104 2aaa aaaa .&.^.w..d.A.*...
00000090: aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa ................
000000a0: aaaa aaaa aaaa aaaa aaad 245a 20ae 19a1 ..........$Z ...
000000b0: b8a0 86b4 e01e dd2c 7748 d14c 923d 4d7e .......,wH.L.=M~
000000c0: 6d7c 61b2 29e9 c5a2 7ece d3d9 0220 1000 m|a.)...~.... ..
000000d0: 0000 0000 0000 0000 0000 0000 0000 14de ................
000000e0: f9de a2f7 9cd6 5812 631a 5cf5 d3ed 0201 ......X.c.\.....
000000f0: 0803 4200 045a 2673 a7f9 8f7d 0479 d593 ..B..Z&s...}.y..
00000100: 4ea4 479f c916 0123 c16c 14dd 58fe 55e1 N.G....#.l..X.U.
00000110: c6c9 01f2 2c6b 3c0e a81e 55fe 1ad8 67da ....,k<...U...g.
00000120: cc5f a3f4 728c 5ad4 b70c 21d0 58a8 da46 ._..r.Z...!.X..F
00000130: 1ae0 e6a6 72 ....r


As you can see the key bytes are the last 65 bytes of the data. So, you have a couple of options here:
  • You can this properly by parsing the ASN.1 SubjectPublicKeyInfo structure yourself. For this you’ll need to either write or acquire an ASN.1 parser )-:

  • You can bodgy this by just extracting the last 65 bytes of the data (someData.suffix(65)). The problem with this is that it only works for this specific key type and size.

Regardless, I encourage you to file an enhancement request for better APIs here. IMO our platforms should have high-level APIs for dealing with common crypto formats, including SubjectPublicKeyInfo.

Please post your bug number, just for the record.

Share and Enjoy

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

Replies

The public key received from the server is but a very long message
(base64 encoded string), which is about 309 bytes when converted to
Data.

Can you post an example of this? Put it in a code block (using the <> button) to make it easier to read.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
I haven't put the exact string as it's given by the client, But have altered it still maintaining the length :

Code Block
"MIIBMTCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////8888888888//7TBEBCAqqqqqqqqqqqqqqqqqttttttttttqffffffffYSRShRAQge0Je0Je0Je0Je0Je8Kr0Je8Kr0Je0Je0JgtenHcQyGQEQQQqqqqqqqqggggggggggqqqqqqqqqqqgggggggggg0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAFFFFFFFFFFFN753qL3nNZYEmMaXPXT7QIBCBNCFFRaJnOn+Y99BHnVk06kR5/JFgEjwWwU3Vj+VeHGyQHyLGs8DqgeVf4a2GfazF+j9HKMWtS3DCHQWKjaRhrg5qZy"


It does look like some tampered string... but the encryption and key creation works in android - so it's valid

I haven't put the exact string as it's given by the client

Right, but it’s a public key so it doesn’t have to be kept secret. If your crypto needs to keep public keys private then you have bigger problems (-:

But have altered it still maintaining the length :

Which has corrupted it )-: Fortunately it’s not corrupted so badly as to prevent some analysis (-:

Consider this:

Code Block
% base64 -D > tmp.dat
MIIBMTCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////8888888888//7TBEBCAqqqqqqqqqqqqqqqqqttttttttttqffffffffYSRShRAQge0Je0Je0Je0Je0Je8Kr0Je8Kr0Je0Je0JgtenHcQyGQEQQQqqqqqqqqggggggggggqqqqqqqqqqqgggggggggg0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAFFFFFFFFFFFN753qL3nNZYEmMaXPXT7QIBCBNCFFRaJnOn+Y99BHnVk06kR5/JFgEjwWwU3Vj+VeHGyQHyLGs8DqgeVf4a2GfazF+j9HKMWtS3DCHQWKjaRhrg5qZy
^D
% xxd tmp.dat
00000000: 3082 0131 3081 ea06 072a 8648 ce3d 0201 0..10....*.H.=..


Well, that looks like ASN.1 so let's dump that:

Code Block
% dumpasn1 -p -a tmp.dat
SEQUENCE {
SEQUENCE {
OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
SEQUENCE {
INTEGER 1
SEQUENCE {
OBJECT IDENTIFIER prime-field (1 2 840 10045 1 1)
INTEGER
7F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF F3 CF 3C F3 CF 3C F3 CF FF ED
}
SEQUENCE {
OCTET STRING
2A AA AA AA AA AA AA AA AA AA AA AA AA B6 DB 6D
B6 DB 6D B6 DA 9F 7D F7 DF 7D F7 D8 49 14 A1 44
OCTET STRING
7B 42 5E D0 97 B4 25 ED 09 7B 42 5E F0 AA F4 25
EF 0A AF 42 5E D0 97 B4 26 0B 5E 9C 77 10 C8 64
}
OCTET STRING
04 2A AA AA AA AA AA A0 82 08 20 82 08 20 82 AA
AA AA AA AA AA AA AA 82 08 20 82 08 20 82 0D 24
5A 20 AE 19 A1 B8 A0 86 B4 E0 1E DD 2C 77 48 D1
4C 92 3D 4D 7E 6D 7C 61 B2 29 E9 C5 A2 7E CE D3
D9
INTEGER
10 00 00 00 00 00 00 00 01 45 14 51 45 14 51 45
14 DE F9 DE A2 F7 9C D6 58 12 63 1A 5C F5 D3 ED
INTEGER 8
}
}
PrintableString
'.TZ&s...}.y..N.G....#.l..X.U.....,k<...U...g.._.'
'.r.Z...!.X..F....r'
Error: PrintableString contains illegal character(s).
}


Now consider this:

Code Block
let d = Curve25519.KeyAgreement.PrivateKey().publicKey.rawRepresentation
debugPrint(d as NSData)
// prints:
// <e8553c4d aa81cfd9 0004a913 d252f162 e107d282 05753cb4 4a9094e0 bc9e315e>


So, the CryptoKit raw representation for a Curve 25519 key is 32 bytes of unstructured data, but you’re trying to feed it a whole bunch of ASN.1. This ASN.1 is probably a SubjectPublicKeyInfo structure as defined by RFC 5280. The raw Curve 25519 bytes are probably there but they’re not present in my dump because of your redaction.

As to how you can strip this header, the best option depends on your platform. Are you targeting macOS? Or an iOS-based platform?

Share and Enjoy

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

Right, but it’s a public key so it doesn’t have to be kept secret. If your crypto needs to keep public keys private then you have bigger problems (-:

haha okay :D
here's the original string without any tampering :)

MIIBMTCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCANCAARaJnOn+Y99BHnVk06kR5/JFgEjwWwU3Vj+VeHGyQHyLGs8DqgeVf4a2GfazF+j9HKMWtS3DCHQWKjaRhrg5qZy


So, the CryptoKit raw representation for a Curve 25519 key is 32 bytes of unstructured data, but you’re trying to feed it a whole bunch of ASN.1.


I tried manually taking out the BIT STRING part.. but I guess I'm no good at extracting.. plus I would definitely need the iOS swift code for extracting the BIT STRING but hours of rummaging through stack overflow or internet hasn't helped me. (you're my last hope Mr. Eskimo :) )

As to how you can strip this header, the best option depends on your platform. Are you targeting macOS? Or an iOS-based platform?

Yes, I guess that's where I'm getting stuck. I am not able to properly extract the required public key info. I'm targeting an iOS-based platform (an iPhone app) and I'm using swift language

here's the original string without any tampering :)

Ta.

Decoding that I get this ASN.1:

Code Block
% dumpasn1 -a public-key.asn1
0 305: SEQUENCE {
4 234: SEQUENCE {
7 7: OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
16 222: SEQUENCE {
19 1: INTEGER 1
22 43: SEQUENCE {
24 7: OBJECT IDENTIFIER prime-field (1 2 840 10045 1 1)
33 32: INTEGER
: 7F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ED
: }
67 68: SEQUENCE {
69 32: OCTET STRING
: 2A AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA
: AA AA AA AA AA AA AA AA AA AA AA 98 49 14 A1 44
103 32: OCTET STRING
: 7B 42 5E D0 97 B4 25 ED 09 7B 42 5E D0 97 B4 25
: ED 09 7B 42 5E D0 97 B4 26 0B 5E 9C 77 10 C8 64
: }
137 65: OCTET STRING
: 04 2A AA AA AA AA AA AA AA AA AA AA AA AA AA AA
: AA AA AA AA AA AA AA AA AA AA AA AA AA AA AD 24
: 5A 20 AE 19 A1 B8 A0 86 B4 E0 1E DD 2C 77 48 D1
: 4C 92 3D 4D 7E 6D 7C 61 B2 29 E9 C5 A2 7E CE D3
: D9
204 32: INTEGER
: 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
: 14 DE F9 DE A2 F7 9C D6 58 12 63 1A 5C F5 D3 ED
238 1: INTEGER 8
: }
: }
241 66: BIT STRING
: 04 5A 26 73 A7 F9 8F 7D 04 79 D5 93 4E A4 47 9F
: C9 16 01 23 C1 6C 14 DD 58 FE 55 E1 C6 C9 01 F2
: 2C 6B 3C 0E A8 1E 55 FE 1A D8 67 DA CC 5F A3 F4
: 72 8C 5A D4 B7 0C 21 D0 58 A8 DA 46 1A E0 E6 A6
: 72
: }
0 warnings, 0 errors.


and this hex dump:

Code Block
% xxd public-key.asn1
00000000: 3082 0131 3081 ea06 072a 8648 ce3d 0201 0..10....*.H.=..
00000010: 3081 de02 0101 302b 0607 2a86 48ce 3d01 0.....0+..*.H.=.
00000020: 0102 207f ffff ffff ffff ffff ffff ffff .. .............
00000030: ffff ffff ffff ffff ffff ffff ffff ffff ................
00000040: ffff ed30 4404 202a aaaa aaaa aaaa aaaa ...0D. *........
00000050: aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa ................
00000060: aaaa 9849 14a1 4404 207b 425e d097 b425 ...I..D. {B^...%
00000070: ed09 7b42 5ed0 97b4 25ed 097b 425e d097 ..{B^...%..{B^..
00000080: b426 0b5e 9c77 10c8 6404 4104 2aaa aaaa .&.^.w..d.A.*...
00000090: aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa ................
000000a0: aaaa aaaa aaaa aaaa aaad 245a 20ae 19a1 ..........$Z ...
000000b0: b8a0 86b4 e01e dd2c 7748 d14c 923d 4d7e .......,wH.L.=M~
000000c0: 6d7c 61b2 29e9 c5a2 7ece d3d9 0220 1000 m|a.)...~.... ..
000000d0: 0000 0000 0000 0000 0000 0000 0000 14de ................
000000e0: f9de a2f7 9cd6 5812 631a 5cf5 d3ed 0201 ......X.c.\.....
000000f0: 0803 4200 045a 2673 a7f9 8f7d 0479 d593 ..B..Z&s...}.y..
00000100: 4ea4 479f c916 0123 c16c 14dd 58fe 55e1 N.G....#.l..X.U.
00000110: c6c9 01f2 2c6b 3c0e a81e 55fe 1ad8 67da ....,k<...U...g.
00000120: cc5f a3f4 728c 5ad4 b70c 21d0 58a8 da46 ._..r.Z...!.X..F
00000130: 1ae0 e6a6 72 ....r


As you can see the key bytes are the last 65 bytes of the data. So, you have a couple of options here:
  • You can this properly by parsing the ASN.1 SubjectPublicKeyInfo structure yourself. For this you’ll need to either write or acquire an ASN.1 parser )-:

  • You can bodgy this by just extracting the last 65 bytes of the data (someData.suffix(65)). The problem with this is that it only works for this specific key type and size.

Regardless, I encourage you to file an enhancement request for better APIs here. IMO our platforms should have high-level APIs for dealing with common crypto formats, including SubjectPublicKeyInfo.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Wow!!! adding suffix(65) worked :D :D

Thanks a lot Eskimo!!

I was able to pass that to SecKeyCreateWithData, and that worked!!

Code Block
 let keyDict:[NSObject:NSObject] = [
       kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
       kSecAttrKeyClass: kSecAttrKeyClassPublic,
       ]
     let publicKeyUsingSecKey = SecKeyCreateWithData(serverPublicKeyData.suffix(65) as NSData, keyDict as NSDictionary, &error)

Although it didn't work for creating the public key using

Code Block
     let serverPublicKeyUsingCurve25519= try! Curve25519.KeyAgreement.PublicKey(rawRepresentation: serverPublicKeyData.suffix(65))


But alas I DID get a SecKey!! now I can encrypt using this..!! Thank you Eskimo :D .. I'll update after I Encrypt :D
The encryption was sadly failing :(

Code Block
     status = SecKeyEncrypt(publicKeyUsingSecKey!, .PKCS1SHA256, message, message.count, &encrypted, &size)
    if status != noErr {
      print("encryption error")
    }


I'm getting status as -50
I also tried creating encrypted data using

Code Block
       cipherData = SecKeyCreateEncryptedData(publicKeyUsingSecKey, .eciesEncryptionStandardVariableIVX963SHA256AESGCM, message.jsonData as CFData, &error)as Data?


but that also returns nil with error:

Code Block
Error Domain=NSOSStatusErrorDomain Code=-26275 "ECpriv failed to compute shared secret (err -1)" UserInfo={numberOfErrorsDeep=0, NSDescription=ECpriv failed to compute shared secret 

what would that mean? the secKey just needs to be from the public key right

OK, I’ve misled you a little here — sorry about that! — but that’s only because the initial premise of this question is incorrect )-: Let me explain…

Consider this code:

Code Block
let privateKey = Curve25519.KeyAgreement.PrivateKey()
let publicKey = privateKey.publicKey
let privateKeyBytes = privateKey.rawRepresentation
let publicKeyBytes = publicKey.rawRepresentation
debugPrint(privateKeyBytes as NSData)
debugPrint(publicKeyBytes as NSData)


It prints something like this:

Code Block
<600b4d0a 63ae1d36 1bafb55d 8309c44b dd4e15ea 06ca8ad2 63a76f41 40bb704b>
<d4ed87f3 bb3ede46 9ec23485 f1585e41 bdb8cb46 7f1d964b c999955a 0e5ebf08>


Note that both the private and public key raw representations are 32-bytes long. The BIT STRING in your ASN.1 dump is 65 bytes long, and looks a lot like a sec prime key. Indeed, that’s supported by the key algorithm being listed as prime-field.

To investigate this further I created a Curve25519 using OpenSSL on Linux (the OpenSSL on macOS is not new enough to support this):

Code Block
% openssl genpkey -algorithm x25519 -out x25519-priv.pem
% openssl pkey -in x25519-priv.pem -pubout -out x25519-pub.pem
% cat x25519-pub.pem
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VuAyEABOOdMqWHy/NL1bpek31k68u2ioMTCaNsOPvhX62vBBM=
-----END PUBLIC KEY-----


Decoding the ASN.1 yields this:

Code Block
% dumpasn1 tmp.asn1
0 42: SEQUENCE {
2 5: SEQUENCE {
4 3: OBJECT IDENTIFIER curveX25519 (1 3 101 110)
: }
9 33: BIT STRING
: 04 E3 9D 32 A5 87 CB F3 4B D5 BA 5E 93 7D 64 EB
: CB B6 8A 83 13 09 A3 6C 38 FB E1 5F AD AF 04 13
: }
0 warnings, 0 errors.


Note that the BITSTRING is 32 bytes, which aligns with the rawRepresentation values we’re seeing from CryptoKit.

So, in summary, I’m not sure what type of key you’re working with here, but I’m pretty darned sure it’s not a Curve25519 one. You need to talk to your server folks about what sort of key they’re sending you.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Yes, I did understand during my investigation that Curve25519 wasn't working.


But using SecKey was working.

I was able to generate a SecKey like so :

Code Block
let keyDict:[NSObject:NSObject] = [      
  kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,      
  kSecAttrKeyClass: kSecAttrKeyClassPublic,      
 ]    
 let publicKey= SecKeyCreateWithData(serverPublicKeyData.suffix(65) as NSData, keyDict as NSDictionary, &error)

but then encryption using this was failing

Code Block
       cipherData = SecKeyCreateEncryptedData(publicKey as! SecKey, .eciesEncryptionStandardVariableIVX963SHA256AESGCM, message as CFData, &error)as Data?

with the error

Code Block
Error Domain=NSOSStatusErrorDomain Code=-26275 "ECpriv failed to compute shared secret (err -1)"


Then I realised it must be because I wasn't creating a shared secret to pass to SecKeyCreateEncryptedData.

I tried creating Shared Secret so :

Code Block swift
     guard let randomPrivateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { return }
         guard let sharedSecret = SecKeyCopyKeyExchangeResult(randomPrivateKey, .ecdhKeyExchangeStandardX963SHA256, publicKey, dict as   CFDictionary, &error) else {return}


But that as well returned the error

Code Block
Error Domain=NSOSStatusErrorDomain Code=-26275 "ECpriv failed to compute shared secret (err -1)"

Please help Eskimo!
When you call SecKeyCreateWithData with kSecAttrKeyTypeECSECPrimeRandom it expects the data to be a secp256r1 key. If you have such a key wrapped in a SubjectPublicKeyInfo structure it looks like this:

Code Block
% dumpasn1 -a -p secp256r1-public.asn1
SEQUENCE {
SEQUENCE {
OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
}
BIT STRING
04 53 68 3A 47 B4 FB 39 69 BF 10 67 34 49 9D C4
7B 27 7F D1 FB 0B F8 B7 E6 3E 8A B6 72 CA FA 4C
67 4F A4 58 29 04 B8 D0 C8 92 91 71 28 B0 8B 4F
85 E1 AF 75 E4 DB 06 A2 99 FD 15 24 31 FB 2F 25
BB
}


Note how the algorithm parameter is prime256v1 (an alias for secp256r1). In your case, however, the algorithm parameters look nothing like that. It’s not using one of the standard named curves but is instead defining its own curve. This is weird, and none of Apple’s built-in crypto APIs support it.

Which brings me back to my previous point: You need to ask your server folks why they’re sending you such a weird key, and also why they told you it’s a Curve25519 key when it clearly isn’t.

Share and Enjoy

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