簡介
AES 的出現(xiàn),就是為了來替代原先的 DES 標(biāo)準(zhǔn)?,F(xiàn)在來說,AES 的用途還是非常廣泛的。
全稱為“Advanced Encryption Standard”,中文名“高級加密標(biāo)準(zhǔn)”,在密碼學(xué)中又稱 Rijndael 加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標(biāo)準(zhǔn)。AES 加密算法作為新一代的數(shù)據(jù)加密標(biāo)準(zhǔn)匯聚了強安全性、高性能、高效率、易用和靈活等優(yōu)點。AES 設(shè)計有三個密鑰長度:128,192,256 位。相對而言,AES 的 128 密鑰比 DES 的 56 密鑰強了 1021 倍。
相對來說,如果密鑰長度變長,那么IV向量的長度對應(yīng)的也要變長才行。應(yīng)為對于塊加密來說,密鑰長度和IV向量的長度應(yīng)該是一致的。
原理
ES 加密算法主要包括三個方面:輪變化、圈數(shù)和密鑰擴展。AES 是分組密鑰,算法輸入 128 位數(shù)據(jù),密鑰長度也是 128 位。用 Nr 表示對一個數(shù)據(jù)分組加密的輪數(shù)。每一輪都需要一個與輸入分組具有相同長度的擴展密鑰 Expandedkey(i) 的參與。由于外部輸入的加密密鑰 K 長度有限,所以在算法中要用一個密鑰擴展程序 (Keyexpansion) 把外部密鑰 K 擴展成更長的比特串,以生成各輪的加密和解密密鑰。
輸出
入口參數(shù)有三個:key、data、mode。
- key 為加密解密使用的密鑰,長度為24字節(jié)
- data 為加密 解密的數(shù)據(jù),
- mode 為其工作模式。
密鑰是192位,但是是分開使用的,每個加密快的長度應(yīng)該還是8字節(jié)的整數(shù)倍
記?。喝绻怯衟adding,如果是明文如果是8字節(jié)的整數(shù)倍的話,加密的密文長度肯定要增加8個字節(jié),因為要有標(biāo)識
java demo
注意,如果是使用的cfb,ofb等需要初始化向量的加解密,則需要把iv也傳給解密器才行
/**
* 加密
*
* @param content 需要加密的內(nèi)容
* @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");// 創(chuàng)建密碼器
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(byteContent);
return result; // 加密
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
2.2 解密
代碼有詳細(xì)注釋,不多廢話
注意:解密的時候要傳入byte數(shù)組
[java] view plain copy
/**解密
* @param content 待解密內(nèi)容
* @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");// 創(chuàng)建密碼器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(content);
return result; // 加密
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**解密
* @param content 待解密內(nèi)容
* @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");// 創(chuàng)建密碼器
// Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");// 這里使用的是這種方式的話,在下面的init處就會報錯,因為沒有傳入iv向量
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(content);
return result; // 加密
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}