RSAEncrypt.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. package com.fdkankan.common.util;
  2. import org.apache.commons.codec.binary.Base64;
  3. import org.springframework.util.ResourceUtils;
  4. import sun.misc.BASE64Decoder;
  5. import javax.crypto.BadPaddingException;
  6. import javax.crypto.Cipher;
  7. import javax.crypto.IllegalBlockSizeException;
  8. import javax.crypto.NoSuchPaddingException;
  9. import java.io.*;
  10. import java.security.*;
  11. import java.security.interfaces.RSAPrivateKey;
  12. import java.security.interfaces.RSAPublicKey;
  13. import java.security.spec.InvalidKeySpecException;
  14. import java.security.spec.PKCS8EncodedKeySpec;
  15. import java.security.spec.X509EncodedKeySpec;
  16. public class RSAEncrypt {
  17. /**
  18. * 字节数据转字符串专用集合
  19. */
  20. private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6',
  21. '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  22. private static final String PRIVATE_KEY = "classpath:key/private_pkcs8.pem";
  23. private static final String PUBLIC_KEY = "classpath:key/public.pem";
  24. /**
  25. * RSA最大解密密文大小
  26. */
  27. private static final int MAX_DECRYPT_BLOCK = 128;
  28. /**
  29. * 随机生成密钥对
  30. */
  31. public static void genKeyPair(String filePath) {
  32. // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
  33. KeyPairGenerator keyPairGen = null;
  34. try {
  35. keyPairGen = KeyPairGenerator.getInstance("RSA");
  36. } catch (NoSuchAlgorithmException e) {
  37. e.printStackTrace();
  38. }
  39. // 初始化密钥对生成器,密钥大小为96-1024位
  40. keyPairGen.initialize(1024, new SecureRandom());
  41. // 生成一个密钥对,保存在keyPair中
  42. KeyPair keyPair = keyPairGen.generateKeyPair();
  43. // 得到私钥
  44. RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  45. // 得到公钥
  46. RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  47. try {
  48. // 得到公钥字符串
  49. Base64 base64 = new Base64();
  50. String publicKeyString = new String(base64.encode(publicKey.getEncoded()));
  51. // 得到私钥字符串
  52. String privateKeyString = new String(base64.encode(privateKey.getEncoded()));
  53. // 将密钥对写入到文件
  54. FileWriter pubfw = new FileWriter(filePath + PUBLIC_KEY);
  55. FileWriter prifw = new FileWriter(filePath + PRIVATE_KEY);
  56. BufferedWriter pubbw = new BufferedWriter(pubfw);
  57. BufferedWriter pribw = new BufferedWriter(prifw);
  58. pubbw.write(publicKeyString);
  59. pribw.write(privateKeyString);
  60. pubbw.flush();
  61. pubbw.close();
  62. pubfw.close();
  63. pribw.flush();
  64. pribw.close();
  65. prifw.close();
  66. } catch (Exception e) {
  67. e.printStackTrace();
  68. }
  69. }
  70. /**
  71. * 从文件中输入流中加载公钥
  72. *
  73. * @throws Exception 加载公钥时产生的异常
  74. */
  75. public static String loadPublicKeyByFile() throws Exception {
  76. try {
  77. BufferedReader br = new BufferedReader(new FileReader(ResourceUtils.getFile(PUBLIC_KEY)));
  78. String readLine = null;
  79. StringBuilder sb = new StringBuilder();
  80. while ((readLine = br.readLine()) != null) {
  81. if (readLine.charAt(0) == '-') {
  82. continue;
  83. } else {
  84. sb.append(readLine);
  85. sb.append('\r');
  86. }
  87. }
  88. br.close();
  89. return sb.toString();
  90. } catch (IOException e) {
  91. throw new Exception("公钥数据流读取错误");
  92. } catch (NullPointerException e) {
  93. throw new Exception("公钥输入流为空");
  94. }
  95. }
  96. /**
  97. * 从文件中输入流中加载公钥
  98. *
  99. * @throws Exception 加载公钥时产生的异常
  100. */
  101. public static String loadPublicKeyByFile(String publicKy) throws Exception {
  102. try {
  103. BufferedReader br = new BufferedReader(new FileReader(new File(publicKy)));
  104. String readLine = null;
  105. StringBuilder sb = new StringBuilder();
  106. while ((readLine = br.readLine()) != null) {
  107. if (readLine.charAt(0) == '-') {
  108. continue;
  109. } else {
  110. sb.append(readLine);
  111. sb.append('\r');
  112. }
  113. }
  114. br.close();
  115. return sb.toString();
  116. } catch (IOException e) {
  117. throw new Exception("公钥数据流读取错误");
  118. } catch (NullPointerException e) {
  119. throw new Exception("公钥输入流为空");
  120. }
  121. }
  122. /**
  123. * 从字符串中加载公钥
  124. *
  125. * @param publicKeyStr 公钥数据字符串
  126. * @throws Exception 加载公钥时产生的异常
  127. */
  128. public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr)
  129. throws Exception {
  130. try {
  131. BASE64Decoder base64 = new BASE64Decoder();
  132. byte[] buffer = base64.decodeBuffer(publicKeyStr);
  133. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  134. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
  135. return (RSAPublicKey) keyFactory.generatePublic(keySpec);
  136. } catch (NoSuchAlgorithmException e) {
  137. throw new Exception("无此算法");
  138. } catch (InvalidKeySpecException e) {
  139. throw new Exception("公钥非法");
  140. } catch (NullPointerException e) {
  141. throw new Exception("公钥数据为空");
  142. }
  143. }
  144. /**
  145. * 从文件中加载私钥
  146. *
  147. * @return 是否成功
  148. * @throws Exception
  149. */
  150. public static String loadPrivateKeyByFile() throws Exception {
  151. try {
  152. InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("key/private_pkcs8.pem");
  153. StringBuilder builder = new StringBuilder();
  154. InputStreamReader reader = new InputStreamReader(inputStream , "UTF-8" );
  155. BufferedReader bfReader = new BufferedReader( reader );
  156. String tmpContent = null;
  157. while ((tmpContent = bfReader.readLine()) != null) {
  158. if (tmpContent.charAt(0) == '-') {
  159. continue;
  160. } else {
  161. builder.append(tmpContent);
  162. builder.append('\r');
  163. }
  164. }
  165. bfReader.close();
  166. return builder.toString();
  167. // BufferedReader br = new BufferedReader(new FileReader(ResourceUtils.getFile(PRIVATE_KEY)));
  168. // String readLine = null;
  169. // StringBuilder sb = new StringBuilder();
  170. // while ((readLine = br.readLine()) != null) {
  171. // if (readLine.charAt(0) == '-') {
  172. // continue;
  173. // } else {
  174. // sb.append(readLine);
  175. // sb.append('\r');
  176. // }
  177. // }
  178. // br.close();
  179. // return sb.toString();
  180. } catch (IOException e) {
  181. throw new Exception("私钥数据读取错误");
  182. } catch (NullPointerException e) {
  183. throw new Exception("私钥输入流为空");
  184. }
  185. }
  186. /**
  187. * 从文件中加载私钥
  188. *
  189. * @return 是否成功
  190. * @throws Exception
  191. */
  192. public static String loadPrivateKeyByFile(String filePath) throws Exception {
  193. try {
  194. InputStream inputStream = new FileInputStream(filePath);
  195. StringBuilder builder = new StringBuilder();
  196. InputStreamReader reader = new InputStreamReader(inputStream , "UTF-8" );
  197. BufferedReader bfReader = new BufferedReader( reader );
  198. String tmpContent = null;
  199. while ((tmpContent = bfReader.readLine()) != null) {
  200. if (tmpContent.charAt(0) == '-') {
  201. continue;
  202. } else {
  203. builder.append(tmpContent);
  204. builder.append('\r');
  205. }
  206. }
  207. bfReader.close();
  208. return builder.toString();
  209. // BufferedReader br = new BufferedReader(new FileReader(ResourceUtils.getFile(PRIVATE_KEY)));
  210. // String readLine = null;
  211. // StringBuilder sb = new StringBuilder();
  212. // while ((readLine = br.readLine()) != null) {
  213. // if (readLine.charAt(0) == '-') {
  214. // continue;
  215. // } else {
  216. // sb.append(readLine);
  217. // sb.append('\r');
  218. // }
  219. // }
  220. // br.close();
  221. // return sb.toString();
  222. } catch (IOException e) {
  223. throw new Exception("私钥数据读取错误");
  224. } catch (NullPointerException e) {
  225. throw new Exception("私钥输入流为空");
  226. }
  227. }
  228. public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)
  229. throws Exception {
  230. try {
  231. BASE64Decoder base64Decoder = new BASE64Decoder();
  232. byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr);
  233. PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
  234. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  235. return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
  236. } catch (NoSuchAlgorithmException e) {
  237. throw new Exception("无此算法");
  238. } catch (InvalidKeySpecException e) {
  239. throw new Exception("私钥非法");
  240. } catch (NullPointerException e) {
  241. throw new Exception("私钥数据为空");
  242. }
  243. }
  244. /**
  245. * 公钥加密过程
  246. *
  247. * @param publicKey 公钥
  248. * @param plainTextData 明文数据
  249. * @return
  250. * @throws Exception 加密过程中的异常信息
  251. */
  252. public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)
  253. throws Exception {
  254. if (publicKey == null) {
  255. throw new Exception("加密公钥为空, 请设置");
  256. }
  257. Cipher cipher = null;
  258. try {
  259. // 使用默认RSA
  260. cipher = Cipher.getInstance("RSA");
  261. // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
  262. cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  263. byte[] output = cipher.doFinal(plainTextData);
  264. return output;
  265. } catch (NoSuchAlgorithmException e) {
  266. throw new Exception("无此加密算法");
  267. } catch (NoSuchPaddingException e) {
  268. e.printStackTrace();
  269. return null;
  270. } catch (InvalidKeyException e) {
  271. throw new Exception("加密公钥非法,请检查");
  272. } catch (IllegalBlockSizeException e) {
  273. throw new Exception("明文长度非法");
  274. } catch (BadPaddingException e) {
  275. throw new Exception("明文数据已损坏");
  276. }
  277. }
  278. /**
  279. * 私钥加密过程
  280. *
  281. * @param privateKey 私钥
  282. * @param plainTextData 明文数据
  283. * @return
  284. * @throws Exception 加密过程中的异常信息
  285. */
  286. public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)
  287. throws Exception {
  288. if (privateKey == null) {
  289. throw new Exception("加密私钥为空, 请设置");
  290. }
  291. Cipher cipher = null;
  292. try {
  293. // 使用默认RSA
  294. cipher = Cipher.getInstance("RSA");
  295. cipher.init(Cipher.ENCRYPT_MODE, privateKey);
  296. byte[] output = cipher.doFinal(plainTextData);
  297. return output;
  298. } catch (NoSuchAlgorithmException e) {
  299. throw new Exception("无此加密算法");
  300. } catch (NoSuchPaddingException e) {
  301. e.printStackTrace();
  302. return null;
  303. } catch (InvalidKeyException e) {
  304. throw new Exception("加密私钥非法,请检查");
  305. } catch (IllegalBlockSizeException e) {
  306. throw new Exception("明文长度非法");
  307. } catch (BadPaddingException e) {
  308. throw new Exception("明文数据已损坏");
  309. }
  310. }
  311. /**
  312. * 私钥解密过程
  313. *
  314. * @param privateKey 私钥
  315. * @param cipherData 密文数据
  316. * @return 明文
  317. * @throws Exception 解密过程中的异常信息
  318. */
  319. public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)
  320. throws Exception {
  321. if (privateKey == null) {
  322. throw new Exception("解密私钥为空, 请设置");
  323. }
  324. Cipher cipher = null;
  325. try {
  326. // 使用默认RSA
  327. cipher = Cipher.getInstance("RSA");
  328. // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
  329. cipher.init(Cipher.DECRYPT_MODE, privateKey);
  330. /*byte[] output = cipher.doFinal(cipherData);
  331. return output;*/
  332. return getDecrytedData(cipherData, cipher);
  333. } catch (NoSuchAlgorithmException e) {
  334. throw new Exception("无此解密算法");
  335. } catch (NoSuchPaddingException e) {
  336. e.printStackTrace();
  337. return null;
  338. } catch (InvalidKeyException e) {
  339. throw new Exception("解密私钥非法,请检查");
  340. } catch (IllegalBlockSizeException e) {
  341. throw new Exception("密文长度非法");
  342. } catch (BadPaddingException e) {
  343. throw new Exception("密文数据已损坏");
  344. }
  345. }
  346. /**
  347. * 公钥解密过程
  348. *
  349. * @param publicKey 公钥
  350. * @param cipherData 密文数据
  351. * @return 明文
  352. * @throws Exception 解密过程中的异常信息
  353. */
  354. public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)
  355. throws Exception {
  356. if (publicKey == null) {
  357. throw new Exception("解密公钥为空, 请设置");
  358. }
  359. Cipher cipher = null;
  360. try {
  361. // 使用默认RSA
  362. cipher = Cipher.getInstance("RSA");
  363. // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
  364. cipher.init(Cipher.DECRYPT_MODE, publicKey);
  365. /*byte[] output = cipher.doFinal(cipherData);
  366. return output;*/
  367. return getDecrytedData(cipherData, cipher);
  368. } catch (NoSuchAlgorithmException e) {
  369. throw new Exception("无此解密算法");
  370. } catch (NoSuchPaddingException e) {
  371. e.printStackTrace();
  372. return null;
  373. } catch (InvalidKeyException e) {
  374. throw new Exception("解密公钥非法,请检查");
  375. } catch (IllegalBlockSizeException e) {
  376. throw new Exception("密文长度非法");
  377. } catch (BadPaddingException e) {
  378. throw new Exception("密文数据已损坏");
  379. }
  380. }
  381. private static byte[] getDecrytedData(byte[] cipherData, Cipher cipher) throws IllegalBlockSizeException, BadPaddingException, IOException {
  382. // int inputLen = cipherData.length;
  383. //// ByteArrayOutputStream out = new ByteArrayOutputStream();
  384. //// int offSet = 0;
  385. //// byte[] cache;
  386. //// int i = 0;
  387. //// // 对数据分段解密
  388. //// while (inputLen - offSet > 0) {
  389. //// if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
  390. //// cache = cipher.doFinal(cipherData, offSet, MAX_DECRYPT_BLOCK);
  391. //// } else {
  392. //// cache = cipher.doFinal(cipherData, offSet, inputLen - offSet);
  393. //// }
  394. //// out.write(cache, 0, cache.length);
  395. //// i++;
  396. //// offSet = i * MAX_DECRYPT_BLOCK;
  397. //// }
  398. //// byte[] decryptedData = out.toByteArray();
  399. //// out.close();
  400. //// return decryptedData;
  401. int inputLen = cipherData.length;
  402. ByteArrayOutputStream out = new ByteArrayOutputStream();
  403. int offSet = 0;
  404. for(int i = 0; inputLen - offSet > 0; offSet = i * 256) {
  405. byte[] cache;
  406. if(inputLen - offSet > 256) {
  407. cache = cipher.doFinal(cipherData, offSet, 256);
  408. } else {
  409. cache = cipher.doFinal(cipherData, offSet, inputLen - offSet);
  410. }
  411. out.write(cache, 0, cache.length);
  412. ++i;
  413. }
  414. byte[] decryptedData = out.toByteArray();
  415. out.close();
  416. return decryptedData;
  417. }
  418. /**
  419. * 字节数据转十六进制字符串
  420. *
  421. * @param data 输入数据
  422. * @return 十六进制内容
  423. */
  424. public static String byteArrayToString(byte[] data) {
  425. StringBuilder stringBuilder = new StringBuilder();
  426. for (int i = 0; i < data.length; i++) {
  427. // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
  428. stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
  429. // 取出字节的低四位 作为索引得到相应的十六进制标识符
  430. stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
  431. if (i < data.length - 1) {
  432. stringBuilder.append(' ');
  433. }
  434. }
  435. return stringBuilder.toString();
  436. }
  437. public static void main(String[] args) throws Exception {
  438. }
  439. }