2017-01-16 3 views
1

Мне нужно реализовать шифрование AES с использованием JavaScript. Использовал AES/CBC/NoPadding Mode и создал метод для завершения 16 блоков длины. Я уже решил это с помощью Java. Это выглядит следующим образом:AES Шифрование с использованием CryptoJS

public static String encrypt(byte[] key, byte[] initVector, String value) { 
    try { 
     IvParameterSpec iv = new IvParameterSpec(initVector); 
     SecretKeySpec skeySpec = new SecretKeySpec(key, "AES"); 
     Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 
     byte[] encrypted = cipher.doFinal(completeBlocks(value)); 
     return Base64.encodeBase64String(encrypted); 
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException ex) { 
     System.out.println("Error: " + ex); 
    } 

    return null; 
} 

/** 
* Completes 16 lenght blocks 
* 
* @param message 
* 
* 
*/ 
static byte[] completeBlocks(String message) { 
    try { 

     int bytesLenght = message.getBytes("UTF-8").length; 
     if (bytesLenght % 16 != 0) { 
      byte[] newArray = new byte[bytesLenght + (16 - (bytesLenght % 16))]; 
      System.arraycopy(message.getBytes(), 0, newArray, 0, bytesLenght); 
      return newArray; 
     } 

     return message.getBytes("UTF-8"); 

    } catch (UnsupportedEncodingException ex) { 
     System.out.println("" + ex); 
    } 
    return null; 
} 

public static void main(String[] args) { 

    String key = "253D3FB468A0E24677C28A624BE0F939"; 
    String strToEncrypt = "My Secret text"; 
    final byte[] initVector = new byte[16]; 
    String resultado = encrypt(new BigInteger(key, 16).toByteArray(), initVector, strToEncrypt.trim()); 
    System.out.println("ENCRYPTED:"); 
    System.out.println(resultado); 
} 

С входами key = 253D3FB468A0E24677C28A624BE0F939, strToEncrypt = "My Secret text" и Ceros IV. Он бросает

7StScX3LnPUly/VNzBes0w ==

Я знаю, что желаемый результат. Это верно! Я попытался воспроизвести это с помощью JavaScript. Я использовал библиотеку CryptoJs. Но я не смог произвести такой же вывод Java. Я судимый:

var text = "My Secret text"; 
var key = CryptoJS.enc.Base64.parse("253D3FB468A0E24677C28A624BE0F939"); 
var iv = CryptoJS.enc.Base64.parse("    "); 
var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv}); 
console.log(encrypted.toString()); 

var decrypted = CryptoJS.AES.decrypt(encrypted, key, {iv: iv}); 
console.log(decrypted.toString(CryptoJS.enc.Utf8)); 

Используя те же входы, я получаю De+CvPVIyiBX2//EE6gXTg== в качестве вывода. Что я делаю не так? Как я могу получить такой же Java-выход? Большое спасибо!!

+0

Он выглядит cryptojs не поддерживает режим CBC. –

+0

Кроме того, ваш ключ задается как hex, а не base64, и предоставление пробелов base64 не совпадает с массивом нулей. –

+0

@TamasHegedus Я думаю, что ты прав! Похоже, что режим CBC не поддерживается. Я нашел это: https://github.com/ricmoo/aes-js. Похоже, он поддерживает режим CBC. Я собираюсь попробовать это! Большое спасибо! –

ответ

4

Предполагая, что вы будете фиксировать такие вещи, как пустой IV &, что это доказательство концепции, ваш код не потому, что:

  1. Вы не используют отступы в Java, вам нужно использовать то же самое в JS
  2. вручную накладка с нулями в Java, вам нужна сделать то же самое в JS
  3. вы base64 расшифровать ключ Бца его не base64 (его шестнадцатеричную строка байт)
  4. Java-IV представляет собой массив нулей, но в JS вы используете пробелы (и ошибочно относитесь к нему как base64).

Чтобы дублировать выход в JS:

CryptoJS.pad.NoPadding = {pad: function(){}, unpad: function(){}}; 

var text = "My Secret text\0\0"; 
var key = CryptoJS.enc.Hex.parse("253D3FB468A0E24677C28A624BE0F939"); 
var iv = CryptoJS.enc.Hex.parse("00000000000000000000000000000000"); 

var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv, padding: CryptoJS.pad.NoPadding}); 
console.log(encrypted.toString()); 

Для:

7StScX3LnPUly/VNzBes0w ==

+0

Минуты поздно. Он забрал меня на заказ. –

+1

Также я хотел бы указать, что пользовательская функция заполнения ошибочна, поскольку при вызове 'getBytes' нескольких мест используется различная кодировка. –

+0

@Alex K. Это выглядит довольно красиво !! У меня есть одно сомнение! Как я могу снова расшифровать это? !! Благодаря! Я попробовал: 'var decrypt = CryptoJS.AES.decrypt (зашифрованный, ключ, {iv: iv});' –