经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
java版RSA工具类
来源:cnblogs  作者:代码唐小白  时间:2018/11/6 18:27:01  对本文有异议
  1. /**
  2. * RSA算法加密/解密工具类
  3. */
  4. public class RSAUtils {
  5. private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class);
  6. /** 算法名称 */
  7. private static final String ALGORITHM = "RSA";
  8. /** 默认密钥大小 */
  9. private static final int KEY_SIZE = 1024;
  10. /** 用来指定保存密钥对的文件名和存储的名称 */
  11. private static final String PUBLIC_KEY_NAME = "publicKey";
  12. private static final String PRIVATE_KEY_NAME = "privateKey";
  13. private static final String PUBLIC_FILENAME = "publicKey.properties";
  14. private static final String PRIVATE_FILENAME = "privateKey.properties";
  15. /** 密钥对生成器 */
  16. private static KeyPairGenerator keyPairGenerator = null;
  17. private static KeyFactory keyFactory = null;
  18. /** 缓存的密钥对 */
  19. private static KeyPair keyPair = null;
  20. /** Base64 编码/解码器 JDK1.8 */
  21. private static Base64.Decoder decoder = Base64.getDecoder();
  22. private static Base64.Encoder encoder = Base64.getEncoder();
  23. /** 初始化密钥工厂 */
  24. static{
  25. try {
  26. keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
  27. keyFactory = KeyFactory.getInstance(ALGORITHM);
  28. } catch (NoSuchAlgorithmException e) {
  29. LOGGER.error(e.getMessage(),e);
  30. }
  31. }
  32. /** 私有构造器 */
  33. private RSAUtils(){}
  34. /**
  35. * 生成密钥对
  36. * 将密钥分别用Base64编码保存到#publicKey.properties#和#privateKey.properties#文件中
  37. * 保存的默认名称分别为publicKey和privateKey
  38. */
  39. public static synchronized Map<String, Object> generateKeyPair(){
  40. try {
  41. keyPairGenerator.initialize(KEY_SIZE,new SecureRandom(UUID.randomUUID().toString().replaceAll("-","").getBytes()));
  42. keyPair = keyPairGenerator.generateKeyPair();
  43. } catch (InvalidParameterException e){
  44. LOGGER.error("KeyPairGenerator does not support a key length of " + KEY_SIZE + ".",e);
  45. } catch (NullPointerException e){
  46. LOGGER.error("RSAUtils#key_pair_gen is null,can not generate KeyPairGenerator instance.",e);
  47. }
  48. RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
  49. RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
  50. String publicKeyString = encoder.encodeToString(rsaPublicKey.getEncoded());
  51. String privateKeyString = encoder.encodeToString(rsaPrivateKey.getEncoded());
  52. storeKey(publicKeyString,PUBLIC_KEY_NAME,PUBLIC_FILENAME);
  53. storeKey(privateKeyString,PRIVATE_KEY_NAME,PRIVATE_FILENAME);
  54. Map<String, Object> keyPair = new HashMap<>();
  55. keyPair.put("public", privateKeyString);
  56. keyPair.put("private", privateKeyString);
  57. return keyPair;
  58. }
  59. /**
  60. * 将指定的密钥字符串保存到文件中,如果找不到文件,就创建
  61. * @param keyString 密钥的Base64编码字符串(值)
  62. * @param keyName 保存在文件中的名称(键)
  63. * @param fileName 目标文件名
  64. */
  65. private static void storeKey(String keyString,String keyName,String fileName){
  66. Properties properties = new Properties();
  67. //存放密钥的绝对地址
  68. String path = null;
  69. try{
  70. path = RSAUtils.class.getClassLoader().getResource(fileName).toString();
  71. path = path.substring(path.indexOf(":") + 1);
  72. }catch (NullPointerException e){
  73. //如果不存#fileName#就创建
  74. LOGGER.warn("storeKey()# " + fileName + " is not exist.Begin to create this file.");
  75. String classPath = RSAUtils.class.getClassLoader().getResource("").toString();
  76. String prefix = classPath.substring(classPath.indexOf(":") + 1);
  77. String suffix = fileName;
  78. File file = new File(prefix + suffix);
  79. try {
  80. file.createNewFile();
  81. path = file.getAbsolutePath();
  82. } catch (IOException e1) {
  83. LOGGER.error(fileName +" create fail.",e1);
  84. }
  85. }
  86. try(OutputStream out = new FileOutputStream(path)){
  87. properties.setProperty(keyName,keyString);
  88. properties.store(out,"There is " + keyName);
  89. } catch (FileNotFoundException e) {
  90. LOGGER.error("ModulusAndExponent.properties is not found.",e);
  91. } catch (IOException e) {
  92. LOGGER.error("OutputStream output failed.",e);
  93. }
  94. }
  95. /**
  96. * 获取密钥字符串
  97. * @param keyName 需要获取的密钥名
  98. * @param fileName 密钥所在文件
  99. * @return Base64编码的密钥字符串
  100. */
  101. private static String getKeyString(String keyName,String fileName){
  102. if (RSAUtils.class.getClassLoader().getResource(fileName) == null){
  103. LOGGER.warn("getKeyString()# " + fileName + " is not exist.Will run #generateKeyPair()# firstly.");
  104. generateKeyPair();
  105. }
  106. try(InputStream in = RSAUtils.class.getClassLoader().getResource(fileName).openStream()){
  107. Properties properties = new Properties();
  108. properties.load(in);
  109. return properties.getProperty(keyName);
  110. } catch (IOException e) {
  111. LOGGER.error("getKeyString()#" + e.getMessage(),e);
  112. }
  113. return null;
  114. }
  115. /**
  116. * 从文件获取RSA公钥
  117. * @return RSA公钥
  118. * @throws InvalidKeySpecException
  119. */
  120. public static RSAPublicKey getPublicKey(){
  121. try {
  122. byte[] keyBytes = decoder.decode(getKeyString(PUBLIC_KEY_NAME,PUBLIC_FILENAME));
  123. X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
  124. return (RSAPublicKey)keyFactory.generatePublic(x509EncodedKeySpec);
  125. }catch (InvalidKeySpecException e) {
  126. LOGGER.error("getPublicKey()#" + e.getMessage(),e);
  127. }
  128. return null;
  129. }
  130. /**
  131. * 从文件获取RSA私钥
  132. * @return RSA私钥
  133. * @throws InvalidKeySpecException
  134. */
  135. public static RSAPrivateKey getPrivateKey(){
  136. try {
  137. byte[] keyBytes = decoder.decode(getKeyString(PRIVATE_KEY_NAME,PRIVATE_FILENAME));
  138. PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
  139. return (RSAPrivateKey)keyFactory.generatePrivate(pkcs8EncodedKeySpec);
  140. } catch (InvalidKeySpecException e) {
  141. LOGGER.error("getPrivateKey()#" + e.getMessage(),e);
  142. }
  143. return null;
  144. }
  145. /**
  146. * RSA公钥加密
  147. * @param content 等待加密的数据
  148. * @param publicKey RSA 公钥 if null then getPublicKey()
  149. * @return 加密后的密文(16进制的字符串)
  150. */
  151. public static String encryptByPublic(byte[] content,PublicKey publicKey){
  152. if (publicKey == null){
  153. publicKey = getPublicKey();
  154. }
  155. try {
  156. Cipher cipher = Cipher.getInstance("RSA");
  157. cipher.init(Cipher.ENCRYPT_MODE,publicKey);
  158. //该密钥能够加密的最大字节长度
  159. int splitLength = ((RSAPublicKey)publicKey).getModulus().bitLength() / 8 -11;
  160. byte[][] arrays = splitBytes(content,splitLength);
  161. StringBuffer stringBuffer = new StringBuffer();
  162. for (byte[] array : arrays){
  163. stringBuffer.append(bytesToHexString(cipher.doFinal(array)));
  164. }
  165. return stringBuffer.toString();
  166. } catch (NoSuchAlgorithmException e) {
  167. LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
  168. } catch (NoSuchPaddingException e) {
  169. LOGGER.error("encrypt()#NoSuchPaddingException",e);
  170. } catch (InvalidKeyException e) {
  171. LOGGER.error("encrypt()#InvalidKeyException",e);
  172. } catch (BadPaddingException e) {
  173. LOGGER.error("encrypt()#BadPaddingException",e);
  174. } catch (IllegalBlockSizeException e) {
  175. LOGGER.error("encrypt()#IllegalBlockSizeException",e);
  176. }
  177. return null;
  178. }
  179. /**
  180. * RSA私钥加密
  181. * @param content 等待加密的数据
  182. * @param privateKey RSA 私钥 if null then getPrivateKey()
  183. * @return 加密后的密文(16进制的字符串)
  184. */
  185. public static String encryptByPrivate(byte[] content,PrivateKey privateKey){
  186. if (privateKey == null){
  187. privateKey = getPrivateKey();
  188. }
  189. try {
  190. Cipher cipher = Cipher.getInstance("RSA");
  191. cipher.init(Cipher.ENCRYPT_MODE,privateKey);
  192. //该密钥能够加密的最大字节长度
  193. int splitLength = ((RSAPrivateKey)privateKey).getModulus().bitLength() / 8 -11;
  194. byte[][] arrays = splitBytes(content,splitLength);
  195. StringBuffer stringBuffer = new StringBuffer();
  196. for(byte[] array : arrays){
  197. stringBuffer.append(bytesToHexString(cipher.doFinal(array)));
  198. }
  199. return stringBuffer.toString();
  200. } catch (NoSuchAlgorithmException e) {
  201. LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
  202. } catch (NoSuchPaddingException e) {
  203. LOGGER.error("encrypt()#NoSuchPaddingException",e);
  204. } catch (InvalidKeyException e) {
  205. LOGGER.error("encrypt()#InvalidKeyException",e);
  206. } catch (BadPaddingException e) {
  207. LOGGER.error("encrypt()#BadPaddingException",e);
  208. } catch (IllegalBlockSizeException e) {
  209. LOGGER.error("encrypt()#IllegalBlockSizeException",e);
  210. }
  211. return null;
  212. }
  213. /**
  214. * RSA私钥解密
  215. * @param content 等待解密的数据
  216. * @param privateKey RSA 私钥 if null then getPrivateKey()
  217. * @return 解密后的明文
  218. */
  219. public static String decryptByPrivate(String content,PrivateKey privateKey){
  220. if (privateKey == null){
  221. privateKey = getPrivateKey();
  222. }
  223. try {
  224. Cipher cipher = Cipher.getInstance("RSA");
  225. cipher.init(Cipher.DECRYPT_MODE,privateKey);
  226. //该密钥能够加密的最大字节长度
  227. int splitLength = ((RSAPrivateKey)privateKey).getModulus().bitLength() / 8;
  228. byte[] contentBytes = hexStringToBytes(content);
  229. byte[][] arrays = splitBytes(contentBytes,splitLength);
  230. StringBuffer stringBuffer = new StringBuffer();
  231. String sTemp = null;
  232. for (byte[] array : arrays){
  233. stringBuffer.append(new String(cipher.doFinal(array)));
  234. }
  235. return stringBuffer.toString();
  236. } catch (NoSuchAlgorithmException e) {
  237. LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
  238. } catch (NoSuchPaddingException e) {
  239. LOGGER.error("encrypt()#NoSuchPaddingException",e);
  240. } catch (InvalidKeyException e) {
  241. LOGGER.error("encrypt()#InvalidKeyException",e);
  242. } catch (BadPaddingException e) {
  243. LOGGER.error("encrypt()#BadPaddingException",e);
  244. } catch (IllegalBlockSizeException e) {
  245. LOGGER.error("encrypt()#IllegalBlockSizeException",e);
  246. }
  247. return null;
  248. }
  249. /**
  250. * RSA公钥解密
  251. * @param content 等待解密的数据
  252. * @param publicKey RSA 公钥 if null then getPublicKey()
  253. * @return 解密后的明文
  254. */
  255. public static String decryptByPublic(String content,PublicKey publicKey){
  256. if (publicKey == null){
  257. publicKey = getPublicKey();
  258. }
  259. try {
  260. Cipher cipher = Cipher.getInstance("RSA");
  261. cipher.init(Cipher.DECRYPT_MODE,publicKey);
  262. //该密钥能够加密的最大字节长度
  263. int splitLength = ((RSAPublicKey)publicKey).getModulus().bitLength() / 8;
  264. byte[] contentBytes = hexStringToBytes(content);
  265. byte[][] arrays = splitBytes(contentBytes,splitLength);
  266. StringBuffer stringBuffer = new StringBuffer();
  267. String sTemp = null;
  268. for (byte[] array : arrays){
  269. stringBuffer.append(new String(cipher.doFinal(array)));
  270. }
  271. return stringBuffer.toString();
  272. } catch (NoSuchAlgorithmException e) {
  273. LOGGER.error("encrypt()#NoSuchAlgorithmException",e);
  274. } catch (NoSuchPaddingException e) {
  275. LOGGER.error("encrypt()#NoSuchPaddingException",e);
  276. } catch (InvalidKeyException e) {
  277. LOGGER.error("encrypt()#InvalidKeyException",e);
  278. } catch (BadPaddingException e) {
  279. LOGGER.error("encrypt()#BadPaddingException",e);
  280. } catch (IllegalBlockSizeException e) {
  281. LOGGER.error("encrypt()#IllegalBlockSizeException",e);
  282. }
  283. return null;
  284. }
  285. /**
  286. * 根据限定的每组字节长度,将字节数组分组
  287. * @param bytes 等待分组的字节组
  288. * @param splitLength 每组长度
  289. * @return 分组后的字节组
  290. */
  291. public static byte[][] splitBytes(byte[] bytes,int splitLength){
  292. //bytes与splitLength的余数
  293. int remainder = bytes.length % splitLength;
  294. //数据拆分后的组数,余数不为0时加1
  295. int quotient = remainder != 0 ? bytes.length / splitLength + 1:bytes.length / splitLength;
  296. byte[][] arrays = new byte[quotient][];
  297. byte[] array = null;
  298. for (int i =0;i<quotient;i++){
  299. //如果是最后一组(quotient-1),同时余数不等于0,就将最后一组设置为remainder的长度
  300. if (i == quotient -1 && remainder != 0){
  301. array = new byte[remainder];
  302. System.arraycopy(bytes,i * splitLength,array,0,remainder);
  303. } else {
  304. array = new byte[splitLength];
  305. System.arraycopy(bytes,i*splitLength,array,0,splitLength);
  306. }
  307. arrays[i] = array;
  308. }
  309. return arrays;
  310. }
  311. /**
  312. * 将字节数组转换成16进制字符串
  313. * @param bytes 即将转换的数据
  314. * @return 16进制字符串
  315. */
  316. public static String bytesToHexString(byte[] bytes){
  317. StringBuffer sb = new StringBuffer(bytes.length);
  318. String temp = null;
  319. for (int i = 0;i< bytes.length;i++){
  320. temp = Integer.toHexString(0xFF & bytes[i]);
  321. if(temp.length() <2){
  322. sb.append(0);
  323. }
  324. sb.append(temp);
  325. }
  326. return sb.toString();
  327. }
  328. /**
  329. * 将16进制字符串转换成字节数组
  330. * @param hex 16进制字符串
  331. * @return byte[]
  332. */
  333. public static byte[] hexStringToBytes(String hex){
  334. int len = (hex.length() / 2);
  335. hex = hex.toUpperCase();
  336. byte[] result = new byte[len];
  337. char[] chars = hex.toCharArray();
  338. for (int i= 0;i<len;i++){
  339. int pos = i * 2;
  340. result[i] = (byte)(toByte(chars[pos]) << 4 | toByte(chars[pos + 1]));
  341. }
  342. return result;
  343. }
  344. /**
  345. * 将char转换为byte
  346. * @param c char
  347. * @return byte
  348. */
  349. private static byte toByte(char c){
  350. return (byte)"0123456789ABCDEF".indexOf(c);
  351. }
  352. public static void main(String[] args) {
  353. String s = "test";
  354. RSAUtils.generateKeyPair();
  355. String c1 = RSAUtils.encryptByPublic(s.getBytes(),null);
  356. String m1 = RSAUtils.decryptByPrivate(c1,null);
  357. String c2 = RSAUtils.encryptByPrivate(s.getBytes(),null);
  358. String m2 = RSAUtils.decryptByPublic(c2,null);
  359. System.out.println(c1);
  360. System.out.println(m1);
  361. System.out.println(c2);
  362. System.out.println(m2);
  363. }
  364. }

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号