java - 无法在 java 中解密 aes-256-gcm 加密数据
问题描述
我已经使用 OpenSSL aes-256-gcm 加密了一个文件。由于命令行不支持 aes-256-gcm,我已经安装了 LibreSSL,并且可以使用以下命令来加密文件的数据。
openssl enc -aes-256-gcm -K 61616161616161616161616161616161 -iv 768A5C31A97D5FE9 -e -in file.in -out file.out
我需要用 Java 解密 file.out 的数据,但我无法做到这一点。
示例代码:
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
String key = "61616161616161616161616161616161";
byte[] IV = "768A5C31A97D5FE9".getBytes();
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
// Create GCMParameterSpec
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, IV);
// Initialize Cipher for DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
// Perform Decryption
byte[] decryptedText = cipher.doFinal(cipherText); // for the data by reading file.out
但是,我收到一个异常说 javax.crypto.AEADBadTagException:标签不匹配!
解决方案
那应该行不通。命令行openssl enc
不支持 AEAD 密码/模式,尽管 1.0.1 的早期版本(低于补丁 h,2012-2014 年)如果您错误地指定了这样的密码并默默地产生了错误的输出,则无法捕获。如果您实际上使用的是 LibreSSL 而不是 OpenSSL,它似乎继承了这个问题并且没有修复它,即使 LibreSSL 项目的全部意义在于他们将修复由无能的 OpenSSL 人员造成的所有错误。
如果这是一个在 OpenSSL(以及 Java)中正常工作的密码,比如 aes-256-ctr,那么你唯一的问题就是将openssl enc -K -iv
它们的参数采用十六进制(适用于 shell 上下文),而 Java 加密是从代码中调用的可以处理二进制数据并期望它的参数以这种形式。因此,您提供给 OpenSSL 的值实际上是 16 字节(128 位)和 8 字节(64 位),而不是应有的 256 位和 128 位(对于 CTR;对于 GCM,96 位的 IV 是正确的,但如前所述,GCM 在这里不起作用)。openssl enc
自动-K -iv
用(二进制)零填充,但 Java 不会。因此,您需要更多类似的东西
byte[] key = Arrays.copyOf( javax.xml.bind.DatatypeConverter.parseHexBinary("61616161616161616161616161616161"), 32);
// Arrays.copyOf zero-pads when expanding an array
// then use SecretKeySpec (key, "AES")
// and IVParameterSpec (iv) instead of GCMParameterSpec
// but after Java8 most of javax.xml is removed, so unless you
// are using a library that contains this (e.g. Apache)
// or have already written your own, you need something like
byte[] fromHex(String h){
byte[] v = new byte[h.length()/2];
for( int i = 0; i < h.length(); i += 2 ) v[i] = Integer.parseInt(h.substring(i,i+2),16);
return v;
}
对比AES加密和openssl命令行工具,Java解密, Blowfish在Java/Scala加密,bash解密(后者是反方向,但需要匹配的都是一样的)
推荐阅读
- javascript - 角度6存储来自json数组中的json数据
- google-apps-script - 为什么我不能在 Google 脚本编辑器中导入库?
- arrays - 同步两个数组
- spring - 拦截器跟踪 MDC 中的并发问题
- sccm - 对于 v_Add_Remove_Programs 中的许多程序,InstallDate00 NULL
- entity-framework - 如何创建代码优先 DbContext 的视图?
- java - Axis2 命名空间/类路径问题
- angular - Angular 6 库智能感知/自动完成
- excel - Private Sub Worksheet_Change(ByVal Target As Range)不起作用
- javascript - 在 React 应用中映射数组以优化性能的最佳实践