使用Diffie Hellman密钥交换和椭圆曲线加密快速加密 [英] Encryption in swift using Diffie Hellman key exchange and an elliptic curve encryption

查看:156
本文介绍了使用Diffie Hellman密钥交换和椭圆曲线加密快速加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've been trying to encrypt and decrypt a string in swift using a Diffie Hellman key exchange and an elliptic curve encryption.

以下是我遵循的代码.

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中做同样的事情.如何使用共享密钥(Shared1)对字符串进行EC加密?我需要执行步骤3.任何人都可以帮忙吗?

I included Java code as well. I have to do the same in Swift. How to do EC Encryption using the Shared key(Shared1) to encrypt the string? I need to do Step 3. Anyone please help on this?

推荐答案

首先,您正在尝试实现ECIES.如果要查找有关方案的信息,知道实际名称很重要.

First of all, you're trying to implement ECIES. Knowing the actual name is important if you want to look up information about the scheme.

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

So lets assume that key pair 1 is from the sender of the ciphertext and key pair 2 is then from the receiver of the ciphertext. In that case key pair 1 should be ephemeral (created on the spot, tied to one encrypted message) and key pair 2 is static (created beforehand and kept). Furthermore, public key 2 is trusted to be from the receiving party. This is all not clear from your simplified code, and in your code you could still switch around the sender and receiver.

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

So with the public key (2) of the receiver the sender can use their private key to create a shared secret, called shared1 in your code. You can now use shared1 to perform symmetric encryption of the data. Then you just have to send the ephemeral public key of the sender and the ciphertext to the receiver. The receiver uses the public key of the sender (1) and their static private key (2) to create shared2. This is identical to shared1 and can thus be used as a key to decrypt the data.

就是这样,除了要注意,由于发件人的私钥(1)已绑定到数据,因此一旦计算shared1就不再需要它,甚至可以在消息发送之前将其丢弃.加密.

So that's it, other than to note that since the private key (1) of the sender is tied to the data, it isn't needed anymore once shared1 is calculated, and may be discarded even before the message is encrypted.

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

If you read above then you can see that having all of this in one method is not a good idea:

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

现在用于加密和发送:

  1. 创建发送者的密钥对;
  2. 派生对称密钥;
  3. 扔掉私钥;
  4. 加密数据;
  5. 发送公钥和数据;

并为接收:

  1. 使用私钥导出对称密钥;
  2. 解密数据.

就是这样.您可能希望在代码中明确执行这些步骤.

And that's it. You probably want to have these steps made explicit in your code.

这篇关于使用Diffie Hellman密钥交换和椭圆曲线加密快速加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