RSA
    这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。

   
这种加密算法的特点主要是密钥的变化,上文我们看到DES只有一个密钥。相当于只有一把钥匙,如果这把钥匙丢了,数据也就不安全了。RSA同时有两把钥匙,公钥与私钥。同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验。确保数据在传输工程中不被修改。



流程分析:

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

按如上步骤给出序列图,如下:

通过java代码实现如下:Coder类见 Java加密技术(一)

  1. import java.security.Key;
  2. import java.security.KeyFactory;
  3. import java.security.KeyPair;
  4. import java.security.KeyPairGenerator;
  5. import java.security.PrivateKey;
  6. import java.security.PublicKey;
  7. import java.security.Signature;
  8. import java.security.interfaces.RSAPrivateKey;
  9. import java.security.interfaces.RSAPublicKey;
  10. import java.security.spec.PKCS8EncodedKeySpec;
  11. import java.security.spec.X509EncodedKeySpec;
  12. import java.util.HashMap;
  13. import java.util.Map;
  14. import javax.crypto.Cipher;
  15. /**
  16. * RSA安全编码组件
  17. *
  18. * @author 梁栋
  19. * @version 1.0
  20. * @since 1.0
  21. */
  22. public abstract class RSACoder extends Coder {
  23. public static final String KEY_ALGORITHM = "RSA";
  24. public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
  25. private static final String PUBLIC_KEY = "RSAPublicKey";
  26. private static final String PRIVATE_KEY = "RSAPrivateKey";
  27. /**
  28. * 用私钥对信息生成数字签名
  29. *
  30. * @param data
  31. *            加密数据
  32. * @param privateKey
  33. *            私钥
  34. *
  35. * @return
  36. * @throws Exception
  37. */
  38. public static String sign(byte[] data, String privateKey) throws Exception {
  39. // 解密由base64编码的私钥
  40. byte[] keyBytes = decryptBASE64(privateKey);
  41. // 构造PKCS8EncodedKeySpec对象
  42. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  43. // KEY_ALGORITHM 指定的加密算法
  44. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  45. // 取私钥匙对象
  46. PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
  47. // 用私钥对信息生成数字签名
  48. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  49. signature.initSign(priKey);
  50. signature.update(data);
  51. return encryptBASE64(signature.sign());
  52. }
  53. /**
  54. * 校验数字签名
  55. *
  56. * @param data
  57. *            加密数据
  58. * @param publicKey
  59. *            公钥
  60. * @param sign
  61. *            数字签名
  62. *
  63. * @return 校验成功返回true 失败返回false
  64. * @throws Exception
  65. *
  66. */
  67. public static boolean verify(byte[] data, String publicKey, String sign)
  68. throws Exception {
  69. // 解密由base64编码的公钥
  70. byte[] keyBytes = decryptBASE64(publicKey);
  71. // 构造X509EncodedKeySpec对象
  72. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
  73. // KEY_ALGORITHM 指定的加密算法
  74. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  75. // 取公钥匙对象
  76. PublicKey pubKey = keyFactory.generatePublic(keySpec);
  77. Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
  78. signature.initVerify(pubKey);
  79. signature.update(data);
  80. // 验证签名是否正常
  81. return signature.verify(decryptBASE64(sign));
  82. }
  83. /**
  84. * 解密<br>
  85. * 用私钥解密
  86. *
  87. * @param data
  88. * @param key
  89. * @return
  90. * @throws Exception
  91. */
  92. public static byte[] decryptByPrivateKey(byte[] data, String key)
  93. throws Exception {
  94. // 对密钥解密
  95. byte[] keyBytes = decryptBASE64(key);
  96. // 取得私钥
  97. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  98. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  99. Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
  100. // 对数据解密
  101. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  102. cipher.init(Cipher.DECRYPT_MODE, privateKey);
  103. return cipher.doFinal(data);
  104. }
  105. /**
  106. * 解密<br>
  107. * 用公钥解密
  108. *
  109. * @param data
  110. * @param key
  111. * @return
  112. * @throws Exception
  113. */
  114. public static byte[] decryptByPublicKey(byte[] data, String key)
  115. throws Exception {
  116. // 对密钥解密
  117. byte[] keyBytes = decryptBASE64(key);
  118. // 取得公钥
  119. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  120. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  121. Key publicKey = keyFactory.generatePublic(x509KeySpec);
  122. // 对数据解密
  123. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  124. cipher.init(Cipher.DECRYPT_MODE, publicKey);
  125. return cipher.doFinal(data);
  126. }
  127. /**
  128. * 加密<br>
  129. * 用公钥加密
  130. *
  131. * @param data
  132. * @param key
  133. * @return
  134. * @throws Exception
  135. */
  136. public static byte[] encryptByPublicKey(byte[] data, String key)
  137. throws Exception {
  138. // 对公钥解密
  139. byte[] keyBytes = decryptBASE64(key);
  140. // 取得公钥
  141. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  142. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  143. Key publicKey = keyFactory.generatePublic(x509KeySpec);
  144. // 对数据加密
  145. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  146. cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  147. return cipher.doFinal(data);
  148. }
  149. /**
  150. * 加密<br>
  151. * 用私钥加密
  152. *
  153. * @param data
  154. * @param key
  155. * @return
  156. * @throws Exception
  157. */
  158. public static byte[] encryptByPrivateKey(byte[] data, String key)
  159. throws Exception {
  160. // 对密钥解密
  161. byte[] keyBytes = decryptBASE64(key);
  162. // 取得私钥
  163. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  164. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  165. Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
  166. // 对数据加密
  167. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  168. cipher.init(Cipher.ENCRYPT_MODE, privateKey);
  169. return cipher.doFinal(data);
  170. }
  171. /**
  172. * 取得私钥
  173. *
  174. * @param keyMap
  175. * @return
  176. * @throws Exception
  177. */
  178. public static String getPrivateKey(Map<String, Object> keyMap)
  179. throws Exception {
  180. Key key = (Key) keyMap.get(PRIVATE_KEY);
  181. return encryptBASE64(key.getEncoded());
  182. }
  183. /**
  184. * 取得公钥
  185. *
  186. * @param keyMap
  187. * @return
  188. * @throws Exception
  189. */
  190. public static String getPublicKey(Map<String, Object> keyMap)
  191. throws Exception {
  192. Key key = (Key) keyMap.get(PUBLIC_KEY);
  193. return encryptBASE64(key.getEncoded());
  194. }
  195. /**
  196. * 初始化密钥
  197. *
  198. * @return
  199. * @throws Exception
  200. */
  201. public static Map<String, Object> initKey() throws Exception {
  202. KeyPairGenerator keyPairGen = KeyPairGenerator
  203. .getInstance(KEY_ALGORITHM);
  204. keyPairGen.initialize(1024);
  205. KeyPair keyPair = keyPairGen.generateKeyPair();
  206. // 公钥
  207. RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  208. // 私钥
  209. RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  210. Map<String, Object> keyMap = new HashMap<String, Object>(2);
  211. keyMap.put(PUBLIC_KEY, publicKey);
  212. keyMap.put(PRIVATE_KEY, privateKey);
  213. return keyMap;
  214. }
  215. }

