cryptojs aes 256 шифрование и расшифровка java

Я зашифровал сообщение с помощью cryptojs aes 256 на стороне клиента. Но не смог расшифровать его на стороне java. Сначала я передаю ключ непосредственно на сервер как шестнадцатеричный, а затем конвертирую его из шестнадцатеричного в java bytearray. Это не сработало. Затем я передаю серверу фразу salt, iv как шестнадцатеричную. Затем сгенерируйте ключ. Это все еще не сработало. Всегда жаловаться на неправильную длину ключа.

Сторона клиента:

var salt = CryptoJS.lib.WordArray.random(16);
var salt_hex = CryptoJS.enc.Hex.stringify(salt);

var iv = CryptoJS.lib.WordArray.random(256/32);
var iv_hex = CryptoJS.enc.Hex.stringify(iv);


var key = CryptoJS.PBKDF2(secret, salt, { keySize: 256/32, iterations: 10 });
var key_hex=CryptoJS.enc.Hex.stringify(key);

var encrypted = CryptoJS.AES.encrypt(plaintext, key, { iv: iv });    

var encryptedtxt = secret+":"+salt_hex+":"+iv_hex+":"+encrypted.ciphertext.toString(CryptoJS.enc.Base64)+":"+key_hex;

Сторона сервера:

    if (encrypted != null)
    {
        //Get the passphras, salt, IV and msg
        String data[] = encrypted.split(":");
        String passphrase = data[0];
        String salt_hex = data[1];
        String iv_hex = data[2];
        String msg64 = data[3];
        String jskey_hex = data[4];
        byte[] jskey = hexStringToByteArray(jskey_hex);
        byte[] iv = hexStringToByteArray(iv_hex);
        byte[] salt = hexStringToByteArray(salt_hex);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] msg = decoder.decodeBuffer(msg64);

        try {
             //theClear = AES.decrypt(encrypted);
            /* Decrypt the message, given derived key and initialization vector. */
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), salt, 10, 256/32);
            SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            String plaintext = new String(cipher.doFinal(msg), "UTF-8");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

person rickcoup    schedule 25.06.2014    source источник
comment
Если длина ключа неправильная, проблема может заключаться в начальных нулях. Преобразует ли метод stringify() [0x01, 0x02, 0x03] в "123"? Ваш код дешифрования, вероятно, предполагает "010203". "123", вероятно, выдаст двухбайтовый массив [0x12, 0x03], который не соответствует вводу и имеет неправильную длину. Это фатально для криптографического ключа.   -  person rossum    schedule 25.06.2014
comment
256/32 == 8, а поддерживаемые размеры ключей для AES - 16, 24 или 32 байта. Вам нужно будет изменить код JS и Java, чтобы использовать ключ длиной не менее 16 байт.   -  person Oleg Estekhin    schedule 25.06.2014
comment
rossum - шестнадцатеричный строковый ключ похож на 010203. Но я делаю шестнадцатеричное декодирование на стороне Java в байтовый массив. Интересно, как массив слов на JS совпадает с массивом байтов на java?   -  person rickcoup    schedule 25.06.2014
comment
Ваш IV также имеет неверный размер в CryptoJS. AES использует 128-битные блоки, поэтому IV также должен быть 128-битным.   -  person Maarten Bodewes    schedule 26.06.2014
comment
Оулстед - Вы абсолютно правы по поводу IV. Меняем это.   -  person rickcoup    schedule 26.06.2014


Ответы (1)


Наконец разобрался. По умолчанию JRE 7 не поддерживает 256-битный ключ. Мне пришлось загрузить новые банки с сайта http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html и перезапишите их в папке jre / lib / security. Вам придется проделать то же самое для Websphere 6 или 7. Если вы этого не сделаете, появится запрос «Неверный размер ключа». Я также видел «недопустимый размер ключа x», где x - это число. Значит, размер ключа не тот. Ниже приведен код.

Сторона сервера:

//@Override
public String getClearText() throws IOException {
    // Get the body
    String encrypted = super.getParameter("aes"); //base64

    if (encrypted != null)
    {
        //Get the passphras, salt, IV and msg
        String data[] = encrypted.split(":");
        String passphrase = data[0];
        String salt_hex = data[1];
        String iv_hex = data[2];
        String msg64 = data[3];
        String jskey_hex = data[4];
        byte[] jskey = hexStringToByteArray(jskey_hex);
        byte[] iv = hexStringToByteArray(iv_hex);
        byte[] salt = hexStringToByteArray(salt_hex);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] msg = decoder.decodeBuffer(msg64);
        String plaintext = "";
        try {
            SecretKey key = new SecretKeySpec(jskey, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            plaintext = new String(cipher.doFinal(msg), "UTF-8");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("in filter, decrypted: " +plaintext);
    }
    return plaintext;
}

Клиент:

$(function() {

$('#test').on('submit', function() {

var plaintext = $('#text').val();
var secret = '0123456789abcdef';

var salt = CryptoJS.lib.WordArray.random(16);
var salt_hex = CryptoJS.enc.Hex.stringify(salt);

var iv = CryptoJS.lib.WordArray.random(16);
var iv_hex = CryptoJS.enc.Hex.stringify(iv);


var key = CryptoJS.PBKDF2(secret, salt, { keySize: 256/32, iterations: 1 });
//var key_hex=CryptoJS.enc.Hex.stringify(key);
var key_hex= key;

var encrypted = CryptoJS.AES.encrypt(plaintext, key, { iv: iv });    


//decrypt
var decrypted = CryptoJS.AES.decrypt(
      encrypted,
      CryptoJS.enc.Hex.parse(key_hex),
      { iv: CryptoJS.enc.Hex.parse(iv_hex) });

var text = decrypted.toString( CryptoJS.enc.Utf8 );
//console.log(encrypted);

// ----- base64 encoding ----------
var encryptedtxt =     secret+":"+salt_hex+":"+iv_hex+":"+encrypted.ciphertext.toString(CryptoJS.enc.Base64)+":"+key_hex;
console.log('html - ciphere txt : ' +encryptedtxt);

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

post ('/E2Efilter/TheServlet', encryptedtxt);
return false;
});
person rickcoup    schedule 26.06.2014
comment
Похоже, вы храните свой ключ со всеми другими параметрами (iv / salt / зашифрованные данные), так почему вы вообще зашифровали? Злоумышленник может так же легко расшифровать данные. - person Elad Nava; 15.11.2014