Быстрое шифрование с использованием обмена ключами Диффи-Хеллмана и шифрования по эллиптической кривой - PullRequest
1 голос
/ 24 сентября 2019

Я пытался быстро зашифровать и расшифровать строку, используя обмен ключами Диффи-Хеллмана и шифрование по эллиптической кривой.

Ниже приведен код, которому я следовал,

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]
        // Stucked from this line 
        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.Как сделать шифрование EC с использованием общего ключа (Shared1) для шифрования строки?Мне нужно сделать Шаг 3. Кто-нибудь, пожалуйста, помогите в этом?

1 Ответ

1 голос
/ 25 сентября 2019

Прежде всего, вы пытаетесь внедрить ECIES.Знание фактического имени важно, если вы хотите найти информацию о схеме.

Итак, давайте предположим, что пара ключей 1 получена от отправителя зашифрованного текста, а пара ключей 2 - от получателя зашифрованного текста.В этом случае пара ключей 1 должна быть эфемерной (созданной на месте, привязанной к одному зашифрованному сообщению), а пара ключей 2 является статической (созданной заранее и сохраненной).Кроме того, общему ключу 2 доверяют принимающая сторона.Это все неясно из вашего упрощенного кода, и в вашем коде вы все еще можете переключаться между отправителем и получателем.

Таким образом, с открытым ключом (2) получателя отправитель может использовать свой закрытый ключ для созданияобщий секрет, называемый shared1 в вашем коде.Теперь вы можете использовать shared1 для симметричного шифрования данных.Тогда вам просто нужно отправить эфемерный открытый ключ отправителя и зашифрованный текст получателю.Получатель использует открытый ключ отправителя (1) и его статический закрытый ключ (2) для создания shared2.Это идентично shared1 и, таким образом, может использоваться в качестве ключа для расшифровки данных.

Вот и все, за исключением того, что следует отметить, что, поскольку закрытый ключ (1) отправителя привязан к данным, он больше не нужен после вычисления shared1 и может быть отброшен даже до того, как сообщение зашифровано.


Если вы прочитаете выше, вы увидите, что все это выполняется одним способомне очень хорошая идея:

  1. создать пару статических ключей получателя;
  2. отправить открытый ключ получателя отправителю и убедиться, что отправитель может доверять общемуключ от получателя (например, с использованием инфраструктуры сертификатов);

Теперь для шифрования и отправки:

создать пару ключей отправителя; получить симметричный ключ; выбросить закрытый ключ; зашифровать данные; отправить открытый ключ и данные;

и для получения:

используйте закрытый ключ для получения симметричного ключа; расшифруйте данные.

И все.Возможно, вы захотите, чтобы эти шаги сделали явным в вашем коде.

...