再给出一个测试类:

  1. import static org.junit.Assert.*;
  2. import org.junit.Before;
  3. import org.junit.Test;
  4. import java.util.Map;
  5. /**
  6. *
  7. * @author 梁栋
  8. * @version 1.0
  9. * @since 1.0
  10. */
  11. public class RSACoderTest {
  12. private String publicKey;
  13. private String privateKey;
  14. @Before
  15. public void setUp() throws Exception {
  16. Map<String, Object> keyMap = RSACoder.initKey();
  17. publicKey = RSACoder.getPublicKey(keyMap);
  18. privateKey = RSACoder.getPrivateKey(keyMap);
  19. System.err.println("公钥: \n\r" + publicKey);
  20. System.err.println("私钥: \n\r" + privateKey);
  21. }
  22. @Test
  23. public void test() throws Exception {
  24. System.err.println("公钥加密——私钥解密");
  25. String inputStr = "abc";
  26. byte[] data = inputStr.getBytes();
  27. byte[] encodedData = RSACoder.encryptByPublicKey(data, publicKey);
  28. byte[] decodedData = RSACoder.decryptByPrivateKey(encodedData,
  29. privateKey);
  30. String outputStr = new String(decodedData);
  31. System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
  32. assertEquals(inputStr, outputStr);
  33. }
  34. @Test
  35. public void testSign() throws Exception {
  36. System.err.println("私钥加密——公钥解密");
  37. String inputStr = "sign";
  38. byte[] data = inputStr.getBytes();
  39. byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);
  40. byte[] decodedData = RSACoder
  41. .decryptByPublicKey(encodedData, publicKey);
  42. String outputStr = new String(decodedData);
  43. System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
  44. assertEquals(inputStr, outputStr);
  45. System.err.println("私钥签名——公钥验证签名");
  46. // 产生签名
  47. String sign = RSACoder.sign(encodedData, privateKey);
  48. System.err.println("签名:\r" + sign);
  49. // 验证签名
  50. boolean status = RSACoder.verify(encodedData, publicKey, sign);
  51. System.err.println("状态:\r" + status);
  52. assertTrue(status);
  53. }
  54. }

