Почему encrypt, затем decrypt дает мне другой результат?

#php #jquery #encryption #cryptojs

#php #jquery #шифрование #cryptojs

Вопрос:

В моем коде я шифрую некоторые данные два раза. Сначала в jQuery:

 var text = ''   CryptoJS.Rabbit.encrypt("12345", "PassPhrase");
  

затем это отправляется с помощью ajax в php и снова шифруется:

 function mc_encrypt($encrypt, $key){
    $encrypt = serialize($encrypt);
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_DEV_URANDOM);
    $key = pack('H*', $key);
    $mac = hash_hmac('sha256', $encrypt, substr(bin2hex($key), -32));
    $passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $encrypt.$mac, MCRYPT_MODE_CBC, $iv);
    $encoded = base64_encode($passcrypt).'|'.base64_encode($iv);
    return $encoded;
}
  

После этого это сохраняется в базе данных. Если пользователь хочет снова получить доступ к значению, я извлекаю его из базы данных и затем расшифровываю:

 function mc_decrypt($decrypt, $key){
    $decrypt = explode('|', $decrypt);
    $decoded = base64_decode($decrypt[0]);
    $iv = base64_decode($decrypt[1]);
    $key = pack('H*', $key);
    $decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $decoded, MCRYPT_MODE_CBC, $iv));
    $mac = substr($decrypted, -64);
    $decrypted = substr($decrypted, 0, -64);
    $calcmac = hash_hmac('sha256', $decrypted, substr(bin2hex($key), -32));
    if($calcmac!==$mac){ return false; }
    $decrypted = unserialize($decrypted);
    return $decrypted;
}
  

Затем это отправляется обратно в jQuery и снова расшифровывается:

 var text = CryptoJS.Rabbit.decrypt(text, "PassPhrase");
text = text.toString();
console.log(text);
  

Однако значение, зарегистрированное в консоли, сильно отличается от значения (‘12345’) в начале. Я не знаю, почему это происходит, и я изучал эту проблему последние два дня, но, похоже, не могу понять проблему…

Комментарии:

1. Во-первых, почему вы это делаете? Почему «двойное» шифрование лучше?

2. если вы получаете разные значения, значит, вы неправильно зашифровали и / или расшифровали. Функции не заботятся о том, все ли «правильно». они просто берут некоторые данные и выполняют с ними кучу математических операций. Если математика идет не так, функциям все равно, они просто будут делать то, что им говорят.

3. Вы пробовали сравнивать ввод / вывод только части PHP? Помогло бы определить, в чем проблема

4. Дело не в том, что двойное шифрование лучше, а в том, что я не хочу отправлять данные в незашифрованном виде в файл PHP.

5. @user3740505 Если вы беспокоитесь о том, что данные не зашифрованы во время транспортировки, для этого и нужен SSL

Ответ №1:

CryptoJS.Rabbit.decrypt возвращает массив слов, и вы вызываете для него toString . Для «12345» я бы предположил, что результат, который вы видите, — «3132333435».

Используйте CryptoJS stringify, например, CryptoJS.enc.Utf16.stringify(текст) или CryptoJS.enc.Utf8.stringify(текст), в зависимости от исходной кодировки.

Вы можете выбрать кодировку по пути, изменив свой код, например, так:

 p = CryptoJS.enc.Utf8.parse("12345");
text = ''   CryptoJS.Rabbit.encrypt(p, "PassPhrase");
  

Затем на обратном пути:

 var text = CryptoJS.Rabbit.decrypt(text, "PassPhrase");
text = CryptoJS.enc.Utf8.stringify(text); // use same encoding as original input
console.log(text);