ios - 使用 Diffie Hellman key 交换和椭圆曲线加密进行快速加密

标签 ios swift encryption ecdsa ecdh

我一直在尝试使用 Diffie Hellman key 交换和椭圆曲线加密来快速加密和解密字符串。

以下是我遵循的代码。

SWIFT 代码:

 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, *) {
 **// Step 1:  Generating the Public & Private Key**
        guard let privateKey1 = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {return false}

        let publicKey1 = SecKeyCopyPublicKey(privateKey1)
        guard let privateKey2 = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {return false}

        let publicKey2 = SecKeyCopyPublicKey(privateKey2)

        let dict: [String: Any] = [:]
 **// Step 2:  Generating Shared Key**   
        guard let shared1 = SecKeyCopyKeyExchangeResult(privateKey1, SecKeyAlgorithm.ecdhKeyExchangeStandardX963SHA256, publicKey2!, dict as CFDictionary, &error) else {return false}

**// Step 3:  Encrypt string using Sharedkey**
        let options: [String: Any] = [kSecAttrKeyType as String: kSecAttrKeyTypeEC,
                                      kSecAttrKeyClass as String: kSecAttrKeyClassPrivate,
                                      kSecAttrKeySizeInBits as String : 256]
        // Stuck from this line on
        guard let key = SecKeyCreateWithData(shared1 ,
                                             options as CFDictionary,
                                             &error) else {return false}
        print(key)


        let str = "Hello"
        let byteStr: [UInt8] = Array(str.utf8)
        let cfData = CFDataCreate(nil, byteStr, byteStr.count)


        guard let encrypted = SecKeyCreateEncryptedData(publicKey1!,
                                                        SecKeyAlgorithm.ecdsaSignatureDigestX962SHA256,
                                                        cfData!,
                                                        &error) else {return false}
        print(encrypted)

    } else {
        print("unsupported")
    }

JAVA代码:

public static Map<String, Object> ecEncrypt(String deviceData, String serverPubKey, String dsTranID)
throws DataEncryptionException {
provider = new BouncyCastleProvider();
HashMap<String, Object> result = null;
JWEObject jweObject = null;
JWK jwk = null;
SecretKey Z = null;
JWEHeader header = null;
ECPublicKey ecpubkey = null;
byte[] byte_pubkey = null;

try {

result = new HashMap<String, Object>();
/*
 * Generate Ephemeral keypair for SDk which constitute Public and
 * Private key of SDK
 */
STEP 1:
sdkKeyPair = Crypto.generateEphemeralKeyPair();

/*
 * Compute Secrete Key Z from SDKs Private Key(pSDK),DS Public
 * key(serverPubKey) and DS ID
 */
//converting string to Bytes
STEP 2:
byte_pubkey = Base64.decode(serverPubKey, android.util.Base64.DEFAULT);

//converting it back to EC public key
STEP 3:
KeyFactory factory = KeyFactory.getInstance("ECDSA", provider);
ecpubkey = (ECPublicKey) factory.generatePublic(new X509EncodedKeySpec(byte_pubkey));
System.out.println("FINAL OUTPUT" + ecpubkey);

STEP 4:
Z = Crypto.generateECDHSecret(ecpubkey,
(ECPrivateKey) sdkKeyPair.getPrivate(), dsTranID,
"A128CBC_HS256");

System.out.println("****Secrete key Z for SDK Computed succesfully *****");
/*
 * Build JWK to construct header
 */
STEP 5:
jwk = new ECKey.Builder(Curve.P_256,
(ECPublicKey) sdkKeyPair.getPublic()).build();

STEP 6:
header = new JWEHeader.Builder(JWEAlgorithm.ECDH_ES,
EncryptionMethod.A128CBC_HS256).ephemeralPublicKey(
ECKey.parse(jwk.toJSONString())).build();

System.out.println("****Header for SDK Computed  succesfully*****");

/*
 * Add Header and payload before encrypting payload using secret key
 * Z
 */

STEP 7:
jweObject = new JWEObject(header, new Payload(deviceData));
jweObject.encrypt(new DirectEncrypter(Z));
/*
 * serialize JWEobject which contains
 * [header-base64url].[encryptedKey
 * -base64url].[iv-base64url].[cipherText
 * -base64url].[authTag-base64url]
 */
System.out
.println("****Payload of SDK encrypted succesfully *****");

return result;
} catch (Exception e) {
e.printStackTrace();
throw new DataEncryptionException();
} finally {
sdkKeyPair = null;
jweObject = null;
jwk = null;
Z = null;
header = null;
}
}

我还包含了 Java 代码。我必须在 Swift 中做同样的事情。如何使用共享 key (Shared1)进行EC加密来加密字符串?我需要执行第 3 步。有人可以帮忙吗?

最佳答案

首先,您正在尝试实现 ECIES。如果您想查找有关该方案的信息,了解实际名称很重要。

因此,我们假设 key 对 1 来自密文的发送方, key 对 2 来自密文的接收方。在这种情况下, key 对 1 应该是临时的(当场创建,与一条加密消息绑定(bind)),而 key 对 2 是静态的(预先创建并保留)。此外,公钥 2 被信任来自接收方。从您的简化代码中,这一切都不清楚,并且在您的代码中您仍然可以切换发送者和接收者。

因此,利用接收者的公钥 (2),发送者可以使用其私钥创建共享 key ,在代码中称为 shared1。您现在可以使用 shared1 对数据执行对称加密。然后您只需将发送方的临时公钥和密文发送给接收方即可。接收方使用发送方的公钥 (1) 及其静态私钥 (2) 创建 shared2。这与 shared1 相同,因此可以用作解密数据的 key 。

就是这样,除了要注意的是,由于发送者的私钥 (1) 与数据绑定(bind)在一起,因此一旦计算出 shared1 就不再需要它,并且可能会被丢弃甚至在消息加密之前。


如果您阅读了上面的内容,您就会发现将所有这些都放在一种方法中并不是一个好主意:

  1. 创建接收者的静态 key 对;
  2. 将接收者的公钥发送给发送者,并确保发送者可以信任来自接收者的公钥(例如使用证书基础设施);

现在进行加密和发送:

  • 创建发送者的 key 对;
  • 导出对称 key ;
  • 扔掉私钥;
  • 加密数据;
  • 发送公钥和数据;
  • 对于接收:

  • 使用私钥导出对称 key ;
  • 解密数据。
  • 就是这样。您可能希望在代码中显式这些步骤。

    关于ios - 使用 Diffie Hellman key 交换和椭圆曲线加密进行快速加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58076132/

    相关文章:

    ios - Swift:在表格 View 中粘贴按钮

    java - 对 Java 中的 Vigenère 密码实现感到困惑

    java - java中使用RSA对加密消息进行加密

    iphone - 如何捕获自定义uitableViewCell中的开关更改事件?

    ios - 文件提供程序扩展,importDocumentAtURL::无法读取给定 URL 处的文件 (iOS 11.4.1)

    ios - Swift - 选择时的 UITableView 单元格动画

    iOS 解析文本文件 Swift

    swift : Unexpectedly found nil

    java - php加密脚本需要类似的java代码

    ios - 在IOS中以行和列显示数据