控制台输出:

  1. 公钥:
  2. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYU/+I0+z1aBl5X6DUUOHQ7FZpmBSDbKTtx89J
  3. EcB64jFCkunELT8qiKly7fzEqD03g8ALlu5XvX+bBqHFy7YPJJP0ekE2X3wjUnh2NxlqpH3/B/xm
  4. 1ZdSlCwDIkbijhBVDjA/bu5BObhZqQmDwIxlQInL9oVz+o6FbAZCyHBd7wIDAQAB
  5. 私钥:
  6. MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhT/4jT7PVoGXlfoNRQ4dDsVmmY
  7. FINspO3Hz0kRwHriMUKS6cQtPyqIqXLt/MSoPTeDwAuW7le9f5sGocXLtg8kk/R6QTZffCNSeHY3
  8. GWqkff8H/GbVl1KULAMiRuKOEFUOMD9u7kE5uFmpCYPAjGVAicv2hXP6joVsBkLIcF3vAgMBAAEC
  9. gYBvZHWoZHmS2EZQqKqeuGr58eobG9hcZzWQoJ4nq/CarBAjw/VovUHE490uK3S9ht4FW7Yzg3LV
  10. /MB06Huifh6qf/X9NQA7SeZRRC8gnCQk6JuDIEVJOud5jU+9tyumJakDKodQ3Jf2zQtNr+5ZdEPl
  11. uwWgv9c4kmpjhAdyMuQmYQJBANn6pcgvyYaia52dnu+yBUsGkaFfwXkzFSExIbi0MXTkhEb/ER/D
  12. rLytukkUu5S5ecz/KBa8U4xIslZDYQbLz5ECQQCy5dutt7RsxN4+dxCWn0/1FrkWl2G329Ucewm3
  13. QU9CKu4D+7Kqdj+Ha3lXP8F0Etaaapi7+EfkRUpukn2ItZV/AkEAlk+I0iphxT1rCB0Q5CjWDY5S
  14. Df2B5JmdEG5Y2o0nLXwG2w44OLct/k2uD4cEcuITY5Dvi/4BftMCZwm/dnhEgQJACIktJSnJwxLV
  15. o9dchENPtlsCM9C/Sd2EWpqISSUlmfugZbJBwR5pQ5XeMUqKeXZYpP+HEBj1nS+tMH9u2/IGEwJA
  16. fL8mZiZXan/oBKrblAbplNcKWGRVD/3y65042PAEeghahlJMiYquV5DzZajuuT0wbJ5xQuZB01+X
  17. nfpFpBJ2dw==
  18. 公钥加密——私钥解密
  19. 加密前: abc
  20. 解密后: abc
  21. 公钥:
  22. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdOj40yEB48XqWxmPILmJAc7UecIN7F32etSHF
  23. 9rwbuEh3+iTPOGSxhoSQpOED0vOb0ZIMkBXZSgsxLaBSin2RZ09YKWRjtpCA0kDkiD11gj4tzTiM
  24. l9qq1kwSK7ZkGAgodEn3yIILVmQDuEImHOXFtulvJ71ka07u3LuwUNdB/wIDAQAB
  25. 私钥:
  26. MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN06PjTIQHjxepbGY8guYkBztR5w
  27. g3sXfZ61IcX2vBu4SHf6JM84ZLGGhJCk4QPS85vRkgyQFdlKCzEtoFKKfZFnT1gpZGO2kIDSQOSI
  28. PXWCPi3NOIyX2qrWTBIrtmQYCCh0SffIggtWZAO4QiYc5cW26W8nvWRrTu7cu7BQ10H/AgMBAAEC
  29. gYEAz2JWBizjI31bqhP4XiP9PuY5F3vqBW4T+L9cFbQiyumKJc58yzTWUAUGKIIn3enXLG7dNqGr
  30. mbJro4JeFIJ3CiVDpXR9+FluIgI4SXm7ioGKF2NOMA9LR5Fu82W+pLfpTN2y2SaLYWEDZyp53BxY
  31. j9gUxaxi1MQs+C1ZgDF2xmECQQDy70bQntbRfysP+ppCtd56YRnES1Tyekw0wryS2tr+ivQJl7JF
  32. gp5rPAOXpgrq36xHDwUspQ0sJ0vj0O7ywxr1AkEA6SAaLhrJJrYucC0jxwAhUYyaPN+aOsWymaRh
  33. 9jA/Wc0wp29SbGTh5CcMuGpXm1g0M+FKW3dGiHgS3rVUKim4owJAbnxgapUzAgiiHxxMeDaavnHW
  34. 9C2GrtjsO7qtZOTgYI/1uT8itvZW8lJTF+9OW8/qXE76fXl7ai9dFnl5kzMk2QJBALfHz/vCsArt
  35. mkRiwY6zApE4Z6tPl1V33ymSVovvUzHnOdD1SKQdD5t+UV/crb3QVi8ED0t2B0u0ZSPfDT/D7kMC
  36. QDpwdj9k2F5aokLHBHUNJPFDAp7a5QMaT64gv/d48ITJ68Co+v5WzLMpzJBYXK6PAtqIhxbuPEc2
  37. I2k1Afmrwyw=
  38. 私钥加密——公钥解密
  39. 加密前: sign
  40. 解密后: sign
  41. 私钥签名——公钥验证签名
  42. 签名:
  43. ud1RsIwmSC1pN22I4IXteg1VD2FbiehKUfNxgVSHzvQNIK+d20FCkHCqh9djP3h94iWnIUY0ifU+
  44. mbJkhAl/i5krExOE0hknOnPMcEP+lZV1RbJI2zG2YooSp2XDleqrQk5e/QF2Mx0Zxt8Xsg7ucVpn
  45. i3wwbYWs9wSzIf0UjlM=
  46. 状态:
  47. true

