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

时间:2010-10-17 18:25:40

标签: 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;
    }

}

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

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。

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

6 个答案:

答案 0 :(得分:54)

您的加密订单: getBytes,encrypt,encode,toString
您的解密订单(错*): getBytes,decrypt,decode,toString

两个问题:

  1. 正如有人提到的那样,你应该颠倒解密操作的顺序。你不这样做。
  2. encrypt为您提供16个字节,编码24个字节,但toString提供106个字节。与无效字符占用额外空间有关。
  3. 注意:此外,您无需再次拨打generateKey()

    使用相反的解释顺序修复问题#1 正确的解密顺序: getBytes,decode,decrypt,toString

    xxx.toString()替换为new String(xxx)

    修复问题#2 。在加密和解密函数中执行此操作。

    您的解密应如下所示:

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

    这应该会给你“dude5”

答案 1 :(得分:3)

该行

String encryptedValue = encryptedByteValue.toString();

是问题所在。 encryptedByteValue的类型是byte [],并且在它上面调用toString不是你想要做的。而是尝试

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

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

答案 2 :(得分:2)

您在哪里获得具有encodeToString或encodeBase64String的apache编解码器版本?

我从apache站点下载了1.5,虽然它在文档中说这些方法存在,但是当你完成代码时它们不会出现,并且当你提供它们时它们会创建一个未知的方法。

我能够做到:

byte raw[] = md.digest(); //step 4
byte hashBytes[] = Base64.encodeBase64(raw); //step 5
StringBuffer buffer = new StringBuffer();
for( int i=0; i<hashBytes.length; i++ )
    buffer.append(hashBytes[i]);
return buffer.toString(); //step 6

然后我获得的字符串非常长,但它正确解密。

我不认为这是做事的“正确”方式,但无法找到文档所说的方法。

答案 3 :(得分:1)

我已经替换了示例中的行:

String encryptedValue = encryptedByteValue.toString();

下一个:

String encryptedValue = new String(encryptedByteValue);

一切正常!

答案 4 :(得分:1)

没关系,你只需要

1)使用new String而不是toString(),因为toString()不会返回你需要的东西(在这两种情况下,加密和解密)

2)您需要先解码,因为该值是在base64中编码的。

我遇到了这个帖子,但是花了一些时间来找出实际的点......我正在为其他遇到此问题的人发布我的代码。

public abstract class EncryptionDecryption {
static  byte[]  key = "!@#$!@#$%^&**&^%".getBytes();
final static String algorithm="AES";

public static String encrypt(String data){

    byte[] dataToSend = data.getBytes();
    Cipher c = null;
    try {
        c = Cipher.getInstance(algorithm);
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    SecretKeySpec k =  new SecretKeySpec(key, algorithm);
    try {
        c.init(Cipher.ENCRYPT_MODE, k);
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    byte[] encryptedData = "".getBytes();
    try {
        encryptedData = c.doFinal(dataToSend);
    } catch (IllegalBlockSizeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (BadPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    byte[] encryptedByteValue =    new Base64().encode(encryptedData);
    return  new String(encryptedByteValue);//.toString();
}

public static String decrypt(String data){

    byte[] encryptedData  = new Base64().decode(data);
    Cipher c = null;
    try {
        c = Cipher.getInstance(algorithm);
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    SecretKeySpec k =
            new SecretKeySpec(key, algorithm);
    try {
        c.init(Cipher.DECRYPT_MODE, k);
    } catch (InvalidKeyException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    byte[] decrypted = null;
    try {
        decrypted = c.doFinal(encryptedData);
    } catch (IllegalBlockSizeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (BadPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return new String(decrypted);
}

public static void main(String[] args){
    String password=EncryptionDecryption.encrypt("password123");
    System.out.println(password);
    System.out.println(EncryptionDecryption.decrypt(password));
}
}

答案 5 :(得分:0)

从根本上说,加密功能和解密功能之间存在不对称性。加密时,执行AES加密,然后执行base64编码,解密时不要先撤消base64编码步骤。

我认为你的base64编码有问题,而且[不应该出现在base64编码的字符串中。

查看org.apache.commons.codec.binary.Base64的文档,您应该能够对编码执行此操作:

String encryptedValue = Base64.encodeBase64String(encValue);

这就解码了:

byte[] encValue = Base64.decodeBase64(encryptedValue);