#java #encryption #cryptography #aes #rijndael
#java #шифрование #криптография #aes #rijndael
Вопрос:
По определенным причинам мне нужно реализовать удаление / сжатие Rijndael с размером блока 256 бит вместо AES, который использует размер блока 128 бит (причина: данные шифруются в PHP с использованием Rijndael …).
Как я могу изменить размер блока для шифрования?
Если я просто получу шифр с помощью "RIJNDAEL/CFB/PKCS5Padding"
и попытаюсь инициализировать IV с 256 битами, я получу исключение, потому что размер блока составляет всего 128 бит.
Комментарии:
1. Вероятно, вам придется убедиться, что у вас установлены классы шифрования Java JCE unlimited. Они не являются частью типичного стандартного дистрибутива Java, потому что они незаконны в некоторых странах.
2. они у всех уже есть. все еще не могу выяснить, как получить зашифрованный объект с требуемым размером блока
3. Тогда я полагаю, что у @ GregS есть ответ. Я полагал, что Rijndael-256 является частью JCE Unlimited Providers, но я привык использовать несколько настроенную Java моей компании, для которой есть поставщик JCE, но это вполне может быть частная реализация.
4. Вы должны удалить AES из названия, AES были стандартизированы только с 128-битным блоком. Безопасность Rijndael с 256-битными блоками недостаточно изучена и вполне может быть намного слабее, чем AES. Какая бы причина, по которой вам пришлось использовать Rijndael с 256-битными блоками, вряд ли была хорошей.
Ответ №1:
Ни один из поставщиков Sun JCE не поддерживает ничего, кроме Rijndael со 128-битным размером блока: это алгоритм AES. Чтобы получить rijndael с 256-битным размером блока, вам придется обратиться куда-нибудь еще. Я предлагаю библиотеку Bouncycastle java. Класс RijndaelEngine имеет конструктор, который принимает размер блока в битах. Большинство людей считают, что класс PaddedBufferedBlockCipher более удобен при использовании с подходящим заполнением, например
PaddedBufferedBlockCipher c = new PaddedBufferedBlockCipher(new RijndaelEngine(256), new PKCS7Padding());
Ответ №2:
Обратите внимание, что PHP mcrypt использует заполнение нулевыми байтами, поэтому new ZeroBytePadding()
следует использовать вместо new PKCS7Padding()
.
Ниже приведена полная реализация с использованием CBC
и RIJNDAEL 256
.
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.RijndaelEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.paddings.ZeroBytePadding;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.encoders.Base64;
public static String encryptWithAesCBC(String plaintext, String key, String iv)
{
try {
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), new ZeroBytePadding());
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key.getBytes()), iv.getBytes());
cipher.init(true, ivAndKey);
return new String(Base64.encode(cipherData(cipher, plaintext.getBytes())));
} catch (InvalidCipherTextException e) {
throw new RuntimeException(e);
}
}
public static String decryptWithAesCBC(String encrypted, String key, String iv)
{
try {
byte[] ciphertext = Base64.decode(encrypted);
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), new ZeroBytePadding());
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key.getBytes()), iv.getBytes());
aes.init(false, ivAndKey);
return new String(cipherData(aes, ciphertext));
} catch (InvalidCipherTextException e) {
throw new RuntimeException(e);
}
}
private static byte[] cipherData(PaddedBufferedBlockCipher cipher, byte[] data) throws InvalidCipherTextException
{
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
int actualLength = length1 length2;
byte[] cipherArray = new byte[actualLength];
for (int x = 0; x < actualLength; x ) {
cipherArray[x] = outBuf[x];
}
return cipherArray;
}
private String md5(String string)
{
try {
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
byte[] array = md.digest(string.getBytes());
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; i) {
sb.append(Integer.toHexString((array[i] amp; 0xFF) | 0x100).substring(1, 3));
}
return sb.toString();
} catch (java.security.NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
При использовании CFB PaddedBufferedBlockCipher
следует заменить следующим:
PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CFBBlockCipher(new RijndaelEngine(256),8), new ZeroBytePadding());
// PHP mcrypt uses a blocksize of 8 bit for CFB
Использование:
String salt = "fbhweui3497";
String key = md5(salt);
String iv = md5(md5(salt));
String encrypted = encryptWithAesCBC("text to encript", key, iv);
String decrypted = decryptWithAesCBC(encrypted, key, iv);
Комментарии:
1. Не могли бы вы, пожалуйста, предоставить md5()? Строка md5(Строковый ввод) { String result = ввод; MessageDigest md; попробуйте { md = MessageDigest.getInstance(«MD5»); md.update(input.getBytes()); BigInteger hash = новый BigInteger(1, md.digest()); результат = hash.toString(16); в то время как (результат. длина () < 32) { // 40 для SHA-1 результат = «0» результат; } } catch (исключение NoSuchAlgorithmException e) { e.printStackTrace(); } возвращает результат; } Приведенный выше метод выдает: » java.lang. Исключение IllegalArgumentException: длина ключа не 128/160/192/224/256 бит.»
2. @Krish Я только что добавил к ответу реализацию md5.