Encryption in swift using Diffie Hellman key exchange and an elliptic curve encryption

倖福魔咒の 提交于 2019-12-11 06:24:35

问题


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

Following is the code that I followed.

SWIFT Code :

 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 Code :

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;
}
}

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?


回答1:


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.

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.

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.

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. create the static key pair of the receiver;
  2. send the public key of the receiver to the sender and make sure that the sender can trust the public key to be from the receiver (e.g. using certificate infrastructure);

Now for the encryption and sending:

  1. create the key pair of the sender;
  2. derive the symmetric key;
  3. throw away the private key;
  4. encrypt the data;
  5. send the public key and the data;

and for the receiving:

  1. use the private key to derive the symmetric key;
  2. decrypt the data.

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



来源:https://stackoverflow.com/questions/58076132/encryption-in-swift-using-diffie-hellman-key-exchange-and-an-elliptic-curve-encr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!