【问题标题】:Minimal example of doing PBKDF2WithHmacSHA256 + AES/GCM/NoPadding throwing: javax.crypto.AEADBadTagException: mac check in GCM failed做 PBKDF2WithHmacSHA256 + AES/GCM/NoPadding throwing 的最小示例:javax.crypto.AEADBadTagException: mac check in GCM failed
【发布时间】:2018-02-11 07:15:29
【问题描述】:

我用 Java 编写了这个加密和解密的最小示例,使用 Bouncy Castle、PBKDF2WithHmacSHA256 从密码中派生密钥,并使用 AES/GCM/NoPadding 来加密/验证有效负载:

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import tech.dashman.dashman.crypto.Util;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Arrays;

public class Scratch {
    public static void main(String[] args) throws Exception {
        Security.insertProviderAt(new BouncyCastleProvider(), 1);

        String password = "password";
        String payload = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean in tincidunt metus. Nam nec diam sed velit blandit porta quis et augue. Praesent imperdiet, nulla vel aliquam porta, dui nisi dictum justo, pellentesque elementum purus orci at leo. Duis scelerisque, urna sit amet fringilla interdum, mauris felis sagittis eros, eleifend tincidunt risus nulla ut erat. Aliquam id sapien non neque rutrum lacinia at vitae lorem. Vivamus quis ligula nunc. Aenean facilisis pretium leo, vitae gravida quam ultrices et. Ut venenatis eros in justo semper fermentum. Pellentesque convallis lectus urna, fringilla rhoncus metus faucibus quis. Sed eu rhoncus tortor. Donec lacinia tempor elementum.";

        int keyLength = 256;
        int saltLength = keyLength / 8; // It's bytes, not bits.
        int iterations = 65536;

        byte[] salt = new SecureRandom().generateSeed(saltLength);
        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, iterations, keyLength);
        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256", "BC");
        SecretKey passwordKey = secretKeyFactory.generateSecret(keySpec);

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, passwordKey);
        byte[] iv = cipher.getIV();
        System.out.println(Arrays.toString(cipher.getIV()));
        byte[] cipherText = cipher.doFinal(payload.getBytes());

        System.out.println(Base64.toBase64String(cipherText));

        keySpec = new PBEKeySpec(password.toCharArray(), salt, iterations, keyLength);
        secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256", "BC");
        passwordKey = secretKeyFactory.generateSecret(keySpec);

        cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
        cipher.init(Cipher.DECRYPT_MODE, passwordKey, new IvParameterSpec(iv));
        System.out.println(Arrays.toString(cipher.getIV()));
        byte[] plainText = cipher.doFinal(payload.getBytes());
        System.out.println(new String(plainText));
    }
}

但它不起作用。我遇到了这个异常:

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:423)
    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:2165)
    at tech.dashman.dashman.Scratch.main(Scratch.java:51)

为了以防万一,我已经验证了两个密码的初始向量是相同的。我还缺少什么?

【问题讨论】:

    标签: java encryption bouncycastle


    【解决方案1】:

    您正在尝试解密明文而不是密文。倒数第二行:

    byte[] plainText = cipher.doFinal(payload.getBytes());
    

    应该是:

    byte[] plainText = cipher.doFinal(cipherText);
    

    【讨论】:

      猜你喜欢
      • 2018-02-19
      • 2021-09-24
      • 1970-01-01
      • 2016-11-14
      • 2018-09-20
      • 2021-11-23
      • 2021-12-05
      • 2019-02-20
      • 2019-05-30
      相关资源
      最近更新 更多