Neardupe Дешифрование строк из node.js в Java? , что то же самое в противоположном направлении.
[В Java] я сгенерировал 128-битный ключ AES и зашифровал его с помощью алгоритма AES, а затем зашифровал этот сгенерированный ключ с помощью алгоритма RSA.
Нет, ты не сделал. Ваш Java-код создает экземпляр KeyGenerator
для AES-128, но не использует его для генерации ключа. Ключ, который вы фактически использовали (и, как вы говорите, сервер правильно расшифровывается из RSA-OAEP), составляет 32 байта, что соответствует AES-256.
Но ваша главная проблема в том, что createDecipher
принимает пароль, а НЕ ключ. По документу
crypto.createDecipher (алгоритм, пароль [, параметры])
Реализация crypto.createDecipher () получает ключи, используя функцию OpenSSL EVP_BytesToKey с алгоритмом дайджеста, установленным на MD5, одной итерацией и без соли.
Вы передали то, что на самом деле является ключом, в качестве пароля; это приводит к тому, что nodejs использует ключ, который полностью отличается от ключа, используемого в Java, и, следовательно, дает совершенно неверные результаты. Вместо этого вы должны использовать createDecipheriv
, который действительно берет ключ, и IV (Вектор инициализации).
И это ваша другая проблема. Для дешифрования вы должны использовать тот же IV, что и для шифрования, обычно путем добавления IV к зашифрованному тексту, отправляемому от отправителя к получателю, но вы этого не делаете. В результате следующий (упрощенный) код не может расшифровать первые 16 байтов ваших данных, но делает все остальное.
const crypto = require('crypto');
msg = Buffer.from('SfosHg+cTrQXYUdF0FuqCJMHgfcP13ckp2L0B9QqOcl8UtWnnl8fLi5lxgR2SKOj','base64');
aeskey = Buffer.from('JUtwW8+qU6Mv/FcgbMbkOdOKy72pun4B490KQrRB4QQ=','base64');
dec = crypto.createDecipheriv('aes-256-cbc',aeskey,Buffer.alloc(16)/*this should be the IV*/);
console.log(dec.update(msg,'','latin1')+dec.final('latin1'));
// I used latin1 instead of utf8 because the garbaged first block
// isn't valid UTF-8, and the rest is ASCII which works as either.
->
Y;øï«*M2WÚâeage to be encrypted
// some garbaged chars are control chars and Stack (or browser?)
// may not display them but there really are 16 in total
Кроме того, утверждение в документе, что «векторы инициализации [должны] быть непредсказуемыми и уникальными ... [но не секретными]» является правильным для режима CBC, но не для некоторых других режимов, поддерживаемых OpenSSL (таким образом, nodejs) и Java. Тем не менее, это не программирование Q и, следовательно, оффтоп здесь; он принадлежит к crypto.SX или, возможно, security.SX, где на него уже много раз отвечали.