Java AES и использование моего собственного Ключа

Я хочу зашифровать строковое использование AES с моим собственным ключом. Но я испытываю затруднения из-за длины в битах ключа. Можете Вы рассматривать мой код и видеть то, что я должен фиксировать/изменять.

public static void main(String[] args) throws Exception {
    String username = "bob@google.org";
    String password = "Password1";
    String secretID = "BlahBlahBlah";
    String SALT2 = "deliciously salty";

    // Get the Key
    byte[] key = (SALT2 + username + password).getBytes();
    System.out.println((SALT2 + username + password).getBytes().length);

    // Need to pad key for AES
    // TODO: Best way?

    // Generate the secret key specs.
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

    // Instantiate the cipher
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

    byte[] encrypted = cipher.doFinal((secrectID).getBytes());
    System.out.println("encrypted string: " + asHex(encrypted));

    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
    byte[] original = cipher.doFinal(encrypted);
    String originalString = new String(original);
    System.out.println("Original string: " + originalString + "\nOriginal string (Hex): " + asHex(original));
}

Прямо сейчас я получаю исключение "Недопустимая длина ключа AES: 86 байтов". Я должен заполнить свой ключ? Как я должен сделать это?

Также я должен установить что-нибудь для ЕЦБ или CBC?

Спасибо

84
задан Bernie Perez 10 August 2010 в 17:24
поделиться

2 ответа

Изменить:

Как написано в комментариях, старый код не является «лучшей практикой». Вы должны использовать алгоритм генерации ключей, такой как PBKDF2, с большим количеством итераций. Вы также должны использовать, по крайней мере, частично нестатическую (то есть для каждой исключительной "идентичности") соль. Если возможно, генерируется случайным образом и сохраняется вместе с зашифрованным текстом.

    SecureRandom sr = SecureRandom.getInstanceStrong();
    byte[] salt = new byte[16];
    sr.nextBytes(salt);

    PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1000, 128 * 8);
    SecretKey key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(spec);
    Cipher aes = Cipher.getInstance("AES");
    aes.init(Cipher.ENCRYPT_MODE, key);

===========

Старый ответ

Вы должны использовать SHA-1, чтобы сгенерировать хэш из вашего ключа и обрезать результат до 128 бит (16 байтов).

Кроме того, не создавайте байтовые массивы из строк через getBytes () , он использует кодировку платформы по умолчанию. Таким образом, пароль «blaöä» приводит к разным байтовым массивам на разных платформах.

byte[] key = (SALT2 + username + password).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit

SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

Редактировать: Если вам нужен размер ключа 256 бит, вам необходимо загрузить «Файлы политики юрисдикции неограниченной надежности Java Cryptography Extension (JCE)» Ссылка для загрузки Oracle , используйте SHA-256 в качестве хэша и удалите массивы . Строка copyOf . «ECB» - это режим шифрования по умолчанию, а «PKCS5Padding» - заполнение по умолчанию. Вы можете использовать различные режимы шифрования и режимы заполнения в строке Cipher.getInstance , используя следующий формат: «Cipher / Mode / Padding»

Для AES, использующих CTS и PKCS5P, добавляемая строка: «AES / CTS / PKCS5Padding "

120
ответ дан 24 November 2019 в 08:36
поделиться

Вы должны использовать KeyGenerator для генерации ключа,

длина ключа AES составляет 128, 192 и 256 бит в зависимости от шифра, который вы хотите использовать.

Взгляните на учебник здесь

Вот код для шифрования на основе пароля, пароль вводится через System.in, вы можете изменить его, чтобы использовать сохраненный пароль, если хотите.

        PBEKeySpec pbeKeySpec;
        PBEParameterSpec pbeParamSpec;
        SecretKeyFactory keyFac;

        // Salt
        byte[] salt = {
            (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
            (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
        };

        // Iteration count
        int count = 20;

        // Create PBE parameter set
        pbeParamSpec = new PBEParameterSpec(salt, count);

        // Prompt user for encryption password.
        // Collect user password as char array (using the
        // "readPassword" method from above), and convert
        // it into a SecretKey object, using a PBE key
        // factory.
        System.out.print("Enter encryption password:  ");
        System.out.flush();
        pbeKeySpec = new PBEKeySpec(readPassword(System.in));
        keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

        // Create PBE Cipher
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");

        // Initialize PBE Cipher with key and parameters
        pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);

        // Our cleartext
        byte[] cleartext = "This is another example".getBytes();

        // Encrypt the cleartext
        byte[] ciphertext = pbeCipher.doFinal(cleartext);
14
ответ дан 24 November 2019 в 08:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: