Подтвердить что ты не робот

Шифрование с помощью PHP, расшифровка с помощью Javascript (cryptojs)

У меня возникают проблемы с базовым шифрованием/расшифровкой. Я посмотрел вокруг рабочего примера, но не нашел рабочего примера.

-I будет шифроваться в php, расшифровать cryptojs для небольшого уровня безопасности

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js">
<?
$text = "this is the text here";
$key = "encryptionkey";

$msgEncrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND));
$msgBase64 = trim(base64_encode($msgEncrypted));

echo "<h2>PHP</h2>";
echo "<p>Encrypted:</p>";
echo $msgEncrypted;
echo "<p>Base64:</p>";
echo $msgBase64;
 ?>

<p>AES Decrypt</p>
<script> 
    var key = 'encryptionkey';
    var encrypted = "<?php echo $msgBase64 ?>";
    //tried  var base64decode = CryptoJS.enc.Base64.parse(encrypted); 
    var decrypted = CryptoJS.AES.decrypt(encrypted, key);
    console.log( decrypted.toString(CryptoJS.enc.Utf8) );
</script>

Какой шаг мне не хватает?

4b9b3361

Ответ 1

Мне нужно то же самое, и я написал небольшую библиотеку, которая работает для CryptoJS 3.x и PHP с поддержкой openssl. Надеюсь, что это поможет, исходный плюс примеры файлов здесь https://github.com/brainfoolong/cryptojs-aes-php

PHP Lib

/**
* Decrypt data from a CryptoJS json encoding string
*
* @param mixed $passphrase
* @param mixed $jsonString
* @return mixed
*/
function cryptoJsAesDecrypt($passphrase, $jsonString){
    $jsondata = json_decode($jsonString, true);
    $salt = hex2bin($jsondata["s"]);
    $ct = base64_decode($jsondata["ct"]);
    $iv  = hex2bin($jsondata["iv"]);
    $concatedPassphrase = $passphrase.$salt;
    $md5 = array();
    $md5[0] = md5($concatedPassphrase, true);
    $result = $md5[0];
    for ($i = 1; $i < 3; $i++) {
        $md5[$i] = md5($md5[$i - 1].$concatedPassphrase, true);
        $result .= $md5[$i];
    }
    $key = substr($result, 0, 32);
    $data = openssl_decrypt($ct, 'aes-256-cbc', $key, true, $iv);
    return json_decode($data, true);
}

/**
* Encrypt value to a cryptojs compatiable json encoding string
*
* @param mixed $passphrase
* @param mixed $value
* @return string
*/
function cryptoJsAesEncrypt($passphrase, $value){
    $salt = openssl_random_pseudo_bytes(8);
    $salted = '';
    $dx = '';
    while (strlen($salted) < 48) {
        $dx = md5($dx.$passphrase.$salt, true);
        $salted .= $dx;
    }
    $key = substr($salted, 0, 32);
    $iv  = substr($salted, 32,16);
    $encrypted_data = openssl_encrypt(json_encode($value), 'aes-256-cbc', $key, true, $iv);
    $data = array("ct" => base64_encode($encrypted_data), "iv" => bin2hex($iv), "s" => bin2hex($salt));
    return json_encode($data);
}

Javascript Lib

var CryptoJSAesJson = {
    stringify: function (cipherParams) {
        var j = {ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64)};
        if (cipherParams.iv) j.iv = cipherParams.iv.toString();
        if (cipherParams.salt) j.s = cipherParams.salt.toString();
        return JSON.stringify(j);
    },
    parse: function (jsonStr) {
        var j = JSON.parse(jsonStr);
        var cipherParams = CryptoJS.lib.CipherParams.create({ciphertext: CryptoJS.enc.Base64.parse(j.ct)});
        if (j.iv) cipherParams.iv = CryptoJS.enc.Hex.parse(j.iv)
        if (j.s) cipherParams.salt = CryptoJS.enc.Hex.parse(j.s)
        return cipherParams;
    }
}

Пример Javascript

var encrypted = CryptoJS.AES.encrypt(JSON.stringify("value to encrypt"), "my passphrase", {format: CryptoJSAesJson}).toString();
var decrypted = JSON.parse(CryptoJS.AES.decrypt(encrypted, "my passphrase", {format: CryptoJSAesJson}).toString(CryptoJS.enc.Utf8));

Пример PHP

$encrypted = cryptoJsAesEncrypt("my passphrase", "value to encrypt");
$decrypted = cryptoJsAesDecrypt("my passphrase", $encrypted);

Ответ 2

Замечание по безопасности: код этого ответа уязвим для атак с использованием зашифрованного текста. Смотрите этот ответ вместо безопасного шифрования.

Вот рабочий пример шифрования вашей строки с помощью PHP и дешифрования с помощью CryptoJS.

