RSAUtils.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. package com.sdyc.datahub.api.utils;
  2. /**
  3. * <pre>
  4. *
  5. * Created by zhenqin.
  6. * User: zhenqin
  7. * Date: 17/1/10
  8. * Time: 14:41
  9. * Vendor: NowledgeData
  10. * To change this template use File | Settings | File Templates.
  11. *
  12. * </pre>
  13. *
  14. * @author zhenqin
  15. */
  16. import org.apache.commons.codec.binary.Base64;
  17. import org.apache.commons.io.IOUtils;
  18. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  19. import org.bouncycastle.openssl.PEMReader;
  20. import javax.crypto.Cipher;
  21. import java.io.ByteArrayOutputStream;
  22. import java.io.File;
  23. import java.io.FileReader;
  24. import java.nio.ByteBuffer;
  25. import java.security.*;
  26. import java.security.interfaces.RSAPrivateKey;
  27. import java.security.interfaces.RSAPublicKey;
  28. import java.security.spec.PKCS8EncodedKeySpec;
  29. import java.security.spec.X509EncodedKeySpec;
  30. import java.util.HashMap;
  31. import java.util.Map;
  32. /**
  33. * <p>
  34. * RSA公钥/私钥/签名工具包
  35. * <p>
  36. * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
  37. * 由于非对称加密速度极其缓慢,一般文件不使用它来加密而是使用对称加密,<br/>
  38. * 非对称加密算法可以用来对对称加密的密钥加密,这样保证密钥的安全也就保证了数据的安全
  39. * </p>
  40. *
  41. */
  42. public class RSAUtils {
  43. /**
  44. * 加密算法RSA
  45. */
  46. public static final String KEY_ALGORITHM = "RSA";
  47. /**
  48. * 签名算法
  49. */
  50. public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
  51. /**
  52. * 获取公钥的key
  53. */
  54. public static final String PUBLIC_KEY = "LocatorPublicKey";
  55. /**
  56. * 获取私钥的key
  57. */
  58. public static final String PRIVATE_KEY = "LocatorPrivateKey";
  59. /**
  60. * RSA最大加密明文大小
  61. */
  62. public static final int MAX_ENCRYPT_BLOCK = 1024;
  63. /**
  64. * RSA最大解密密文大小
  65. */
  66. public static final int MAX_DECRYPT_BLOCK = 128;
  67. static {
  68. Security.addProvider(new BouncyCastleProvider());
  69. }
  70. static class CipherXX {
  71. final Cipher decryptCipher;
  72. final Cipher encryptCihper;
  73. CipherXX(Key key) {
  74. try {
  75. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  76. if(key instanceof PublicKey) {
  77. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key.getEncoded());
  78. Key publicK = keyFactory.generatePublic(x509KeySpec);
  79. decryptCipher = Cipher.getInstance(keyFactory.getAlgorithm());
  80. decryptCipher.init(Cipher.DECRYPT_MODE, publicK);
  81. // 对数据加密
  82. encryptCihper = Cipher.getInstance(keyFactory.getAlgorithm());
  83. encryptCihper.init(Cipher.ENCRYPT_MODE, publicK);
  84. } else {
  85. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key.getEncoded());
  86. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  87. decryptCipher = Cipher.getInstance(keyFactory.getAlgorithm());
  88. decryptCipher.init(Cipher.DECRYPT_MODE, privateK);
  89. encryptCihper = Cipher.getInstance(keyFactory.getAlgorithm());
  90. encryptCihper.init(Cipher.ENCRYPT_MODE, privateK);
  91. }
  92. } catch (Exception e) {
  93. throw new IllegalStateException(e);
  94. }
  95. }
  96. public Cipher getDecryptCipher() {
  97. return decryptCipher;
  98. }
  99. public Cipher getEncryptCihper() {
  100. return encryptCihper;
  101. }
  102. }
  103. /**
  104. * Thread Local
  105. */
  106. protected final static ThreadLocal<Map> THREAD_LOCAL = new ThreadLocal<Map>();
  107. private RSAUtils() {
  108. }
  109. private static Cipher getCipher(Key key, int mode) throws Exception {
  110. Map<Key, CipherXX> KEY_CIPHER_MAP = THREAD_LOCAL.get();
  111. boolean put = false;
  112. if(KEY_CIPHER_MAP == null) {
  113. KEY_CIPHER_MAP = new HashMap<Key, CipherXX>(3);
  114. put = true;
  115. }
  116. CipherXX cipher = KEY_CIPHER_MAP.get(key);
  117. if(cipher == null) {
  118. cipher = new CipherXX(key);
  119. KEY_CIPHER_MAP.put(key, cipher);
  120. }
  121. if(put) THREAD_LOCAL.set(KEY_CIPHER_MAP);
  122. return mode == Cipher.ENCRYPT_MODE ? cipher.getEncryptCihper() : cipher.getDecryptCipher();
  123. }
  124. /**
  125. * <p>
  126. * 生成密钥对(公钥和私钥)
  127. * </p>
  128. *
  129. * @return
  130. * @throws Exception
  131. */
  132. public static Map<String, Object> genKeyPair() throws Exception {
  133. KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  134. keyPairGen.initialize(1024);
  135. KeyPair keyPair = keyPairGen.generateKeyPair();
  136. PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  137. PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  138. Map<String, Object> keyMap = new HashMap<String, Object>(2);
  139. keyMap.put(PUBLIC_KEY, publicKey);
  140. keyMap.put(PRIVATE_KEY, privateKey);
  141. return keyMap;
  142. }
  143. /**
  144. * <p>
  145. * 生成密钥对(公钥和私钥)
  146. * </p>
  147. *
  148. * @return
  149. * @throws Exception
  150. */
  151. public static Map<String, Object> genFileKeyPair(File privateKeyFile) throws Exception {
  152. PEMReader reader = null;
  153. try {
  154. reader = new PEMReader(new FileReader(privateKeyFile), null);
  155. KeyPair keyPair = (KeyPair) reader.readObject();
  156. PublicKey publicKey = keyPair.getPublic();
  157. PrivateKey privateKey = keyPair.getPrivate();
  158. Map<String, Object> keyMap = new HashMap<String, Object>(2);
  159. keyMap.put(PUBLIC_KEY, publicKey);
  160. keyMap.put(PRIVATE_KEY, privateKey);
  161. return keyMap;
  162. } finally {
  163. IOUtils.closeQuietly(reader);
  164. }
  165. }
  166. /**
  167. * <p>
  168. * 生成密钥对(公钥和私钥)
  169. * </p>
  170. *
  171. * @return
  172. * @throws Exception
  173. */
  174. public static PublicKey genPublicKey(File publicKeyFile) throws Exception {
  175. PEMReader reader = null;
  176. try {
  177. reader = new PEMReader(new FileReader(publicKeyFile), null);
  178. return (PublicKey) reader.readObject();
  179. } finally {
  180. IOUtils.closeQuietly(reader);
  181. }
  182. }
  183. /**
  184. * <p>
  185. * 用私钥对信息生成数字签名
  186. * </p>
  187. *
  188. * @param data 已加密数据
  189. * @param privateKey 私钥(BASE64编码)
  190. *
  191. * @return
  192. * @throws Exception
  193. */
  194. public static String sign(byte[] data, PrivateKey privateKey) throws Exception {
  195. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
  196. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  197. PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  198. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  199. signature.initSign(privateK);
  200. signature.update(data);
  201. return Base64.encodeBase64String(signature.sign());
  202. }
  203. /**
  204. * <p>
  205. * 校验数字签名
  206. * </p>
  207. *
  208. * @param data 已加密数据
  209. * @param publicKey 公钥(BASE64编码)
  210. * @param sign 数字签名
  211. *
  212. * @return
  213. * @throws Exception
  214. *
  215. */
  216. public static boolean verify(byte[] data, PublicKey publicKey, String sign)
  217. throws Exception {
  218. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey.getEncoded());
  219. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  220. PublicKey publicK = keyFactory.generatePublic(keySpec);
  221. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  222. signature.initVerify(publicK);
  223. signature.update(data);
  224. return signature.verify(Base64.decodeBase64(sign));
  225. }
  226. /**
  227. * <P>
  228. * 私钥解密
  229. * </p>
  230. *
  231. * @param encryptedData 已加密数据
  232. * @param privateKey 私钥(BASE64编码)
  233. * @return
  234. * @throws Exception
  235. */
  236. public static byte[] decryptByPrivateKey(byte[] encryptedData, PrivateKey privateKey)
  237. throws Exception {
  238. Cipher cipher = getCipher(privateKey, Cipher.DECRYPT_MODE);
  239. int inputLen = encryptedData.length;
  240. ByteArrayOutputStream out = new ByteArrayOutputStream();
  241. int offSet = 0;
  242. byte[] cache;
  243. int i = 0;
  244. // 对数据分段解密
  245. while (inputLen - offSet > 0) {
  246. if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
  247. cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
  248. } else {
  249. cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
  250. }
  251. out.write(cache, 0, cache.length);
  252. i++;
  253. offSet = i * MAX_DECRYPT_BLOCK;
  254. }
  255. byte[] decryptedData = out.toByteArray();
  256. out.close();
  257. return decryptedData;
  258. }
  259. /**
  260. * <p>
  261. * 公钥解密
  262. * </p>
  263. *
  264. * @param encryptedData 已加密数据
  265. * @param publicKey 公钥(BASE64编码)
  266. * @return
  267. * @throws Exception
  268. */
  269. public static byte[] decryptByPublicKey(byte[] encryptedData, PublicKey publicKey)
  270. throws Exception {
  271. Cipher cipher = getCipher(publicKey, Cipher.DECRYPT_MODE);
  272. int inputLen = encryptedData.length;
  273. ByteBuffer buffer = ByteBuffer.allocate(MAX_ENCRYPT_BLOCK);
  274. int offSet = 0;
  275. byte[] cache;
  276. int i = 0;
  277. // 对数据分段解密
  278. while (inputLen - offSet > 0) {
  279. if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
  280. cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
  281. } else {
  282. cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
  283. }
  284. buffer.put(cache, 0, cache.length);
  285. i++;
  286. offSet = i * MAX_DECRYPT_BLOCK;
  287. }
  288. buffer.flip();
  289. byte[] dst = new byte[buffer.limit()];
  290. buffer.get(dst, 0, buffer.limit());
  291. return dst;
  292. }
  293. /**
  294. * <p>
  295. * 公钥加密
  296. * </p>
  297. *
  298. * @param data 源数据
  299. * @param publicKey 公钥(BASE64编码)
  300. * @return
  301. * @throws Exception
  302. */
  303. public static byte[] encryptByPublicKey(byte[] data, PublicKey publicKey)
  304. throws Exception {
  305. Cipher cipher = getCipher(publicKey, Cipher.ENCRYPT_MODE);
  306. int inputLen = data.length;
  307. ByteBuffer buffer = ByteBuffer.allocate(MAX_ENCRYPT_BLOCK);
  308. int offSet = 0;
  309. byte[] cache;
  310. int i = 0;
  311. // 对数据分段加密
  312. while (inputLen - offSet > 0) {
  313. if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  314. cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
  315. } else {
  316. cache = cipher.doFinal(data, offSet, inputLen - offSet);
  317. }
  318. buffer.put(cache);
  319. i++;
  320. offSet = i * MAX_ENCRYPT_BLOCK;
  321. }
  322. buffer.flip();
  323. byte[] dst = new byte[buffer.limit()];
  324. buffer.get(dst, 0, buffer.limit());
  325. return dst;
  326. }
  327. /**
  328. * <p>
  329. * 私钥加密
  330. * </p>
  331. *
  332. * @param data 源数据
  333. * @param privateKey 私钥(BASE64编码)
  334. * @return
  335. * @throws Exception
  336. */
  337. public static byte[] encryptByPrivateKey(byte[] data, PrivateKey privateKey)
  338. throws Exception {
  339. Cipher cipher = getCipher(privateKey, Cipher.ENCRYPT_MODE);
  340. int inputLen = data.length;
  341. ByteArrayOutputStream out = new ByteArrayOutputStream();
  342. int offSet = 0;
  343. byte[] cache;
  344. int i = 0;
  345. // 对数据分段加密
  346. while (inputLen - offSet > 0) {
  347. if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
  348. cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
  349. } else {
  350. cache = cipher.doFinal(data, offSet, inputLen - offSet);
  351. }
  352. out.write(cache, 0, cache.length);
  353. i++;
  354. offSet = i * MAX_ENCRYPT_BLOCK;
  355. }
  356. byte[] encryptedData = out.toByteArray();
  357. out.close();
  358. return encryptedData;
  359. }
  360. public static void main(String[] args) throws Exception {
  361. String str = "srcbabababababab";
  362. File privateKeyFile = new File("/Volumes/Media/Workspace/美亚DataHub/id_rsa.keystore");
  363. File publicKeyFile = new File("/Volumes/Media/Workspace/美亚DataHub/id_rsa.keystore.pub");
  364. Map<String, Object> keyPair = genFileKeyPair(privateKeyFile);
  365. PrivateKey privateKey = (PrivateKey) keyPair.get(PRIVATE_KEY);
  366. PublicKey publicKeyX = (PublicKey) keyPair.get(PUBLIC_KEY);
  367. PublicKey publicKey = genPublicKey(publicKeyFile);
  368. System.out.println("====== encoding by private key, decoding by public key======");
  369. byte[] x = encryptByPrivateKey(str.getBytes(), privateKey);
  370. System.out.println("encode: " + Base64.encodeBase64String(x));
  371. System.out.println("decode: " + new String(decryptByPublicKey(x, publicKeyX)));
  372. System.out.println("decode: " + new String(decryptByPublicKey(x, publicKey)));
  373. System.out.println("====== encoding by public key, decoding by private key======");
  374. x = encryptByPublicKey(str.getBytes(), publicKey);
  375. System.out.println("encode: " + Base64.encodeBase64String(x));
  376. System.out.println("decode: " + new String(decryptByPrivateKey(x, privateKey)));
  377. System.out.println("====== encoding by public key, decoding by private key======");
  378. x = encryptByPublicKey(str.getBytes(), publicKey);
  379. System.out.println("encode: " + Base64.encodeBase64String(x));
  380. System.out.println("encode: " + Base64.encodeBase64String(x));
  381. System.out.println("encode: " + Base64.encodeBase64String(x));
  382. System.out.println("decode: " + new String(decryptByPrivateKey(x, privateKey)));
  383. System.out.println("======================");
  384. }
  385. }