使用Java的AES-256-GCM解密中的标签不匹配错误 [英] Tag mismatch error in AES-256-GCM Decryption using Java

查看:326
本文介绍了使用Java的AES-256-GCM解密中的标签不匹配错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下用JavaScript编写的函数,用于使用aes-256-gcm进行加密:

I have the following function written in Javascript for encryption using aes-256-gcm:

encrypt: function (text, masterkey){
    try {
        // random initialization vector
        var iv = crypto.randomBytes(12);

        // random salt
        var salt = crypto.randomBytes(64);

        // derive key: 32 byte key length - in assumption the masterkey is a cryptographic and NOT a password there is no need for
        // a large number of iterations. It may can replaced by HKDF
        var key = crypto.pbkdf2Sync(masterkey, salt, 2145, 32, 'sha512');

        // AES 256 GCM Mode
        var cipher = crypto.createCipheriv('aes-256-gcm', key, iv);

        // encrypt the given text
        var encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);

        // extract the auth tag
        var tag = cipher.getAuthTag();

        // generate output
        return Buffer.concat([salt, iv, tag, encrypted]).toString('base64');

    }catch(e){
    }

    // error
    return null;
}

使用以下功能成功解密了上述功能的加密文本:

The encrypted text by the above function is successfully decrypted back using the following function:

decrypt: function (data, masterkey){
    try {
        // base64 decoding
        var bData = new Buffer(data, 'base64');
        var salt = bData.slice(0, 64);
        var iv = bData.slice(64, 76);
        var tag = bData.slice(76, 92);
        var text = bData.slice(92);

        // derive key using; 32 byte key length
        var key = crypto.pbkdf2Sync(masterkey, salt , 2145, 32, 'sha512');
        // AES 256 GCM Mode
        var decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
        decipher.setAuthTag(tag);

        // decrypt the given text
        var decrypted = decipher.update(text, 'binary', 'utf8') + decipher.final('utf8');

        return decrypted;

    }catch(e){
    }

    // error
    return null;
}

现在,我需要Java中的解密方法,该方法等效于上面的Javascript解密功能。以下是我编写的用于解密的Java代码:

Now, I need a method in Java for decryption which is the equivalent of the above Javascript decrypt function. Following is the Java code I have written for decryption:

public void decrypt(byte[] nkb, String crKey){
    //nkb is byte array formed by Base64 decoding of 'data' variable in the Javascript code
    //crKey corresponds to the 'masterkey' variable

    byte[] salt = Arrays.copyOfRange(nkb, 0, 64);
    byte[] iv = Arrays.copyOfRange(nkb, 64, 76);
    byte[] tag = Arrays.copyOfRange(nkb, 76, 92);
    byte[] text = Arrays.copyOfRange(nkb, 92, nkb.length);

    PBEKeySpec ks = new PBEKeySpec(crKey.toCharArray(), salt, iterations, 256);
    SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
    SecretKey pbeKey = skf.generateSecret(ks);

    byte[] decrypted = decrypt(iv, pbeKey.getEncoded(), text, tag);
}
    public static byte[] decrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes, byte[] tagBytes)
        throws java.io.UnsupportedEncodingException,
        NoSuchAlgorithmException,
        NoSuchPaddingException,
        InvalidKeyException,
        InvalidAlgorithmParameterException,
        IllegalBlockSizeException,
        BadPaddingException,
        NoSuchProviderException {

        GCMParameterSpec ivSpec = new GCMParameterSpec(tagBytes.length*Byte.SIZE, ivBytes);

        SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec);
        return cipher.doFinal(textBytes); //getting tag mismatch error here
    }

在上面的代码中,我在最后一行收到标签不匹配错误。在找出我做错了什么方面,我将不胜感激。

As I have commented in the above code, I get a Tag mismatch error in the last line. I would appreciate some help in finding out what I am doing wrong.

此行代码中有错误:

cipher.init(Cipher.DECRYPT_MODE, newKey, ivSpec)
java.security.InvalidKeyException: Illegal key size
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1039)
at javax.crypto.Cipher.implInit(Cipher.java:805)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at com.micropro.namwebservice.utils.CryptoUtils.decrypt(CryptoUtils.java:93)
at com.micropro.namwebservice.utils.CryptoUtils.decrypt(CryptoUtils.java:82)


推荐答案

您需要向Java GCM代码提供标记,以便它可以检查消息是否真实。 Java API期望将标签附加到密文中。更改代码的最简单方法是替换行

You need to provide the tag to the Java GCM code so that it can check that the message is authentic. The Java API expects the tag to be appended to the ciphertext. The simplest way to change your code to do that would be to replace the line

return cipher.doFinal(textBytes);

有两行:

cipher.update(textBytes);
return cipher.doFinal(tagBytes);

这篇关于使用Java的AES-256-GCM解密中的标签不匹配错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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