How to generate Curve 25519 key pair with ECDH swift iOS?

I want to generate a Curve25519 key pair with ECDH for the encryption and decryption. I'm using the CryptoKit to generates a keypair.

But, I failed to generate a keypair with the ECDH algorithm.

func generateKeys() -> (publicKey: String, privateKey: String){
           let privateKey = Curve25519.KeyAgreement.PrivateKey()
           let publicKey = privateKey.publicKey
           let publicKeyString = "-----BEGIN PUBLIC KEY-----\(publicKey.rawRepresentation.base64EncodedString())-----END PUBLIC KEY-----"
           print(publicKeyString)
           let privateKeyString = "-----BEGIN PRIVATE KEY-----\(privateKey.rawRepresentation.base64EncodedString(options: .lineLength64Characters))-----END PRIVATE KEY-----\r\n"
           print(privateKeyString)
        return (publicKeyString, [rivateKeyString)
    }

Output:

-----BEGIN PUBLIC KEY-----WSOOXYN/FaCOn4SAlvrW3q4IYueiS8Io+WqL64T2QQA=-----END PUBLIC KEY-----
-----BEGIN PRIVATE KEY-----AAlH4v1vcnmjEKVJrhbarMqCrcNWYZgFwnhReduEokk=-----END PRIVATE KEY-----

Here is one of the Java code using bouncycastle

{
  "privateKey": "-----BEGIN PRIVATE KEY-----MIICRwIBADCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCASCAVMwggFPAgEBBCAOeSuzq+O1tPlhPZj4KZdfAq5Z0+yca15ukbUuwsyJQKCB4TCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCKFEA0IABG56w6jtAyb2T6oguKNN6HvLPQdT0Mms8gCepW51pobrDT/WfXJKfFr5fRuNalS+YkDQggoc7xtpYFin0ELidYw=-----END PRIVATE KEY-----",
  "errorInfo": null,
  "KeyMaterials": {
    "cryptoAlg": "ECDH",
    "curve": "curve25519",
    "params": "",
    "DHPublicKey": {
      "expiry": "2021-12-15T11:29:20.848Z",
      "Parameter": "",
      "KeyValue": "-----BEGIN PUBLIC KEY-----MIIBMTCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCANCAARuesOo7QMm9k+qILijTeh7yz0HU9DJrPIAnqVudaaG6w0/1n1ySnxa+X0bjWpUvmJA0IIKHO8baWBXp9BC4mMW-----END PUBLIC KEY-----"
    }
  }
}

Can anyone guide me for the same keys like java?

Replies

What is your ultimate goal here? Is it to create a Curve25519 key pair in CryptoKit and use them in your app, or to create a Curve25519 key pair and export the keys to somewhere else? Either way, what you have going should get you started:

import CryptoKit
let signingKey = Curve25519.Signing.PrivateKey()
/*:
 Get a data representation of the public key.
 */
let signingPublicKey = signingKey.publicKey
let signingPublicKeyData = signingPublicKey.rawRepresentation
/*:
 Initialize a public key from its raw representation.
 */
let initializedSigningPublicKey = try! Curve25519.Signing.PublicKey(rawRepresentation: signingPublicKeyData)
/*:
 Use the private key to generate a signature.
 */
let dataToSign = "Some sample Data to sign.".data(using: .utf8)!
let signature = try! signingKey.signature(for: dataToSign)
/*:
 Verify the signature with the public key.
 */
if initializedSigningPublicKey.isValidSignature(signature, for: dataToSign) {
    print("The signature is valid.")
}

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
  • Need to convert pem formart like length also same for java Bouncy castle

  • So you are wanting to take a Key/Pair and create it in CryptoKit and then export it so it can be used in Bouncy Castle, correct?

  • Yes,

Add a Comment

Yes

Okay. This is a difficult question to give you a straight forward answer on so what I will do is provide you some general information based on your situation:

  1. Any key, such as the private key in this context, created in the Secure Enclave of a device cannot be exported. The private key can still be used for cryptographic operations, but if it happens to be created in the secure enclave then it cannot be exported. If the key can be exported, SecKeyCopyExternalRepresentation should get you started.

  2. When a key is exported using SecKeyCopyExternalRepresentation, pay attention the format described here:

 For an elliptic curve private key, the output is formatted as the public key concatenated with the big endian encoding of the secret scalar, or 04 || X || Y || K. All of these representations use constant size integers, including leading zeros as needed.

This should give you information then on how best proceed with then importing the key material into your 3rd party APIs.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
  • Thank you, I tried this procedure. Backend api expect same keys like { "privateKey": "-----BEGIN PRIVATE KEY-----MIICRwIBADCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCASCAVMwggFPAgEBBCAOeSuzq+O1tPlhPZj4KZdfAq5Z0+yca15ukbUuwsyJQKCB4TCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCKFEA0IABG56w6jtAyb2T6oguKNN6HvLPQdT0Mms8gCepW51pobrDT/WfXJKfFr5fRuNalS+YkDQggoc7xtpYFin0ELidYw=-----END PRIVATE KEY-----", "errorInfo": null, "KeyMaterials": { "cryptoAlg": "ECDH", "curve": "curve25519", "params": "", "DHPublicKey": { "expiry": "2021-12-15T11:29:20.848Z", "Parameter": "", "KeyValue": "-----BEGIN PUBLIC KEY-----MIIBMTCB6gYHKoZIzj0CATCB3gIBATArBgcqhkjOPQEBAiB/////////////////////////////////////////7TBEBCAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqYSRShRAQge0Je0Je0Je0Je0Je0Je0Je0Je0Je0Je0JgtenHcQyGQEQQQqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq0kWiCuGaG4oIa04B7dLHdI0UySPU1+bXxhsinpxaJ+ztPZAiAQAAAAAAAAAAAAAAAAAAAAFN753qL3nNZYEmMaXPXT7QIBCANCAARuesOo7QMm9k+qILijTeh7yz0HU9DJrPIAnqVudaaG6w0/1n1ySnxa+X0bjWpUvmJA0IIKHO8baWBXp9BC4mMW-----END PUBLIC KEY-----" } } }

    Please suggest me

  • This is very hard to read; please repost using an answer rather than in the comments.

  • I have generated public and private keys using curve25519.keyAgreement , but our keys length is different for android generated key length and format also. so have struck for after generating public keys and private keys converted into ASN.1 and PEM format, Thank you

Add a Comment

For those reading along at home, satyaaakana started a new thread for this.

Share and Enjoy

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