关键词搜索

源码搜索 ×
×

RSA 实现数据加密解密以及Token管理

发布2016-08-02浏览12406次

详情内容

RSA加密解密key都是成对出现的,一个公钥,一个私钥,并且加密解密一般是公钥加密私钥解密。

1.RSA加密工具

  1. package com.wlyd.fmcgwms.util.api;
  2. import java.io.ByteArrayOutputStream;
  3. import java.security.Key;
  4. import java.security.KeyFactory;
  5. import java.security.KeyPair;
  6. import java.security.KeyPairGenerator;
  7. import java.security.PrivateKey;
  8. import java.security.PublicKey;
  9. import java.security.Signature;
  10. import java.security.interfaces.RSAPrivateKey;
  11. import java.security.interfaces.RSAPublicKey;
  12. import java.security.spec.PKCS8EncodedKeySpec;
  13. import java.security.spec.X509EncodedKeySpec;
  14. import java.util.HashMap;
  15. import java.util.Map;
  16. import javax.crypto.Cipher;
  17. /**
  18. * <p>
  19. * RSA公钥/私钥/签名工具包
  20. * </p>
  21. * <p>
  22. * 罗纳德·李维斯特(Ron [R]ivest)、阿迪·萨莫尔(Adi [S]hamir)和伦纳德·阿德曼(Leonard [A]dleman)
  23. * </p>
  24. * <p>
  25. * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
  26. * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
  27. * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
  28. * </p>
  29. *
  30. * @author IceWee
  31. * @date 2012-4-26
  32. * @version 1.0
  33. */
  34. public class RSAUtils {
  35. /**
  36. * 加密算法RSA
  37. */
  38. public static final String KEY_ALGORITHM = "RSA";
  39. /**
  40. * 签名算法
  41. */
  42. public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
  43. /**
  44. * 获取公钥的key
  45. */
  46. private static final String PUBLIC_KEY = "RSAPublicKey";
  47. /**
  48. * 获取私钥的key
  49. */
  50. private static final String PRIVATE_KEY = "RSAPrivateKey";
  51. /**
  52. * RSA最大加密明文大小
  53. */
  54. private static final int MAX_ENCRYPT_BLOCK = 117;
  55. /**
  56. * RSA最大解密密文大小
  57. */
  58. private static final int MAX_DECRYPT_BLOCK = 128;
  59. /**
  60. * <p>
  61. * 生成密钥对(公钥和私钥)
  62. * </p>
  63. *
  64. * @return
  65. * @throws Exception
  66. */
  67. public static Map<String, Object> genKeyPair() throws Exception {
  68. KeyPairGenerator keyPairGen = KeyPairGenerator
  69. .getInstance(KEY_ALGORITHM);
  70. keyPairGen.initialize(1024);
  71. KeyPair keyPair = keyPairGen.generateKeyPair();
  72. RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  73. RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  74. Map<String, Object> keyMap = new HashMap<String, Object>(2);
  75. keyMap.put(PUBLIC_KEY, publicKey);
  76. keyMap.put(PRIVATE_KEY, privateKey);
  77. return keyMap;
  78. }
  79. /**
  80. * <p>
  81. * 用私钥对信息生成数字签名
  82. * </p>
  83. *
  84. * @param data
  85. * 已加密数据
  86. * @param privateKey
  87. * 私钥(BASE64编码)
  88. *
  89. * @return
  90. * @throws Exception
  91. */
  92. public static String sign(byte[] data, String privateKey) throws Exception {
  93. byte[] keyBytes = Base64Utils.decode(privateKey);
  94. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  95. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  96. PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  97. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  98. signature.initSign(privateK);
  99. signature.update(data);
  100. return Base64Utils.encode(signature.sign());
  101. }
  102. /**
  103. * <p>
  104. * 校验数字签名
  105. * </p>
  106. *
  107. * @param data
  108. * 已加密数据
  109. * @param publicKey
  110. * 公钥(BASE64编码)
  111. * @param sign
  112. * 数字签名
  113. *
  114. * @return
  115. * @throws Exception
  116. *
  117. */
  118. public static boolean verify(byte[] data, String publicKey, String sign)
  119. throws Exception {
  120. byte[] keyBytes = Base64Utils.decode(publicKey);
  121. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
  122. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  123. PublicKey publicK = keyFactory.generatePublic(keySpec);
  124. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  125. signature.initVerify(publicK);
  126. signature.update(data);
  127. return signature.verify(Base64Utils.decode(sign));
  128. }
  129. /**
  130. * <P>
  131. * 私钥解密
  132. * </p>
  133. *
  134. * @param encryptedData
  135. * 已加密数据
  136. * @param privateKey
  137. * 私钥(BASE64编码)
  138. * @return
  139. * @throws Exception
  140. */
  141. public static byte[] decryptByPrivateKey(byte[] encryptedData,
  142. String privateKey) throws Exception {
  143. byte[] keyBytes = Base64Utils.decode(privateKey);
  144. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  145. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  146. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  147. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  148. cipher.init(Cipher.DECRYPT_MODE, privateK);
  149. int inputLen = encryptedData.length;
  150. ByteArrayOutputStream out = new ByteArrayOutputStream();
  151. int offSet = 0;
  152. byte[] cache;
  153. int i = 0;
  154. // 对数据分段解密
  155. while (inputLen - offSet > 0) {
  156. if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
  157. cache = cipher
  158. .doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
  159. } else {
  160. cache = cipher
  161. .doFinal(encryptedData, offSet, inputLen - offSet);
  162. }
  163. out.write(cache, 0, cache.length);
  164. i++;
  165. offSet = i * MAX_DECRYPT_BLOCK;
  166. }
  167. byte[] decryptedData = out.toByteArray();
  168. out.close();
  169. return decryptedData;
  170. }
  171. /**
  172. * <p>
  173. * 公钥解密
  174. * </p>
  175. *
  176. * @param encryptedData
  177. * 已加密数据
  178. * @param publicKey
  179. * 公钥(BASE64编码)
  180. * @return
  181. * @throws Exception
  182. */
  183. public static byte[] decryptByPublicKey(byte[] encryptedData,
  184. String publicKey) throws Exception {
  185. byte[] keyBytes = Base64Utils.decode(publicKey);
  186. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  187. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  188. Key publicK = keyFactory.generatePublic(x509KeySpec);
  189. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  190. cipher.init(Cipher.DECRYPT_MODE, publicK);
  191. int inputLen = encryptedData.length;
  192. ByteArrayOutputStream out = new ByteArrayOutputStream();
  193. int offSet = 0;
  194. byte[] cache;
  195. int i = 0;
  196. // 对数据分段解密
  197. while (inputLen - offSet > 0) {
  198. if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
  199. cache = cipher
  200. .doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
  201. } else {
  202. cache = cipher
  203. .doFinal(encryptedData, offSet, inputLen - offSet);
  204. }
  205. out.write(cache, 0, cache.length);
  206. i++;
  207. offSet = i * MAX_DECRYPT_BLOCK;
  208. }
  209. byte[] decryptedData = out.toByteArray();
  210. out.close();
  211. return decryptedData;
  212. }
  213. /**
  214. * <p>
  215. * 公钥加密
  216. * </p>
  217. *
  218. * @param data
  219. * 源数据
  220. * @param publicKey
  221. * 公钥(BASE64编码)
  222. * @return
  223. * @throws Exception
  224. */
  225. public static byte[] encryptByPublicKey(byte[] data, String publicKey)
  226. throws Exception {
  227. byte[] keyBytes = Base64Utils.decode(publicKey);
  228. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  229. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  230. Key publicK = keyFactory.generatePublic(x509KeySpec);
  231. // 对数据加密
  232. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  233. cipher.init(Cipher.ENCRYPT_MODE, publicK);
  234. int inputLen = data.length;
  235. ByteArrayOutputStream out = new ByteArrayOutputStream();
  236. int offSet = 0;
  237. byte[] cache;
  238. int i = 0;
  239. // 对数据分段加密
  240. while (inputLen - offSet > 0) {
  241. if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  242. cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
  243. } else {
  244. cache = cipher.doFinal(data, offSet, inputLen - offSet);
  245. }
  246. out.write(cache, 0, cache.length);
  247. i++;
  248. offSet = i * MAX_ENCRYPT_BLOCK;
  249. }
  250. byte[] encryptedData = out.toByteArray();
  251. out.close();
  252. return encryptedData;
  253. }
  254. /**
  255. * <p>
  256. * 私钥加密
  257. * </p>
  258. *
  259. * @param data
  260. * 源数据
  261. * @param privateKey
  262. * 私钥(BASE64编码)
  263. * @return
  264. * @throws Exception
  265. */
  266. public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
  267. throws Exception {
  268. byte[] keyBytes = Base64Utils.decode(privateKey);
  269. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  270. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  271. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  272. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  273. cipher.init(Cipher.ENCRYPT_MODE, privateK);
  274. int inputLen = data.length;
  275. ByteArrayOutputStream out = new ByteArrayOutputStream();
  276. int offSet = 0;
  277. byte[] cache;
  278. int i = 0;
  279. // 对数据分段加密
  280. while (inputLen - offSet > 0) {
  281. if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  282. cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
  283. } else {
  284. cache = cipher.doFinal(data, offSet, inputLen - offSet);
  285. }
  286. out.write(cache, 0, cache.length);
  287. i++;
  288. offSet = i * MAX_ENCRYPT_BLOCK;
  289. }
  290. byte[] encryptedData = out.toByteArray();
  291. out.close();
  292. return encryptedData;
  293. }
  294. /**
  295. * <p>
  296. * 获取私钥
  297. * </p>
  298. *
  299. * @param keyMap
  300. * 密钥对
  301. * @return
  302. * @throws Exception
  303. */
  304. public static String getPrivateKey(Map<String, Object> keyMap)
  305. throws Exception {
  306. Key key = (Key) keyMap.get(PRIVATE_KEY);
  307. return Base64Utils.encode(key.getEncoded());
  308. }
  309. /**
  310. * <p>
  311. * 获取公钥
  312. * </p>
  313. *
  314. * @param keyMap
  315. * 密钥对
  316. * @return
  317. * @throws Exception
  318. */
  319. public static String getPublicKey(Map<String, Object> keyMap)
  320. throws Exception {
  321. Key key = (Key) keyMap.get(PUBLIC_KEY);
  322. return Base64Utils.encode(key.getEncoded());
  323. }
  324. }