На стороне PHP:

Используйте MCRYPT_RIJNDAEL_128 (не 256) для сопряжения с AES. 128 здесь размер блока, а не размер ключа.

Отправить IV тоже. Вам нужен IV для расшифровки.

$text = "this is the text here";
$key = "encryptionkey";

// Note: MCRYPT_RIJNDAEL_128 is compatible with AES (all key sizes)
$iv = random_bytes(16);

$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);

echo "iv:".base64_encode($iv)."\n";
echo "ciphertext:".base64_encode($ciphertext)."\n";

Вот пример вывода из тестового прогона:

iv:BMcOODpuQurUYGICmOqqbQ==
ciphertext:ZJAab8YtkRq5TL7uyIR7frM2b3krftJzn1pTqRTAda4=

ВАЖНО: поскольку мы не аутентифицируем наш зашифрованный текст, расшифровка становится уязвимой для атак оракула. Смотрите также: аутентифицированное шифрование в PHP.

На стороне CryptoJS:

Ваш ключ - всего 13 печатных символов ASCII, что очень слабо. Mcrypt проложенного ключа к действительному KeySize с использованием нулевых байт.

Преобразуйте ключ и IV в массивы слов.

Мне не очень повезло, расшифровывать с помощью зашифрованного текста в виде массива слов, поэтому я оставил его в формате Base64.

CryptoJS = require("crypto-js")

// Mcrypt pads a short key with zero bytes
key = CryptoJS.enc.Utf8.parse('encryptionkey\u0000\u0000\u0000')

iv = CryptoJS.enc.Base64.parse('BMcOODpuQurUYGICmOqqbQ==')

// Keep the ciphertext in Base64 form
ciphertext = 'ZJAab8YtkRq5TL7uyIR7frM2b3krftJzn1pTqRTAda4='

/**
 * DANGER DANGER WILL ROBINSON! <== Stop editing my answer or I will delete it.
 *
 * This example code doesn't demonstrate AUTHENTICATED ENCRYPTION
 * and is therefore vulnerable to chosen-ciphertext attacks.
 *
 * NEVER USE THIS CODE TO PROTECT SENSITIVE DATA!
 */

// Mcrypt uses ZERO padding
plaintext = CryptoJS.AES.decrypt(ciphertext, key, { iv: iv, padding: CryptoJS.pad.ZeroPadding })

// I ran this in nodejs
process.stdout.write(CryptoJS.enc.Utf8.stringify(plaintext))

Ответ 3

Вы используете две библиотеки, которые пытаются разместить входные данные, а именно - строго говоря - недействительны. Для Rijndael требуются ключи, которые имеют случайные байтовые строки длиной 16, 24 или 32 байта. Вы предоставляете 13-значную строку. Mcrypt, библиотека PHP, использует строку (предположительно закодированную utf8) непосредственно как двоичный вход, а нуль заполняет ее необходимыми 32 байтами для MCRYPT_RIJNDAEL_256, CryptoJS, с другой стороны решает, что вы ввели что-то вроде фразу и вместо этого используете функцию деривации ключа для генерации 32-байтового ключа.

Кроме того, используемые алгоритмы шифрования даже не совпадают. Mcrypt использует редко реализованный вариант оригинального Rijndael для 256-битной версии, тогда как CryptoJS реализует широко известный вариант AES256 предложения Rijndael. 128-разрядная версия обоих (MCRYPT_RIJNDAEL_128 и AES128) идентична.

Третья проблема, с которой вам предстоит столкнуться, заключается в том, что Mcrypt также использует сумасшедшую схему дополнений для зашифрованных данных. Поскольку Rijndael является блочным шифрованием, он может шифровать только блоки из 16, 24 или 32 байта (в зависимости от варианта - AES всегда использует 16 байтовых блоков). Поскольку такие данные должны быть дополнены. Mcrypt делает это неинъекционным способом, просто добавляя нули. Если вы только кодирующие строки, это не будет для вас большой проблемой, поскольку строки, закодированные в utf8, никогда не содержат нулевых байтов, поэтому вы можете просто отключить их (CryptoJS даже поддерживает это изначально).

Самое простое исправить все эти проблемы - избежать необходимости выполнять какую-либо криптографию самостоятельно (в любом случае она сильно не приветствуется без широкого знания предмета). Можете ли вы вместо этого передать свою конфиденциальную информацию через https, которая будет использовать TLS (ранее называемый SSL) для шифрования и аутентификации канала?

Ответ 4

Не зацикливайтесь на кодировании, просто используйте декодер base64

по php-коду:

$encrypt_val=base64_encode("value");

а на js просто:

var my_orignal_val = window.atob(passed_val);

Этого будет достаточно для вашего требования.