简要总结一下,使用公钥加密、私钥解密,完成了乙方到甲方的一次数据传递,通过私钥加密、公钥解密,同时通过私钥签名、公钥验证签名,完成了一次甲方到乙方的数据传递与验证,两次数据传递完成一整套的数据交互!



类似数字签名,数字信封是这样描述的:



数字信封

  数字信封用加密技术来保证只有特定的收信人才能阅读信的内容。

流程:

    信息发送方采用对称密钥来加密信息,然后再用接收方的公钥来加密此对称密钥(这部分称为数字信封),再将它和信息一起发送给接收方;接收方先用相应的私钥打开数字信封,得到对称密钥,然后使用对称密钥再解开信息。

非对称加密算法——RSA的更多相关文章

  1. 非对称加密算法RSA使用注意事项

    原文:非对称加密算法RSA使用注意事项 第一个问题,也是最重要的一个——RSA无法对超过117字节的数据进行加密!切记!其实也勿需要求对更大数据的加密,虽然网上已经有相关解决方案,比如BigInteg ...

  2. Java进阶(七)Java加密技术之非对称加密算法RSA

    Java加密技术(四)--非对称加密算法RSA 非对称加密算法--RSA 基本概念 非对称加密算法是一种密钥的保密方法. 非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(priv ...

  3. 非对称加密算法-RSA算法

    一.概述 1.RSA是基于大数因子分解难题.目前各种主流计算机语言都支持RSA算法的实现 2.java6支持RSA算法 3.RSA算法可以用于数据加密和数字签名 4.RSA算法相对于DES/AES等对 ...

  4. JAVA 非对称加密算法RSA

    非对称加密算法 RSA过程 : 以甲乙双方为例 1.初始化密钥 构建密钥对,生成公钥.私钥保存到keymap中 KeyPairGenerator ---> KeyPair --> RSAP ...

  5. Java加密技术(四)非对称加密算法RSA

    RSA      这样的算法1978年就出现了.它是第一个既能用于数据加密也能用于数字签名的算法.它易于理解和操作.也非常流行.算法的名字以发明者的名字命名:Ron Rivest, AdiShamir ...

  6. 非对称加密算法RSA 学习

    非对称加密算法RSA 学习 RSA加密算法是一种非对称加密算法.RSA是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Ad ...

  7. 非对称加密算法-RSA

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 12.1.RSA(最经典的非对称加密算法) 特点: 使用一套密钥即可完成加解密(与D ...

  8. 信息加密之非对称加密算法RSA

    前面为大家已经总结了,基于密钥交换的DH算法,现在就为大家再介绍一种基于因子分解的RSA算法,这种加密算法有两种实现形式:1.公钥加密,私钥解密:2.私钥加密,公钥解密.下面就为大家分析一下实现代码, ...

  9. 第十二章 非对称加密算法-RSA

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第8章“高等加密算法--非对称加密算法” 12.1.RSA(最经典的非对称加密算法) 特点: 使用一套密钥即可完成加解密(与D ...

  10. openssl 非对称加密算法RSA命令详解

    1.非对称加密算法概述 非对称加密算法也称公开密钥算法,其解决了对称加密算法密钥分配的问题,非对称加密算法基本特点如下: 1.加密密钥和解密密钥不同 2.密钥对中的一个密钥可以公开 3.根据公开密钥很 ...

随机推荐

  1. Oracle Linux 5.7安装VMware Tools的问题

    案例环境介绍:     虚拟机的版本:VMware® Workstation 8.0.3 build-703057    操作系统版本:Oracle Linux Server release 5.7 ...

  2. YourSQLDba版本升级总结

    在使用YourSQLDba做数据库备份.维护时,像其它软件一样,版本升级是不可避免的.因为YourSQLDba一直在不停更新版本.扩展功能.下面介绍一下升级YourSQLDba时的具体步骤和一些注意事 ...

  3. CREATE FILE encountered operating system error 5(Access is denied.)

    这篇博文主要演示"CREATE FILE encountered operating system error 5(Access is denied.)"错误如出现的原因(当然只是 ...

  4. JVM之CMS收集器

    CMS(Concurrent Mark Sweep) 最短回收停顿,适合维持响应时间上的要求. 初始标记 Initial mark:标记GC Roots能够关联到的对象.stop-mark. 并发标记 ...

  5. cnless.sh:改进版less,可自动识别GBK编码或UTF-8编码。

    #!/bin/bash #功能:让GBK编码的文件可以使用less正常显示中文(自动识别GBK和UTF-8编码) #v0. 在LINUX下,使用UTF-8编码,less UTF-8的文件时显示中文正常 ...

  6. HDU 4622 Reincarnation (查询一段字符串的不同子串个数,后缀自动机)

    Reincarnation Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

  7. 【2016-11-7】【坚持学习】【Day22】【C# 委托的应用】

    我觉得我对委托的概念还没有完全掌握,于是,我需要继续思考,学习它的应用实现.

  8. 修改VMware虚拟机里面的显卡名称

    修改VMware虚拟机里面的显卡名称 现在有些蛋疼坑爹的游戏,会检测显卡的名称,如果其中有“Vmware”这类的字眼,就会提示程序在虚拟机中运行而拒绝执行(太不科学了嘛,我要是把我的实机驱动名称也改成 ...

  9. [CareerCup] 17.2 Tic Tac Toe 井字棋游戏

    17.2 Design an algorithm to figure out if someone has won a game oftic-tac-toe. 这道题让我们判断玩家是否能赢井字棋游戏, ...

  10. 在WebAPI使用Session

    最近在改写WebApp时要将以前用泛型处理例程写的Captcha 改成使用WebApi 来实作机制,在实作的过程中发现使用IRequiresSessionState session也无法使用(cont ...