У меня есть код в PHP для шифрования строки.
$password = 'secret';
$iv_length = openssl_cipher_iv_length('AES-256-CBC');
$key = substr(sha1($password, true), 0, $iv_length);
$string = 'Brevity is the soul of wit';
$iv = hex2bin('2ceb02a85f6d4de6c28b2e59fda886d5');
$encrypted_string = openssl_encrypt($string, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
echo base64_encode($encrypted_string);
Возвращает зашифрованный текст в base64 Ky27sjhxUY7BFoscEgyFToxRDAsARzRFgQBIApbPmjQ=.
Я передаю его и IV в javascript и пытаюсь расшифровать с помощью этого кода:
const crypto = require("crypto");
const Algorithm = "aes-256-cbc";
function encrypt(plainText, key, iv, outputEncoding = "base64") {
const cipher = crypto.createCipheriv(Algorithm, key, iv);
const output = Buffer.concat([cipher.update(plainText), cipher.final()]).toString(outputEncoding);
return output.replace('+', '-').replace('/', '_').replace('=', '');
}
function decrypt(cipherText, key, iv, outputEncoding = "base64") {
cipherText = Buffer.from(cipherText.replace('-', '+').replace('_', '/'), "base64");
const cipher = crypto.createDecipheriv(Algorithm, key, iv, {
});
return Buffer.concat([cipher.update(cipherText), cipher.final()]).toString(outputEncoding);
}
const string = "Brevity is the soul of wit";
const password = 'secret';
const iv_length = 16;
let KEY = crypto
.createHash('sha1')
.update(password)
.digest('bin')
.slice(0, iv_length);
const IV = Buffer.from('2ceb02a85f6d4de6c28b2e59fda886d5', 'hex');
const decrypted = decrypt('GIyzBeAUpxr93RIyjUZZ6W4lm/qHiF1lf/8drSEgfGs=', KEY, IV, "utf8")
console.info("Decrypted:", decrypted);
Но он терпит неудачу с этой ошибкой:
internal/crypto/cipher.js:103
this[kHandle].initiv(cipher, credential, iv, authTagLength);
^
Error: Invalid key length
at Decipheriv.createCipherBase (internal/crypto/cipher.js:103:19)
at Decipheriv.createCipherWithIV (internal/crypto/cipher.js:121:20)
at new Decipheriv (internal/crypto/cipher.js:264:22)
at Object.createDecipheriv (crypto.js:130:10)
at decrypt (/Users/sacram/code/decrypt/test.js:12:24)
at Object.<anonymous> (/Users/sacram/code/decrypt/test.js:36:19)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
Можно ли расшифровать его без изменения кода PHP?
Я пытаюсь расшифровать строку с помощью js, которая была зашифрована в php.
@Topaco, вы хотите опубликовать ответ или это дубликат или существующий вопрос?
@Topaco, не могли бы вы опубликовать свой комментарий в качестве ответа, и я приму его как правильный ответ. Большое спасибо.
Пожалуйста. Я поставил свой комментарий в качестве ответа.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


В обоих кодах длина ключа определяется по заданному алгоритму: AES-256-CBC требуется ключ размером 32 байта.
В коде PHP/OpenSSL в качестве ключа используются первые 16 байт хэша SHA-1 пароля. Слишком короткий ключ автоматически дополняется значениями 0x00 до требуемой длины в 32 байта (слишком длинный ключ будет автоматически усечен до требуемой длины в конце), см. описание параметра фразы-пароля в openssl_encrypt() документация.
В коде NodeJS ключ также определяется как первые 16 байт хэша SHA-1 пароля. Однако, в отличие от кода PHP/OpenSSL, ключ не дополняется (и не усекается). Ключ неправильной длины идентифицируется как недопустимый, и выдается соответствующее исключение. Это причина возникновения исключения в коде NodeJS.
Чтобы в коде NodeJS использовался тот же ключ, что и в коде PHP, в код NodeJS необходимо добавить следующее:
KEY = Buffer.concat([KEY, Buffer.alloc(16, '\0')])
Код PHP имеет ряд уязвимостей:
В коде NodeJS отсутствует
KEY = Buffer.concat([KEY, Buffer.alloc(16, '\0')]), что неявно происходит в коде PHP (заполнение слишком коротких ключей). Обратите внимание, что SHA1 и добавление значений 0x00 в генерацию ключа являются уязвимостями.