| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- /**
- * Copyright (c) 2005-2012 springside.org.cn
- */
- package com.jeeplus.common.security;
- import java.io.UnsupportedEncodingException;
- import java.security.GeneralSecurityException;
- import java.security.SecureRandom;
- import java.util.Arrays;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.Mac;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.IvParameterSpec;
- import javax.crypto.spec.SecretKeySpec;
- import com.jeeplus.common.utils.Encodes;
- import com.jeeplus.common.utils.Exceptions;
- /**
- * 支持HMAC-SHA1消息签名 及 DES/AES对称加密的工具类.
- *
- * 支持Hex与Base64两种编码方式.
- *
- * @author calvin
- */
- public class Cryptos {
- private static final String AES = "AES";
- private static final String AES_CBC = "AES/CBC/PKCS5Padding";
- private static final String HMACSHA1 = "HmacSHA1";
- private static final String DEFAULT_URL_ENCODING = "UTF-8";
- 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 final byte[] DEFAULT_KEY = new byte[]{-97,88,-94,9,70,-76,126,25,0,3,-20,113,108,28,69,125};
- private static SecureRandom random = new SecureRandom();
- //-- HMAC-SHA1 funciton --//
- /**
- * 使用HMAC-SHA1进行消息签名, 返回字节数组,长度为20字节.
- *
- * @param input 原始输入字符数组
- * @param key HMAC-SHA1密钥
- */
- public static byte[] hmacSha1(byte[] input, byte[] key) {
- try {
- SecretKey secretKey = new SecretKeySpec(key, HMACSHA1);
- Mac mac = Mac.getInstance(HMACSHA1);
- mac.init(secretKey);
- return mac.doFinal(input);
- } catch (GeneralSecurityException e) {
- throw Exceptions.unchecked(e);
- }
- }
- /**
- * 校验HMAC-SHA1签名是否正确.
- *
- * @param expected 已存在的签名
- * @param input 原始输入字符串
- * @param key 密钥
- */
- public static boolean isMacValid(byte[] expected, byte[] input, byte[] key) {
- byte[] actual = hmacSha1(input, key);
- return Arrays.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();
- return secretKey.getEncoded();
- } catch (GeneralSecurityException e) {
- throw Exceptions.unchecked(e);
- }
- }
- //-- AES funciton --//
- /**
- * 使用AES加密原始字符串.
- *
- * @param input 原始输入字符数组
- */
- public static String aesEncrypt(String input) {
- try {
- return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), DEFAULT_KEY));
- } catch (UnsupportedEncodingException e) {
- return "";
- }
- }
-
- /**
- * 使用AES加密原始字符串.
- *
- * @param input 原始输入字符数组
- * @param key 符合AES要求的密钥
- */
- public static String aesEncrypt(String input, String key) {
- try {
- return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), Encodes.decodeHex(key)));
- } catch (UnsupportedEncodingException e) {
- return "";
- }
- }
-
- /**
- * 使用AES加密原始字符串.
- *
- * @param input 原始输入字符数组
- * @param key 符合AES要求的密钥
- */
- public static byte[] aesEncrypt(byte[] input, byte[] key) {
- return aes(input, key, Cipher.ENCRYPT_MODE);
- }
- /**
- * 使用AES加密原始字符串.
- *
- * @param input 原始输入字符数组
- * @param key 符合AES要求的密钥
- * @param iv 初始向量
- */
- public static byte[] aesEncrypt(byte[] input, byte[] key, byte[] iv) {
- return aes(input, key, iv, Cipher.ENCRYPT_MODE);
- }
- /**
- * 使用AES解密字符串, 返回原始字符串.
- *
- * @param input Hex编码的加密字符串
- */
- public static String aesDecrypt(String input) {
- try {
- return new String(aesDecrypt(Encodes.decodeHex(input), DEFAULT_KEY), DEFAULT_URL_ENCODING);
- } catch (UnsupportedEncodingException e) {
- return "";
- }
- }
-
- /**
- * 使用AES解密字符串, 返回原始字符串.
- *
- * @param input Hex编码的加密字符串
- * @param key 符合AES要求的密钥
- */
- public static String aesDecrypt(String input, String key) {
- try {
- return new String(aesDecrypt(Encodes.decodeHex(input), Encodes.decodeHex(key)), DEFAULT_URL_ENCODING);
- } catch (UnsupportedEncodingException e) {
- return "";
- }
- }
-
- /**
- * 使用AES解密字符串, 返回原始字符串.
- *
- * @param input Hex编码的加密字符串
- * @param key 符合AES要求的密钥
- */
- public static byte[] aesDecrypt(byte[] input, byte[] key) {
- return aes(input, key, Cipher.DECRYPT_MODE);
- }
- /**
- * 使用AES解密字符串, 返回原始字符串.
- *
- * @param input Hex编码的加密字符串
- * @param key 符合AES要求的密钥
- * @param iv 初始向量
- */
- public static byte[] aesDecrypt(byte[] input, byte[] key, byte[] iv) {
- return aes(input, key, iv, Cipher.DECRYPT_MODE);
- }
- /**
- * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
- *
- * @param input 原始字节数组
- * @param key 符合AES要求的密钥
- * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
- */
- private static byte[] aes(byte[] input, byte[] key, int mode) {
- try {
- SecretKey secretKey = new SecretKeySpec(key, AES);
- Cipher cipher = Cipher.getInstance(AES);
- cipher.init(mode, secretKey);
- return cipher.doFinal(input);
- } catch (GeneralSecurityException e) {
- throw Exceptions.unchecked(e);
- }
- }
- /**
- * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
- *
- * @param input 原始字节数组
- * @param key 符合AES要求的密钥
- * @param iv 初始向量
- * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
- */
- private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
- try {
- SecretKey secretKey = new SecretKeySpec(key, AES);
- IvParameterSpec ivSpec = new IvParameterSpec(iv);
- Cipher cipher = Cipher.getInstance(AES_CBC);
- cipher.init(mode, secretKey, ivSpec);
- return cipher.doFinal(input);
- } catch (GeneralSecurityException e) {
- throw Exceptions.unchecked(e);
- }
- }
- /**
- * 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
- */
- public static String generateAesKeyString() {
- return Encodes.encodeHex(generateAesKey(DEFAULT_AES_KEYSIZE));
- }
-
- /**
- * 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
- */
- public static byte[] generateAesKey() {
- return generateAesKey(DEFAULT_AES_KEYSIZE);
- }
- /**
- * 生成AES密钥,可选长度为128,192,256位.
- */
- public static byte[] generateAesKey(int keysize) {
- try {
- KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
- keyGenerator.init(keysize);
- SecretKey secretKey = keyGenerator.generateKey();
- return secretKey.getEncoded();
- } catch (GeneralSecurityException e) {
- throw Exceptions.unchecked(e);
- }
- }
- /**
- * 生成随机向量,默认大小为cipher.getBlockSize(), 16字节.
- */
- public static byte[] generateIV() {
- byte[] bytes = new byte[DEFAULT_IVSIZE];
- random.nextBytes(bytes);
- return bytes;
- }
- }
|