2.Token管理工具

  1. package com.wlyd.fmcgwms.util;
  2. import java.sql.Timestamp;
  3. import java.util.Date;
  4. import java.util.Map;
  5. import java.util.concurrent.ConcurrentHashMap;
  6. import com.wlyd.fmcgwms.persistence.beans.api.AccessToken;
  7. import com.wlyd.fmcgwms.util.api.RSAUtils;
  8. /**
  9. * SAAS Token管理工具
  10. *
  11. * @packge com.wlyd.wmscloud.util.SAASTokenManager
  12. * @date 2016年5月6日 上午10:20:01
  13. * @author pengjunlin
  14. * @comment
  15. * @update
  16. */
  17. public class SAASTokenManager {
  18. /**
  19. * Token存储对象,保持5000个并发容量(K-useraccount@corCode,V-token)
  20. */
  21. public static Map<String, Object> map = new ConcurrentHashMap<String, Object>(
  22. 5000);
  23. /**
  24. * 获取用户Token
  25. *
  26. * @MethodName: getToken
  27. * @Description:
  28. * @param key
  29. * @return
  30. * @throws
  31. */
  32. public static AccessToken getToken(String key) {
  33. if (map.containsKey(key)) {
  34. return (AccessToken) map.get(key);
  35. }
  36. return null;
  37. }
  38. /**
  39. * 添加用户token
  40. *
  41. * @MethodName: putToken
  42. * @Description:
  43. * @param key
  44. * useraccount@corCode
  45. * @param accessToken
  46. * @throws
  47. */
  48. public static void putToken(String key, AccessToken accessToken) {
  49. map.put(key, accessToken);
  50. }
  51. /**
  52. * 移除token
  53. *
  54. * @MethodName: removeToken
  55. * @Description:
  56. * @param key
  57. * useraccount@corCode
  58. * @throws
  59. */
  60. public static void removeToken(String key) {
  61. if (map.containsKey(key)) {
  62. map.remove(key);
  63. }
  64. }
  65. /**
  66. * 验证Token是否过期
  67. *
  68. * @MethodName: isVlidateToken
  69. * @Description:
  70. * @param key
  71. * useraccount@corCode
  72. * @return
  73. * @throws
  74. */
  75. public static boolean isVlidateToken(String key) {
  76. if (map.containsKey(key)) {
  77. AccessToken accessToken = (AccessToken) map.get(key);
  78. long currentTimestamp = new Date().getTime();
  79. // 有效时间两小时
  80. if (accessToken.getLongTime() - currentTimestamp > 2 * 3600 * 1000) {
  81. return false;
  82. }
  83. return true;
  84. }
  85. return false;
  86. }
  87. /**
  88. * 更新Token
  89. *
  90. * @MethodName: reputToken
  91. * @Description:
  92. * @param key
  93. * useraccount@corCode
  94. * @param accessToken
  95. * @return
  96. * @throws
  97. */
  98. public static void reputToken(String key, AccessToken accessToken) {
  99. if (map.containsKey(key)) {
  100. putToken(key, accessToken);
  101. }
  102. }
  103. /**
  104. * 更新Token
  105. *
  106. * @MethodName: reputToken
  107. * @Description:
  108. * @param key
  109. * useraccount@corCode
  110. * @param tokenStr
  111. * @return
  112. * @throws
  113. */
  114. public static void reputToken(String key, String tokenStr) {
  115. if (map.containsKey(key)) {
  116. AccessToken accessToken = new AccessToken();
  117. accessToken.setToken(tokenStr);
  118. accessToken.setTimestamp(new Timestamp(new Date().getTime()));
  119. putToken(key, accessToken);
  120. }
  121. }
  122. /**
  123. * 是否包含用户token
  124. * @MethodName: iscontainKey
  125. * @Description:
  126. * @param key
  127. * useraccount@corCode
  128. * @return
  129. * @throws
  130. */
  131. public static boolean iscontainKey(String key){
  132. return map.containsKey(key);
  133. }
  134. /**
  135. * 生成RSA加密 Token
  136. *
  137. * @MethodName: generateToken
  138. * @Description:
  139. * @param platformCode
  140. * @param tenantCode
  141. * @return
  142. * @throws
  143. */
  144. public static String generateToken(String publicKey,String platformCode,String tenantCode){
  145. String str=platformCode+tenantCode+new Date().getTime();
  146. try {
  147. byte [] bytes= RSAUtils.encryptByPublicKey(str.getBytes(),publicKey);
  148. return new String( bytes ,"UTF-8");
  149. } catch (Exception e) {
  150. e.printStackTrace();
  151. }
  152. return null;
  153. }
  154. /**
  155. * @throws Exception
  156. * 测试函数入口
  157. *
  158. * @MethodName: main
  159. * @Description:
  160. * @param args
  161. * @throws
  162. */
  163. public static void main(String[] args) throws Exception {
  164. System.out.println(Md5.getMD5Str("123456"));
  165. String key = "wmsadmin@10000";
  166. AccessToken accessToken = new AccessToken();
  167. accessToken.setToken("token==xxjisifdihfifdds");
  168. accessToken.setTimestamp(new Timestamp(new Date().getTime()));
  169. putToken(key, accessToken);
  170. AccessToken accessToken2 = getToken(key);
  171. System.out.println("token:" + accessToken2.getToken());
  172. System.out.println("isValidate:" + isVlidateToken(key));
  173. Map<String, Object> keyMap=RSAUtils.genKeyPair();
  174. String publicKey=RSAUtils.getPublicKey(keyMap);
  175. String privateKey=RSAUtils.getPrivateKey(keyMap);
  176. String token=generateToken(publicKey,"abcdefghijklmnopqrstuvwxyz", "10000");
  177. System.out.println("RSA Token:"+token);
  178. System.out.println("加密:"+new String(RSAUtils.encryptByPublicKey("this is data".getBytes(), publicKey),"UTF-8"));
  179. System.out.println("明文:"+new String(RSAUtils.decryptByPrivateKey(RSAUtils.encryptByPublicKey("this is data".getBytes(), publicKey), privateKey)));
  180. }
  181. }

