在對(duì)安全性要求比較高的報(bào)文做加密的時(shí)候绰精,算法有很多種,我這里主要用到的就是AES加密算法聊疲。由于在國(guó)內(nèi)使用茬底,所以不可避免的要對(duì)中文進(jìn)行加密和解密,而在這個(gè)過(guò)程中获洲,發(fā)現(xiàn),如果不做處理殿如,很容易會(huì)出現(xiàn)中文亂碼贡珊。
下面是常見(jiàn)的情況:
一最爬、中文亂碼
不對(duì)密碼進(jìn)行編碼處理
byte[] decryptResult = decrypt(encryptResult, password);
System.out.println("解密后:" + new String(decryptResult));
運(yùn)行后
加密前:我是shoneworn
解密后:鎴戞槸shoneworn
二、對(duì)文字進(jìn)行編碼處理门岔,但是在傳輸過(guò)程中草率的將byte[]轉(zhuǎn)成String, String code = new String(bytes); 由于AES加密算法要求密文是16位的倍數(shù)爱致。所以,這么處理寒随,在解密的時(shí)候糠悯,就會(huì)報(bào)各種錯(cuò)。比如下面的妻往。
String code = new String(encryptResult);
byte[] decryptResult = decrypt(code.getBytes(), password);
結(jié)果就.........
加密前:我是shoneworn
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at com.ailin.test.AES.decrypt(AES.java:72)
at com.ailin.test.AES.main(AES.java:173)
Exception in thread "main" java.lang.NullPointerException
at java.lang.String.<init>(Unknown Source)
at com.ailin.test.AES.main(AES.java:174)
三互艾、給功能正常的,能傳中文的讯泣,不報(bào)錯(cuò)的AES加密加密算法源碼
package com.ailin.test;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AES {
/**
* 加密
*
* @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;
}
/**
* 解密
*
* @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;
}
/**
* 將二進(jìn)制轉(zhuǎn)換成16進(jìn)制
*
* @param buf
* @return
*/
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();
}
/**
* 將16進(jìn)制轉(zhuǎn)換為二進(jìn)制
*
* @param hexStr
* @return
*/
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;
}
/**
* 加密
*
* @param content
* 需要加密的內(nèi)容
* @param password
* 加密密碼
* @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 (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;
}
public static void main(String[] args) throws UnsupportedEncodingException {
String content = "我是shoneworn";
String password = "12345678";
// 加密
System.out.println("加密前:" + content);
byte[] encode = encrypt(content, password);
//傳輸過(guò)程,不轉(zhuǎn)成16進(jìn)制的字符串纫普,就等著程序崩潰掉吧
String code = parseByte2HexStr(encode);
System.out.println("密文字符串:" + code);
byte[] decode = parseHexStr2Byte(code);
// 解密
byte[] decryptResult = decrypt(decode, password);
System.out.println("解密后:" + new String(decryptResult, "UTF-8")); //不轉(zhuǎn)碼會(huì)亂碼
}
}