Java шифрует AES, PHP расшифровывает AES

#java #php #encryption #cryptography #aes

#java #php #шифрование #криптография #aes

Вопрос:

Я искал способ зашифровать строку в Java и расшифровать ее в PHP. Я нашел это в ответе где-то на Stackoverflow и изменил его, чтобы сделать прямо противоположное. Это мой код для шифрования на Java:

 public static String encrypt(String data, String initialVectorString, String secretKey) {
        String encryptedData = null;
        try {
            SecretKeySpec skeySpec = new SecretKeySpec(md5(secretKey).substring(0, 16).getBytes(), "AES");
            IvParameterSpec initialVector = new IvParameterSpec(initialVectorString.getBytes());
            Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, initialVector);
            byte[] encrypted = cipher.doFinal(data.getBytes());
            byte[] base64encrypted = (new org.apache.commons.codec.binary.Base64()).encode(encrypted);
            encryptedData = new String(base64encrypted, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encryptedData;
    }
 

и это мой код для расшифровки на PHP:

 function decrypt($message, $initialVector, $secretKey) {
        return (
        mcrypt_decrypt( 
        MCRYPT_RIJNDAEL_128,
        substr(md5($secretKey), 0, 16),
        base64_decode($message),  
        MCRYPT_MODE_CFB,
        $initialVector
        )
        );
    }
 

Секретный ключ и начальный вектор меняются каждый раз.
Код работает в течение 90% времени, но иногда он только частично расшифровывает строку, а остальные символы нечитаемы, например: Microsoft Windows [Version 10.0.1��× что должно сказать Microsoft Windows [Version 10.0.14393] . Я допустил какие-либо ошибки, изменяя код?

РЕДАКТИРОВАТЬ: возможно, мне потребуется добавить, что дешифрование в Java с использованием кода из приведенной выше ссылки ДЕЙСТВИТЕЛЬНО работает.

EDIT2: Найден ответ, это была глупая ошибка, PHP получил в зашифрованной строке base64 как пробел. Спасибо за всю вашу помощь, я все равно буду использовать ее.

Комментарии:

1. Происходит ли сбой в 10% случаев в одной и той же строке, т.Е. Передача «Hello world» 10 раз корректно работает только 9 раз из 10? Или вы имеете в виду, что передача 10 разных строк приводит к тому, что одна из них нарушается? Я не уверен, что это ваша проблема, но следует отметить одну вещь: у вас должно быть правильное количество байтов в строке base64. Если у вас нет нужного количества, декодирование может дать вам разные результаты. При необходимости попробуйте добавить отступы в конец строки base64.

2. Этот код действительно небезопасен. Хотя ваш «ключ» содержит 16 символов, но поскольку эти символы являются шестнадцатеричными, каждый из них содержит только 4 бита (вместо 8 бит, если вы на самом деле использовали необработанный двоичный вывод). Итак, ваш ключ имеет только 64 бита, что в настоящее время является принудительным.

3. Лучше не использовать mcrypt, он заброшен, годами не обновлялся. mcrypt имеет много выдающихся ошибок , относящихся к 2003 году. Вместо этого рассмотрите возможность использования defuse или RNCryptor , они предоставляют комплексное решение, поддерживаются и являются правильными.

4. Вероятно, модифицируется строка base 64, поскольку она не была правильно закодирована в URL. Сравните зашифрованный текст и IV перед их декодированием. Обратите внимание, что initialVectorString.getBytes() это также может привести к сбоям, хотя это не приведет к этой конкретной проблеме.

5. Если вы можете использовать все, что вам нравится, тогда вам следует рассмотреть возможность использования RNCryptor . Это действительно безопасно и предоставляет реализации для разных языков, так что вам не нужно думать о специфике криптографических примитивов.