JAVA加密解密之RSA算法

x33g5p2x  于2021-12-25 转载在 其他  
字(12.4k)|赞(0)|评价(0)|浏览(488)

RSA算法简介

RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

  1. 甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。
  2. 甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效。
  3. 如果有效使用公钥对数据解密。 乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。

RSA算法实现

  1. package com.jianggujin.codec;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.security.Key;
  5. import java.security.KeyFactory;
  6. import java.security.KeyPair;
  7. import java.security.KeyPairGenerator;
  8. import java.security.PrivateKey;
  9. import java.security.PublicKey;
  10. import java.security.Signature;
  11. import java.security.spec.PKCS8EncodedKeySpec;
  12. import java.security.spec.X509EncodedKeySpec;
  13. import javax.crypto.Cipher;
  14. import com.jianggujin.codec.util.JCipherInputStream;
  15. import com.jianggujin.codec.util.JCipherOutputStream;
  16. import com.jianggujin.codec.util.JCodecException;
  17. /** * RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard * Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。 * RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。 * 今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长, * 用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。 * RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。 * * 1、甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。 * 2、甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效, * 3、如果有效使用公钥对数据解密。 乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。 * * @author jianggujin * */
  18. public class JRSA {
  19. private static final String ALGORITHM = "RSA";
  20. /** * RSA签名算法 * * @author jianggujin * */
  21. public static enum JRSASignatureAlgorithm {
  22. MD2withRSA, MD5withRSA, SHA1withRSA, SHA224withRSA, SHA256withRSA, SHA384withRSA, SHA512withRSA;
  23. public String getName() {
  24. return this.name();
  25. }
  26. }
  27. /** * 初始化密钥 * * @return */
  28. public static KeyPair initKey() {
  29. return initKey(1024);
  30. }
  31. /** * 初始化密钥 * * @param keySize * @return */
  32. public static KeyPair initKey(int keySize) {
  33. try {
  34. KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
  35. keyPairGen.initialize(keySize);
  36. return keyPairGen.generateKeyPair();
  37. } catch (Exception e) {
  38. throw new JCodecException(e);
  39. }
  40. }
  41. /** * 签名 * * @param data * @param privateKey * @param signatureAlgorithm * @return */
  42. public static byte[] sign(byte[] data, byte[] privateKey, String signatureAlgorithm) {
  43. try {
  44. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
  45. KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
  46. PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
  47. Signature signature = Signature.getInstance(signatureAlgorithm);
  48. signature.initSign(priKey);
  49. signature.update(data);
  50. return signature.sign();
  51. } catch (Exception e) {
  52. throw new JCodecException(e);
  53. }
  54. }
  55. /** * 验签 * * @param data * @param publicKey * @param sign * @param signatureAlgorithm * @return */
  56. public static boolean verify(byte[] data, byte[] publicKey, byte[] sign, String signatureAlgorithm) {
  57. try {
  58. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
  59. KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
  60. PublicKey pubKey = keyFactory.generatePublic(keySpec);
  61. Signature signature = Signature.getInstance(signatureAlgorithm);
  62. signature.initVerify(pubKey);
  63. signature.update(data);
  64. return signature.verify(sign);
  65. } catch (Exception e) {
  66. throw new JCodecException(e);
  67. }
  68. }
  69. /** * 公钥加密 * * @param data * @param publicKey * @return */
  70. public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) {
  71. Cipher cipher = getEncryptCipherByPublicKey(publicKey);
  72. try {
  73. return cipher.doFinal(data);
  74. } catch (Exception e) {
  75. throw new JCodecException(e);
  76. }
  77. }
  78. /** * 私钥加密 * * @param data * @param privateKey * @return */
  79. public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) {
  80. Cipher cipher = getEncryptCipherByPrivateKey(privateKey);
  81. try {
  82. return cipher.doFinal(data);
  83. } catch (Exception e) {
  84. throw new JCodecException(e);
  85. }
  86. }
  87. /** * 包裹输出流,包裹后的输出流为公钥加密输出流 * * @param out * @param publicKey * @return */
  88. public static OutputStream wrapByPublicKey(OutputStream out, byte[] publicKey) {
  89. Cipher cipher = getEncryptCipherByPublicKey(publicKey);
  90. return new JCipherOutputStream(cipher, out);
  91. }
  92. /** * 包裹输出流,包裹后的输出流为私钥加密输出流 * * @param out * @param privateKey * @return */
  93. public static OutputStream wrapByPrivateKey(OutputStream out, byte[] privateKey) {
  94. Cipher cipher = getEncryptCipherByPrivateKey(privateKey);
  95. return new JCipherOutputStream(cipher, out);
  96. }
  97. /** * 获得公钥加密模式的{@link Cipher} * * @param publicKey * @return */
  98. public static Cipher getEncryptCipherByPublicKey(byte[] publicKey) {
  99. return getCipherByPublicKey(publicKey, Cipher.ENCRYPT_MODE);
  100. }
  101. /** * 获得私钥加密模式的{@link Cipher} * * @param privateKey * @return */
  102. public static Cipher getEncryptCipherByPrivateKey(byte[] privateKey) {
  103. return getCipherByPrivateKey(privateKey, Cipher.ENCRYPT_MODE);
  104. }
  105. /** * 公钥解密 * * @param data * @param publicKey * @return */
  106. public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) {
  107. Cipher cipher = getDecryptCipherByPublicKey(publicKey);
  108. try {
  109. return cipher.doFinal(data);
  110. } catch (Exception e) {
  111. throw new JCodecException(e);
  112. }
  113. }
  114. /** * 私钥解密 * * @param data * @param privateKey * @return */
  115. public static byte[] decryptByPrivateKey(byte[] data, byte[] privateKey) {
  116. Cipher cipher = getDecryptCipherByPrivateKey(privateKey);
  117. try {
  118. return cipher.doFinal(data);
  119. } catch (Exception e) {
  120. throw new JCodecException(e);
  121. }
  122. }
  123. /** * 包裹输入流,原输入流为公钥加密数据输入流 * * @param in * @param publicKey * @return */
  124. public static InputStream wrapByPublicKey(InputStream in, byte[] publicKey) {
  125. Cipher cipher = getDecryptCipherByPublicKey(publicKey);
  126. return new JCipherInputStream(cipher, in);
  127. }
  128. /** * 包裹输入流,原输入流为私钥加密数据输入流 * * @param in * @param privateKey * @return */
  129. public static InputStream wrapByPrivateKey(InputStream in, byte[] privateKey) {
  130. Cipher cipher = getDecryptCipherByPrivateKey(privateKey);
  131. return new JCipherInputStream(cipher, in);
  132. }
  133. /** * 获得公钥解密模式的{@link Cipher} * * @param publicKey * @return */
  134. public static Cipher getDecryptCipherByPublicKey(byte[] publicKey) {
  135. return getCipherByPublicKey(publicKey, Cipher.DECRYPT_MODE);
  136. }
  137. /** * 获得私钥解密模式的{@link Cipher} * * @param privateKey * @return */
  138. public static Cipher getDecryptCipherByPrivateKey(byte[] privateKey) {
  139. return getCipherByPrivateKey(privateKey, Cipher.DECRYPT_MODE);
  140. }
  141. private static Cipher getCipherByPublicKey(byte[] publicKey, int opmode) {
  142. try {
  143. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKey);
  144. KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
  145. Key publicK = keyFactory.generatePublic(x509KeySpec);
  146. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  147. cipher.init(opmode, publicK);
  148. return cipher;
  149. } catch (Exception e) {
  150. throw new JCodecException(e);
  151. }
  152. }
  153. private static Cipher getCipherByPrivateKey(byte[] privateKey, int opmode) {
  154. try {
  155. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
  156. KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
  157. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  158. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  159. cipher.init(opmode, privateK);
  160. return cipher;
  161. } catch (Exception e) {
  162. throw new JCodecException(e);
  163. }
  164. }
  165. }

测试代码:

  1. package com.jianggujin.codec.test;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import java.security.KeyPair;
  8. import org.junit.Test;
  9. import com.jianggujin.codec.JBase64;
  10. import com.jianggujin.codec.JBase64.JEncoder;
  11. import com.jianggujin.codec.JRSA;
  12. import com.jianggujin.codec.JRSA.JRSASignatureAlgorithm;
  13. public class RSATest {
  14. String str = "jianggujin";
  15. File file = new File(getClass().getSimpleName() + ".dat");
  16. @Test
  17. public void test() throws Exception {
  18. System.out.println("原串:" + str);
  19. JEncoder encoder = JBase64.getEncoder();
  20. KeyPair keyPair = JRSA.initKey();
  21. byte[] privateKey = keyPair.getPrivate().getEncoded();
  22. byte[] publicKey = keyPair.getPublic().getEncoded();
  23. System.out.println("私钥:" + encoder.encodeToString(privateKey, "UTF-8"));
  24. System.out.println("公钥:" + encoder.encodeToString(publicKey, "UTF-8"));
  25. for (JRSASignatureAlgorithm algorithm : JRSASignatureAlgorithm.values()) {
  26. System.out.println("-----------------------------------------");
  27. System.out.println("签名算法:" + algorithm.getName());
  28. byte[] signed = JRSA.sign(str.getBytes(), privateKey, algorithm.getName());
  29. System.out.println("签名:" + encoder.encodeToString(signed, "UTF-8"));
  30. boolean verify = JRSA.verify(str.getBytes(), publicKey, signed, algorithm.getName());
  31. System.out.println("验签:" + verify);
  32. }
  33. byte[] encrypt = JRSA.encryptByPrivateKey(str.getBytes(), privateKey);
  34. System.out.println("私钥加密:" + encoder.encodeToString(encrypt, "UTF-8"));
  35. System.out.println("公钥解密:" + new String(JRSA.decryptByPublicKey(encrypt, publicKey)));
  36. System.out.print("输出流私钥加密:" + file.getAbsolutePath());
  37. OutputStream out = JRSA.wrapByPrivateKey(new FileOutputStream(file), privateKey);
  38. out.write(str.getBytes());
  39. out.flush();
  40. out.close();
  41. System.out.println();
  42. System.out.print("输入流公钥解密:");
  43. InputStream in = JRSA.wrapByPublicKey(new FileInputStream(file), publicKey);
  44. byte[] buffer = new byte[1024];
  45. int len = in.read(buffer);
  46. System.out.println(new String(buffer, 0, len));
  47. encrypt = JRSA.encryptByPublicKey(str.getBytes(), publicKey);
  48. System.out.println("公钥加密:" + encoder.encodeToString(encrypt, "UTF-8"));
  49. System.out.println("私钥解密:" + new String(JRSA.decryptByPrivateKey(encrypt, privateKey)));
  50. System.out.print("输出流公钥加密:" + file.getAbsolutePath());
  51. out = JRSA.wrapByPublicKey(new FileOutputStream(file), publicKey);
  52. out.write(str.getBytes());
  53. out.flush();
  54. out.close();
  55. System.out.println();
  56. System.out.print("输入流私钥解密:");
  57. in = JRSA.wrapByPrivateKey(new FileInputStream(file), privateKey);
  58. len = in.read(buffer);
  59. System.out.println(new String(buffer, 0, len));
  60. }
  61. }

