前言:
AES:高级加密标准(英语:Advanced Encryption Standard,缩写:AES),这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用,AES的优势之一是至今尚未被破解。AES通常用于移动通信系统加密以及基于SSH协议的软件。
测试:
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
import org.junit.Test;
public class testAES {
@Test
public void AES() {
try {
String middleKey = "123456"; //就是所谓的密钥,加密和解密双方都需要
String password = "kevin"; //需要被加密的内容
// 生成KEY
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(new SecureRandom(middleKey.getBytes()));
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
Key key = new SecretKeySpec(byteKey, "AES");
// 加密
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] result = cipher.doFinal(password.getBytes());
System.out.println("加密后:" + Hex.encodeHexString(result));
// 解密
cipher.init(Cipher.DECRYPT_MODE, key);
result = cipher.doFinal(result);
System.out.println("解密后:" + new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果如下:
编写工具类:
AesUtils:
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
public class AesUtils {
private final String MiddleKey = "123456";//生成key需要的密码
public String encrypt(String password) {
try {
// 加密
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, getKey());
byte[] result = cipher.doFinal(password.getBytes());
// return Hex.encodeHexString(result);
return Base64.encodeBase64String(result);//通过Base64转码返回
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/*
* encryptedPassword:待解密的密文
*/
public String decrypt(String encryptedPassword) {
try {
// 解密
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, getKey());
// byte[] result = cipher.doFinal(encryptedPassword.getBytes());
byte[] result = cipher.doFinal(Base64.decodeBase64(encryptedPassword));
return new String(result);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
private Key key;
public Key getKey() {
if (key == null) {
try {
// 生成KEY ,AES 要求密钥长度为 128
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(MiddleKey.getBytes());
keyGenerator.init(128,secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
byte[] byteKey = secretKey.getEncoded();
// 转换KEY
key = new SecretKeySpec(byteKey, "AES");
return key;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} else {
return key;
}
}
}
使用:
public void main() {
AesUtils aesUtils=new AesUtils();
String encryptStr = aesUtils.encrypt("hello world");
System.out.println("加密后的结果:"+ encryptStr);
String decryptStr = aesUtils.decrypt(encryptStr);
System.out.println("解密后的结果:"+ decryptStr);
}
运行结果如下:
问题:
1.AesUtils中加密和加密函数中分别有一句被注释的代码,然后改成了base64转码,这是因为使用注释的代码在解密的时候会报错:
javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption. at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:991)
原因是直接用tostring 和getbytes方法操作 加密后的byte [ ] 会丢失信息
解决方案就是:
要么使用Base64来转码
要么像上方Test方法中一样,直接用byte [ ]去解密
2.在windows下能正常解密,但是相同的代码拷贝到linux下既失效。
解决方法:把getkey中的初始化SecureRandom,改成如下方式即可:
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(MiddleKey.getBytes());
keyGenerator.init(128,secureRandom);