AES-GCM:AEADBadTagException:GCM中的mac检查失败 [英] AES-GCM: AEADBadTagException: mac check in GCM failed

查看:516
本文介绍了AES-GCM:AEADBadTagException:GCM中的mac检查失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试首次实施AES-GCM时,我们在生成AuthenticationTag,Encrypted cipher& amp; GCM mac检查最终失败。对于当前实现标签[] 正在填充,但 byte []加密仍为空。因为这个 cipher.doFinal(data1,offset)在GCM中给出' mac check '。它似乎是围绕字节数组大小的一些问题,有人可以分享在什么基础上确定输出缓冲区大小?这应该以块的形式完成吗?

While trying to implement AES-GCM for the first time, we are facing issue in generating AuthenticationTag, Encrypted cipher & GCM mac check fails in the end. For out current implementation tag[] is being populated but byte[] encrypted remains empty. And because of this cipher.doFinal(data1, offset) gives 'mac check in GCM failed'. It appears to be some issue around the size of byte arrays, can someone please share on what basis should the output buffer size be determined? Should this be done in chunks?

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

Any pointers/links to AES-GCM implementation will be highly appreciated.

以下是我们的实现:

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)

提前致谢!!

推荐答案

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

I was having this same issue. For me, it had to do with encoding the string. I ended up doing:


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

  2. 加密字节

  3. 在Base64字符串中编码字节

然后解密字符串我做了:

Then to decrypt string I did:


  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()给我?

Any variables I didn't include how to initialize them can be inferred from the java docs. I was trying to do this in Android so I'm not sure how different it is. I found this post to be incredibly helpful: Java AES/GCM/NoPadding - What is cipher.getIV() giving me?

这篇关于AES-GCM:AEADBadTagException:GCM中的mac检查失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