Cryptos.java 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /**
  2. * Copyright (c) 2005-2012 springside.org.cn
  3. */
  4. package com.jeeplus.common.security;
  5. import java.io.UnsupportedEncodingException;
  6. import java.security.GeneralSecurityException;
  7. import java.security.SecureRandom;
  8. import java.util.Arrays;
  9. import javax.crypto.Cipher;
  10. import javax.crypto.KeyGenerator;
  11. import javax.crypto.Mac;
  12. import javax.crypto.SecretKey;
  13. import javax.crypto.spec.IvParameterSpec;
  14. import javax.crypto.spec.SecretKeySpec;
  15. import com.jeeplus.common.utils.Encodes;
  16. import com.jeeplus.common.utils.Exceptions;
  17. /**
  18. * 支持HMAC-SHA1消息签名 及 DES/AES对称加密的工具类.
  19. *
  20. * 支持Hex与Base64两种编码方式.
  21. *
  22. * @author calvin
  23. */
  24. public class Cryptos {
  25. private static final String AES = "AES";
  26. private static final String AES_CBC = "AES/CBC/PKCS5Padding";
  27. private static final String HMACSHA1 = "HmacSHA1";
  28. private static final String DEFAULT_URL_ENCODING = "UTF-8";
  29. private static final int DEFAULT_HMACSHA1_KEYSIZE = 160; //RFC2401
  30. private static final int DEFAULT_AES_KEYSIZE = 128;
  31. private static final int DEFAULT_IVSIZE = 16;
  32. private static final byte[] DEFAULT_KEY = new byte[]{-97,88,-94,9,70,-76,126,25,0,3,-20,113,108,28,69,125};
  33. private static SecureRandom random = new SecureRandom();
  34. //-- HMAC-SHA1 funciton --//
  35. /**
  36. * 使用HMAC-SHA1进行消息签名, 返回字节数组,长度为20字节.
  37. *
  38. * @param input 原始输入字符数组
  39. * @param key HMAC-SHA1密钥
  40. */
  41. public static byte[] hmacSha1(byte[] input, byte[] key) {
  42. try {
  43. SecretKey secretKey = new SecretKeySpec(key, HMACSHA1);
  44. Mac mac = Mac.getInstance(HMACSHA1);
  45. mac.init(secretKey);
  46. return mac.doFinal(input);
  47. } catch (GeneralSecurityException e) {
  48. throw Exceptions.unchecked(e);
  49. }
  50. }
  51. /**
  52. * 校验HMAC-SHA1签名是否正确.
  53. *
  54. * @param expected 已存在的签名
  55. * @param input 原始输入字符串
  56. * @param key 密钥
  57. */
  58. public static boolean isMacValid(byte[] expected, byte[] input, byte[] key) {
  59. byte[] actual = hmacSha1(input, key);
  60. return Arrays.equals(expected, actual);
  61. }
  62. /**
  63. * 生成HMAC-SHA1密钥,返回字节数组,长度为160位(20字节).
  64. * HMAC-SHA1算法对密钥无特殊要求, RFC2401建议最少长度为160位(20字节).
  65. */
  66. public static byte[] generateHmacSha1Key() {
  67. try {
  68. KeyGenerator keyGenerator = KeyGenerator.getInstance(HMACSHA1);
  69. keyGenerator.init(DEFAULT_HMACSHA1_KEYSIZE);
  70. SecretKey secretKey = keyGenerator.generateKey();
  71. return secretKey.getEncoded();
  72. } catch (GeneralSecurityException e) {
  73. throw Exceptions.unchecked(e);
  74. }
  75. }
  76. //-- AES funciton --//
  77. /**
  78. * 使用AES加密原始字符串.
  79. *
  80. * @param input 原始输入字符数组
  81. */
  82. public static String aesEncrypt(String input) {
  83. try {
  84. return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), DEFAULT_KEY));
  85. } catch (UnsupportedEncodingException e) {
  86. return "";
  87. }
  88. }
  89. /**
  90. * 使用AES加密原始字符串.
  91. *
  92. * @param input 原始输入字符数组
  93. * @param key 符合AES要求的密钥
  94. */
  95. public static String aesEncrypt(String input, String key) {
  96. try {
  97. return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), Encodes.decodeHex(key)));
  98. } catch (UnsupportedEncodingException e) {
  99. return "";
  100. }
  101. }
  102. /**
  103. * 使用AES加密原始字符串.
  104. *
  105. * @param input 原始输入字符数组
  106. * @param key 符合AES要求的密钥
  107. */
  108. public static byte[] aesEncrypt(byte[] input, byte[] key) {
  109. return aes(input, key, Cipher.ENCRYPT_MODE);
  110. }
  111. /**
  112. * 使用AES加密原始字符串.
  113. *
  114. * @param input 原始输入字符数组
  115. * @param key 符合AES要求的密钥
  116. * @param iv 初始向量
  117. */
  118. public static byte[] aesEncrypt(byte[] input, byte[] key, byte[] iv) {
  119. return aes(input, key, iv, Cipher.ENCRYPT_MODE);
  120. }
  121. /**
  122. * 使用AES解密字符串, 返回原始字符串.
  123. *
  124. * @param input Hex编码的加密字符串
  125. */
  126. public static String aesDecrypt(String input) {
  127. try {
  128. return new String(aesDecrypt(Encodes.decodeHex(input), DEFAULT_KEY), DEFAULT_URL_ENCODING);
  129. } catch (UnsupportedEncodingException e) {
  130. return "";
  131. }
  132. }
  133. /**
  134. * 使用AES解密字符串, 返回原始字符串.
  135. *
  136. * @param input Hex编码的加密字符串
  137. * @param key 符合AES要求的密钥
  138. */
  139. public static String aesDecrypt(String input, String key) {
  140. try {
  141. return new String(aesDecrypt(Encodes.decodeHex(input), Encodes.decodeHex(key)), DEFAULT_URL_ENCODING);
  142. } catch (UnsupportedEncodingException e) {
  143. return "";
  144. }
  145. }
  146. /**
  147. * 使用AES解密字符串, 返回原始字符串.
  148. *
  149. * @param input Hex编码的加密字符串
  150. * @param key 符合AES要求的密钥
  151. */
  152. public static byte[] aesDecrypt(byte[] input, byte[] key) {
  153. return aes(input, key, Cipher.DECRYPT_MODE);
  154. }
  155. /**
  156. * 使用AES解密字符串, 返回原始字符串.
  157. *
  158. * @param input Hex编码的加密字符串
  159. * @param key 符合AES要求的密钥
  160. * @param iv 初始向量
  161. */
  162. public static byte[] aesDecrypt(byte[] input, byte[] key, byte[] iv) {
  163. return aes(input, key, iv, Cipher.DECRYPT_MODE);
  164. }
  165. /**
  166. * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
  167. *
  168. * @param input 原始字节数组
  169. * @param key 符合AES要求的密钥
  170. * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
  171. */
  172. private static byte[] aes(byte[] input, byte[] key, int mode) {
  173. try {
  174. SecretKey secretKey = new SecretKeySpec(key, AES);
  175. Cipher cipher = Cipher.getInstance(AES);
  176. cipher.init(mode, secretKey);
  177. return cipher.doFinal(input);
  178. } catch (GeneralSecurityException e) {
  179. throw Exceptions.unchecked(e);
  180. }
  181. }
  182. /**
  183. * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
  184. *
  185. * @param input 原始字节数组
  186. * @param key 符合AES要求的密钥
  187. * @param iv 初始向量
  188. * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
  189. */
  190. private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
  191. try {
  192. SecretKey secretKey = new SecretKeySpec(key, AES);
  193. IvParameterSpec ivSpec = new IvParameterSpec(iv);
  194. Cipher cipher = Cipher.getInstance(AES_CBC);
  195. cipher.init(mode, secretKey, ivSpec);
  196. return cipher.doFinal(input);
  197. } catch (GeneralSecurityException e) {
  198. throw Exceptions.unchecked(e);
  199. }
  200. }
  201. /**
  202. * 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
  203. */
  204. public static String generateAesKeyString() {
  205. return Encodes.encodeHex(generateAesKey(DEFAULT_AES_KEYSIZE));
  206. }
  207. /**
  208. * 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
  209. */
  210. public static byte[] generateAesKey() {
  211. return generateAesKey(DEFAULT_AES_KEYSIZE);
  212. }
  213. /**
  214. * 生成AES密钥,可选长度为128,192,256位.
  215. */
  216. public static byte[] generateAesKey(int keysize) {
  217. try {
  218. KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
  219. keyGenerator.init(keysize);
  220. SecretKey secretKey = keyGenerator.generateKey();
  221. return secretKey.getEncoded();
  222. } catch (GeneralSecurityException e) {
  223. throw Exceptions.unchecked(e);
  224. }
  225. }
  226. /**
  227. * 生成随机向量,默认大小为cipher.getBlockSize(), 16字节.
  228. */
  229. public static byte[] generateIV() {
  230. byte[] bytes = new byte[DEFAULT_IVSIZE];
  231. random.nextBytes(bytes);
  232. return bytes;
  233. }
  234. }