java實現AES加解密


近些年DES使用越來越少,原因就在於其使用56位密鑰,比較容易被破解,近些年來逐漸被AES替代,AES已經變成目前對稱加密中最流行算法之一;
AES可以使用128、192、和256位密鑰,並且用128位分組加密和解密數據。本文就簡單介紹如何通過JAVA實現AES加密。

/**
* AES加密字符串
* @param content 需要被加密的字符串
* @param password 加密需要的密碼
* @return 密文
*/
public static String aesEncrypt(String content, byte [] password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 創建AES的Key生產者

kgen.init(128, new SecureRandom(password));// 利用用戶密碼作為隨機數初始化出
// 128位的key生產者
//加密沒關系,SecureRandom是生成安全隨機數序列,password.getBytes()是種子,只要種子相同,序列就一樣,所以解密只要有password就行

SecretKey secretKey = kgen.generateKey();// 根據用戶密碼,生成一個密鑰

byte[] enCodeFormat = secretKey.getEncoded();// 返回基本編碼格式的密鑰,如果此密鑰不支持編碼,則返回// null。

SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 轉換為AES專用密鑰

Cipher cipher = Cipher.getInstance("AES");// 創建密碼器

byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);

cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化為加密模式的密碼器

byte[] result = cipher.doFinal(byteContent);// 加密

return Base64.getEncoder().encodeToString(result);//返回字節數據用Base64編碼,解密之前先用Base64解碼

} catch (Exception e) {
e.printStackTrace();
}
return null;
}

注意:加密后的byte數組是不能強制轉換成字符串的,換言之:字符串和byte數組在這種情況下不是互逆的;要避免這種情況,可以考慮將二進制數據轉換成十六進制表示或者用Base64編碼成字符串表示;

/**
* 解密AES加密過的字符串
* @param content AES加密過過的內容
* @param password 加密時的密碼
* @return 明文
*/
public static String aesDecrypt(String content, byte [] password) {
try {
//base64解碼
byte [] message = Base64.getDecoder().decode(content);
KeyGenerator kgen = KeyGenerator.getInstance("AES");// 創建AES的Key生產者
kgen.init(128, new SecureRandom(password));
SecretKey secretKey = kgen.generateKey();// 根據用戶密碼,生成一個密鑰
byte[] enCodeFormat = secretKey.getEncoded();// 返回基本編碼格式的密鑰
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 轉換為AES專用密鑰
Cipher cipher = Cipher.getInstance("AES");// 創建密碼器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化為解密模式的密碼器
byte[] result = cipher.doFinal(message);
return new String(result,StandardCharsets.UTF_8); // 明文

} catch (Exception e) {
e.printStackTrace();
}
return null;
}


另外一種加密方式

/**
* 加密
* @param content 需要加密的內容, 待加密內容的長度必須是16的倍數
* @param password 加密密碼, 密鑰必須是16位的
* @return
*/
public static byte[] encrypt2(String content, String password) {
  try {
    SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");
    Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
    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;
}

這種加密方式有兩種限制:
1.密鑰必須是16位的
2.待加密內容的長度必須是16的倍數,如果不是16的倍數,就會出如下異常:
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
        at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)
        at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
        at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
        at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
        at javax.crypto.Cipher.doFinal(DashoA13*..)
要解決如上異常,可以通過補全傳入加密內容等方式進行避免。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM