Почему AES производят другой результат и почему DES не производят - PullRequest
0 голосов
/ 21 марта 2019

Я пытаюсь изменить алгоритм шифрования существующего проекта. Но я немного запутался. Когда я использую «PBEWithHmacSHA512AndAES_256» в качестве параметра, он дает другой результат, но когда я использую «PBEWithMD5AndDES» в качестве параметра, он дает тот же результат. Мои функции:

 public static synchronized String encrypt1(final String textToEncrypt, final String pathPublicKey) throws Exception {
    final KeySpec pbeKeySpec = new PBEKeySpec(DbKeyHandler.getDbKey(pathPublicKey).toCharArray());
    final SecretKey pbeKey = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(pbeKeySpec);
    // Prepare the parameter to the ciphers
    final AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
    final Cipher cipher = Cipher.getInstance(pbeKey.getAlgorithm());

    // Create the ciphers
    cipher.init(Cipher.ENCRYPT_MODE, pbeKey, paramSpec);

    // Encode the string into bytes using utf-8
    final byte[] utf8 = textToEncrypt.getBytes("UTF8");

    // Encrypt
    final byte[] enc = cipher.doFinal(utf8);

    // Encode bytes to base64 to get a string
    return new sun.misc.BASE64Encoder().encode(enc);
}


public static synchronized String encrypt2 (final String textToEncrypt, final String pathPublicKey) throws Exception {
    final KeySpec pbeKeySpec = new PBEKeySpec(DbKeyHandler.getDbKey(pathPublicKey).toCharArray());
    final SecretKey pbeKey = SecretKeyFactory.getInstance("PBEWithHmacSHA512AndAES_256").generateSecret(pbeKeySpec);
    // Prepare the parameter to the ciphers
    final AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
    final Cipher cipher = Cipher.getInstance(pbeKey.getAlgorithm());

    // Create the ciphers
    cipher.init(Cipher.ENCRYPT_MODE, pbeKey, paramSpec);

    // Encode the string into bytes using utf-8
    final byte[] utf8 = textToEncrypt.getBytes("UTF8");

    // Encrypt
    final byte[] enc = cipher.doFinal(utf8);

    // Encode bytes to base64 to get a string
    return new sun.misc.BASE64Encoder().encode(enc);
}

Любые предложения, идеи помогут мне понять, что здесь происходит.

Также это дает разные результаты:

    KeyStore keyStore = KeyStore.getInstance("JCEKS");
    keyStore.load(new FileInputStream((pathOfJKSfile)), password.toCharArray());
    Key key = keyStore.getKey(keyName, keyPass.toCharArray());
    byte[] raw = key.getEncoded();
    SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "PBEWithHmacSHA512AndAES_256");
    final AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATIONS);

    final Cipher cipherEncrypt = Cipher.getInstance(ALGORITHM);
    cipherEncrypt.init(Cipher.ENCRYPT_MODE, secretKeySpec, paramSpec);

    final byte[] enc = cipherEncrypt.doFinal(messageBytes);
    System.out.println( new sun.misc.BASE64Encoder().encode(enc));

И я знаю, что cipher.init () использует "JceSecurity.RANDOM" для получения разных результатов.

1 Ответ

2 голосов
/ 22 марта 2019
  • Оба алгоритма, PBEWithHmacSHA512AndAES_256 и PBEWithMD5AndDES, сначала генерируют ключ шифрования путем обработки пароля, соли и числа итераций (используя HmacSHA512 и MD5 соответственно), а затемзашифруйте обычный текст (с помощью AES-256 и DES соответственно), используя этот ключ и режим CBC .Когда Cipher -инстанция инициализируется, генерируется псевдослучайный вектор инициализации (IV), который требуется для режима CBC -.

  • В контексте PBEWithHmacSHA512AndAES_256 IV генерируется с использованием SecureRandom реализации установленного поставщика с самым высоким приоритетом , по крайней мере для Cipher#init() -метода, используемого вкод (обратите внимание, что существует несколько перегрузок Cipher#init() -метода и что SecureRandom -экземпляр также может быть передан явно).Т.е. с каждой Cipher -инициализацией генерируется new (random) IV, и поэтому зашифрованный текст всегда отличается, даже для идентичного простого текста.По этой причине зашифрованный текст в ваших примерах изменяется в этом контексте.

  • В контексте PBEWithMD5AndDES IV равен только , определяемый паролем,соль, число итераций (и, конечно, сам MD5 -хэш-алгоритм).Следовательно, IV и зашифрованный текст не изменяются в случае повторения (при условии, что пароль, соль, количество итераций и т. Д. Совпадают).По этой причине зашифрованный текст в вашем примере не меняется в этом контексте.

  • Генерация нового случайного IV во время инициализации шифра имеет смысл с учетом следующих требованийдля IV: В целях безопасности IV в режиме CBC (кстати, это также относится и к другим режимам) может использоваться только один раз под тем же ключом .Кроме того, IV должен быть непредсказуемым.

  • PBEWithMD5AndDES is устарел .

РЕДАКТИРОВАТЬ:

  • В настоящее время использование IV является стандартным (по соображениям безопасности).По этой теме в Интернете можно найти много информации, например, здесь .Далее я опишу только несколько основных вещей.

  • IV, используемый для шифрования, должен каким-то образом храниться, поскольку он требуется для дешифрования.IV не должен храниться в секрете, поэтому он обычно объединяется с зашифрованными данными (например, перед зашифрованными данными) и хранится вместе с ними.Во время дешифрования обе части могут быть разделены, потому что длина IV известна (16 байт для AES).Например, для объединения в методе шифрования используется что-то вроде следующего (пусть iv и enc будут байтовыми массивами с IV и зашифрованными данными соответственно):

    byte[] result = new byte[enc.length + iv.length];
    System.arraycopy(iv, 0, result, 0, iv.length);
    System.arraycopy(enc, 0, result, iv.length, enc.length);
    

    ив методе дешифрования соответствующий аналог (имея в виду, что длина IV в AES составляет 16 байт).

  • В методе шифрования IV можно определить с помощью Cipher#getIV() (это, конечно, должно произойти после вызова Cipher#init()).

  • В методе дешифрования вы должны передать IV в PBEParameterSpec -ктору (например, пусть ivбыть байтовым массивом с IV):

    IvParameterSpec ivSpec = new IvParameterSpec(iv); 
    AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount, ivSpec);
    
  • Генерация IV также может происходить вне Cipher -класса, см., например, Генерация случайного IVдля AES в Java .Затем вы должны передать этот IV в методе шифрования таким же образом, как описано выше для метода дешифрования.

  • Обратите внимание, что в связи с IV необходимо учитывать некоторые моменты, например, используя режим без IV (например, ECB), используя IV, состоящий исключительно из 0 -значений, используяпредсказуемый IV или использование IV более одного раза под одним и тем же ключом и т. д. в целом значительно снижает безопасность, см., например, здесь !

...