如何使用 BouncyCastle 解密,这是一个使用 GCM Tag 、 IV string 和 Key string 的字符串,所有这些都是十六进制的?
How can I decrypt using BouncyCastle, a string using a GCM Tag , IV string and Key string, all of them in HEX?
我正在尝试使用 GCM 模式和 HEX 输入从 CyberChef 复制 AES-Decrypt 函数。
运行截图:
到目前为止,我已经编写了以下代码:
package decryption;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
public class Main {
public static final int GCM_TAG_LENGTH = 32;
public static void main(String[] args) throws Exception {
String IV = "9092d522e11120919fce8492";
String input = "90fab0";
String GCMTag = "02883e111ad6f79cd53674b5f833abab";
String key = "8cda92dcb3283da821daa275359642c7a05d60a4badb5769618193a930c1cdec";
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), 0, key.getBytes(StandardCharsets.UTF_8).length, "AES");
System.out.println(decrypt(input.getBytes(StandardCharsets.UTF_8), secretKey, IV.getBytes(StandardCharsets.UTF_8)));
}
public static String decrypt(byte[] cipherText, SecretKeySpec key, byte[] IV) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, IV);
cipher.init(Cipher.DECRYPT_MODE, key, gcmParameterSpec);
byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText);
}
}
对于上面的代码,我得到:
Exception in thread "main" org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$InvalidKeyOrParametersException: Invalid value for MAC size: 256
at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(Unknown Source)
at java.base/javax.crypto.Cipher.init(Cipher.java:1442)
at java.base/javax.crypto.Cipher.init(Cipher.java:1375)
at decryption.Main.decrypt(Main.java:29)
at decryption.Main.main(Main.java:19)
我很确定我跑题了,但我没有找到任何关于如何将 GCM 标签用作输入的 articles/tutorials。
这里使用的GCM标签长度不是32,而是16字节
此外,BC 提供者期望密文和标签以串联形式 (ciphertext|tag)。
而且你必须对密钥、IV、密文和标签进行十六进制解码。由于您是 运行 BouncyCastle,您可以使用 org.bouncycastle.util.encoders.Hex.decode(...)
.
总体:
import org.bouncycastle.util.encoders.Hex;
...
public static final int GCM_TAG_LENGTH = 16;
...
SecretKeySpec secretKey = new SecretKeySpec(Hex.decode(key), "AES");
System.out.println(decrypt(Hex.decode(input + GCMTag), secretKey, Hex.decode(IV))); // 985
从您的代码中不清楚您是否在使用静态 IV/nonce。如果是这样,您应该意识到对 GCM 使用静态 IV/nonce 是一个严重的问题,s。例如here.
相反,对于每次加密,都会生成一个随机(非秘密)IV/nonce,与密文(和标签)连接,并一起发送到解密方,解密方可以根据已知 IV/nonce 大小(GCM 为 12 字节)。
SunJCE 提供程序也支持 AES/GCM(至少从 Java 8 开始,例如 ), so you may not need BouncyCastle. For hex decoding you can then use a solution from this post。从 Java 17 开始,有一个内置的支持。
我正在尝试使用 GCM 模式和 HEX 输入从 CyberChef 复制 AES-Decrypt 函数。 运行截图:
到目前为止,我已经编写了以下代码:
package decryption;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
public class Main {
public static final int GCM_TAG_LENGTH = 32;
public static void main(String[] args) throws Exception {
String IV = "9092d522e11120919fce8492";
String input = "90fab0";
String GCMTag = "02883e111ad6f79cd53674b5f833abab";
String key = "8cda92dcb3283da821daa275359642c7a05d60a4badb5769618193a930c1cdec";
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), 0, key.getBytes(StandardCharsets.UTF_8).length, "AES");
System.out.println(decrypt(input.getBytes(StandardCharsets.UTF_8), secretKey, IV.getBytes(StandardCharsets.UTF_8)));
}
public static String decrypt(byte[] cipherText, SecretKeySpec key, byte[] IV) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, IV);
cipher.init(Cipher.DECRYPT_MODE, key, gcmParameterSpec);
byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText);
}
}
对于上面的代码,我得到:
Exception in thread "main" org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$InvalidKeyOrParametersException: Invalid value for MAC size: 256
at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineInit(Unknown Source)
at java.base/javax.crypto.Cipher.init(Cipher.java:1442)
at java.base/javax.crypto.Cipher.init(Cipher.java:1375)
at decryption.Main.decrypt(Main.java:29)
at decryption.Main.main(Main.java:19)
我很确定我跑题了,但我没有找到任何关于如何将 GCM 标签用作输入的 articles/tutorials。
这里使用的GCM标签长度不是32,而是16字节
此外,BC 提供者期望密文和标签以串联形式 (ciphertext|tag)。
而且你必须对密钥、IV、密文和标签进行十六进制解码。由于您是 运行 BouncyCastle,您可以使用 org.bouncycastle.util.encoders.Hex.decode(...)
.
总体:
import org.bouncycastle.util.encoders.Hex;
...
public static final int GCM_TAG_LENGTH = 16;
...
SecretKeySpec secretKey = new SecretKeySpec(Hex.decode(key), "AES");
System.out.println(decrypt(Hex.decode(input + GCMTag), secretKey, Hex.decode(IV))); // 985
从您的代码中不清楚您是否在使用静态 IV/nonce。如果是这样,您应该意识到对 GCM 使用静态 IV/nonce 是一个严重的问题,s。例如here.
相反,对于每次加密,都会生成一个随机(非秘密)IV/nonce,与密文(和标签)连接,并一起发送到解密方,解密方可以根据已知 IV/nonce 大小(GCM 为 12 字节)。
SunJCE 提供程序也支持
AES/GCM(至少从 Java 8 开始,例如