#java #encryption #cryptography #aes #cryptojs
#java #шифрование #криптография #aes #cryptojs
Вопрос:
Ниже приведен код для шифрования некоторого содержимого файла в Java с использованием режима AES / CTR / NOPADDING. Я использую криптопакет javax. Также я использую тот же секретный ключ для генерации ключа и iv.
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
byte[] secretKey = Base64.decodeBase64("uQsaW WMUrjcsq1HMf 2JQ==");
SecretKeySpec key = new SecretKeySpec(secretKey, "AES");
IvParameterSpec iv = new IvParameterSpec(secretKey);
cipher.init(mode, key , iv);
FileInputStream fileInputStream = new FileInputStream(sourceFilePath);
FileOutputStream fileOutputStream = new FileOutputStream(destFilePath);
int read = 0;
while ((fileInputStream.available()) > 0) {
byte[] block = new byte[4096];
read = fileInputStream.read(block);
byte[] writeBuffer = cipher.update(block);
fileOutputStream.write(writeBuffer, 0, read);
}
byte[] writeBuffer = cipher.doFinal();
fileOutputStream.write(writeBuffer, 0, writeBuffer.length);
fileInputStream.close();
fileOutputStream.close();
Я не могу расшифровать зашифрованный контент в javascript с помощью cryptojs.
Вот что я попробовал.
var key = CryptoJS.enc.Hex.parse(atob('uQsaW WMUrjcsq1HMf 2JQ=='));
var decrypted = CryptoJS.AES.decrypt(encryptedContent, key, {
mode: CryptoJS.mode.CTR,
iv: key,
padding: CryptoJS.pad.NoPadding
});
var decryptedText = CryptoJS.enc.Utf8.stringify(decrypted);
Может кто-нибудь сказать мне, что я делаю не так? Или скажите мне, как это сделать.
Я могу шифровать и расшифровывать на java и javascript независимо.
Комментарии:
1. Использовать ключ в качестве IV — это очень плохая идея, особенно для режима CTR. Нужно ли предоставлять ключ для nodejs в шестнадцатеричном формате?
2. да, CryptoJS принимает key и iv как шестнадцатеричные.
3. Да, я читал то же самое, что использование ключа в качестве iv плохо, но в текущей ситуации что еще происходит не так. @gusto2 Спасибо.
4. что вы подразумеваете под «не удается расшифровать»? Есть ли у вас исключение (post the stacktrace) или искаженный вывод?
5. CryptoJS возвращает wordArray в качестве выходных данных. Он выдает пустой wordArray. Никаких исключений или ошибок. Также я исправил ключ, который передается методу decrypt. Ранее это передавалось как массив слов [0,256].
Ответ №1:
-
В
CryptoJS
документации объясняется, какие типы данных и параметры ожидаетCryptoJS.decrypt()
метод и какие кодировщики доступны:- Ключ должен быть передан
CryptoJS.decrypt()
-методу какWordArray
. Поскольку ключевые данные закодированы в Base64, они могут быть преобразованы вWordArray
сCryptoJS.enc.Base64.parse()
помощью-method. - Зашифрованный текст может быть передан
CryptoJS.decrypt()
-методу какWordArray
внутриCipherParams
-объекта. Java-код хранит зашифрованные данные в файле. Предполагая, что строкаencryptedContent
содержит эти данные в виде шестнадцатеричной строки (к сожалению, это не вытекает из опубликованного кода, так что здесь должно быть сделано предположение), они могут быть преобразованы вWordArray
с помощьюCryptoJS.enc.Hex.parse()
-метода и обернуты вCipherParams
-объект. CryptoJS.decrypt()
-Метод возвращаетWordArray
, который может быть преобразован с помощьюCryptoJS.enc.Utf8.stringify()
-метода в строку.
- Ключ должен быть передан
-
Если во входном файле содержится следующий простой текст:
This is the plain text which needs to be encrypted!
Java-код сохраняет следующую последовательность байтов (= зашифрованные данные) в выходном файле:
52F415AB673427C42278E8D6F34C16134D7E3FE7986500980ED4063F3CF51162592CE0F5412CCA0BC2DBAE3F2AEC2D585EE8D7
JavaScript-код для дешифрования является:
var key = CryptoJS.enc.Base64.parse('uQsaW WMUrjcsq1HMf 2JQ=='); var encryptedContent = '52F415AB673427C42278E8D6F34C16134D7E3FE7986500980ED4063F3CF51162592CE0F5412CCA0BC2DBAE3F2AEC2D585EE8D7'; var cipherParams = CryptoJS.lib.CipherParams.create({ ciphertext: CryptoJS.enc.Hex.parse(encryptedContent) }); var decrypted = CryptoJS.AES.decrypt(cipherParams, key, { mode: CryptoJS.mode.CTR, iv: key, padding: CryptoJS.pad.NoPadding }); var decryptedText = CryptoJS.enc.Utf8.stringify(decrypted); console.log(decryptedText);
который отображает исходный обычный текст в консоли. Для запуска приведенного выше кода необходима как минимум версия CryptoJS 3.1.4 (см. Версии, cdnjs).
Комментарии:
1. Спасибо @Topaco. Я думаю, что есть некоторая проблема с моей кодировкой в java, я использую приведенный выше код, но я получаю несколько случайных символов (нечитаемых) в качестве зашифрованных данных. Я проверил свой импорт, я использую javax.crypto.
2. Вам пришлось бы более подробно описать, как зашифрованные данные считываются из сохраненного файла в JavaScript-код (или, точнее, в переменную
encryptedContent
). Это не видно из вашего кода. Вероятно, проблема здесь. Лучший способ — опубликовать недостающий код. Или вы пытаетесь определить зашифрованные данные из файла вручную ? В этом случае вы должны использовать не текстовый редактор, а шестнадцатеричный , поскольку требуется шестнадцатеричное представление зашифрованных данных.3. На самом деле я говорил о коде Java. Когда я записываю зашифрованный контент в файл на java, он записывается с некоторыми случайными символами (многие символы, не являющиеся клавиатурными). Код Java в том виде, в каком он скопирован, без импорта и попытки перехватить блок. В JavaScript я перехватываю запрос на выборку файла и считываю содержимое в виде текста.
4. Зашифрованные данные состоят из байтов со значениями между
0x00
и0xFF
. Если вы открываете файл в текстовом редакторе, то в зависимости от кодировки отображаются буквенно-цифровые символы, специальные символы, управляющие символы и т.д. (Что вполне нормально). Я полагаю, вы имеете в виду это. Чтобы увидетьactual
(шестнадцатеричные) значения, вы должны открыть файл в шестнадцатеричном редакторе. Наконец, задача состоит в том, чтобы предоставить эти шестнадцатеричные значения в JavaScript-коде, чтобы можно было выполнить дешифрование.5. Для дальнейшего анализа вы могли бы продолжить шаг за шагом: Создайте файл с зашифрованными данными с открытым текстом из моего ответа: Это обычный текст, который необходимо зашифровать! . Содержит ли сгенерированный файл шестнадцатеричные значения из моего ответа: 52F415AB673427C42278E8D6F34C16134D7E3FE7986500980ED4063F3CF51162592CE0F5412CCA0BC2DBAE3F2AEC2D585EE8D7 ? Следующий шаг — проверить, содержатся ли эти значения также в JavaScript-коде в
encryptedContent
. Я подозреваю, что проблема возникает на последнем шаге.
Ответ №2:
Ваш цикл шифрования неверен. Я не уверен, является ли это причиной ваших проблем, но я бы начал с этого
read = fileInputStream.read(block);
byte[] writeBuffer = cipher.update(block);
даже если вы читаете только частичный размер блока, вы выполняете операцию шифрования по всему блоку, вы можете попробовать
byte[] writeBuffer = cipher.update(block, 0, read);
Что касается использования ключа в качестве IV, я должен подчеркнуть, что в режиме CTR безопасность будет полностью нарушена.
Комментарии:
1. Спасибо за предложение. Это не сработало. Обратите внимание, что я могу расшифровать в java, используя те же шаги, что и в написанном в методе, и просто изменив режим экземпляра cipher.