AES/EAX 使用 JCE 加密 - Mac 签入 EAX 失败
AES/EAX Crypto with JCE - Mac check in EAX failed
我正在尝试使用 AES/EAX/NoPadding 执行 encryption/decryption。由于 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 check in EAX failed"。
@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);
}
}
详情:
- getParameterSpec() returns 带有 IV 的 IvParameterSpec 实例。
- 在加密过程中,IV 字节被插入到密文字节的开头[],并在解密过程中从密文中检索。
- 正在使用的标记大小是 16 个字节。
- AesEaxKey 只是一个包装器 class,它实现了 SecretKey 并委托了它的所有方法。
我有一个 AES/GCM/NoPadding 的实现,它使用完全相同的完美代码。
我做错了什么?
诸如 EAX 之类的 AEAD 模式需要更复杂的 AlgorithmParameterSpec,因为必须指定随机数(也称为 IV)和以位为单位的标记长度。 Java 自 1.7 以来,为 GCM 密码提供了 GCMParameterSpec。 EAX 模式需要相同的数据,显然 Bouncycastle 提供程序也将为 EAX 模式使用 GCMParameterSpec。
请注意,对于 GCMParameterSpec,标签长度以位为单位指定,而为了调整数组大小,标签长度需要以字节为单位指定。
我正在尝试使用 AES/EAX/NoPadding 执行 encryption/decryption。由于 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 check in EAX failed"。
@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);
}
}
详情:
- getParameterSpec() returns 带有 IV 的 IvParameterSpec 实例。
- 在加密过程中,IV 字节被插入到密文字节的开头[],并在解密过程中从密文中检索。
- 正在使用的标记大小是 16 个字节。
- AesEaxKey 只是一个包装器 class,它实现了 SecretKey 并委托了它的所有方法。
我有一个 AES/GCM/NoPadding 的实现,它使用完全相同的完美代码。
我做错了什么?
诸如 EAX 之类的 AEAD 模式需要更复杂的 AlgorithmParameterSpec,因为必须指定随机数(也称为 IV)和以位为单位的标记长度。 Java 自 1.7 以来,为 GCM 密码提供了 GCMParameterSpec。 EAX 模式需要相同的数据,显然 Bouncycastle 提供程序也将为 EAX 模式使用 GCMParameterSpec。
请注意,对于 GCMParameterSpec,标签长度以位为单位指定,而为了调整数组大小,标签长度需要以字节为单位指定。