在webservice开发时进行传输内容的AES加密要求:
密钥:密钥使用192比特(24字节),如果小于 192比特,末尾用 0x00补齐
明文:加密明文为 16字节倍数(128比特)无法被16整除的情况加密数据内容采用PKCS7Padding 方式填充(即长度以16字节切分,不能被 16 整除的末尾部分,根据长度不足 8 字节的部分,填充 ”0x01”—“0x10”,如不足1 字节,则填充 1 个"0x01",如不足2 字节,则填充 2 个"0x02”,以此类推,如整除,则填充 16 个“0x10")
代码如下:
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
/**
* AES采用192位密钥(共16,24,32字节三种), jdk默认只支持128位密钥
* 其他位数需更换 jdk安装路径中jre/lib/security下的local_policy.jar,US_export_policy.jar
*
* @author tanch
* */
public class SecretTransUtil {
public static final int SIZE = 24;
public final static String AES = "AES";
/**
* AES加密
*
* @param content 需要加密的内容
* @param password 解密密钥
* @return
*/
public String encryptAES(String content, String password) {
try {
byte[] compBefore = password.getBytes();
byte[] compAfter = Arrays.copyOf(compBefore, 24);
SecretKeySpec key = new SecretKeySpec(compAfter, AES);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // 创建密码器
byte[] byteContent = content.getBytes("utf-8" );
cipher.init(Cipher. ENCRYPT_MODE, key);// 初始化
byte[] encryptResult = cipher.doFinal(byteContent);
String result = parseByte2HexStr(encryptResult);
return result; // 加密
} catch (Exception e) {
e.printStackTrace();
}
return null ;
}
/**AES解密
* @param content 待解密内容
* @param password 解密密钥
* @return
*/
public synchronized String decryptAES(String content, String password) {
try {
byte[] compBefore = password.getBytes();
byte[] compAfter = Arrays.copyOf(compBefore, 24);
SecretKeySpec key = new SecretKeySpec(compAfter, AES);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // 创建密码器
cipher.init(Cipher. DECRYPT_MODE, key);// 初始化
byte[] decryptResult = cipher.doFinal(parseHexStr2Byte(content));
return new String(decryptResult);
} catch (Exception e) {
return null ;
}
}
/**将二进制转换成16进制
* @param buf
* @return
*/
public 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进制转换为二进制
* @param hexStr
* @return
*/
public 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;
}
补充知识:二进制与十六进制的转化
1 首先需要记住8,4,2,1四个数字分别代表:1000,0100,0010,0001
十六进制的最高F为15,也就是8+4+2+1,4个bit可以表示一位十六进制字符
java中byte占8bit,即byte可以容纳两个十六进制字符
2 buf[i] & 0xFF:
Integer.toHexString的参数是int,如果不进行&0xff,由于java的二进制采用的是补码形式,
那么当一个byte会转换成int时, 由于int是32位,而byte只有8位这时会进行补位。
例如:补码11111111的十进制数为-1转换为int时变为11111111111111111111111111111111
即0xffffffff这种补位就会造成误差。 和0xff相与后,高24比特就会被清0了,结果就对了。
补充知识来自:http://franksinger.iteye.com/blog/614540