Java с использованием шифрования AES 256 и 128 с симметричным ключом

Я новичок в технологии шифрования. Я нашел этот код для Symmetric Encryption.

byte[] key = //... secret sequence of bytes
byte[] dataToSend = ...
Cipher c = Cipher.getInstance("AES");
SecretKeySpec k = new SecretKeySpec(key, "AES");
c.init(Cipher.ENCRYPT_MODE, k);
byte[] encryptedData = c.doFinal(dataToSend);

Работает. Здесь я могу использовать свой собственный пароль. И вот что мне нужно. Но я не знаю, как сделать 128 или 256 симметричных Enctryption. Как я могу использовать 128 и 256 ключей в свой код?

Ответ 1

Использует ли AES режим 128 или 256 бит, зависит от размера вашего ключа, который должен иметь длину 128 или 256 бит. Как правило, вы не используете свой пароль в качестве ключа, потому что пароли редко имеют точную длину по мере необходимости. Вместо этого вы получаете ключ шифрования с вашего пароля, используя некоторую функцию деривации ключей.

Очень простой пример: возьмите MD5 своего пароля, чтобы получить 128-битный ключ. Если вы хотите использовать 256-битный ключ, вы можете использовать SHA-256 для получения 256-битного хэша вашего пароля. Функции вывода ключей обычно запускают это хеширование в несколько сотен раз и используют дополнительную соль. Подробнее см. http://en.wikipedia.org/wiki/Key_derivation_function.

Также обратите внимание: для запуска шифрования более сильного, чем 128-битного, вам нужно будет загрузить и установить "Расширение Java Cryptography Extension (JCE) Неограниченные сильные файлы политики юрисдикции 6" из http://www.oracle.com/technetwork/java/javase/downloads/index.html.

Ответ 2

Ответ на 128 бит

Следующий метод заключается в шифровании строки (valueEnc) с помощью AES-шифрования:

private static final String ALGORITHM = "AES"; 

public String encrypt(final String valueEnc, final String secKey) { 

    String encryptedVal = null;

    try {
        final Key key = generateKeyFromString(secKey);
        final Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.ENCRYPT_MODE, key);
        final byte[] encValue = c.doFinal(valueEnc.getBytes());
        encryptedVal = new BASE64Encoder().encode(encValue);
    } catch(Exception ex) {
        System.out.println("The Exception is=" + ex);
    }

    return encryptedVal;
}

Следующий метод расшифрует зашифрованную строку AES (encryptedVal):

    public String decrypt(final String encryptedValue, final String secretKey) {

    String decryptedValue = null;

    try {

        final Key key = generateKeyFromString(secretKey);
        final Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.DECRYPT_MODE, key);
        final byte[] decorVal = new BASE64Decoder().decodeBuffer(encryptedValue);
        final byte[] decValue = c.doFinal(decorVal);
        decryptedValue = new String(decValue);
    } catch(Exception ex) {
        System.out.println("The Exception is=" + ex);
    }

    return decryptedValue;
}

secKey - это 128-битный ключ, который закодирован в BASE64Encoder. BASE64Decoder в следующем методе генерирует соответствующий 128-битный ключ

private Key generateKeyFromString(final String secKey) throws Exception {
    final byte[] keyVal = new BASE64Decoder().decodeBuffer(secKey);
    final Key key = new SecretKeySpec(keyVal, ALGORITHM);
    return key;
}

Ответ 3

Вы можете использовать простой объект KeyGenerator следующим образом:

KeyGenerator generator = KeyGenerator.getInstance("AES/CTR/PKCS5PADDING");
generator.init(128);
SecretKey key = generator.generateKey();
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
...

Ответ 4

Из Документы Java для Cipher.init(...):

public final void init (int opmode,                        Key key)

Броски:     InvalidKeyException - если данный ключ не подходит для инициализации этот шифр, или если этот шифр инициализируется для дешифрования и требует параметров алгоритма, которые не может быть определено из данного ключ, или если заданный ключ имеет ключи который превышает максимально допустимый keyizes (как определено из настроенные файлы политики политики).

Для меня это означает, что, как сказал Martijn Courteaux в своем комментарии, вы должны использовать ключ из 256 бит (т.е. инициализировать SecretKeySpec с байтовым массивом, содержащим 32 байта), и шифр примет его и будет использовать, или отклонить его и выбросить исключение, если его размер неприемлем.

Если вы получаете исключение, возможно, потому, что вы не установили криптографические файлы с неограниченной силой (по умолчанию JDK-установка позволяет 128-битные ключи, как описано в этом crypto spec document). Загрузите неограниченный силовой пакет crypto здесь.

Ответ 5

public class CipherUtils
{
    private static byte[] key = {
            0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79
    };//"thisIsASecretKey";

    public static String encrypt(String strToEncrypt)
    {
        try
        {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
            return encryptedString;
        }
        catch (Exception e)
        {
           e.printStackTrace();
        }
        return null;
    }
}