Использование CryptoJS для шифрования в Javascript и расшифровки в Java

Я пытаюсь что-то зашифровать в JavaScript, используя https://code.google.com/p/crypto-js/#AES именно так, как в примере. Проблема в том, что когда я пытаюсь расшифровать его на Java, результат сильно отличается. Единственная разница, которую я вижу, это заполнение (CryptoJs использует Pkcs7, тогда как java использует Pkcs5). Немного почитав, я понял, что Pkcs7 и Pkcs5 в основном одинаковы.

Вот пример кода, который я шифрую в Javascript:

var crypto = require('./aes.js');
var login = 'ABCD';
var key = crypto.CryptoJS.enc.Hex.parse('0123456789012345');
var ive  = crypto.CryptoJS.enc.Hex.parse('0123456789012345');

var encrypted = crypto.CryptoJS.AES.encrypt(login, key, {iv: ive});
console.log('encrypted msg = ' + encrypted)

Это код, который я использую в Java для его расшифровки:

public String decrypt(byte[] cipherText) throws Exception {

    String psk = "0123456789012345";
    String iv = "0123456789012345";
    try {
        String encryptionKey = psk;
        final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
        final SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes(UTF8), "AES");
        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes(UTF8)));
        return new String(cipher.doFinal(cipherText), UTF8);
    } catch (BadPaddingException | IllegalBlockSizeException | UnsupportedEncodingException | InvalidAlgorithmParameterException | InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | NoSuchProviderException ex) {
        LOG.log(Level.SEVERE, ex.getMessage(), ex);
        throw new Exception(ex.getMessage());
    }
}

У вас есть идеи, почему это так плохо? Это другой алгоритм или я ошибаюсь где-то еще?


person mdagis    schedule 19.10.2015    source источник


Ответы (2)


Вы не используете один и тот же ключ и IV в CryptoJS и Java. Ключ и IV в CryptoJS слишком короткие, чтобы быть действительными, потому что вы анализируете 16-символьную строку как Hex, что дает только 8 байтов, но AES поддерживает только размеры ключа 128, 192 и 256 бит.

Использовать

var key = crypto.CryptoJS.enc.Utf8.parse('0123456789012345');
var ive  = crypto.CryptoJS.enc.Utf8.parse('0123456789012345');

Другие соображения:

  • Всегда используйте случайный IV. Поскольку он не обязательно должен быть секретным, вы можете добавить его к зашифрованному тексту или отправить другим способом.

  • Аутентифицируйте зашифрованные тексты с помощью HMAC или используйте режим аутентификации, такой как GCM, чтобы предотвратить некоторые атаки, такие как атака оракула заполнения.

person Artjom B.    schedule 19.10.2015
comment
Это хороший момент. Тем не менее, проблема все еще существует. У меня есть алгоритм Java, который шифрует строку ABCD с теми же настройками, что и тот, который я опубликовал ранее, который выполняет расшифровку. Странно то, что результатом шифрования Java является массив байтов со следующими байтами: 534A5782E4AB47B71C4DC7AFB5A64F5C Зашифрованная строка из CryptoJS — U0pXguSrR7ccTcevtaZPXA== - person mdagis; 20.10.2015
comment
Вы не показали часть своего кода, где вы анализируете результат из CryptoJS. Обратите внимание, что один кодируется в шестнадцатеричном формате, а другой — в кодировке Base64. Довольно легко заметить разницу, не заглядывая в документацию или исходный код. - person Artjom B.; 20.10.2015
comment
Используя enc.Utf8.parse, javascript генерирует =U0pXguSrR7ccTcevtaZPXA==, но не может сделать его кратным 16, как того требует метод java. Кто-нибудь может помочь? - person user1767316; 30.08.2016
comment
хорошо: вы должны добавить, как эффективно расшифровывать сгенерированный код: decrypt(new Base64().decode(U0pXguSrR7ccTcevtaZPXA.getBytes()))) удаление начального и конечного =, поскольку это не очевидно. (здесь используется apache common base64) - person user1767316; 30.08.2016
comment
@user1767316 user1767316 Я не знаю, как вы создали свой =U0pXguSrR7ccTcevtaZPXA== и каким он должен быть. Вы должны задать новый вопрос со всеми подробностями. Stack Overflow — это не форум. - person Artjom B.; 31.08.2016

Хорошо, я нашел проблему. Вместо передачи в качестве параметра encrypted я должен передать encrypted.ciphertext. У меня сейчас работает идеально.

person mdagis    schedule 19.10.2015
comment
как вы передаете зашифрованный текст на сервер? - person kavi; 28.08.2020