<p>我们也有同样的问题。我们希望在iOS安全enclave上使用Java后端实现EC密钥交换</p>
<p>经过三天的审讯,;错误,我们终于找到了一个正在工作的Java实现</p>
<p>Java代码取自<a href="https://github.com/O2-Czech-Republic/BC-ECIES-for-iOS" rel="nofollow noreferrer">https://github.com/O2-Czech-Republic/BC-ECIES-for-iOS</a></p>
<p>和iOS代码,使用ECiseEncryptionCofactorVariableIVX963SHA256AESGCM算法:</p>
<pre><code> static func getExportableKeyFromECKey() -> String? {
// If exists already a created EC Key, then export the public part
if let privateKey = self.loadECPrivateKey() {
if let publicKey = self.getECPublicKey(privateKey) {
if self.algorithmAcceptedForEC(publicKey) {
var error: Unmanaged<CFError>?
// Get Public key External represenatation
guard let cfdata = SecKeyCopyExternalRepresentation(publicKey, &error) else {
return nil
}
let pubKeyData: Data = cfdata as Data
return pubKeyData.base64EncodedString()
}
}
}
// If no EC Key created, then first create one
else {
var error: Unmanaged<CFError>?
let tag = Config.skName.data(using: .utf8) ?? Data()
let attributes: [String: Any] = [kSecClass as String: kSecClassKey,
kSecAttrKeyType as String: Config.skType,
kSecAttrKeySizeInBits as String: Config.ecKeySize,
kSecPrivateKeyAttrs as String: [ kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: tag]]
do {
// Create Private Key
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
throw error!.takeRetainedValue() as Error
}
// Get Public Key
guard let publicKey = SecKeyCopyPublicKey(privateKey) else {
throw error!.takeRetainedValue() as Error
}
// Get Public key External represenatation
guard let cfdata = SecKeyCopyExternalRepresentation(publicKey, &error) else {
throw error!.takeRetainedValue() as Error
}
let pubKeyData: Data = cfdata as Data
return pubKeyData.base64EncodedString()
} catch {
print(error)
}
}
return nil
}
static func loadECPrivateKey() -> SecKey? {
let tag = Config.skName.data(using: .utf8)!
let query: [String: Any] = [kSecClass as String: kSecClassKey,
kSecAttrApplicationTag as String: tag,
kSecAttrKeyType as String: Config.skType,
kSecReturnRef as String: true]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess else {
return nil
}
print("LOAD PRIVATE KEY: \n \(item as! SecKey) \n")
return (item as! SecKey)
}
static func getECPublicKey(_ privateKey: SecKey) -> SecKey? {
guard let publicKey = SecKeyCopyPublicKey(privateKey) else {
// Can't get public key
return nil
}
return publicKey
}
static func algorithmAcceptedForEC(_ publicKey: SecKey) -> Bool {
guard SecKeyIsAlgorithmSupported(publicKey, .encrypt, Config.ecAlgorithm) else {
// Algorith not supported
print("\nEncrytion Algorithm not supported!!!\n")
return false
}
return true
}
/// if let encryptedData = Data(base64Encoded: "BOqw779hxsGLMEV7X81Mphcx+SMtxSQs388s5CydkvJ4V2XuuWoyp48GCmgDMBnYlEIRqAdHxIc/Ts3ATxa9ENCDGdIZf5CjpWsOIVXYxLvupdap4w==", options:.ignoreUnknownCharacters)
static func decryptStr(_ encData: Data) {
/// 1. Step: Get the Private Key and decrypt the symmetric key
let privateKey = loadECPrivateKey()
guard SecKeyIsAlgorithmSupported(privateKey!, .decrypt, Config.ecAlgorithm) else {
print("Can't decrypt\nAlgorithm not supported")
return
}
DispatchQueue.global().async {
var error: Unmanaged<CFError>?
let clearTextData = SecKeyCreateDecryptedData(privateKey!,
Config.ecAlgorithm,
encData as CFData,
&error) as Data?
DispatchQueue.main.async {
guard clearTextData != nil else {
print("Can't decrypt")
return
}
let clearText = String(decoding: clearTextData!, as: UTF8.self)
print("Decrypted Info: \(clearText)")
// clearText is our decrypted string
}
}
}
</code></pre>