使用 AES 和 Base64 编码进行加密和解密

2022-09-01 08:13:05

我有以下用于加密数据的程序。

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class Test {

    private static final String ALGORITHM = "AES";
    private static final byte[] keyValue = "ADBSJHJS12547896".getBytes();

    public static void main(String args[]) throws Exception {
        String encriptValue = encrypt("dude5");
        decrypt(encriptValue);

    }

    /**
     * @param args
     * @throws Exception
     */

    public static String encrypt(String valueToEnc) throws Exception {

        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.ENCRYPT_MODE, key);

        System.out.println("valueToEnc.getBytes().length "+valueToEnc.getBytes().length);
        byte[] encValue = c.doFinal(valueToEnc.getBytes());
        System.out.println("encValue length" + encValue.length);
        byte[] encryptedByteValue = new Base64().encode(encValue);
        String encryptedValue = encryptedByteValue.toString();
        System.out.println("encryptedValue " + encryptedValue);

        return encryptedValue;
    }

    public static String decrypt(String encryptedValue) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.DECRYPT_MODE, key);

        byte[] enctVal = c.doFinal(encryptedValue.getBytes());
        System.out.println("enctVal length " + enctVal.length);

        byte[] decordedValue = new Base64().decode(enctVal);

        return decordedValue.toString();
    }

    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGORITHM);
        return key;
    }

}

在这里,我得到了以下放出例外?

valueToEnc.getBytes().length 5
encValue length16
encryptedValue [B@aa9835
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)

有人能解释一下原因吗?为什么解密时只说这个长度应该是16。它不是像使用doFinal方法加密一样转换为16吗?

正如例外所说“如何在没有填充密码的情况下解密?


答案 1

您的加密顺序:getBytes,加密,编码,toString
您的解密顺序(错误*):getBytes,解密,解码,toString

两个问题:

  1. 正如有人已经提到的那样,您应该颠倒解密的操作顺序。你没有那样做。
  2. encrypt给你16个字节,编码24个字节,但toString给你106个字节。与占用额外空间的无效字符有关。

注意:此外,您无需拨打两次电话。generateKey()

通过使用反向解密顺序修复问题 #1
解密的正确顺序:getBytes、decode、decrypt、toString

通过将 替换为 修复问题 #2。在加密和解密功能中执行此操作。xxx.toString()new String(xxx)

您的解密应如下所示:

c.init(Cipher.DECRYPT_MODE, key)
val decodedValue = new Base64().decode(encryptedValue.getBytes())
val decryptedVal = c.doFinal(decodedValue)
return new String(decryptedVal)

这应该给你“伙计5”


答案 2

生产线

String encryptedValue = encryptedByteValue.toString();

是问题所在。加密ByteValue的类型是byte[],并且调用String不是你想在那里做的。相反,请尝试

String encryptedValue = Base64.getEncoder().encodeToString(encValue);

然后在解密中使用。但是,在尝试解密之前,您必须执行此操作。必须按加密方法的相反顺序撤消操作。Base64.decodeBase64(encryptedValue)


推荐