Я пытаюсь расшифровать в NodeJs. Он работает на Java. Но я не могу добиться того же в Node.
node-version: 8.4
Найдите мой код NodeJs:
var crypto = require('crypto');
function decryption (message, key) {
var messageArray = Buffer.from(message, 'base64');
// var kekbuf = Buffer(key, 'utf8');
var ivBuffer = new Buffer([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
var iv = ivBuffer.slice(0, 16);
var decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
decipher.setAutoPadding(false);
var dec = decipher.update(messageArray, 'base64');
dec += decipher.final();
return dec.toString();
}
Найдите рабочий код расшифровки Java
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
class Test1 {
public String decrypt(String message, String key) throws Exception {
DatatypeConverter dtc = null;
byte[] messagArray = dtc.parseBase64Binary(message);
byte[] keyArray = dtc.parseBase64Binary(key);
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKey secretKey = new SecretKeySpec(keyArray, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);
return new String(cipher.doFinal(messagArray));
}
}
Я получаю другой расшифрованный текст. Я не могу добиться того же результата в NodeJs, что и в Java. Кроме того, я не мог изменить свой код шифрования Java. Итак, мне нужно разобраться с расшифровкой в Node.
Не могли бы вы помочь мне с этим.
Спасибо! Не могли бы вы предоставить какой-нибудь фрагмент кода узла.
Код NodeJS setAutoPadding(false) означает, что заполнение отсутствует, а данные, подлежащие шифрованию, должны быть точным кратным размеру блока (16 байтов для AES). Но код Java указывает: "AES/CBC/PKCS5PADDING" с указанием заполнения (на самом деле PKCS # 7), поэтому они несовместимы.




Вот полные примеры на Java, а также на Node.js, они используют одни и те же ключи / iv / plaintext и дадут идентичные результаты.
Ява
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
class AES
{
public AES()
{
}
public String encrypt(String plainText, String keyBase64, String ivBase64) throws Exception
{
byte[] plainTextArray = plainText.getBytes(StandardCharsets.UTF_8);
byte[] keyArray = DatatypeConverter.parseBase64Binary(keyBase64);
byte[] iv = DatatypeConverter.parseBase64Binary(ivBase64);
SecretKeySpec secretKey = new SecretKeySpec(keyArray, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));
return new String(DatatypeConverter.printBase64Binary(cipher.doFinal(plainTextArray)));
}
public String decrypt(String messageBase64, String keyBase64, String ivBase64) throws Exception {
byte[] messageArray = DatatypeConverter.parseBase64Binary(messageBase64);
byte[] keyArray = DatatypeConverter.parseBase64Binary(keyBase64);
byte[] iv = DatatypeConverter.parseBase64Binary(ivBase64);
SecretKey secretKey = new SecretKeySpec(keyArray, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
return new String(cipher.doFinal(messageArray));
}
public static void main(String[] args) {
try
{
String plainText = "Hello world!";
String encryptionKeyBase64 = "DWIzFkO22qfVMgx2fIsxOXnwz10pRuZfFJBvf4RS3eY = ";
String ivBase64 = "AcynMwikMkW4c7+mHtwtfw= = ";
AES AES = new AES();
String cipherText = AES.encrypt(plainText, encryptionKeyBase64, ivBase64);
String decryptedCipherText = AES.decrypt(cipherText, encryptionKeyBase64, ivBase64);
System.out.println("Plaintext: " + plainText);
System.out.println("Ciphertext: " + cipherText);
System.out.println("Decrypted text: " + decryptedCipherText);
}
catch (Exception e)
{
System.out.println(e.toString());
}
}
}
Node.js
var crypto = require('crypto');
function getAlgorithm(keyBase64) {
var key = Buffer.from(keyBase64, 'base64');
switch (key.length) {
case 16:
return 'aes-128-cbc';
case 32:
return 'aes-256-cbc';
}
throw new Error('Invalid key length: ' + key.length);
}
function encrypt(plainText, keyBase64, ivBase64) {
const key = Buffer.from(keyBase64, 'base64');
const iv = Buffer.from(ivBase64, 'base64');
const cipher = crypto.createCipheriv(getAlgorithm(keyBase64), key, iv);
let encrypted = cipher.update(plainText, 'utf8', 'base64')
encrypted += cipher.final('base64');
return encrypted;
};
function decrypt (messagebase64, keyBase64, ivBase64) {
const key = Buffer.from(keyBase64, 'base64');
const iv = Buffer.from(ivBase64, 'base64');
const decipher = crypto.createDecipheriv(getAlgorithm(keyBase64), key, iv);
let decrypted = decipher.update(messagebase64, 'base64');
decrypted += decipher.final();
return decrypted;
}
var keyBase64 = "DWIzFkO22qfVMgx2fIsxOXnwz10pRuZfFJBvf4RS3eY = ";
var ivBase64 = 'AcynMwikMkW4c7+mHtwtfw==';
var plainText = 'Why, then, ’tis none to you, for there is nothing either good or bad, but thinking makes it so';
var cipherText = encrypt(plainText, keyBase64, ivBase64);
var decryptedCipherText = decrypt(cipherText, keyBase64, ivBase64);
console.info('Algorithm: ' + getAlgorithm(keyBase64));
console.info('Plaintext: ' + plainText);
console.info('Ciphertext: ' + cipherText);
console.info('Decoded Ciphertext: ' + decryptedCipherText);
После этого я получаю сообщение об ошибке: this._handle.initiv (cipher, toBuf (key), toBuf (iv)); ^ Ошибка: неверная длина ключа в новом Decipheriv (crypto.js: 265: 16)
Я проверю, может, вы дадите мне ключ и зашифрованный текст?
Какой длины ключ шифрования вы используете? Его длина должна составлять 16 байт.
Длина ключа 32
Итак, если длина ключа 32, мы говорим о 256-битном AES. Может, мне стоит обновить ответ, чтобы использовать это?
Я обновил ответ, поэтому алгоритм определяется по длине ключа. Затем это расшифрует 256-битный зашифрованный текст AES.
Это сработало после обновления 'aes-192-cbc', мой key.length показывал 24. Кроме того, я сделал строки concat, возвращаемые update () и final (). БОЛЬШОЕ ТЕБЕ СПАСИБО :)
@TerryLennox Я получаю при расшифровке из Node.js ошибку: 06065064: подпрограммы цифрового конверта: EVP_DecryptFinal_ex: плохая расшифровка
Поскольку я не могу комментировать. Вышеупомянутый код Node.js не может зашифровать / расшифровать что-либо, превышающее 15 символов / байтов. Простое исправление выглядит следующим образом:
Изменить возврат на объединенный возврат cipher.final и decipher.final
function encrypt(plainText, keyBase64, ivBase64) {
var key = Buffer.from(keyBase64, 'base64');
var iv = Buffer.from(ivBase64, 'base64');
var cipher = crypto.createCipheriv(getAlgorithm(keyBase64), key, iv);
let cip = cipher.update(plainText, 'utf8', 'base64')
cip += cipher.final('base64');
return cip;
};
function decrypt (messagebase64, keyBase64, ivBase64) {
var key = Buffer.from(keyBase64, 'base64');
var iv = Buffer.from(ivBase64, 'base64');
var decipher = crypto.createDecipheriv(getAlgorithm(keyBase64), key, iv);
let dec = decipher.update(messagebase64, 'base64');
dec += decipher.final();
return dec;
}
Спасибо @Sundeep за указание на ошибку, я обновил ответ.
Проверьте преобразование java conde в Nodejs:
Ява:
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.util.Base64;
public class Main {
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
public static String encrypt(String message, String key) throws GeneralSecurityException, UnsupportedEncodingException {
Cipher cipher = Cipher.getInstance(ALGORITHM);
byte[] messageArr = message.getBytes();
byte[] decodedBytes = Base64.getDecoder().decode(key);
SecretKeySpec keySpec = new
SecretKeySpec(Base64.getDecoder().decode(key), "AES");
byte[] ivParams = new byte[16];
byte[] encoded = new byte[messageArr.length + 16];
System.arraycopy(ivParams,0,encoded,0,16);
System.arraycopy(messageArr, 0, encoded, 16, messageArr.length);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ivParams));
byte[] encryptedBytes = cipher.doFinal(encoded);
encryptedBytes = Base64.getEncoder().encode(encryptedBytes);
return new String(encryptedBytes);
}
public static String decrypt(String encryptedStr, String key) throws GeneralSecurityException, UnsupportedEncodingException {
Cipher cipher = Cipher.getInstance(ALGORITHM);
SecretKeySpec keySpec = new
SecretKeySpec(Base64.getDecoder().decode(key), "AES");
byte[] encoded = encryptedStr.getBytes();
encoded = Base64.getDecoder().decode(encoded);
byte[] decodedEncrypted = new byte[encoded.length-16];
System.arraycopy(encoded, 16, decodedEncrypted, 0,encoded.length-16);
byte[] ivParams = new byte[16];
System.arraycopy(encoded,0, ivParams,0, ivParams.length);
String ivString = new String(ivParams);
cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivParams));
byte[] decryptedBytes = cipher.doFinal(decodedEncrypted);
return new String(decryptedBytes);
}
NodeJS:
var crypto = require ('крипто'); const encrypt = (plainText, keyBase64) => {
const textBuffer = Buffer.from(plainText);
const key = Buffer.from(keyBase64, 'base64');
var iv = Buffer.from([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
var encoded = Buffer.concat([iv,textBuffer]);
const cipher = crypto.createCipheriv('aes-192-cbc', key, iv);
let encrypted = cipher.update(encoded, 'binary', 'base64')
encrypted += cipher.final('base64');
return encrypted;
};
const decrypt = (messagebase64, keyBase64) =>{
const key = Buffer.from(keyBase64, 'base64');
const encoded = Buffer.from(messagebase64, 'base64');
var iv = encoded.slice(0, 16);
var decoded = encoded.slice(16,encoded.length);
const decipher = crypto.createDecipheriv('aes-192-cbc', key, iv);
let decrypted = decipher.update(decoded, 'binary','utf-8');
decrypted += decipher.final();
return decrypted;
}
Этот тип ответа уже был добавлен @Terry и принят. Вы должны предложить улучшения, если они есть!
В коде Java вы анализируете ключ base64
dtc.parseBase64Binary(key);, и этот шаг кажется отсутствующим в коде nodejs.