I need on iOS with Swift to:
- Generate a Diffie–Hellman key pair with a pre-agreed modulus P and a base G
- Compute a shared secret with a local private key, a remote public key and pre-agreed modulus P
And this without Elliptic-curve Diffie–Hellman (ECDH).
I wrote this code using BigInt repository.
/// Diffie–Hellman key pair
struct DHKeyPair {
var privateKey: Data
var publicKey: Data
init(privateKey: Data, publicKey: Data) {
self.privateKey = privateKey
self.publicKey = publicKey
}
}
/// Generate a Diffie–Hellman key pair
///
/// - Parameter modulus: Diffie-Hellman modulus P
/// - Parameter base: Diffie-Hellman base G
/// - Returns: DH key pair, or nil on error
static func generateDhKeyPair(modulus: Data, base: Data) -> DHKeyPair? {
// Modulus
let modulusBigUInt = BigUInt(modulus)
// Base
let baseBigUInt = BigUInt(base)
// Generate random private key
guard let privateKey = Crypto.randomBytes(length: 512) else {
return nil
}
let privateKeyBigUInt = BigUInt(privateKey)
// Compute public key
let publicKeyBigUInt = baseBigUInt.power(privateKeyBigUInt, modulus: modulusBigUInt)
var publicKey = publicKeyBigUInt.serialize()
// Set Diffie-Hellman key pair
let dhKeypair = DHKeyPair(privateKey: privateKey, publicKey: publicKey)
return dhKeypair
}
/// Compute a shared secret based on local pair key (public/private) and remote public key
///
/// - Parameter privateKey: Private key
/// - Parameter remotePublicKey: Remote public key
/// - Parameter modulus: Diffie-Hellman modulus P
/// - Returns: the computed shared secret
static func computeSharedSecret(privateKey: Data, remotePublicKey: Data, modulus: Data) -> Data {
// Private key
let privateKeyBigUInt = BigUInt(privateKey)
// Remote public key
let remotePublicKeyBigUInt = BigUInt(remotePublicKey)
// Modulus
let modulusBigUInt = BigUInt(modulus)
// Compute shared secret
let sharedSecretBigUInt = remotePublicKeyBigUInt.power(privateKeyBigUInt, modulus: modulusBigUInt)
var sharedSecret = sharedSecretBigUInt.serialize()
return sharedSecret
}
It's well working but it takes too long, about 50 seconds to generate the key pair, and the same to compute the shared secret. This is because of the BigUInt modular exponentiation function (see doc).
I couldn't find anything for these operations in the Keys documentation of the API for Swift.
So how can I do these Diffie-Hellman operations faster? Can it be done also with Swift API?
PS: we've the same function on the JDK which takes just a few seconds.
EDIT 1:
These 2 operations take about 4 seconds with a build in release, which is acceptable. But the execution time is still too long in debug (on a real device or a simulator), and also the unit tests are commented because the execution time is too long when running the unit tests.