![](/img/trans.png)
[英]How to perform encryption and decryption in java using secp256r1 Elliptical Curve key pair?
[英]iOS Elliptical curve key used for encryption decryption with Java Backend
我是一名 iOS 開發人員,並嘗試使用 Secure enclave 生成 ECC 對密鑰。 我可以使用這里的示例應用程序成功地做到這一點: https : //github.com/agens-no/EllipticCurveKeyPair 。 當我使用這個密鑰和 Python 實現來進行這里提到的加密和解密時: https : //gist.github.com/dschuetz/2ff54d738041fc888613f925a7708a06它可以工作。
問題是我需要一個 Java 代碼來做同樣的事情。 任何人都可以幫助我實現這一目標,或者向我指出與 Python 代碼執行相同工作的代碼。
在 iOS 方面,我正在做eciesEncryptionStandardX963SHA256AESGCM
加密和解密邏輯。
我知道我應該嘗試自己解決這個問題。 但我是一名 iOS 工程師,正在嘗試使用 Java 后端。 如果有人可以指導我,那將非常有幫助。
根據答案創建了一個示例 Java 代碼。 代碼鏈接: https : //gist.github.com/balrajOla/fa2f6030538b20a396c086377a6f7114
使用此處提供的示例 iOS 應用程序: https : //github.com/agens-no/EllipticCurveKeyPair 。 我生成了 ECC 密鑰。 然后將公鑰傳遞給 Java 代碼以創建加密消息。 此加密消息將傳遞回上述示例 iOS 應用程序,以使用eciesEncryptionStandardX963SHA256AESGCM算法進行解密。 但是我們在快照下面提到了一個錯誤。
我們遇到了同樣的問題。 我們希望從帶有 Java 后端的 iOS 安全飛地帶來一個 EC 密鑰交換。
經過三天的反復試驗,我們終於找到了一個可以工作的Java實現。
Java 代碼取自https://github.com/O2-Czech-Republic/BC-ECIES-for-iOS
和 iOS 代碼,使用eciesEncryptionCofactorVariableIVX963SHA256AESGCM算法:
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
}
}
}
在 Java 中,您有兩個有趣的類 - ECGenParameterSpec和KeyPairGenerator 。 ECGenParameterSpec指定生成橢圓曲線域參數的參數, KeyPairGenerator用於生成公私鑰對。
在 Nokilay Elenkov 所著的Android Security Internals一書中,有一個很好的代碼示例,說明它們組合生成密鑰對。
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDH");
ECGenParameterSpec ecParamSpec = new ECGenParameterSpec("secp256r1");
kpg.initialize(ecParamSpec);
KeyPair keyPair = kpg.generateKeyPair();
這是對前面代碼的解釋
有兩種方法可以初始化 KeyPairGenerator:通過指定所需的密鑰大小和指定特定於算法的參數。 在這兩種情況下,您都可以選擇傳遞一個 SecureRandom 實例以用於密鑰生成。 如果僅指定了密鑰大小,則密鑰生成將使用默認參數(如果有)。 要指定其他參數,您必須實例化和配置適合您使用的非對稱算法的 AlgorithmParameterSpec 實例,並將其傳遞給 initialize() 方法,如例 5-15 所示。 在此示例中,在第 2 行中初始化的 ECGenParameterSpec 是一個 AlgorithmParameterSpec,它允許您指定在生成橢圓曲線 (EC) 加密密鑰時使用的曲線名稱。 它被傳遞給initialize()方法在第3行后,在第4行以后的generateKeyPair()調用將使用指定的曲線(secp256r1)來生成密鑰對。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.