测试结果:
原串:jianggujin
私钥:MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIg0EUOutbMRJDuNNCJT97QPK2rrTYFBLBu9vXk6upCvTCn9yZA2M2wNrCv39hVGbXXHSxs2zXpYlWR1IKUvWppQfIscckB3sXJIvvR25xWJWKJSOrbddNKXyvdLjDgor13QVaXJECZJMXsDLFw9kJ+GXz5nzQ43qHyefzLC2YkdAgMBAAECgYAPdlm/ZUYbXgbO++i/POkR9+bl7HCQC+YGADRSXuhvJHdxDO6lAII18hdppmy5XZVvmYBdRottKEFNdj6OgiG22GT2qe0voBaTFpnMEtTNJWJsDjRfnl369XQFC8uPfYF9Qn1nYBSTS+1pxyJSybZkkmAv99sKh1WTHFd+CdhZwQJBANBty698Yy5IXyHHs56EMC81DJjmmZ+WYpRqmUJTSyoCmW9KTztVStX42RMG0tLYOPstbJ0M6rr0G9JVWjJJ3OcCQQCnSjz8hKzu6LC0Arj6fVKPAWboHAjHCQ8AG71JEFkjhvXKYW7dJYua1ePYm4+b8+rr7Ovw6Mvesl36mCWYDIVbAkBkNKU8lTzJv5mdD/nXOA5CY+rOh+9Lvm1elXFhZdI5PE6wJrW4/OShwqX6c8lf/PxIJiqVxuQDReEqWkam7sP5AkA19u/HcbErfGqMFxi+zTCVqxkcJPb75cMuAMTFzf1DRaUCPP37XsIzF25hkIT6BOwyYQIXe7FQTG+eh/gQnXFjAkAGRVxiTmzpSchUjuKOXgS1zjVd4oYqiP4UXQRrrCTmhldkLIEVhm+zsf+t6o01aS/Bc5pJcAUElYvW2AiNFDRx
公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCINBFDrrWzESQ7jTQiU/e0Dytq602BQSwbvb15OrqQr0wp/cmQNjNsDawr9/YVRm11x0sbNs16WJVkdSClL1qaUHyLHHJAd7FySL70ducViViiUjq23XTSl8r3S4w4KK9d0FWlyRAmSTF7AyxcPZCfhl8+Z80ON6h8nn8ywtmJHQIDAQAB
—————————————–
签名算法:MD2withRSA
签名:U1gqODkxXTwQJOqLqHRV3S4gbhIxC036k+LpG4W4kcxhZogDrZxtfFpisXSqgp3DSw+PGgKy6rT7RLIExCi1Qvdh23vmB2Fe7F6yHQ34rhm1NNnbye9ELro7m45t3DP3doY/6qXtGW8N/M5aBs2Mwh2r8uB0KZxE53VvXdWJVac=
验签:true
—————————————–
签名算法:MD5withRSA
签名:AHd5QQTqZgDlXFmS1YF8PSZI7d4gGB50vMnFELwdADZ49PVuMKkiPDHsao5g//6p6e5f13PIuUgZYrOPSyifSSKSy7kT/zhjh7quMUtK3xeNspOQH2pXI1PlU8duY3aejeYfqBQ5rc+L+tFk/B29H/WmtlGVImWV62aCvt8YduY=
验签:true
—————————————–
签名算法:SHA1withRSA
签名:g0bsq25OrrngrAntLNdsXDixO3Zo+DZOe1xdT4n1FLiQDkvv5NvS/HM5jyl8pkZa2VV+536oyRKDrqyLQR8bkbsnjWae9aBF2JweRIXGo4sVm1csQglrz52t4W4/gF0oWqlJhHucTClPdX1XGMBMnRjfXHM01F7QdN1Rezc+1xk=
验签:true
—————————————–
签名算法:SHA224withRSA
签名:QeD1a4s6gaEee9bDTakjergCfwqKfX7x89D8e7GY6rroMf8d3g9JCZkt4PePbhWdorVsUiDexTkHTCXcAGXHu6l9Lxh97O7S/H090i24JLThhVLKBLRZDHidLzfclbvqBky7Fk2PSSlpuxARmxbbc3N5J1a0Sqk9NnMO0AMvgMI=
验签:true
—————————————–
签名算法:SHA256withRSA
签名:FQAliYG2d1rJi+iShdrTuxAQ+TYaghbCcQ0WuvYwmMHf5mz8ilMgGXxuRM75TRLy/LX/Si6uec+gnfB3vC8ep+qWOPh/HXdmofEOpKih+Z3/iy8zvRH+PpuNSwwCifqgGXHzA/thaw93hTx+Ji5qnl8PUn6Rt/cHYsx5takQXGQ=
验签:true
—————————————–
签名算法:SHA384withRSA
签名:ZuD/Cg8DFHZUzj3h61kLHDDU30xBjgq9x4xvwmSkqyEddQfyr2MPAIj4PpiAXhSNpkmKtm+tC0VQseXzfH2tE0Ylzilwun3rfl/Th83bwB9uG4i0xU0vYQkN7flCS7LwbTc/XQc+i3bpSYdJ7/x34kSYEC+K9KMI3n55CNOEEiw=
验签:true
—————————————–
签名算法:SHA512withRSA
签名:euYju1srslIb3yWTM7sAQZIARvgTPKlfd7hCWQ3a6GMK9272kLQWi4b4TQe4gKbMBh6KmMhXJNdRYrEk1AM61d46YHyGqh0TvsaLrk66wemtILBogJzmEFiOpXbPbEtIuOfQMzc+NPDoLDhdCcLJ1ZhSid6a7eR0mb4aYqdJbfY=
验签:true
私钥加密:a4HdJteeI56m1aYbulriTzyvheKlarumWNEesksoO6iQqWNUPHtqe6GfZJuAdu6YOcmf9xctPdRAnTmTTC9pwKlfr0FcIdsheV05ZmdnkfkW5jd73aeP5MCVSiS/gZ74sECB/q3ByJxu+1kHy4dGx920lra7K9iwT0KtaRFFnwI=
公钥解密:jianggujin
输出流私钥加密:F:\workspace\java\eclipse\JCodec\RSATest.dat
输入流公钥解密:jianggujin
公钥加密:FD8wt6qDlmEdGt58ez0YnbZom9+756BOIF701NosVtpYTnG7agyfxdsq486PV5BTeiFU9zH+KKJkh4bXBDFUA0UV+YiLaeX+a/mScG5R7teoqiYpQ63pLhRnD6eFBbbcM+i5oEW3maM9si5nbWjEZ4aYxxQaz4C16Tl9Yeg9OPY=
私钥解密:jianggujin
输出流公钥加密:F:\workspace\java\eclipse\JCodec\RSATest.dat
输入流私钥解密:jianggujin

相关文章