AES-GCM:AEADBadTagException:GCM 中的 mac 检查失败

2024-06-03

在第一次尝试实现 AES-GCM 时,我们在生成 AuthenticationTag 时面临问题,加密密码和 GCM mac 检查最终失败。对于当前的实施tag[]正在填充但是byte[] encrypted仍然是空的。也正因为如此cipher.doFinal(data1, offset) gives 'mac check in GCM failed'。这似乎是关于字节数组大小的一些问题,有人可以分享一下应该在什么基础上确定输出缓冲区大小吗?这应该分块完成吗?

任何指向 AES-GCM 实现的指针/链接都将受到高度赞赏。

以下是我们的实现:

public class GCMTest {

    public static void main(String[] args) throws Exception {

        //***********************************************************
        //Key
        byte[] key = MessageDigest.getInstance("MD5").digest("1234567890123456".getBytes("UTF-8"));//this is the random key

        //Iv
        SecureRandom srand = SecureRandom.getInstance("SHA1PRNG");
        byte[] iv = new byte[256];
        srand.nextBytes(iv);

        //Input
        byte[] data="inputPlainText".getBytes();

        final GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(16 * Byte.SIZE, iv);

        //***********************************************************
        //Encryption
        final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", new BouncyCastleProvider());
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), gcmParameterSpec);

        cipher.updateAAD("MyAAD".getBytes("UTF-8"));

        //Encrypted output
        final byte[] encrypted = new byte[cipher.getOutputSize(data.length)];
        cipher.update(data, 0, data.length, encrypted, 0);  //Not being updated for current data. 

        //Tag output
        byte[] tag = new byte[cipher.getOutputSize(data.length)];
        cipher.doFinal(tag, 0);


        //***********************************************************
        //Decryption
        final SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);

        cipher.updateAAD("MyAAD".getBytes("UTF-8"));

        //What size should be assigned to outputBuffer?
        final byte[] data1 = new byte[256];

        int offset = cipher.update(encrypted, 0, encrypted.length, data1, 0);
        cipher.update(tag, 0, tag.length, data1, offset);
        cipher.doFinal(data1, offset);

        boolean isValid = checkEquals(data, data1);
        System.out.println("isValid :"+isValid);
    }

    private static boolean checkEquals(byte[] a, byte[] b)
    {
        int diff = a.length ^ b.length;
        for(int i = 0; i < a.length && i < b.length; i++)
            diff |= a[i] ^ b[i];
        return diff == 0;
    }
}

它给出以下异常:

Exception in thread "main" javax.crypto.AEADBadTagException: mac check in GCM failed
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
    at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$AEADGenericBlockCipher.doFinal(Unknown Source)
    at org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(Unknown Source)
    at javax.crypto.Cipher.doFinal(Cipher.java:2068)
    at GCMTest.main(GCMTest.java:56)

提前致谢!!


我也遇到了同样的问题。对我来说,这与对字符串进行编码有关。我最终做了:

  1. 从要加密的字符串中获取 ASCII 字节(在您的情况下为 UTF-8)
  2. 加密字节
  3. 将字节编码为 Base64 字符串

然后解密字符串我做了:

  1. 将加密字符串解码为 Base64 字节
  2. 解密 Base64 字节
  3. 使用 ASCII 创建新字符串。

这是代码:

private String encrypt(String src) {
    byte[] srcBytes = src.getBytes(StandardCharsets.US_ASCII);
    cipher.init(Cipher.ENCRYPT_MODE, secretKey, secureRandom);

    byte[] cipherText = cipher.doFinal(srcBytes);
    byte[] encryptedBytes = new byte[12 + cipherText.length];

    System.arraycopy(ivBytes, 0, encryptedBytes, 0, 12);
    System.arraycopy(cipherText, 0, encryptedBytes, 12, cipherText.length);

    return Base64.encodeToString(encryptedBytes, Base64.DEFAULT);
}

private String decrypt(String encryptedString) {
    byte[] encryptedBytes = Base64.decode(encryptedString, Base64.DEFAULT);

    cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(128, encryptedBytes, 0, 12));
    byte[] decryptedBytes = cipher.doFinal(encryptedBytes, 12, encryptedBytes.length-12);

    return Base64.encodeToString(decryptedBytes, Base64.DEFAULT);
}

我没有包含如何初始化它们的任何变量都可以从 java 文档中推断出来。我试图在 Android 中执行此操作,所以我不确定它有什么不同。我发现这篇文章非常有帮助:Java AES/GCM/NoPadding - cipher.getIV() 给了我什么? https://stackoverflow.com/questions/31851612/java-aes-gcm-nopadding-what-is-cipher-getiv-giving-me/31863209#31863209

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AES-GCM:AEADBadTagException:GCM 中的 mac 检查失败 的相关文章

