AES / EAX Crypto с JCE - проверка Mac в EAX не удалась - PullRequest
1 голос
/ 18 июня 2019

Я пытаюсь выполнить шифрование / дешифрование с помощью AES / EAX / NoPadding. Поскольку EAX, по-видимому, недоступен без BouncyCastle, BC был добавлен в качестве поставщика.

Когда я пытаюсь зашифровать «Hello World!», Кажется, что он успешно зашифрован.

@NotNull
@Override
public byte[] encrypt(@NotNull Key key, @NotNull byte[] plain, @Nullable byte[] authentication) throws CryptoException {
    try {
        final AesEaxKey aesEaxKey = (AesEaxKey) key;
        final Cipher cipher = Cipher.getInstance(getCipherAlgorithm(), BouncyCastleProvider.PROVIDER_NAME);
        final byte[] cipherText = new byte[getIvSize(aesEaxKey) + plain.length + getTagSize()];
        final byte[] iv = randomIv(aesEaxKey);

        System.arraycopy(iv, 0, cipherText, 0, getIvSize(aesEaxKey));
        cipher.init(Cipher.ENCRYPT_MODE, aesEaxKey, getParameterSpec(iv));

        if (authentication != null && authentication.length != 0) {
            cipher.updateAAD(authentication);
        }

        cipher.doFinal(plain, 0, plain.length, cipherText, getIvSize(aesEaxKey));
        return cipherText;
    } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchProviderException |
            InvalidKeyException | BadPaddingException | IllegalBlockSizeException | ShortBufferException e) {
        throw new CryptoException(e.getMessage(), e);
    }
}

Когда я пытаюсь расшифровать зашифрованный текст, он выдает «Ошибка проверки Mac в EAX».

@NotNull
@Override
public byte[] decrypt(@NotNull Key key, @NotNull byte[] cipherText, @Nullable byte[] authentication) throws CryptoException {
    try {
        final AesEaxKey aesEaxKey = (AesEaxKey) key;
        final Cipher cipher = Cipher.getInstance(getCipherAlgorithm(), BouncyCastleProvider.PROVIDER_NAME);
        cipher.init(Cipher.DECRYPT_MODE, aesEaxKey, getParameterSpec(cipherText, 0, getIvSize(aesEaxKey)));
        if (authentication != null && authentication.length != 0) {
            cipher.updateAAD(authentication);
        }
        return cipher.doFinal(cipherText, getIvSize(aesEaxKey), cipherText.length - getIvSize(aesEaxKey));
    } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException |
            InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
        throw new CryptoException(e.getMessage(), e);
    }
}

подробности:

  1. getParameterSpec () возвращает экземпляр IvParameterSpec с IV.
  2. Во время шифрования IV байты вставляются в начало байта зашифрованного текста [] и извлекаются из зашифрованного текста во время дешифрования.
  3. Используемый размер тега составляет 16 байт.
  4. AesEaxKey - это просто класс-оболочка, который реализует SecretKey и делегирует все его методы.

У меня есть реализация AES / GCM / NoPadding, которая использует тот же самый точный код, который отлично работает.

Что я делаю не так?

1 Ответ

2 голосов
/ 18 июня 2019

Режимы AEAD, такие как EAX, требуют более сложного AlgorithmParameterSpec, потому что должны быть указаны как nonce (aka IV), так и длина тега в битах.Java начиная с 1.7 предоставляет GCMParameterSpec для шифров GCM.Те же данные необходимы для режима EAX, и, очевидно, поставщик Bouncycastle будет использовать GCMParameterSpec для режима EAX.

Обратите внимание, что для GCMParameterSpec длина тега указывается в битах, тогда как для целейразмерные массивы длина тега должна быть указана в байтах.

...