Можно ли расшифровать шифрование AES256 на Java без неограниченного количества файлов JCE?

Проект, над которым я работаю, имеет сегмент, который требует шифрования и дешифрования AES. Из всего возможного интернет-источника, который я мог найти, было сложно найти ссылку на шифрование AES256, не загружая и не устанавливая файлы UnCE с неограниченной силой с Sun (теперь на веб-сайте Oracle). Помимо любых юридических проблем, которые существуют с их распределением, это не помогает нам очень практически, когда дело доходит до того, чтобы конечный пользователь посетил конкретный веб-сайт и загрузил некоторые файлы, поместил их в каталог и затем добавил вещи в путь к классам, если на Windows и т.д.

В Интернете было несколько ссылок на легкий API-интерфейс BountyCastle, который, возможно, не требовал файлов JCE, но я не мог найти очень релевантную ссылку или пример, продемонстрировавший это.

Не уверен, но это проблема с любым другим языком программирования?

Если не возможно иметь 256-битное шифрование AES без тех, где установлены эти JCE файлы, может ли подход JNI помочь?

Чтобы разработать бит, можно ли шифрование AES 256 выполнить на C/С++, а затем я могу вызвать тех, кто использует JNI, чтобы получить желаемые результаты? Будет ли упаковка программного обеспечения (как файла jar) вызывать беспокойство или могут возникнуть другие проблемы?

Еще один важный фактор, который приходит в игру, заключается в том, что проект будет работать как на Mac, так и на Windows, поэтому могут быть ограничения с использованием C/С++ (конкретные версии компилятора/интерпретатора или что-то еще)?

Есть ли другой способ справиться с этим? Любой другой подход (ы)?

Ответ 1

Ограничения по размеру ключа реализованы в классе Cipher Java. Можно использовать любой другой класс, который реализует AES для получения функциональности AES-256. Например, можно использовать "легкий" API Bouncy Castle для использования ключевых размеров любой силы. В этом случае вы можете, например, используйте org.bouncycastle.crypto.engines.AESFastEngine напрямую (и mode и a padding по-прежнему можно использовать обычный .jar для Bouncy Castle, но вы не будете использовать Функциональность JCA поставщика BouncyCastle.

Это имеет некоторые недостатки и преимущества. Легкий Bouncy Castle API несколько ниже уровня функциональности JCA, добавленного в классы Sun провайдером "BC". Кроме того, многие компоненты (такие как уровень SSL в Java, JSSE или библиотеки шифрования XML) используют JCA для обеспечения требуемой криптографической функциональности. Библиотеки, требующие функциональности JCA, по-прежнему будут ограничены размерами ограниченного ключа.

Обратите внимание, что использование других поставщиков не будет работать, поскольку сам класс Cipher проверяет размер ключа. Классы реализации CipherSpi, которые могут содержаться в JCA-провайдере, не могут (положительно) влиять на допустимые размеры ключей. Вы можете использовать только классы реализации.

Ответ 2

Прежде всего, это не проблема с каждой средой программирования. OpenSSL, который написан на C, поддерживает большие клавиши, например. Из опыта работы как с JCE, так и с JNI я бы предположил, что вы нашли способ использовать чистую Java вместо загрузки собственной библиотеки через JNI. Это намного проще.

Практическое решение: Установлено ли ваше приложение с помощью какого-либо приложения-установщика во время установки? Если это так, то одним из решений может быть использование этого установщика для установки JCE.

BouncyCastle, к сожалению, также использует JCE, как указано в их часто задаваемых вопросах.

ОБНОВЛЕНИЕ 1: Я нашел эту библиотеку, которая может быть тем, что вы ищете. Похоже, что он больше не поддерживается: http://www.cryptix.org/

ОБНОВЛЕНИЕ 2: GNU имеет библиотеку, которая реализует AES256: http://www.gnu.org/software/gnu-crypto/. Подробнее о доступных шифрах здесь: http://www.gnu.org/software/gnu-crypto/manual/Ciphers.html

Пример кода с использованием GNU-Crypto с учетом того, что ваш ключ уже загружен в key_bytes:

IBlockCipher cipher = CipherFactory.getInstance("AES");
Map attributes = new HashMap();
attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, new Integer(16));
attributes.put(IBlockCipher.KEY_MATERIAL, key_bytes);
cipher.init(attributes);
int bs = cipher.currentBlockSize();

for (int i = 0; i + bs < pt.length; i += bs)
{
    cipher.encryptBlock(pt, i, ct, i);
}

for (int i = 0; i + bs < cpt.length; i += bs)
{
    cipher.decryptBlock(ct, i, cpt, i);
}

Пожалуйста, убедитесь, что вы используете криптографически безопасный генератор случайных чисел, например SecureRandom, чтобы создать 256 байтов для ключа:

byte[] seed = xxx; // Be sure to get a good new seed on every client machine.
SecureRandom random = new SecureRandom(seed);
byte[] key_bytes = new byte[256];
random.nextBytes(key_bytes);