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

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

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


通过java代码实现如下:

[java]  view plain copy print ?
  1. package com.somnus.cipher;  
  2.   
  3. import java.io.InputStream;  
  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.interfaces.RSAPrivateKey;  
  12. import java.security.interfaces.RSAPublicKey;  
  13. import java.security.spec.PKCS8EncodedKeySpec;  
  14. import java.security.spec.X509EncodedKeySpec;  
  15. import java.util.Arrays;  
  16. import java.util.HashMap;  
  17. import java.util.Map;  
  18.   
  19. import javax.crypto.Cipher;  
  20.   
  21. import org.apache.commons.codec.binary.Base64;  
  22. import org.apache.commons.codec.binary.Hex;  
  23.   
  24. /** 非对称加密算法RSA 
  25.  * @Title: RsaEncrypt.java  
  26.  * @Description: TODO 
  27.  * @author Somnus 
  28.  * @date 2015年6月5日 下午2:02:44  
  29.  * @version V1.0  
  30.  */  
  31. public class RSAUtil {  
  32.     public static final String ALGORITHM = "RSA";    
  33.     public static final String SIGNATURE_ALGORITHM = "MD5withRSA";    
  34.     
  35.     private static final String PUBLIC_KEY = "RSAPublicKey";    
  36.     private static final String PRIVATE_KEY = "RSAPrivateKey";    
  37.       
  38.     private static final String PUBLIC_KEY_PATH = "public.cer";  
  39.     private static final String PRIVATE_KEY_PATH = "private.key";  
  40.       
  41.     /**  
  42.      * 用私钥对信息生成数字签名  
  43.      *   
  44.      * @param data  
  45.      *            加密数据  
  46.      * @param privateKey  
  47.      *            私钥  
  48.      * @return  
  49.      * @throws Exception  
  50.      */    
  51.     public static String sign(String data) throws Exception {   
  52.         // 解密由base64编码的私钥    
  53.         byte[] keyBytes = Base64.decodeBase64(getPrivateKey());  
  54.         // 构造PKCS8EncodedKeySpec对象    
  55.         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);    
  56.         // ALGORITHM 指定的加密算法    
  57.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);    
  58.         // 取私钥匙对象    
  59.         PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);    
  60.         // 用私钥对信息生成数字签名    
  61.         Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);    
  62.         signature.initSign(priKey);    
  63.         signature.update(Hex.decodeHex(data.toCharArray()));    
  64.         return Base64.encodeBase64String(signature.sign());  
  65.     }    
  66.     
  67.     /**  
  68.      * 校验数字签名  
  69.      *   
  70.      * @param data  
  71.      *            加密数据  
  72.      * @param publicKey  
  73.      *            公钥  
  74.      * @param sign  
  75.      *            数字签名  
  76.      *   
  77.      * @return 校验成功返回true 失败返回false  
  78.      * @throws Exception  
  79.      *   
  80.      */    
  81.     public static boolean verify(String data,String sign)throws Exception {    
  82.         // 解密由base64编码的公钥    
  83.         byte[] keyBytes = Base64.decodeBase64(getPublicKey());  
  84.         // 构造X509EncodedKeySpec对象    
  85.         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);    
  86.         // ALGORITHM 指定的加密算法    
  87.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);    
  88.         // 取公钥匙对象    
  89.         PublicKey pubKey = keyFactory.generatePublic(keySpec);    
  90.         Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);    
  91.         signature.initVerify(pubKey);    
  92.         signature.update(Hex.decodeHex(data.toCharArray()));    
  93.         // 验证签名是否正常    
  94.         return signature.verify(Base64.decodeBase64(sign));    
  95.     }    
  96.     
  97.     /**  
  98.      * 解密<br>  
  99.      * 用私钥解密  
  100.      *   
  101.      * @param data  
  102.      * @return  
  103.      * @throws Exception  
  104.      */    
  105.     public static String decryptByPrivateKey(String data)throws Exception {    
  106.         // 对密钥解密    
  107.         byte[] keyBytes = Base64.decodeBase64(getPrivateKey());  
  108.         // 取得私钥    
  109.         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);    
  110.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);    
  111.         Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);    
  112.         //初始化Cipher对象,设置为解密模式  
  113.         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());    
  114.         cipher.init(Cipher.DECRYPT_MODE, privateKey);  
  115.         // 执行解密操作  
  116.         byte[] buff = cipher.doFinal(Hex.decodeHex(data.toCharArray()));  
  117.         System.out.println(Arrays.toString(buff));  
  118.         return new String(buff);  
  119.     }    
  120.     
  121.     /**  
  122.      * 解密<br>  
  123.      * 用公钥解密  
  124.      *   
  125.      * @param data  
  126.      * @return  
  127.      * @throws Exception  
  128.      */    
  129.     public static String decryptByPublicKey(String data)throws Exception {    
  130.         // 对密钥解密    
  131.         byte[] keyBytes = Base64.decodeBase64(getPublicKey());   
  132.         // 取得公钥    
  133.         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);    
  134.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);    
  135.         Key publicKey = keyFactory.generatePublic(x509KeySpec);    
  136.         //初始化Cipher对象,设置为解密模式  
  137.         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());    
  138.         cipher.init(Cipher.DECRYPT_MODE, publicKey);    
  139.         // 执行解密操作  
  140.         byte[] buff = cipher.doFinal(Hex.decodeHex(data.toCharArray()));  
  141.         System.out.println(Arrays.toString(buff));  
  142.         return new String(buff);   
  143.     }    
  144.     
  145.     /**  
  146.      * 加密<br>  
  147.      * 用公钥加密  
  148.      *   
  149.      * @param data  
  150.      * @return  
  151.      * @throws Exception  
  152.      */    
  153.     public static String encryptByPublicKey(String data)throws Exception {    
  154.         // 对公钥解密    
  155.         byte[] keyBytes = Base64.decodeBase64(getPublicKey());  
  156.         // 取得公钥    
  157.         X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);    
  158.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);    
  159.         Key publicKey = keyFactory.generatePublic(x509KeySpec);    
  160.         // 实例化Cipher对象,它用于完成实际的加密操作  
  161.         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());    
  162.         cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
  163.         byte[] buff = cipher.doFinal(data.getBytes());  
  164.         System.out.println(Arrays.toString(buff));  
  165.         // 执行加密操作。加密后的结果通常都会用Base64编码进行传输   
  166.         return Hex.encodeHexString(buff);  
  167.     }    
  168.     
  169.     /**  
  170.      * 加密<br>  
  171.      * 用私钥加密  
  172.      *   
  173.      * @param data  
  174.      * @return  
  175.      * @throws Exception  
  176.      */    
  177.     public static String encryptByPrivateKey(String data) throws Exception {    
  178.         // 对密钥解密    
  179.         byte[] keyBytes = Base64.decodeBase64(getPrivateKey());   
  180.         // 取得私钥    
  181.         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);    
  182.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);    
  183.         Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);    
  184.         // 对数据加密    
  185.         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());    
  186.         cipher.init(Cipher.ENCRYPT_MODE, privateKey);    
  187.         byte[] buff = cipher.doFinal(data.getBytes());  
  188.         System.out.println(Arrays.toString(buff));  
  189.         // 执行加密操作。加密后的结果通常都会用Base64编码进行传输   
  190.         return Hex.encodeHexString(buff);  
  191.     }    
  192.     
  193.     /**  
  194.      * 取得私钥  
  195.      *   
  196.      * @param keyMap  
  197.      * @return  
  198.      * @throws Exception  
  199.      */    
  200.     public static String getPrivateKey()throws Exception{    
  201.         Key key = (Key)initKey().get(PRIVATE_KEY);   
  202.         return Base64.encodeBase64String(key.getEncoded());  
  203.     }    
  204.     
  205.     /**  
  206.      * 取得公钥  
  207.      *   
  208.      * @param keyMap  
  209.      * @return  
  210.      * @throws Exception  
  211.      */    
  212.     public static String getPublicKey()throws Exception {    
  213.         Key key = (Key) initKey().get(PUBLIC_KEY);  
  214.         return Base64.encodeBase64String(key.getEncoded());  
  215.     }    
  216.     
  217.     /**  
  218.      * 初始化密钥  
  219.      *   
  220.      * @return  
  221.      * @throws Exception  
  222.      * @throws Exception  
  223.      */    
  224.     public static Map<String, Object> initKey() throws Exception{  
  225.         InputStream in1 = RSAUtil.class.getClassLoader().getResourceAsStream(PUBLIC_KEY_PATH);  
  226.         InputStream in2 = RSAUtil.class.getClassLoader().getResourceAsStream(PRIVATE_KEY_PATH);  
  227.         try {  
  228.             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
  229.             /*生成公钥*/  
  230.             byte[] encodedpubkey = new byte[in1.available()];  
  231.             in1.read(encodedpubkey);  
  232.             X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encodedpubkey);  
  233.             PublicKey publicKey = keyFactory.generatePublic(pubKeySpec);  
  234.             /*生成私钥*/  
  235.             byte[] encodedprikey = new byte[in2.available()];  
  236.             in2.read(encodedprikey);  
  237.             PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(encodedprikey);  
  238.             PrivateKey privateKey = keyFactory.generatePrivate(priKeySpec);  
  239.             /*封装进map*/  
  240.             Map<String, Object> keyMap = new HashMap<String, Object>();  
  241.             keyMap.put(PUBLIC_KEY, publicKey);  
  242.             keyMap.put(PRIVATE_KEY, privateKey);   
  243.             return keyMap;  
  244.         } catch(Exception e){  
  245.             e.printStackTrace();  
  246.             throw e;  
  247.         } finally {  
  248.             in1.close();  
  249.             in2.close();  
  250.         }  
  251.     }  
  252.     /**  
  253.      * 初始化密钥 2 
  254.      * @return  
  255.      * @throws Exception  
  256.      */    
  257.     public static Map<String, Object> initKey2() throws Exception {    
  258.         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);    
  259.         keyPairGen.initialize(1024);    
  260.         KeyPair keyPair = keyPairGen.generateKeyPair();    
  261.         // 公钥    
  262.         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();    
  263.         // 私钥    
  264.         RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();    
  265.         Map<String, Object> keyMap = new HashMap<String, Object>(2);    
  266.         keyMap.put(PUBLIC_KEY, publicKey);    
  267.         keyMap.put(PRIVATE_KEY, privateKey);    
  268.         return keyMap;    
  269.     }    
  270.       
  271.     public static void main(String[] args) throws Exception {  
  272.         String publicKey = getPublicKey();    
  273.         String privateKey = getPrivateKey();    
  274.         System.out.println("公钥:\r" + publicKey);    
  275.         System.out.println("私钥:\r" + privateKey);   
  276.           
  277.         System.out.println("公钥加密————————————————————私钥解密");    
  278.         String data = "Somnus";   
  279.         System.out.println("原文: " + data);  
  280.         String encryptData = encryptByPublicKey(data);  
  281.         System.out.println("加密后: " + encryptData);  
  282.         String decryptData = decryptByPrivateKey(encryptData);   
  283.         System.out.println("解密后: " + decryptData);  
  284.           
  285.         System.out.println("私钥加密————————————————————公钥解密");     
  286.         System.out.println("原文: " + data);  
  287.         String encryptData2 = encryptByPrivateKey(data);  
  288.         System.out.println("加密后: " + encryptData2);  
  289.         String decryptData2 = decryptByPublicKey(encryptData2);   
  290.         System.out.println("解密后: " + decryptData2);  
  291.           
  292.         System.out.println("私钥签名——公钥验证签名");    
  293.         // 产生签名    
  294.         String sign = sign(encryptData2);    
  295.         System.out.println("签名:\r" + sign);    
  296.         // 验证签名    
  297.         boolean status = verify(encryptData2,sign);    
  298.         System.out.println("状态:" + status);    
  299.     }  
  300. }  


