Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elliptic Curve Diffie Hellman in ios/swift

Does iOS expose API for key generation, and secret key derivation using ECDH?

From what I see, apple are using it (and specifically x25519) internally but I don't see it exposed as public API by common crypto or otherwise.

Thanks,

Z

like image 938
Zohar Etzioni Avatar asked Sep 19 '17 13:09

Zohar Etzioni


2 Answers

Here is the latest code with swift 5 and changes in parameters.

var error: Unmanaged<CFError>?
  
       let keyPairAttr:[String : Any] = [kSecAttrKeySizeInBits as String: 256,
                                         SecKeyKeyExchangeParameter.requestedSize.rawValue as String: 32,
                                         kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
                                         kSecPrivateKeyAttrs as String: [kSecAttrIsPermanent as String: false],
                                         kSecPublicKeyAttrs as String:[kSecAttrIsPermanent as String: false]]
       let algorithm:SecKeyAlgorithm = SecKeyAlgorithm.ecdhKeyExchangeStandardX963SHA256//ecdhKeyExchangeStandardX963SHA256
       
       do {
           guard let privateKey = SecKeyCreateRandomKey(keyPairAttr as CFDictionary, &error) else {
               throw error!.takeRetainedValue() as Error
           }
           let publicKey = SecKeyCopyPublicKey(privateKey)
           print("public ky1: \(String(describing: publicKey)),\n private key: \(privateKey)")
           
        
           
           guard let privateKey2 = SecKeyCreateRandomKey(keyPairAttr as CFDictionary, &error) else {
               throw error!.takeRetainedValue() as Error
           }
           let publicKey2 = SecKeyCopyPublicKey(privateKey2)
           print("public ky2: \(String(describing: publicKey2)),\n private key2: \(privateKey2)")

           
           
           let shared:CFData? = SecKeyCopyKeyExchangeResult(privateKey, algorithm, publicKey2!, keyPairAttr as CFDictionary, &error)
           let sharedData:Data = shared! as Data
           print("shared Secret key: \(sharedData.hexEncodedString())")

           let shared2:CFData? = SecKeyCopyKeyExchangeResult(privateKey2, algorithm, publicKey!, keyPairAttr as CFDictionary, &error)
           let sharedData2:Data = shared2! as Data
           print("shared Secret key 2: \(sharedData2.hexEncodedString())")
           
           // shared secret key and shared secret key 2 should be same
       
       } catch let error as NSError {
           print("error: \(error)")
       } catch  {
           print("unknown error")
       }
like image 77
virtplay Avatar answered Oct 07 '22 01:10

virtplay


Done in playground with Xcode 8.3.3, generates a private/public key using EC for Alice, Bob, then calculating the shared secret for Alice using Alice's private and Bob's public, and share secret for Bob using Bob's private and Alice's public and finally asserting that they're equal.

import Security
import UIKit

let attributes: [String: Any] =
    [kSecAttrKeySizeInBits as String:      256,
     kSecAttrKeyType as String: kSecAttrKeyTypeEC,
     kSecPrivateKeyAttrs as String:
        [kSecAttrIsPermanent as String:    false]
]

var error: Unmanaged<CFError>?
if #available(iOS 10.0, *) {
    // generate a key for alice
    guard let privateKey1 = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
        throw error!.takeRetainedValue() as Error
    }
    let publicKey1 = SecKeyCopyPublicKey(privateKey1)

    // generate a key for bob
    guard let privateKey2 = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
        throw error!.takeRetainedValue() as Error
    }
    let publicKey2 = SecKeyCopyPublicKey(privateKey2)

    let dict: [String: Any] = [:]

    // alice is calculating the shared secret
    guard let shared1 = SecKeyCopyKeyExchangeResult(privateKey1, SecKeyAlgorithm.ecdhKeyExchangeStandardX963SHA256, publicKey2!, dict as     CFDictionary, &error) else {
        throw error!.takeRetainedValue() as Error
    }

    // bob is calculating the shared secret
    guard let shared2 = SecKeyCopyKeyExchangeResult(privateKey2, SecKeyAlgorithm.ecdhKeyExchangeStandardX963SHA256, publicKey1!, dict as CFDictionary, &error) else {
        throw error!.takeRetainedValue() as Error
    }

    print(shared1==shared2)


} else {
    // Fallback on earlier versions
    print("unsupported")
}

Thanks @Mats for sending me in the right direction..3

like image 33
Zohar Etzioni Avatar answered Oct 07 '22 03:10

Zohar Etzioni