Java加密技术(四)

来源:互联网 发布:苹果电脑mac是什么 编辑:程序博客网 时间:2024/06/05 16:04

关键字: rsa, 公钥, 私钥, 数字签名, 非对称加密

    接下来我们介绍典型的非对称加密算法——RSA

RSA
    这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。
    这种加密算法的特点主要是密钥的变化,上文我们看到DES只有一个密钥。相当于只有一把钥匙,如果这把钥匙丢了,数据也就不安全了。RSA同时有两把钥匙,公钥与私钥。同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验。确保数据在传输工程中不被修改。

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


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


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

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

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


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

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

数字信封
  数字信封用加密技术来保证只有特定的收信人才能阅读信的内容。
流程:
    信息发送方采用对称密钥来加密信息,然后再用接收方的公钥来加密此对称密钥(这部分称为数字信封),再将它和信息一起发送给接收方;接收方先用相应的私钥打开数字信封,得到对称密钥,然后使用对称密钥再解开信息。


相关链接:
Java加密技术(一)
Java加密技术(二)
Java加密技术(三)
Java加密技术(四)
Java加密技术(五)
Java加密技术(六)
Java加密技术(七)
Java加密技术(八)
Java加密技术(九)
Java加密技术(十)
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 五个月宝宝流鼻涕鼻塞怎么办 4个月宝宝流鼻涕怎么办 大便经常是稀的怎么办 拉黑色的稀大便怎么办 孕晚期半夜饿了怎么办 肠胃不好大便不成型怎么办 螃蟹吃多了过敏怎么办 吃螃蟹过敏很痒怎么办 吃螃蟹喝啤酒了怎么办 1个月宝宝拉肚子怎么办 被雨林蝎子蛰了怎么办 在家被蜈蚣咬了怎么办 宝宝被蝎子蜇了怎么办 仓鼠只吃面包虫怎么办 套装但是装等低怎么办 被香港人骗了钱怎么办 被红头蛇咬了怎么办 爸妈吵架闹离婚怎么办 包包用酒精擦了怎么办 灰色泰迪毛发白怎么办 手被野猫抓伤了怎么办 想去香港玩两天怎么办 受凉了一直想吐怎么办 受寒后头晕想吐怎么办 肚子受凉了想吐怎么办 想吐但吐不出来怎么办 抽烟抽的牙黄怎么办 借了大耳窿的钱怎么办 5岁左眼视力不好怎么办 老公才30性不行怎么办 老婆出轨跑了怎么办啊 海螺吃多了头晕怎么办 读书的好与不好怎么办 衣服泡久了发黄怎么办 白衣服洗变色了怎么办 高达贴纸贴错了怎么办 小孩大门牙长歪怎么办 小孩乳牙长歪了怎么办 小孩牙齿张歪了怎么办 8小孩门牙长歪了怎么办 婴儿乳牙长歪了怎么办