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

Har*_*ana 30 java encryption aes

我有以下加密数据的程序.

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

在这里,我得到以下输出异常?

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*..)
Run Code Online (Sandbox Code Playgroud)

有人可以解释一下原因吗?为什么在解密该长度时它唯一的说法应该是16.它不会像使用doFinal方法加密那样转换为16.

并且例外情况说" 如何在没有填充密码的情况下进行解密?"

Bab*_*san 57

您的加密订单: getBytes,encrypt,encode,toString
您的解密订单(错误*): getBytes,decrypt,decode,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)
Run Code Online (Sandbox Code Playgroud)

这应该给你回"dude5"

  • Magnus,在我的答案的顶部,当我提到"你的订单......"时,这就是OP执行序列的顺序."你的"是指OP.那不是'我'的命令. (4认同)
  • 同样重要的是要注意,在从byte []创建String时应始终使用特定的Charset,反之亦然:例如`new String(bytes,"UTF-8")`和`string.getBytes("UTF-8" )`.这确保了如果在具有不同系统字符集的不同系统上执行加密和解密,则不会导致失败. (3认同)

laz*_*laz 5

线路

String encryptedValue = encryptedByteValue.toString();
Run Code Online (Sandbox Code Playgroud)

是问题所在。cryptoByteValue 的类型是 byte[],并且在其上调用 toString 并不是您想要执行的操作。相反尝试

String encryptedValue = Base64.getEncoder().encodeToString(encValue);
Run Code Online (Sandbox Code Playgroud)

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