Как расшифровать зашифрованную строку AES-256 из CryptoJS с помощью Java?

У меня есть шифрованная строка AES-256 от CryptoJS с парольной фразой. Мне нужно расшифровать его на Java, но не могу понять, как это сделать. Кажется, что вам нужно IV, ключ и соль для расшифровки, и, как и в главной странице CryptoJS , зашифрованные данные уже содержат все их, и CryptoJS может каким-то образом разобрать их из зашифрованного ввода.

Кто-нибудь знает, как это сделать? Я видел так много примеров о CryptoJS – шифровании / расшифровке Java, но большинство из них использует hardcoded IV / key или просто отправляют IV / key с стороны cryptoJS на Java. Все, что у меня есть, фраза, как и то, что делает этот сайт !

Когда сообщение зашифровывается таким образом:

 CryptoJS.AES.encrypt("message", "passphrase") 

используется подход, основанный на пароле. Для этого CryptoJS генерирует новую соль и использует эту соль в сочетании с парольной фразой для получения ключа и IV (я написал функцию деривации для этого вопроса ).
После создания зашифрованного текста специальный кодировщик OpenSSL используется для кодирования зашифрованного текста, включая используемую соль:

 var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); 

Вам может понадобиться декодировать закодированную строку Base64, чтобы получить массив байтов, если он. Затем вы можете проверить соответствие заголовка:

 byte[] ctBytes = Base64.getDecoder().decode(ciphertext.getBytes("UTF-8")); System.out.println("Is salted: " + new String(Arrays.copyOf(ctBytes, 8)).equals("Salted__")); 

После этого вы сможете получить из него соль и зашифрованный текст:

 byte[] saltBytes = Arrays.copyOfRange(ctBytes, 8, 16); byte[] ciphertextBytes = Arrays.copyOfRange(ctBytes, 16, ctBytes.length); 

Вывести ключ + IV:

 byte[] key = new byte[keySize/8]; byte[] iv = new byte[ivSize/8]; EvpKDF(password.getBytes("UTF-8"), keySize, ivSize, saltBytes, key, iv); 

И расшифруйте зашифрованный текст:

 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv)); byte[] recoveredPlaintextBytes = cipher.doFinal(ciphertextBytes); String recoveredPlaintext = new String(recoveredPlaintextBytes); 

Полный полный код:

 public static void main(String[] args) throws UnsupportedEncodingException, GeneralSecurityException { String ciphertext = "U2FsdGVkX1+0m/gle/XQX1shjnpveUrl1fO3oOlurPMlTks6+oQlEPfOrucihzEz"; String plaintext = "This is some example plaintext"; String password = "This is a very strong password"; int keySize = 256; int ivSize = 128; // var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); byte[] ctBytes = Base64.getDecoder().decode(ciphertext.getBytes("UTF-8")); System.out.println("Is salted: " + Arrays.equals(Arrays.copyOf(ctBytes, 8), new byte[]{0x53, 0x61, 0x6c, 0x74, 0x65, 0x64, 0x5f, 0x5f})); System.out.println("Is salted: " + new String(Arrays.copyOf(ctBytes, 8)).equals("Salted__")); byte[] saltBytes = Arrays.copyOfRange(ctBytes, 8, 16); System.out.println("Salt matches: " + Arrays.equals(saltBytes, hexStringToByteArray("b49bf8257bf5d05f"))); byte[] ciphertextBytes = Arrays.copyOfRange(ctBytes, 16, ctBytes.length); System.out.println("CT matches: " + Arrays.equals(ciphertextBytes, hexStringToByteArray("5b218e7a6f794ae5d5f3b7a0e96eacf3254e4b3afa842510f7ceaee722873133"))); byte[] key = new byte[keySize/8]; byte[] iv = new byte[ivSize/8]; EvpKDF(password.getBytes("UTF-8"), keySize, ivSize, saltBytes, key, iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv)); byte[] recoveredPlaintextBytes = cipher.doFinal(ciphertextBytes); String recoveredPlaintext = new String(recoveredPlaintextBytes); System.out.println("Recovered Plaintext: " + recoveredPlaintext); System.out.println("Expected Plaintext: " + plaintext); } public static byte[] EvpKDF(byte[] password, int keySize, int ivSize, byte[] salt, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException { return EvpKDF(password, keySize, ivSize, salt, 1, "MD5", resultKey, resultIv); } public static byte[] EvpKDF(byte[] password, int keySize, int ivSize, byte[] salt, int iterations, String hashAlgorithm, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException { keySize = keySize / 32; ivSize = ivSize / 32; int targetKeySize = keySize + ivSize; byte[] derivedBytes = new byte[targetKeySize * 4]; int numberOfDerivedWords = 0; byte[] block = null; MessageDigest hasher = MessageDigest.getInstance(hashAlgorithm); while (numberOfDerivedWords < targetKeySize) { if (block != null) { hasher.update(block); } hasher.update(password); block = hasher.digest(salt); hasher.reset(); // Iterations for (int i = 1; i < iterations; i++) { block = hasher.digest(block); hasher.reset(); } System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4, Math.min(block.length, (targetKeySize - numberOfDerivedWords) * 4)); numberOfDerivedWords += block.length/4; } System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4); System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4); return derivedBytes; // key + iv } /** * Copied from https://stackoverflow.com/a/140861 * */ public static byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } return data; } 

Код JavaScript:

 var pw = "This is a very strong password"; var pt = "This is some example plaintext"; var encrypted = CryptoJS.AES.encrypt(pt, pw); encrypted.toString(); // U2FsdGVkX1+0m/gle/XQX1shjnpveUrl1fO3oOlurPMlTks6+oQlEPfOrucihzEz encrypted.salt.toString(); // b49bf8257bf5d05f encrypted.ciphertext.toString(); // 5b218e7a6f794ae5d5f3b7a0e96eacf3254e4b3afa842510f7ceaee722873133 
  • Почему при использовании функции Non-Random IV с режимом CBC существует уязвимость?
  • Хеширование, соль и хранение хешированных значений
  • Шифрование настроек приложения в web.config
  • Обработка криптовых исключений
  • Почему безопасность через неясность - плохая идея?
  • Interesting Posts

    Как создать активность и службу Android, которые используют отдельные процессы

    Шаблонная специализация отдельных участников?

    Выводит как stderr, так и stdout в файл, и только stderr в командной строке

    как загрузить файл и данные json в почтальоне

    Антенна с высоким коэффициентом усиления: установите Wi-Fi-маршрутизатор на одну антенну или два

    как заменить одиночную обратную косую черту в R

    Являются ли массивы Java максимальным?

    Ошибка построения игрока: CommandInvokationFailure: невозможно преобразовать classы в формат dex

    Как скрыть элемент при прокрутке страницы?

    Перемещение папки пользователей в Windows Vista на другой раздел – плохая идея?

    Ошибка загрузки Windows 8 EFI

    Сумма двух дат в Java

    Javascript для преобразования UTC в местное время

    Необходимо обрабатывать неперехваченное исключение и отправлять файл журнала

    Является ли массив примитивным типом или объектом (или чем-то еще полностью)?

    Давайте будем гением компьютера.