RsaUtils.java 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. package com.fdkankan.sign;
  2. import javax.crypto.BadPaddingException;
  3. import javax.crypto.Cipher;
  4. import javax.crypto.IllegalBlockSizeException;
  5. import java.io.ByteArrayOutputStream;
  6. import java.io.IOException;
  7. import java.security.*;
  8. import java.security.interfaces.RSAPrivateKey;
  9. import java.security.interfaces.RSAPublicKey;
  10. import java.security.spec.InvalidKeySpecException;
  11. import java.security.spec.PKCS8EncodedKeySpec;
  12. import java.security.spec.X509EncodedKeySpec;
  13. import java.util.Base64;
  14. public class RsaUtils {
  15. static final Base64.Decoder decoder = Base64.getDecoder();
  16. static final Base64.Encoder encoder = Base64.getEncoder();
  17. /**
  18. * RSA密钥长度必须是64的倍数,在512~65536之间。默认是1024
  19. */
  20. public static final int KEY_SIZE = 512;
  21. public static void main(String[] args) {
  22. KeyPairInfo keyPair = getKeyPair();
  23. String publicKey = keyPair.getPublicKey();
  24. String privateKey = keyPair.getPrivateKey();
  25. System.out.println("公钥:"+publicKey);
  26. System.out.println("私钥:"+privateKey);
  27. String ciphertext = RsaUtils.encipher("123", publicKey);
  28. System.out.println(String.format("密文:"+ciphertext));
  29. String deTxt = RsaUtils.decipher(ciphertext, privateKey);
  30. System.out.println(deTxt);
  31. }
  32. /**
  33. * 生成公钥、私钥对(keysize=1024)
  34. */
  35. public static KeyPairInfo getKeyPair() {
  36. return getKeyPair(KEY_SIZE);
  37. }
  38. /**
  39. * 生成公钥、私钥对
  40. *
  41. * @param keySize
  42. * @return
  43. */
  44. public static KeyPairInfo getKeyPair(int keySize) {
  45. try {
  46. KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
  47. keyPairGen.initialize(keySize);
  48. // 生成一个密钥对,保存在keyPair中
  49. KeyPair keyPair = keyPairGen.generateKeyPair();
  50. // 得到私钥
  51. RSAPrivateKey oraprivateKey = (RSAPrivateKey) keyPair.getPrivate();
  52. // 得到公钥
  53. RSAPublicKey orapublicKey = (RSAPublicKey) keyPair.getPublic();
  54. KeyPairInfo pairInfo = new KeyPairInfo(keySize);
  55. // 公钥
  56. byte[] publicKeybyte = orapublicKey.getEncoded();
  57. String publicKeyString = encoder.encodeToString(publicKeybyte);
  58. pairInfo.setPublicKey(publicKeyString);
  59. // 私钥
  60. byte[] privateKeybyte = oraprivateKey.getEncoded();
  61. String privateKeyString = encoder.encodeToString(privateKeybyte);
  62. pairInfo.setPrivateKey(privateKeyString);
  63. return pairInfo;
  64. } catch (Exception e) {
  65. e.printStackTrace();
  66. return null;
  67. }
  68. }
  69. /**
  70. * 获取公钥对象
  71. *
  72. * @param publicKeyBase64
  73. * @return
  74. * @throws InvalidKeySpecException
  75. * @throws NoSuchAlgorithmException
  76. */
  77. public static PublicKey getPublicKey(String publicKeyBase64) throws InvalidKeySpecException, NoSuchAlgorithmException {
  78. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  79. X509EncodedKeySpec publicpkcs8KeySpec = new X509EncodedKeySpec(decoder.decode(publicKeyBase64));
  80. PublicKey publicKey = keyFactory.generatePublic(publicpkcs8KeySpec);
  81. return publicKey;
  82. }
  83. /**
  84. * 获取私钥对象
  85. *
  86. * @param privateKeyBase64
  87. * @return
  88. * @throws NoSuchAlgorithmException
  89. * @throws InvalidKeySpecException
  90. */
  91. public static PrivateKey getPrivateKey(String privateKeyBase64) throws NoSuchAlgorithmException, InvalidKeySpecException {
  92. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  93. PKCS8EncodedKeySpec privatekcs8KeySpec = new PKCS8EncodedKeySpec(decoder.decode(privateKeyBase64));
  94. PrivateKey privateKey = keyFactory.generatePrivate(privatekcs8KeySpec);
  95. return privateKey;
  96. }
  97. /**
  98. * 使用工钥加密
  99. *
  100. * @param content 待加密内容
  101. * @param publicKeyBase64 公钥 base64 编码
  102. * @return 经过 base64 编码后的字符串
  103. */
  104. public static String encipher(String content, String publicKeyBase64) {
  105. return encipher(content, publicKeyBase64, KEY_SIZE / 8 - 11);
  106. }
  107. /**
  108. * 使用公司钥加密(分段加密)
  109. *
  110. * @param content 待加密内容
  111. * @param publicKeyBase64 公钥 base64 编码
  112. * @param segmentSize 分段大小,一般小于 keySize/8(段小于等于0时,将不使用分段加密)
  113. * @return 经过 base64 编码后的字符串
  114. */
  115. public static String encipher(String content, String publicKeyBase64, int segmentSize) {
  116. try {
  117. PublicKey publicKey = getPublicKey(publicKeyBase64);
  118. return encipher(content, publicKey, segmentSize);
  119. } catch (Exception e) {
  120. e.printStackTrace();
  121. return null;
  122. }
  123. }
  124. /**
  125. * 分段加密
  126. *
  127. * @param ciphertext 密文
  128. * @param key 加密秘钥
  129. * @param segmentSize 分段大小,<=0 不分段
  130. * @return
  131. */
  132. public static String encipher(String ciphertext, Key key, int segmentSize) {
  133. try {
  134. // 用公钥加密
  135. byte[] srcBytes = ciphertext.getBytes();
  136. // Cipher负责完成加密或解密工作,基于RSA
  137. Cipher cipher = Cipher.getInstance("RSA");
  138. // 根据公钥,对Cipher对象进行初始化
  139. cipher.init(Cipher.ENCRYPT_MODE, key);
  140. byte[] resultBytes = null;
  141. if (segmentSize > 0)
  142. resultBytes = cipherDoFinal(cipher, srcBytes, segmentSize); // 分段加密
  143. else
  144. resultBytes = cipher.doFinal(srcBytes);
  145. String base64Str = Base64.getEncoder().encodeToString(resultBytes);
  146. return base64Str;
  147. } catch (Exception e) {
  148. e.printStackTrace();
  149. return null;
  150. }
  151. }
  152. /**
  153. * 分段大小
  154. *
  155. * @param cipher
  156. * @param srcBytes
  157. * @param segmentSize
  158. * @return
  159. * @throws IllegalBlockSizeException
  160. * @throws BadPaddingException
  161. * @throws IOException
  162. */
  163. public static byte[] cipherDoFinal(Cipher cipher, byte[] srcBytes, int segmentSize) throws IllegalBlockSizeException, BadPaddingException, IOException {
  164. if (segmentSize <= 0)
  165. throw new RuntimeException("分段大小必须大于0");
  166. ByteArrayOutputStream out = new ByteArrayOutputStream();
  167. int inputLen = srcBytes.length;
  168. int offSet = 0;
  169. byte[] cache;
  170. int i = 0;
  171. // 对数据分段解密
  172. while (inputLen - offSet > 0) {
  173. if (inputLen - offSet > segmentSize) {
  174. cache = cipher.doFinal(srcBytes, offSet, segmentSize);
  175. } else {
  176. cache = cipher.doFinal(srcBytes, offSet, inputLen - offSet);
  177. }
  178. out.write(cache, 0, cache.length);
  179. i++;
  180. offSet = i * segmentSize;
  181. }
  182. byte[] data = out.toByteArray();
  183. out.close();
  184. return data;
  185. }
  186. /**
  187. * 使用私钥解密
  188. *
  189. * @param contentBase64 待加密内容,base64 编码
  190. * @param privateKeyBase64 私钥 base64 编码
  191. * @return
  192. * @segmentSize 分段大小
  193. */
  194. public static String decipher(String contentBase64, String privateKeyBase64) {
  195. return decipher(contentBase64, privateKeyBase64, KEY_SIZE / 8);
  196. }
  197. /**
  198. * 使用私钥解密(分段解密)
  199. *
  200. * @param contentBase64 待加密内容,base64 编码
  201. * @param privateKeyBase64 私钥 base64 编码
  202. * @return
  203. * @segmentSize 分段大小
  204. */
  205. public static String decipher(String contentBase64, String privateKeyBase64, int segmentSize) {
  206. try {
  207. PrivateKey privateKey = getPrivateKey(privateKeyBase64);
  208. return decipher(contentBase64, privateKey, segmentSize);
  209. } catch (Exception e) {
  210. e.printStackTrace();
  211. return null;
  212. }
  213. }
  214. /**
  215. * 分段解密
  216. *
  217. * @param contentBase64 密文
  218. * @param key 解密秘钥
  219. * @param segmentSize 分段大小(小于等于0不分段)
  220. * @return
  221. */
  222. public static String decipher(String contentBase64, Key key, int segmentSize) {
  223. try {
  224. // 用私钥解密
  225. byte[] srcBytes = Base64.getDecoder().decode(contentBase64);
  226. // Cipher负责完成加密或解密工作,基于RSA
  227. Cipher deCipher = Cipher.getInstance("RSA");
  228. // 根据公钥,对Cipher对象进行初始化
  229. deCipher.init(Cipher.DECRYPT_MODE, key);
  230. byte[] decBytes = null;// deCipher.doFinal(srcBytes);
  231. if (segmentSize > 0)
  232. decBytes = cipherDoFinal(deCipher, srcBytes, segmentSize); // 分段加密
  233. else
  234. decBytes = deCipher.doFinal(srcBytes);
  235. String decrytStr = new String(decBytes);
  236. return decrytStr;
  237. } catch (Exception e) {
  238. e.printStackTrace();
  239. return null;
  240. }
  241. }
  242. /**
  243. * 秘钥对
  244. */
  245. public static class KeyPairInfo {
  246. String privateKey;
  247. String publicKey;
  248. int keySize = 0;
  249. public KeyPairInfo(int keySize) {
  250. setKeySize(keySize);
  251. }
  252. public KeyPairInfo(String publicKey, String privateKey) {
  253. setPrivateKey(privateKey);
  254. setPublicKey(publicKey);
  255. }
  256. public String getPrivateKey() {
  257. return privateKey;
  258. }
  259. public void setPrivateKey(String privateKey) {
  260. this.privateKey = privateKey;
  261. }
  262. public String getPublicKey() {
  263. return publicKey;
  264. }
  265. public void setPublicKey(String publicKey) {
  266. this.publicKey = publicKey;
  267. }
  268. public int getKeySize() {
  269. return keySize;
  270. }
  271. public void setKeySize(int keySize) {
  272. this.keySize = keySize;
  273. }
  274. }
  275. }