В результате шифрование AES в узле приводит к разным результатам по сравнению с Java - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь перенести код Java для шифрования AES ECB в node.js

Проблема заключается в том, что выходные данные из Java и узла не совпадают.

Вот Javaкод

 public static final String DEFAULT_ENCODING = "UTF-8";
 public static final String SEC_PROVIDER = "SunJCE";
 public static final String AES_ALGORITHM = "AES";
 public static final String RIJNDAEL_CIPHER = **"Rijndael/ECB/NoPadding"**;
 public static final int **CIPHER_PAD_SIZE = 32**;
 public static final String HEX_KEY = "3b6ce332ca3b6519eac769710f41ca5c";

public static String encryptData(String text, String hexKey) throws 
    Exception {
     byte[] b1 = Hex.decodeHex(HEX_KEY.toCharArray());
     SecretKey key = new SecretKeySpec(b1, AES_ALGORITHM); 
     Cipher cipher = Cipher.getInstance(RIJNDAEL_CIPHER, SEC_PROVIDER); 
     text = padRightToMod(text, CIPHER_PAD_SIZE); 
     byte[] buf = text.getBytes(DEFAULT_ENCODING); 
     cipher.init(Cipher.ENCRYPT_MODE, key);
     buf = cipher.doFinal(buf); 
     String result = new String(Hex.encodeHex(buf)); 
     result = result.toUpperCase(); 
     return result;
}

// ensure block size of 32
public static String padRightToMod(String text, int mod) {
    if (text == null || mod <= 0) {
        return text;
    }
    final int len = text.length();
    StringBuilder buf = new StringBuilder(512);
    buf.append(text);
    for (int i = len; i % mod > 0; i++) {
        buf.append(" ");
    }
    String rs = buf.toString();
    System.out.println(rs.length());
    return rs;
}

// Call to the encrypt function 

   String encText = encryptData("Hello", HEX_KEY);

результат CC0AC95B5FFD4758DBFA40F909C285F0F86A8F19ED1A12C1BFC098348A2AC683

1009 * И с этим яваскрипта код
crypto = require('crypto');

function encrypt(data,key) {
var cipher = crypto.createCipher('**aes-128-ecb**', key); //create aes cipher 
var encrypted = cipher.update(data,'utf8', 'hex'); //output as hex
return encrypted;
}

function padRightTo32(str) // ensure block size of 32
  {
    len=str.length;
    for(i=len; i%32>0; i++){
    str=str +" ";
  }
  return str;
 }

// call to encryption function
hexkey="3b6ce332ca3b6519eac769710f41ca5c"
encStr=encrypt(padRightTo32("Hello"),hexKey);
console.log(encStr);

результат 1B928CF3C18D53BA5138DD1484D181939FD2B7BB2A17AE6A79664488B5C12652

1014 * ==== Обновление ======

Я пытался https://github.com/Snack-X/rijndael-js реализация формы GitHub с этим кодом

const Rijndael = require("./node_modules/node-rijndael-master");
function padRightTo32(str)
{
    len=str.length;

    for(i=len; i%32>0; i++){
        str=str +" ";
    }
    console.log(str);
    console.log(str.length);
return str;
}
let key = "3b6ce332ca3b6519eac769710f41ca5c";
let original = padRightTo32("Hello");
let cipher = new Rijndael(key, "ecb");
let ciphertext = cipher.encrypt(original, 128);
console.log(ciphertext.toString("hex"));

Я получаю этот результатПопытка размера блока 256 также не помогает.

что мне не хватает, что приводит к другому выводу?

1 Ответ

0 голосов
/ 26 февраля 2019

Что касается вашего ключа, вы должны преобразовать свою шестнадцатеричную строку в двоичные данные, используя буфер (см., Например, Шифрование двоичных данных с помощью aes-ecb на node.js ).

Кроме того,Вы должны использовать метод crypto.createCipheriv для создания экземпляра шифра (см., например, https://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv_options). Используемый в настоящее время (не рекомендуется) метод crypto.creataCipher ожидает пароль и генерирует ключ из пароля (см., например, https://nodejs.org/api/crypto.html#crypto_crypto_createcipher_algorithm_password_options).

Следующий код

crypto = require('crypto');

function encrypt(data,key) {
    var cipher = crypto.createCipheriv('aes-128-ecb', key,''); //create aes-128 cipher 
    var encrypted = cipher.update(data,'utf8', 'hex'); //output as hex
    return encrypted;
}

function padRightTo32(str) { // ensure block size of 32

    len=str.length;
    for(i=len; i%32>0; i++) {
        str=str +" ";
    }
    return str;
}

// call to encryption function
var hexKey = new Buffer('3b6ce332ca3b6519eac769710f41ca5c', 'hex'); // 16 Byte-key
encStr=encrypt(padRightTo32("Hello"),hexKey);
console.log(encStr);  

имеет вывод

cc0ac95b5ffd4758dbfa40f909c285f0f86a8f19ed1a12c1bfc098348a2ac683

, который равен выводу кода Java.

В Java длинаключ определяет используемый AES-вариант, например, если вы выбираете 16-байтовый ключ, используется AES-128, если выбран 32-байтовый ключ, используется AES-256. В коде nodejs вы должны явно указывает вариант AES, то есть aes-128-ecb для 16-байтового ключа и aes-256-ecb для 32-байтового ключа и т. д.

Как уже упоминалось в комментариях ECB в 't безопасный режим (см., например, https://crypto.stackexchange.com/questions/20941/why-shouldnt-i-use-ecb-encryption).

Я не знаю, действительно ли существует разница между Rijndael/ECB/NoPadding и AES/ECB/NoPadding conпроверка шифрования в Java.В моих тестовых случаях, по крайней мере, результаты идентичны.Таким образом, для nodejs-кода должен работать выбор aes-128-ecb (для 16-байтового ключа) или aes-256-ecb (для 32-байтового ключа).

...