#javascript #reactjs #encryption #cryptojs #pako
#javascript #reactjs #шифрование #cryptojs #пако
Вопрос:
У меня есть PHP-код, который имеет 2 функции: шифрование и дешифрование, которые используют OpenSSL, на самом деле, прежде чем я его переработал, я закодировал результат OpenSSL в base64, потому что он слишком длинный, я меняю его на сжатие с использованием zlib (gzdeflate, gzinflate), затем преобразую последний результат в шестнадцатеричный.
вот мой PHP-код, он отлично работает на PHP:
$secret_key = 'thisIsK3y';
$secret_iv = 'tHis1s1v';
$output = false;
$encrypt_method = "AES-256-CBC";
$key = hash( 'sha256', $secret_key );
$iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );
$action = 'e';
$string = "33f6f1d3ebe5b9da5fd0e3a1c7dd71c6e484be914731cf96adac0c00" //decrypted = "test"
if( $action == 'e' )
{
$output = bin2hex(gzdeflate( gzdeflate(openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ), 9), 9) );
}
else if( $action == 'd' )
{
if (!empty($string))
$output = openssl_decrypt( gzinflate(gzinflate(pack("H*", $string ) ) ), $encrypt_method, $key, 0, $iv );
}
echo $output; // output : "test", it's working fine on PHP
затем я попытался перевести язык на JS в React и сделал простые утилиты, вот мой JS-код на данный момент, :
let secret_key = "thisIsK3y";
let secret_iv = "tHis1s1v";
var output = false;
let encrypt_method = "AES-256-CBC";
let key = String(sha256(secret_key)).toString(Hex).substr(0, 32);
let iv = String(sha256(secret_iv)).toString(Hex).substr(0, 16);
if (action == 'd') { // Decryption
let enc = gzinflate(gzinflate(hex2bin(string)));
enc = enc.toString(Utf8);
let decrypted = AES.decrypt(enc, Utf8.parse(key), {
iv: Utf8.parse(iv),
}).toString(Utf8);
console.log('sss', hex2bin('33f6f1d3ebe5b9da5fd0e3a1c7dd71c6e484be914731cf96adac0c00'));
debugger;
output = decrypted;
}
Я разделил метод gzinfalte, gzdeflate, hex2bin, bin2hex на другой JS-файл с именем string.js и импортируйте некоторые пакеты CryptoJS и PakoJS
string.js содержит некоторые методы, подобные этому :
export function gzdeflate(str) {
return pako.deflateRaw(str);
}
export function gzinflate(str) {
return pako.inflateRaw(str);
}
export function bin2hex(s) {
let i
let l
let o = ''
let n
s = ''
for (i = 0, l = s.length; i < l; i ) {
n = s.charCodeAt(i)
.toString(16)
o = n.length < 2 ? '0' n : n
}
return o
}
export function hex2bin(hex) {
let bytes = [], str;
for(var i=0; i< hex.length-1; i =2){
bytes.push(parseInt(hex.substr(i, 2), 16));
}
str = String.fromCharCode.apply(String, bytes);
return str;
}
при попытке его отладки в методе hex2bin нет ошибки
console.log(hex2bin('33f6f1d3ebe5b9da5fd0e3a1c7dd71c6e484be914731cf96adac0c00'));
НО, когда я пытаюсь преобразовать двоичный файл в gzinflate, он показывает мне ошибку
console.log(gzinflate(gzinflate(hex2bin(33f6f1d3ebe5b9da5fd0e3a1c7dd71c6e484be914731cf96adac0c00))))
Не удается прочитать свойство ‘ciphertext’ неопределенного
и когда я пытаюсь изменить secret_key и iv, появляется ошибка :
let secret_key = 'ffffffffffffffffffffffff{Curi}ty';
let secret_iv = 'ffffffffffffffffffffffff{Curi}ty';
покажите мне ошибку
Ошибка: недопустимые сохраненные длины блоков
Кто-нибудь может мне помочь?
Ответ №1:
Я не эксперт по PHP, но у меня есть другие предположения, что PHP может усекать некоторые ключи для вас.
Я предлагаю убедиться, что функции генерации ключей ведут себя одинаково для вас на обоих языках, и убедитесь, что они имеют длину всего 32 байта.
Я хочу указать на еще одну проблему, которую я вижу в вашем коде. Хотя это будет работать, вы снижаете безопасность своего шифрования.
пусть ключ = строка(sha256(secret_key)).toString(Hex).substr(0, 32);
Каждый раз, когда вы берете 32-байтовое двоичное значение, преобразуете в шестнадцатеричное, а затем принимаете только 32 символа шестнадцатеричного вывода, вы значительно снижаете надежность своего ключа. Найдите способ сохранить значение в виде байта.
Вы пытаетесь создать 256-битный ключ (32 байта с 256 возможными значениями для каждого байта). На самом деле вы создаете строку из 32 символов, и каждый символ имеет только 16 возможных значений (0-1a-f). Вы изменили безопасность вашего ключа шифрования с предполагаемых 256 ^ 32 (1.1E77) на 16 ^ 32 (3.4E38).
Найдите способ использовать значения байтов, созданные SHA256.