3.Token实体对象

  1. package com.wlyd.fmcgwms.persistence.beans.api;
  2. import java.io.Serializable;
  3. import java.sql.Timestamp;
  4. /**
  5. * SAAS Token WMS管理实体
  6. *
  7. * @packge com.wlyd.wmscloud.persistence.beans.api.AccessToken
  8. * @date 2016年5月6日 上午10:27:55
  9. * @author pengjunlin
  10. * @comment
  11. * @update
  12. */
  13. public class AccessToken implements Serializable{
  14. /**
  15. *
  16. */
  17. private static final long serialVersionUID = 4759692267927548118L;
  18. private String token;// AccessToken字符串
  19. private Timestamp timestamp;// 时间戳(用于验证token和重新获取token)
  20. public String getToken() {
  21. return token;
  22. }
  23. public void setToken(String token) {
  24. this.token = token;
  25. }
  26. public Timestamp getTimestamp() {
  27. return timestamp;
  28. }
  29. public void setTimestamp(Timestamp timestamp) {
  30. this.timestamp = timestamp;
  31. }
  32. public long getLongTime(){
  33. if(timestamp!=null){
  34. return timestamp.getTime();
  35. }
  36. return 0;
  37. }
  38. }

RSA使用时记住:公钥加密私钥解密。

