JavaScript — Php и cryptoJS IV

Я шифрую и дешифрую данные, используя PHP следующим образом:

<?php
function encrypt($data, $secret){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return base64_encode($iv.openssl_encrypt($data, 'aes-256-cbc', $secret, 0, $iv));
}

function decrypt($encryptedData, $secret){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$data = base64_decode($encryptedData);
$iv = substr($data, 0, $iv_size);
return openssl_decrypt(substr($data, $iv_size), 'aes-256-cbc', $secret, 0, $iv);
}
?>

Теперь я хочу иметь возможность шифровать свои данные локально (идентично методу PHP), используя Crypto-JS. Я сделал то же, что и выше, чтобы получить ключ и iv:

var key = '<?php echo $secret;?>';
var iv = '<?php echo base64_encode(mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND));?>';

Теперь при использовании Crypto-JS Я пытался зашифровать с помощью:

var encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(text), CryptoJS.enc.Hex.parse(key), { iv: CryptoJS.enc.Hex.parse(iv) });

Но мне также нужно хранить IV, как я делаю с PHP, поэтому я добавил:

var withIV = iv+encrypted;

но это не закодировано. Итак, я добавил:

CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(withIV));

Но почему-то это не та же кодировка, что и в PHP выше?

1

Решение

Вот как я шифрую данные с CryptoJS:

function encrypt(str, key, iv) {
var key = CryptoJS.enc.Hex.parse(key);
var iv = CryptoJS.enc.Hex.parse(iv);
return CryptoJS.AES.encrypt(str, key, { iv: iv }).toString();
};

В PHP я расшифровываю зашифрованную строку, созданную этой функцией, используя следующую строку кода:

openssl_decrypt($encrypted_data_string, "AES-128-CBC", hex2bin($key_hex_string), 0, hex2bin($iv_hex_string));

Я полагаю, что вы можете закодировать / декодировать зашифрованные данные в базе 64 вместо шестнадцатеричного, если хотите. В любом случае, надеюсь, это поможет!

0

Другие решения

Кажется, у вас есть проблемы с конкатенацией IV и зашифрованного текста в CryptoJS. Это довольно просто, потому что собственный двоичный формат данных CryptoJS (WordArray) поддерживает concat функция:

var ivWords = CryptoJS.enc.Hex.parse(iv); // WordArray instance
var plaintext = CryptoJS.enc.Utf8.parse(text); // WordArray instance
var keyWords = CryptoJS.enc.Hex.parse(key); // WordArray instance
var encrypted = CryptoJS.AES.encrypt(plaintext, keyWords, { iv: ivWords }); // CipherParams instance

var ct = ivWords.clone().concat(encrypted.ciphertext); // WordArray instance
var ct = ct.toString(CryptoJS.enc.Base64); // string instance
console.log(ct);
// example data
var iv = "0102030405060708090a0b0c0d0e0f";
var text = "text";
var key = "1112131415161718191a1b1c1d1e1f";

// actual code
var ivWords = CryptoJS.enc.Hex.parse(iv); // WordArray instance
var plaintext = CryptoJS.enc.Utf8.parse(text); // WordArray instance
var keyWords = CryptoJS.enc.Hex.parse(key); // WordArray instance
var encrypted = CryptoJS.AES.encrypt(plaintext, keyWords, { iv: ivWords }); // CipherParams instance

var ct = ivWords.clone().concat(encrypted.ciphertext); // WordArray instance
var ct = ct.toString(CryptoJS.enc.Base64); // string instance
output.innerHTML = ct;
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/components/enc-base64-min.js"></script>
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/aes.js"></script>
<div id="output"></div>

Это даст тот же результат, что и

base64_encode($iv.openssl_encrypt($data, 'aes-256-cbc', $secret, 0, $iv));

пока iv на самом деле строка в шестнадцатеричном коде с тем же байтами, что и декодированная версия в $iv, То же самое должно быть верно для text (кроме кодировки), key а также $data, $secretсоответственно.

0