Android中AES的使用
常見(jiàn)的加密算法大致有兩種,一種是對(duì)稱(chēng)加密算法如AES,另一種是非對(duì)稱(chēng)加密算法如RSA。在對(duì)稱(chēng)加密算法中田炭,加密與解密的密鑰是相同的查吊。密鑰是絕對(duì)不可以泄漏的谐区,否則會(huì)被攻擊者還原密文,竊取機(jī)密數(shù)據(jù)逻卖。非對(duì)稱(chēng)加密算法需要兩個(gè)密鑰:公開(kāi)密鑰(publickey)和私有密鑰(privatekey)宋列。公開(kāi)密鑰與私有密鑰是一對(duì),如果用公開(kāi)密鑰對(duì)數(shù)據(jù)進(jìn)行加密评也,只有用對(duì)應(yīng)的私有密鑰才能解密炼杖;如果用私有密鑰對(duì)數(shù)據(jù)進(jìn)行加密灭返,那么只有用對(duì)應(yīng)的公開(kāi)密鑰才能解密。AES是對(duì)稱(chēng)加密算法的一種坤邪,對(duì)稱(chēng)加密速度非澄鹾快,適合經(jīng)常發(fā)送數(shù)據(jù)的場(chǎng)合艇纺。缺點(diǎn)是密鑰的傳輸比較麻煩怎静。
AES加密需要:明文 + 密鑰+ 偏移量(IV)+密碼模式(算法/模式/填充)
AES解密需要:密文 + 密鑰+ 偏移量(IV)+密碼模式(算法/模式/填充)
其中加密和解密的密鑰,偏移量和密碼模式要相同黔衡。實(shí)際工作中蚓聘,對(duì)加密結(jié)果做Base64轉(zhuǎn)換,在解密之前要做Base64逆轉(zhuǎn)換盟劫。上代碼:
import android.util.Base64;
import java.io.UnsupportedEncodingException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESUtil {
//-- 算法/模式/填充
private static final String CipherMode = "AES/CBC/PKCS7Padding";
//--創(chuàng)建密鑰
private static SecretKeySpec createKey(String password) {
byte[] data = null;
if (password == null) {
password = "";
}
StringBuffer sb = new StringBuffer();
sb.append(password);
String s =null;
while (sb.length() < 32) {
sb.append(" ");//--密碼長(zhǎng)度不夠32補(bǔ)足到32
}
s =sb.substring(0,32);//--截取32位密碼
try {
data = s.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new SecretKeySpec(data, "AES");
}
//--創(chuàng)建偏移量
private static IvParameterSpec createIV(String iv) {
byte[] data = null;
if (iv == null) {
iv = "";
}
StringBuffer sb = new StringBuffer(16);
sb.append(iv);
String s =null;
while (sb.length() < 16) {
sb.append(" ");//--偏移量長(zhǎng)度不夠16補(bǔ)足到16
}
s =sb.substring(0,16);//--截取16位偏移量
try {
data = s.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new IvParameterSpec(data);
}
//--加密字節(jié)數(shù)組到字節(jié)數(shù)組
public static byte[] encryptByte2Byte(byte[] content,String password,String iv){
try {
SecretKeySpec key = createKey(password);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.ENCRYPT_MODE, key, createIV(iv));
byte[] result = cipher.doFinal(content);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//--加密字節(jié)數(shù)組到字符串
public static String encryptByte2String(byte[] content,String password,String iv){
byte[] data =encryptByte2Byte(content,password,iv);
String result =new String(data);
return result;
}
//--加密字節(jié)數(shù)組到base64
public static String encryptByte2Base64(byte[] content,String password,String iv){
byte[] data =encryptByte2Byte(content,password,iv);
String result = new String(Base64.encode(data,Base64.DEFAULT));
return result;
}
//--加密字符串到字節(jié)數(shù)組
public static byte[] encryptString2Byte(String content, String password, String iv){
byte[] data = null;
try {
data = content.getBytes("UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
data = encryptByte2Byte(data,password,iv);
return data;
}
//--加密字符串到字符串
public static String encryptString2String(String content, String password, String iv){
byte[] data = null;
try {
data = content.getBytes("UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
data = encryptByte2Byte(data,password,iv);
String result =new String(data);
return result;
}
//--加密字符串到base64
public static String encryptString2Base64(String content, String password, String iv){
byte[] data = null;
try {
data = content.getBytes("UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
data = encryptByte2Byte(data,password,iv);
String result =new String(Base64.encode(data,Base64.DEFAULT));
return result;
}
//-- 解密字節(jié)數(shù)組到字節(jié)數(shù)組
public static byte[] decryptByte2Byte(byte[] content, String password, String iv) {
try {
SecretKeySpec key = createKey(password);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.DECRYPT_MODE, key, createIV(iv));
byte[] result = cipher.doFinal(content);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//--解密字符串到字節(jié)數(shù)組
public static byte[] decryptString2Byte(String content, String password, String iv) {
byte[] data = null;
try {
data = content.getBytes("UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
data = decryptByte2Byte(data,password,iv);
return data;
}
//--解密base64到字節(jié)數(shù)組
public static byte[] decryptBase642Byte(String content, String password, String iv) {
byte[] data = null;
try {
data = Base64.decode(content,Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
data = decryptByte2Byte(data,password,iv);
return data;
}
//-- 解密字節(jié)數(shù)組到字符串
public static String decryptByte2String(byte[] content, String password, String iv) {
byte[] data =decryptByte2Byte(content,password,iv);
String result =new String(data);
return result;
}
//-- 解密字節(jié)數(shù)組到字符串
public static String decryptBase642String(String content, String password, String iv) {
byte[] data =Base64.decode(content,Base64.DEFAULT);
String result=decryptByte2String(data,password,iv);
return result;
}
}
AES加密的工具類(lèi)AESUtil.java夜牡,封裝了”AES/CBC/PKCS7Padding” 模式的加密方法。包括字節(jié)數(shù)組加密輸出字節(jié)數(shù)組侣签,字符串加密輸出Base64等方法塘装。
在實(shí)際工作中多是服務(wù)端使用密鑰將字符串加密輸出base64傳遞到客戶(hù)端,客戶(hù)端解密的時(shí)候硝岗,先將base64逆轉(zhuǎn)換成字節(jié)數(shù)組氢哮,在使用ASE密鑰解密得到解密后的字節(jié)數(shù)組,將解密后的字節(jié)數(shù)組轉(zhuǎn)成字符串型檀。
String base64String =AESUtil.encryptString2Base64("歡迎來(lái)到王者榮 耀","kakuishdyshifncgyrsjdiosfnvjfeas","asadfdedwderfvgd");
LogUtil.i("load_Aes"," base64String "+base64String);//--U0E01UZ5ed7hijY7YY1+v/x5rsbWtknI9piWP3QHvfQ=
String string = AESUtil.decryptBase642String(base64String,"kakuishdyshifncgyrsjdiosfnvjfeas","asadfdedwderfvgd");
LogUtil.i("load_Aes"," string "+string);//--歡迎來(lái)到王者榮耀
總結(jié):上例先對(duì)字符串“歡迎來(lái)到王者榮耀”進(jìn)行加密冗尤,輸出base64,然后解密得到字符串“歡迎來(lái)到王者榮耀”胀溺。AES加密算法師對(duì)稱(chēng)加密算法裂七,速度較快,在實(shí)際應(yīng)用中較多仓坞。