4.Base64Utils

  1. package com.wlyd.fmcgwms.util.api;
  2. import java.io.ByteArrayInputStream;
  3. import java.io.ByteArrayOutputStream;
  4. import java.io.File;
  5. import java.io.FileInputStream;
  6. import java.io.FileOutputStream;
  7. import java.io.InputStream;
  8. import java.io.OutputStream;
  9. import org.bouncycastle.util.encoders.Base64;
  10. /**
  11. * <p>
  12. * BASE64编码解码工具包
  13. * </p>
  14. * <p>
  15. * 依赖javabase64-1.3.1.jar
  16. * </p>
  17. *
  18. * @author IceWee
  19. * @date 2012-5-19
  20. * @version 1.0
  21. */
  22. public class Base64Utils {
  23. /**
  24. * 文件读取缓冲区大小
  25. */
  26. private static final int CACHE_SIZE = 1024;
  27. /**
  28. * <p>
  29. * BASE64字符串解码为二进制数据
  30. * </p>
  31. *
  32. * @param base64
  33. * @return
  34. * @throws Exception
  35. */
  36. public static byte[] decode(String base64) throws Exception {
  37. return Base64.decode(base64.getBytes());
  38. }
  39. /**
  40. * <p>
  41. * 二进制数据编码为BASE64字符串
  42. * </p>
  43. *
  44. * @param bytes
  45. * @return
  46. * @throws Exception
  47. */
  48. public static String encode(byte[] bytes) throws Exception {
  49. return new String(Base64.encode(bytes));
  50. }
  51. /**
  52. * <p>
  53. * 将文件编码为BASE64字符串
  54. * </p>
  55. * <p>
  56. * 大文件慎用,可能会导致内存溢出
  57. * </p>
  58. *
  59. * @param filePath 文件绝对路径
  60. * @return
  61. * @throws Exception
  62. */
  63. public static String encodeFile(String filePath) throws Exception {
  64. byte[] bytes = fileToByte(filePath);
  65. return encode(bytes);
  66. }
  67. /**
  68. * <p>
  69. * BASE64字符串转回文件
  70. * </p>
  71. *
  72. * @param filePath 文件绝对路径
  73. * @param base64 编码字符串
  74. * @throws Exception
  75. */
  76. public static void decodeToFile(String filePath, String base64) throws Exception {
  77. byte[] bytes = decode(base64);
  78. byteArrayToFile(bytes, filePath);
  79. }
  80. /**
  81. * <p>
  82. * 文件转换为二进制数组
  83. * </p>
  84. *
  85. * @param filePath 文件路径
  86. * @return
  87. * @throws Exception
  88. */
  89. public static byte[] fileToByte(String filePath) throws Exception {
  90. byte[] data = new byte[0];
  91. File file = new File(filePath);
  92. if (file.exists()) {
  93. FileInputStream in = new FileInputStream(file);
  94. ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
  95. byte[] cache = new byte[CACHE_SIZE];
  96. int nRead = 0;
  97. while ((nRead = in.read(cache)) != -1) {
  98. out.write(cache, 0, nRead);
  99. out.flush();
  100. }
  101. out.close();
  102. in.close();
  103. data = out.toByteArray();
  104. }
  105. return data;
  106. }
  107. /**
  108. * <p>
  109. * 二进制数据写文件
  110. * </p>
  111. *
  112. * @param bytes 二进制数据
  113. * @param filePath 文件生成目录
  114. */
  115. public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
  116. InputStream in = new ByteArrayInputStream(bytes);
  117. File destFile = new File(filePath);
  118. if (!destFile.getParentFile().exists()) {
  119. destFile.getParentFile().mkdirs();
  120. }
  121. destFile.createNewFile();
  122. OutputStream out = new FileOutputStream(destFile);
  123. byte[] cache = new byte[CACHE_SIZE];
  124. int nRead = 0;
  125. while ((nRead = in.read(cache)) != -1) {
  126. out.write(cache, 0, nRead);
  127. out.flush();
  128. }
  129. out.close();
  130. in.close();
  131. }
  132. }
Base64的工具网上很多,随便找了个用的。



相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载