importjava.io.UnsupportedEncodingException;importjava.security.GeneralSecurityException;importjava.security.SecureRandom;importjava.util.Arrays;importjavax.crypto.Cipher;importjavax.crypto.KeyGenerator;importjavax.crypto.Mac;importjavax.crypto.SecretKey;importjavax.crypto.spec.IvParameterSpec;importjavax.crypto.spec.SecretKeySpec;importorg.apache.log4j.Logger;/*** @包名 com.energy.util
* @创建人 jiangwenzhang
* @日期 2018/6/8 0008
* @时间 8:36
* @描述*/
/*** 支持HMAC-SHA1消息签名 及 DES/AES对称加密的工具类.
*
* 支持Hex与Base64两种编码方式.
**/
public classCryptos {private static Logger logger = Logger.getLogger(Cryptos.class);/*** 自定义密钥*/
private String strDefaultKey = "1865338218031218";private byte[] key =strDefaultKey.getBytes();private static final String AES = "AES";private static final String AES_CBC = "AES/CBC/PKCS5Padding";private static final String HMACSHA1 = "HmacSHA1";private static final int DEFAULT_HMACSHA1_KEYSIZE = 160; //RFC2401
private static final int DEFAULT_AES_KEYSIZE = 128;private static final int DEFAULT_IVSIZE = 16;private static SecureRandom random = newSecureRandom();publicCryptos(){
}publicCryptos(String strDefaultKey){this.strDefaultKey =strDefaultKey;this.key =strDefaultKey.getBytes();
}//-- HMAC-SHA1 funciton --// /*** 使用HMAC-SHA1进行消息签名, 返回字节数组,长度为20字节.
*
*@paraminput 原始输入字符数组
*@paramkey HMAC-SHA1密钥*/
public static byte[] hmacSha1(byte[] input, byte[] key) {try{
SecretKey secretKey= newSecretKeySpec(key, HMACSHA1);
Mac mac=Mac.getInstance(HMACSHA1);
mac.init(secretKey);returnmac.doFinal(input);
}catch(GeneralSecurityException e) {
e.printStackTrace();throw new CryptException("使用HMAC-SHA1进行消息签名出错:",e);
}
}/*** 校验HMAC-SHA1签名是否正确.
*
*@paramexpected 已存在的签名
*@paraminput 原始输入字符串
*@paramkey 密钥*/
public static boolean isMacValid(byte[] expected, byte[] input, byte[] key) {byte[] actual =hmacSha1(input, key);returnArrays.equals(expected, actual);
}/*** 生成HMAC-SHA1密钥,返回字节数组,长度为160位(20字节).
* HMAC-SHA1算法对密钥无特殊要求, RFC2401建议最少长度为160位(20字节).*/
public static byte[] generateHmacSha1Key() {try{
KeyGenerator keyGenerator=KeyGenerator.getInstance(HMACSHA1);
keyGenerator.init(DEFAULT_HMACSHA1_KEYSIZE);
SecretKey secretKey=keyGenerator.generateKey();returnsecretKey.getEncoded();
}catch(GeneralSecurityException e) {
e.printStackTrace();throw new CryptException("生成HMAC-SHA1密钥出错:",e);
}
}//-- AES funciton --// /*** 使用AES加密原始字符串.
*
*@paraminput 原始输入字符数组
*@paramkey 符合AES要求的密钥*/
public byte[] aesEncrypt(byte[] input) {if (key.length != 16) {
logger.info("Key长度不是16位");
}returnaes(input, key, Cipher.ENCRYPT_MODE);
}/*** 使用AES加密原始字符串.
*
*@paraminput 原始输入字符串*/
publicString aesEncrypt(String input) {try{byte[] encryptResult =aesEncrypt(input.getBytes());returnEncodes.encodeHex(encryptResult);
}catch(Exception e) {
e.printStackTrace();throw new CryptException("生成HMAC-SHA1密钥出错:",e);
}
}/*** 使用AES加密原始字符串
*@paraminput 原始输入字符数组
*@paramkey 符合AES要求的密钥
*@paramiv 初始向量*/
public static byte[] aesEncrypt(byte[] input, byte[] key, byte[] iv) {returnaes(input, key, iv, Cipher.ENCRYPT_MODE);
}/*** 使用AES解密字符串, 返回原始字符串.
*
*@paraminput Hex编码的加密字符串
*@paramkey 符合AES要求的密钥
*@throwsUnsupportedEncodingException*/
public String aesDecrypt(byte[] input) throwsUnsupportedEncodingException {if (key.length != 16) {
logger.info("Key长度不是16位");
}byte[] decryptResult =aes(input, key, Cipher.DECRYPT_MODE);//return new String(decryptResult);
return new String(decryptResult,"utf-8");
}/*** 使用AES解密字符串, 返回原始字符串.
*
*@paraminput Hex编码的加密字符串
*@throwsUnsupportedEncodingException*/
publicString aesDecrypt(String input) {try{returnaesDecrypt(Encodes.decodeHex(input));
}catch(Exception e) {
e.printStackTrace();throw new CryptException("解密出错:",e);
}
}/*** 使用AES解密字符串, 返回原始字符串.
*@paraminput Hex编码的加密字符串
*@paramkey 符合AES要求的密钥
*@paramiv 初始向量
*@throwsUnsupportedEncodingException*/
public static String aesDecrypt(byte[] input, byte[] key, byte[] iv) throwsUnsupportedEncodingException {byte[] decryptResult =aes(input, key, iv, Cipher.DECRYPT_MODE);return new String(decryptResult,"utf-8");
}/*** 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
*
*@paraminput 原始字节数组
*@paramkey 符合AES要求的密钥
*@parammode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE*/
private static byte[] aes(byte[] input, byte[] key, intmode) {try{
SecretKey secretKey= newSecretKeySpec(key, AES);
Cipher cipher=Cipher.getInstance(AES);
cipher.init(mode, secretKey);returncipher.doFinal(input);
}catch(GeneralSecurityException e) {
e.printStackTrace();throw new CryptException("使用AES加密或解密无编码的原始字节数组出错:",e);
}
}/*** 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
*
*@paraminput 原始字节数组
*@paramkey 符合AES要求的密钥
*@paramiv 初始向量
*@parammode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE*/
private static byte[] aes(byte[] input, byte[] key, byte[] iv, intmode) {try{
SecretKey secretKey= newSecretKeySpec(key, AES);
IvParameterSpec ivSpec= newIvParameterSpec(iv);
Cipher cipher=Cipher.getInstance(AES_CBC);
cipher.init(mode, secretKey, ivSpec);returncipher.doFinal(input);
}catch(GeneralSecurityException e) {
e.printStackTrace();throw new CryptException("使用AES加密或解密无编码的原始字节数组:",e);
}
}/*** 生成AES密钥,返回字节数组, 默认长度为128位(16字节).*/
public static byte[] generateAesKey() {returngenerateAesKey(DEFAULT_AES_KEYSIZE);
}/*** 生成AES密钥,可选长度为128,192,256位.*/
public static byte[] generateAesKey(intkeysize) {try{
KeyGenerator keyGenerator=KeyGenerator.getInstance(AES);
keyGenerator.init(keysize);
SecretKey secretKey=keyGenerator.generateKey();returnsecretKey.getEncoded();
}catch(GeneralSecurityException e) {
e.printStackTrace();throw new CryptException("生成AES密钥出错:",e);
}
}/*** 生成随机向量,默认大小为cipher.getBlockSize(), 16字节.*/
public static byte[] generateIV() {byte[] bytes = new byte[DEFAULT_IVSIZE];
random.nextBytes(bytes);returnbytes;
}public byte[] getKey() {returnkey;
}public void setKey(byte[] key) {this.key =key;
}
}