Я пытаюсь зашифровать и расшифровать данные на стороне сервера и клиента, используя тот же тип операции, что и AES-256.
На сервере я использую PHP, а на клиенте я использую CryptoJS, пока я мог только шифровать и дешифровать клиента на сервере, см. Код:
JS
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/pbkdf2.js"></script>
<script>
var salt = CryptoJS.lib.WordArray.random(128/8);
var key256Bits500Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 256/32, iterations: 500 });
var iv = CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');
var encrypted = CryptoJS.AES.encrypt("Message", key256Bits500Iterations, { iv: iv });
var data_base64 = encrypted.ciphertext.toString(CryptoJS.enc.Base64);
var iv_base64 = encrypted.iv.toString(CryptoJS.enc.Base64);
var key_base64 = encrypted.key.toString(CryptoJS.enc.Base64);
</script>
PHP
<?php
$encrypted = base64_decode("data_base64"); // data_base64 from JS
$iv = base64_decode("iv_base64"); // iv_base64 from JS
$key = base64_decode("key_base64"); // key_base64 from JS
$plaintext = rtrim( mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv ), "\t\0 " );
Как я могу зашифровать и расшифровать данные с обеих сторон (клиента и сервера), чтобы общаться на одном языке с помощью PHP и CryptoJS?
Ваш код выглядит хорошо, за исключением несоответствия отступов. CryptoJS по умолчанию использует заполнение PKCS # 5 / PKCS # 7, тогда как MCrypt поддерживает только ZeroPadding.
Если вы отправляете только текстовые сообщения, вы можете смело использовать
CryptoJS.AES.encrypt("Message", key, { iv: iv, padding: CryptoJS.pad.ZeroPadding });
Если нет, то вы должны использовать правильный pkcs7unpad в PHP:
$plaintext = pkcs7unpad( mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv ), 16 );
Другие проблемы с вашим кодом, которые вы используете напрямую CryptoJS.AES.encrypt(...).toString()
, Это создаст строку в формате OpenSSL, которая не является просто зашифрованным текстом. Вам нужно использовать
CryptoJS.AES.encrypt(...).ciphertext.toString(CryptoJS.enc.Base64);
также быть уверенным в кодировке.
Прямо сейчас это только запутывание, так как вы отправляете ключ вместе с зашифрованным текстом. Я подозреваю, что вы хотите получить ключ в PHP тоже. Если да, то вам нужно будет только отправить случайную соль вместе с зашифрованным текстом при условии, что сервер знает пароль.
PHP обеспечивает Внедрение PBKDF2 начиная с версии 5.5.
Полная часть JavaScript без участия PBKDF2:
var message = 'My string - Could also be an JS array/object';
var iv = 'a1a2a3a4a5a6a7a8b1b2b3b4b5b6b7b8';
var key = 'c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8'; // 256-bit hex encoded
var keyBytes = CryptoJS.enc.Hex.parse(key);
var ivBytes = CryptoJS.enc.Hex.parse(iv);
var encrypt = CryptoJS.AES.encrypt(message, keyBytes, {
iv: ivBytes,
padding: CryptoJS.pad.ZeroPadding
}).ciphertext.toString(CryptoJS.enc.Base64);
производит:
j86KHBVRsDGKUnOiYdkEotsFL / LY / 1tzz / h3Ay + vlEX11fC055m7vaF6q7w13eUj
Полная часть PHP без участия PBKDF2:
<?php
$iv = 'a1a2a3a4a5a6a7a8b1b2b3b4b5b6b7b8';
$key = 'c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8';
$ct = 'j86KHBVRsDGKUnOiYdkEotsFL/lY/1tzz/h3Ay+vlEX11fC055m7vaF6q7w13eUj';
$ivBytes = hex2bin($iv);
$keyBytes = hex2bin($key);
$ctBytes = base64_decode($ct);
$decrypt = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $keyBytes, $ctBytes, MCRYPT_MODE_CBC, $ivBytes));
echo $decrypt;
производит:
Моя строка — также может быть массивом / объектом JS
То же самое возможно с расширением OpenSSL:
<?php
$iv = 'a1a2a3a4a5a6a7a8b1b2b3b4b5b6b7b8';
$key = 'c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8';
$ct = 'j86KHBVRsDGKUnOiYdkEotsFL/lY/1tzz/h3Ay+vlEX11fC055m7vaF6q7w13eUj';
$ivBytes = hex2bin($iv);
$keyBytes = hex2bin($key);
$ctBytes = base64_decode($ct);
$decrypt = openssl_decrypt($ctBytes, "aes-256-cbc", $keyBytes, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $ivBytes);
echo($decrypt);
Других решений пока нет …