随机推荐

  • 如何通过单击图像按钮上传新文件

    我有一项任务是通过单击图像按钮上传新文件 我的代码是
  • 停止视频时隐藏 YouTube iframe 中的“更多视频”

    当用户停止视频时 如何隐藏 Youtube iframe 中的 更多视频 部分 例子 我找不到任何解决方案here https developers google com youtube player parameters 如果您安装了 u
  • 带完整堆栈跟踪的单元测试

    这似乎是一个愚蠢的问题 但我无法在任何地方找到答案 我正在使用 Rails 3 1 和 Test Unit 当测试失败时 我只能看到堆栈的顶部 例如 ERROR creating a message sends emails 1 35s N
  • R闪亮:在渲染表格时显示“正在加载...”消息

    在 Rstudio Shiny 中 我得到了一些renderDataTable通过 RMySQL 从数据库获取信息的调用 有些查询可能需要几秒钟才能完成 我想添加一条 正在加载 消息 其中表格将在等待时最终呈现 这个问题与这个问题类似 R闪
  • 容器内的 Docker Macvlan 网络无法到达其自己的主机

    我在 2 个 docker 主机之间设置了 Macvlan 网络 如下所示 主机设置 HOST 1ens192 172 18 0 21 创建macvlan桥接口 docker network create d macvlan subnet
  • 迪菲-赫尔曼私钥

    我有下面的代码行来生成私钥 int Xa randomNo nextInt 10000 int Ya int Math pow G Xa P G and P是静态数字 然而Xa是随机生成的 每次我运行该程序时 它都会给出相同的结果Ya 这对
  • 我不明白 JSONP 与 AJAX 有什么不同

    我不明白 JSONP 中的回调函数与 AJAX 中的成功回调函数有什么不同 鉴于 1 我不明白它如何从根本上更安全 那么唯一的区别是 AJAX 的人为同域约束吗 为什么AJAX不能只允许跨域请求 如果这会导致安全漏洞 那么攻击难道不只是 X
  • 如何从 S3 中的 zip 存档中提取文件

    我在 S3 的某个位置上传了一个 zip 存档 例如 foo bar zip 我想提取 bar zip 中的值并将其放在 foo 下 而不下载或重新上传提取的文件 我怎样才能做到这一点 以便 S3 被视为非常像文件系统 S3 的设计初衷并不
  • 更快的输入和输出

    include
  • 将 WPF 控件类作为模板类

    有没有办法让 WPF UserControl 类成为具有模板类型的类 例如 public partial class MyControl UserControl 应该 public partial class MyControl
  • DiscordJS中如何在没有缓存的情况下获取语音频道中的用户?

    我正在尝试让所有用户连接到我的服务器上的语音通道 当有人与机器人交谈时 general 我想让用户进去Voice Channel 1 我正在使用 Node 17 和 DiscordJS 13 这是我的代码 message guild cha
  • 在 SQL Server SELECT 语句中使用 CASE 时消除 NULL

    我有一份大而混乱的报告要写 它连接了 5 个表 一个表中有一列用于多个不同的值 本质上是一个 标签 列 其中标签根据用户想要使用的各种元数据的类型以创造性的方式使用 因此 我对报告的查询返回 3 个几乎相同的行 仅 标签 列有所不同 例如
  • 为什么我的 3D 绘图没有显示在 R Studio 绘图查看器中?

    我通常在 RStudio 版本 1 0 44 中查看绘图时没有问题 但是当我尝试查看使用 rgl 包创建的 3D 绘图时 我的 RStudio 绘图查看器中什么也没有出现 我能够毫无问题地绘制图 汽车 散点图 这是我正在使用的代码 inst
  • Python pandas 按日期列表选择行

    如何通过日期列表选择数据框的多行 dates pd date range 20130101 periods 6 df pd DataFrame np random randn 6 4 index dates columns list ABC
  • Powershell v5.1 Invoke-RestMethod 并绕过代理

    我目前使用的是 Powershell V5 1 并且希望在 Invoke RestMethod 命令上绕过 Internet Explorer 代理 在 Powershell V6 中 有 NoProxy 选项 指示 cmdlet 将不使用
  • jsf 2 primefaces openDialog 不起作用?

    我正在尝试使用 Primefaces 的对话框架 但我已经陷入了设置 http www primefaces org showcase ui dialogFrameworkBasic jsf http www primefaces org
  • 如何将条形图的 XtickLabels 向左移动?

    我目前正在尝试创建频率直方图 为此 我必须创建一个条形图 条形图之间没有空格 然而 这集中于XTickLabels在酒吧的中间 由于它是一个直方图 我希望数值位于每个条形之间的线上 以便它可以直观地指示间隔 本质上 我需要将所有刻度标签移至
  • C# 拖放 - 使用基类的 e.Data.GetData

    我正在使用 C 和 Winforms 3 5 我有一个用户控件列表 全部派生自一个基类 这些控件可以添加到各种面板中 我正在尝试实现拖放功能 我遇到的问题是 DragDrop 事件 对于 DragEventArgse Data GetDat
  • 如何下载Android应用程序的sqlite数据库?

    我在我的 Android 应用程序中使用 sqlite 数据库 我想将数据库下载到电脑上 谁能告诉我该怎么办 如果您的应用程序在模拟器中 您只需使用 DDMS 并打开 data data your package name database
  • AES-GCM:AEADBadTagException:GCM 中的 mac 检查失败

    在第一次尝试实现 AES GCM 时 我们在生成 AuthenticationTag 时面临问题 加密密码和 GCM mac 检查最终失败 对于当前的实施tag 正在填充但是byte encrypted仍然是空的 也正因为如此cipher