Search code examples
iosswiftkeychainelliptic-curvecurve-25519

ECC Curve25519 KeyChain


I'm trying to create Curve25519 keys using the KeyChain on iOS. I am aware of the existence of CryptoKit, unfortunately, that is not available for iOS 12. Is there a way to create a Curve25519 key pre CryptoKit, maybe a parameter I'm missing when generating it in the KeyChain? The code below will only generate the P-256 keys.

let attributes: [String: Any] = [
    String(kSecClass): kSecClassKey,
    String(kSecAttrKeyType): kSecAttrKeyTypeECSECPrimeRandom,
    String(kSecAttrKeySizeInBits): 256
]

var error: Unmanaged<CFError>?
let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error)
print(privateKey ?? error!.takeUnretainedValue())

Solution

  • Apple's old core crypto lib CommonCrypto doesn't support modern curves like curve25519 and quite frankly is a total mess, littered with insecure ciphers, they aren't even clear on the actual curve equations being used.

    Additionally, although CryptoKit supports curve25519 for key exchange, it's still limited, for example, you cannot use the "Secure Enclave" to generate curve25519 keys, only P-256, which is likely backdoored (just look at the curve co-efficients), despite all financial institutions seemingly loving it.

    Ultimately a curve25519 private key is just a large (2^256) number (though it is "clamped" before use), so if you just need to generate keys, you can do this with SecRandomCopyBytes.

    Though, if as I suspect you want to do some X25519 KEX or EdDSA signature over 25519, then just use libsodium. It's the goto library for NaCl, there is a really great interface in Swift written by the original libsodium author, called swift-sodium, I've used it and it's great. It also supports iOS 12+.

    Generating keys in libsodium for curve25519 is as simple as:

    import Sodium
    
    let sodium = Sodium()
    let curve25519KeyPair = sodium.box.keyPair()
    let privateKey = curve25519KeyPair!.secretKey
    let publicKey = curve25519KeyPair!.publicKey
    

    You can then manually store in KeyChain.

    Shout if you need further help, and good choice using 25519.