在實際coding中會常常遇到往數據庫存入密碼時加密。URL傳參時的加密。由此簡單封裝了下java中的AES加密算法。
0、import類
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.axis.encoding.Base64; //非必須
1、加密接口
/** * 加密 * @param content 待加密內容 * @param password 加密密鑰 * @return */
public static byte[] encrypt(String content, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(password.getBytes()));
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES");
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] result = cipher.doFinal(byteContent);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
2、解密接口
/**解密 * @param content 待解密內容 * @param password 解密密鑰 * @return */
public static byte[] decrypt(byte[] content, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(password.getBytes()));
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] result = cipher.doFinal(content);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
3、編解碼函數(非必須)
//編碼函數
public static String encode(String content, String key) throws Exception {
byte[] encrypt = encrypt(content, key);
return Base64.encode(encrypt);
}
//解碼函數
public static String decode(String encode, String key) throws Exception {
byte[] encrypt = Base64.decode(encode);
byte[] content = decrypt(encrypt, key);
return new String(content);
}
4、測試
//0-正常使用
public static void main(String[] args) throws Exception{
String content = "holybin";
String password = "12345678";
System.out.println("加密前1:" + content);
byte[] encryptResult1 = encrypt(content, password); //普通加密
byte[] decryptResult1 = decrypt(encryptResult1,password); //普通解密
System.out.println("解密后1:" + new String(decryptResult1));
System.out.println("\n加密前2:" + content);
String encryptResult2 = encode(content, password); //先編碼再加密
System.out.println("加密后2:" + encryptResult2);
String decryptResult2 = decode(encryptResult2, password); //先解碼再解密
System.out.println("解密后2:" + decryptResult2);
}
結果例如以下:
5、問題與思考
(1)普通加密后將得到的byte數組直接轉化為字符串用於輸出,或者普通解密時從字符串轉換為byte數組用於傳參會發生什么?
//1-先測試加密
public static void main(String[] args) throws Exception{
String content = "holybin";
String password = "12345678";
System.out.println("加密前1:" + content);
byte[] encryptResult1 = encrypt(content, password); //普通加密
System.out.println("加密后1:" + encryptResult1);
System.out.println("加密后1:" + new String(encryptResult1));
byte[] decryptResult1 = decrypt(encryptResult1,password); //普通解密
System.out.println("解密后1:" + new String(decryptResult1));
}
結果1:
這里將加密后的byte數組直接轉化成String輸出。出現亂碼。
//2-再測試解密
public static void main(String[] args) throws Exception{
String content = "holybin";
String password = "12345678";
System.out.println("加密前1:" + content);
byte[] encryptResult1 = encrypt(content, password); //普通加密
String strEncryptResult1 = new String(encryptResult1,"UTF-8");
//System.out.println("加密后1:" + strEncryptResult1);
byte[] decryptResult1 = decrypt(strEncryptResult1.getBytes("UTF-8"),password); //普通解密
System.out.println("解密后1:" + new String(decryptResult1));
}
結果2:
這里從加密后的String提取bytes數組用於解密,出現報錯
原因:主要是由於加密后的byte數組是不能強制轉換成字符串的,加密過的字符串也不能直接提取bytes數組用於解密,解決方法有兩個:一是像上面測試的樣例一樣先加密再編碼,或先解碼再解密(參考:4、測試)。二是採用十六進制和二進制的相互轉化函數(參考:以下的第(2)點)。
(2)十六進制和二進制相互轉化函數
// 二進制轉十六進制
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
// 十六進制轉二進制
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
使用演示樣例:
// 3-測試轉化函數
public static void main(String[] args) throws Exception {
String content = "holybin";
String password = "12345678";
//加密
System.out.println("加密前1:" + content);
byte[] encryptResult = encrypt(content, password); // 普通加密
String strEncryptResult = parseByte2HexStr(encryptResult);
System.out.println("加密后1:" + strEncryptResult);
//解密
byte[] byteDecryptResult = parseHexStr2Byte(strEncryptResult);
byte[] decryptResult = decrypt(byteDecryptResult, password); // 普通解密
System.out.println("解密后1:" + new String(decryptResult));
}
結果:
測試代碼:EncrptDecrypt.java