控制台输出: 

[java]  view plain copy print ?
  1. 公钥加密————————————————————私钥解密  
  2. 原文: Somnus  
  3. [8211247, -49, -442811787, -32, -5, -11656, -6087, -1, -368984, -917, -6664, -115, -11472, -867963, -15, -35, -1440, -5016, -10573807, -4875, -114, -6480746, -7424, -59, -5931121, -6345932025, -11651, -74, -402255, -31, -106]  
  4. 加密后: 52702fcfd41c7557e0fb8c38c457ffdc5954f711be408d8e48aa4f3ff1ddf228ce1097495007d04b8ec0504a06b618c5c51f79c12d5d14198c33b6d81637e196  
  5. [83111109110117115]  
  6. 解密后: Somnus  
  7. 私钥加密————————————————————公钥解密  
  8. 原文: Somnus  
  9. [69, -38, -21, -84, -56, -150, -33, -461112437, -106536781, -939, -15, -8959, -491027189, -7224249, -2928114, -36, -1, -123, -7124, -104, -3883127661, -117118, -54999947, -11828, -11983, -5124122, -310945, -38, -319899, -107]  
  10. 加密后: 45daebacc8ff32dfd20b7c2596354351f727f1a73bcf664759f9162a31e31c72dcff85f97c98da530c4c3d8b76ca63632f8a1c8953fb7c7afd6d2ddae1626395  
  11. [83111109110117115]  
  12. 解密后: Somnus  
  13. 私钥签名——公钥验证签名  
  14. 签名:  
  15. GfLuZt88KdtRoTL7nJoeoRYGW0Lqu9eV4o9J8OVzH9jbHHGa/ZZDlCAjqS1jwkMYaXrut+W2a8v867mZDvQJtw==  
  16. 状态:true  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值