【问题标题】:AES GCM encryption and decryption in JAVAJAVA中的AES GCM加解密
【发布时间】:2017-10-21 19:45:52
【问题描述】:

我正在尝试在 JAVA 中实现 AES/GCM/NoPadding 加密和解密 .. 使用的密钥是来自接收方公钥和发送方私钥 (ECDH) 的共享密钥.. 加密效果很好(有和没有 iv)。但是,我无法解密...

我得到了异常:javax.crypto.BadPaddingException: mac check in GCM failed

public static String encryptString(SecretKey key, String plainText) throws NoSuchProviderException, NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

        //IvParameterSpec ivSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");//AES/ECB/PKCS5Padding //"AES/GCM/NoPadding", "BC"
        byte[] plainTextBytes = plainText.getBytes("UTF-8");
        byte[] cipherText;

        //cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);

        cipher.init(Cipher.ENCRYPT_MODE, key);
        return new String(Base64.getEncoder().encode(cipher.doFinal(plainTextBytes)));
      }



           public static String decryptString(SecretKey key, String 
          cipherText) throws NoSuchProviderException, 
          NoSuchAlgorithmException, NoSuchPaddingException, 
          InvalidKeyException, InvalidAlgorithmParameterException, 
          IllegalBlockSizeException, BadPaddingException, 
          UnsupportedEncodingException, ShortBufferException {


        Key decryptionKey = new SecretKeySpec(key.getEncoded(),
                key.getAlgorithm());
       IvParameterSpec ivSpec = new IvParameterSpec(ivString.getBytes("UTF-8"));
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");//AES/GCM/NoPadding", "BC");

        cipher.init(Cipher.DECRYPT_MODE, decryptionKey, ivSpec);
        return new String (Base64.getEncoder().encode(cipher.doFinal(Base64.getDecoder().decode(cipherText.getBytes()))));

    }

【问题讨论】:

  • 为什么你又用base64编码你的解密字符串?这可能是 Base64 编码器引起的问题。你的班级有哪些导入?
  • 我已经否决了这个问题,因为代码甚至无法编译。

标签: java encryption cryptography aes aes-gcm


【解决方案1】:

您必须使用完全相同的 IV 对相同的密文进行加密和解密,并且对于产生不同密文的每次加密,它必须不同。 IV 不是秘密,因此您可以将其与密文一起发送。通常,它只是简单地添加到密文中,并在解密之前被切掉。

【讨论】:

  • 这可能不是完整的答案,但它是一个开始。我不知道Java中GCM模式的身份验证标签是如何处理的。
  • 它被认为是密文的一部分,因此它会抛出一个(派生自)BadPaddingException 的实例。这非常丑陋,是 AEAD 密码最糟糕的设计决策之一。话又说回来,出于某种不可原谅的原因,它已在 RFC 5116 中标准化 - 表明不良做法也确实得到了标准化。
【解决方案2】:

您需要为两个 Cipher.init 调用提供 GCMParameterSpec 实例(包括 IV)。正如已经指出的,加密和解密的 IV 必须相同,并且必须是唯一的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-30
    • 2015-02-18
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    • 2023-01-31
    • 2019-01-31
    • 1970-01-01
    相关资源
    最近更新 更多