如何使用 BouncyCastle 解密,使用 GCM Tag 的字符串,IV 字符串和密钥字符串,所有这些都是十六进制的?

Posted

技术标签:

【中文标题】如何使用 BouncyCastle 解密,使用 GCM Tag 的字符串,IV 字符串和密钥字符串,所有这些都是十六进制的?【英文标题】:How can I decrypt using BouncyCastle, a string using a GCM Tag , IV string and Key string, all of them in HEX? 【发布时间】:2022-01-17 13:26:08 【问题描述】:

我正在尝试使用 GCM 模式和 HEX 输入从 Cyber​​Chef 复制 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 标签用作输入的文章/教程。

【问题讨论】:

【参考方案1】:

这里使用的GCM标签长度不是32,而是16字节。

此外,BC 提供者期望密文和标签以串联形式(密文|标签)。

您必须对密钥、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 分离 IV/nonce大小(GCM 为 12 字节)。


SunJCE 提供程序也支持 AES/GCM(至少从 Java 8 开始,例如here),因此您可能不需要 BouncyCastle。对于十六进制解码,您可以使用this post 的解决方案。从 Java 17 开始,有一个内置支持。

【讨论】:

非常感谢@Topaco!

以上是关于如何使用 BouncyCastle 解密,使用 GCM Tag 的字符串,IV 字符串和密钥字符串,所有这些都是十六进制的?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 BouncyCastle 解密,使用 GCM Tag 的字符串,IV 字符串和密钥字符串,所有这些都是十六进制的?

为 RSACryptoProvider 和 BouncyCastle 生成密钥/加密/解密

尝试使用 BouncyCastle 的 AES-CBC 来解密加密文本的问题

Bouncycastle PGP 解密和验证

C# BouncyCastle RSA 加密和解密

用于解密加密 p8 文件的 BouncyCastle 替代方案