使用Java在AES-256-GCM解密中标记不匹配错误



i具有以下在JavaScript中编写的函数,用于使用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;
}

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

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代码:

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
    }

正如我在上面的代码中评论的那样,我在最后一行中得到了标签不匹配错误。我很感谢您找出我做错了什么的帮助。

我在此行代码中有错误:

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希望将标签附加到密文。更改代码的最简单方法是替换行

return cipher.doFinal(textBytes);

有两行:

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

最新更新