BlogJava 聯(lián)系 聚合 管理  

          Blog Stats

          隨筆檔案


          bitmap

          bitmap

          RSA
              這種算法1978年就出現(xiàn)了,它是第一個既能用于數(shù)據(jù)加密也能用于數(shù)字簽名的算法。它易于理解和操作,也很流行。算法的名字以發(fā)明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。
              這種加密算法的特點主要是密鑰的變化,上文我們看到DES只有一個密鑰。相當于只有一把鑰匙,如果這把鑰匙丟了,數(shù)據(jù)也就不安全了。RSA同時有兩把鑰匙,公鑰與私鑰。同時支持數(shù)字簽名。數(shù)字簽名的意義在于,對傳輸過來的數(shù)據(jù)進行校驗。確保數(shù)據(jù)在傳輸工程中不被修改。

          流程分析:
          1. 甲方構(gòu)建密鑰對兒,將公鑰公布給乙方,將私鑰保留。
          2. 甲方使用私鑰加密數(shù)據(jù),然后用私鑰對加密后的數(shù)據(jù)簽名,發(fā)送給乙方簽名以及加密后的數(shù)據(jù);乙方使用公鑰、簽名來驗證待解密數(shù)據(jù)是否有效,如果有效使用公鑰對數(shù)據(jù)解密。
          3. 乙方使用公鑰加密數(shù)據(jù),向甲方發(fā)送經(jīng)過加密后的數(shù)據(jù);甲方獲得加密數(shù)據(jù),通過私鑰解密。


          按如上步驟給出序列圖,如下:


          通過java代碼實現(xiàn)如下:
          import java.security.Key;   
          import java.security.KeyFactory;   
          import java.security.KeyPair;   
          import java.security.KeyPairGenerator;   
          import java.security.PrivateKey;   
          import java.security.PublicKey;   
          import java.security.Signature;   
          import java.security.interfaces.RSAPrivateKey;   
          import java.security.interfaces.RSAPublicKey;   
          import java.security.spec.PKCS8EncodedKeySpec;   
          import java.security.spec.X509EncodedKeySpec;   
            
          import java.util.HashMap;   
          import java.util.Map;   
            
          import javax.crypto.Cipher;   
            
          /**  
           * RSA安全編碼組件  
           *   
           * 
          @author 梁棟  http://www.bt285.cn http://www.5a520.cn 
           * 
          @version 1.0  
           * 
          @since 1.0  
           
          */
            
          public abstract class RSACoder extends Coder {   
              
          public static final String KEY_ALGORITHM = "RSA";   
              
          public static final String SIGNATURE_ALGORITHM = "MD5withRSA";   
            
              
          private static final String PUBLIC_KEY = "RSAPublicKey";   
              
          private static final String PRIVATE_KEY = "RSAPrivateKey";   
            
              
          /**  
               * 用私鑰對信息生成數(shù)字簽名  
               *   
               * 
          @param data  
               *            加密數(shù)據(jù)  
               * 
          @param privateKey  
               *            私鑰  
               *   
               * 
          @return  
               * 
          @throws Exception  
               
          */
            
              
          public static String sign(byte[] data, String privateKey) throws Exception {   
                  
          // 解密由base64編碼的私鑰   
                  byte[] keyBytes = decryptBASE64(privateKey);   
            
                  
          // 構(gòu)造PKCS8EncodedKeySpec對象   
                  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);   
            
                  
          // KEY_ALGORITHM 指定的加密算法   
                  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);   
            
                  
          // 取私鑰匙對象   
                  PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);   
            
                  
          // 用私鑰對信息生成數(shù)字簽名   
                  Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);   
                  signature.initSign(priKey);   
                  signature.update(data);   
            
                  
          return encryptBASE64(signature.sign());   
              }
             
            
              
          /**  
               * 校驗數(shù)字簽名  
               *   
               * 
          @param data  
               *            加密數(shù)據(jù)  
               * 
          @param publicKey  
               *            公鑰  
               * 
          @param sign  
               *            數(shù)字簽名  
               *   
               * 
          @return 校驗成功返回true 失敗返回false  
               * 
          @throws Exception  
               *   
               
          */
            
              
          public static boolean verify(byte[] data, String publicKey, String sign)   
                      
          throws Exception {   
            
                  
          // 解密由base64編碼的公鑰   
                  byte[] keyBytes = decryptBASE64(publicKey);   
            
                  
          // 構(gòu)造X509EncodedKeySpec對象   
                  X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);   
            
                  
          // KEY_ALGORITHM 指定的加密算法   
                  KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);   
            
                  
          // 取公鑰匙對象   
                  PublicKey pubKey = keyFactory.generatePublic(keySpec);   
            
                  Signature signature 
          = Signature.getInstance(SIGNATURE_ALGORITHM);   
                  signature.initVerify(pubKey);   
                  signature.update(data);   
            
                  
          // 驗證簽名是否正常   
                  return signature.verify(decryptBASE64(sign));   
              }
             
            
              
          /**  
               * 解密<br>  
               * 用私鑰解密  
          http://www.5a520.cn http://www.feng123.com
               *   
               * 
          @param data  
               * 
          @param key  
               * 
          @return  
               * 
          @throws Exception  
               
          */
            
              
          public static byte[] decryptByPrivateKey(byte[] data, String key)   
                      
          throws Exception {   
                  
          // 對密鑰解密   
                  byte[] keyBytes = decryptBASE64(key);   
            
                  
          // 取得私鑰   
                  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);   
                  KeyFactory keyFactory 
          = KeyFactory.getInstance(KEY_ALGORITHM);   
                  Key privateKey 
          = keyFactory.generatePrivate(pkcs8KeySpec);   
            
                  
          // 對數(shù)據(jù)解密   
                  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());   
                  cipher.init(Cipher.DECRYPT_MODE, privateKey);   
            
                  
          return cipher.doFinal(data);   
              }
             
            
              
          /**  
               * 解密<br>  
               * 用私鑰解密  
               *   
               * 
          @param data  
               * 
          @param key  
               * 
          @return  
               * 
          @throws Exception  
               
          */
            
              
          public static byte[] decryptByPublicKey(byte[] data, String key)   
                      
          throws Exception {   
                  
          // 對密鑰解密   
                  byte[] keyBytes = decryptBASE64(key);   
            
                  
          // 取得公鑰   
                  X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);   
                  KeyFactory keyFactory 
          = KeyFactory.getInstance(KEY_ALGORITHM);   
                  Key publicKey 
          = keyFactory.generatePublic(x509KeySpec);   
            
                  
          // 對數(shù)據(jù)解密   
                  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());   
                  cipher.init(Cipher.DECRYPT_MODE, publicKey);   
            
                  
          return cipher.doFinal(data);   
              }
             
            
              
          /**  
               * 加密<br>  
               * 用公鑰加密  
               *   
               * 
          @param data  
               * 
          @param key  
               * 
          @return  
               * 
          @throws Exception  
               
          */
            
              
          public static byte[] encryptByPublicKey(byte[] data, String key)   
                      
          throws Exception {   
                  
          // 對公鑰解密   
                  byte[] keyBytes = decryptBASE64(key);   
            
                  
          // 取得公鑰   
                  X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);   
                  KeyFactory keyFactory 
          = KeyFactory.getInstance(KEY_ALGORITHM);   
                  Key publicKey 
          = keyFactory.generatePublic(x509KeySpec);   
            
                  
          // 對數(shù)據(jù)加密   
                  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());   
                  cipher.init(Cipher.ENCRYPT_MODE, publicKey);   
            
                  
          return cipher.doFinal(data);   
              }
             
            
              
          /**  
               * 加密<br>  
               * 用私鑰加密  
               *   
               * 
          @param data  
               * 
          @param key  
               * 
          @return  
               * 
          @throws Exception  
               
          */
            
              
          public static byte[] encryptByPrivateKey(byte[] data, String key)   
                      
          throws Exception {   
                  
          // 對密鑰解密   
                  byte[] keyBytes = decryptBASE64(key);   
            
                  
          // 取得私鑰   
                  PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);   
                  KeyFactory keyFactory 
          = KeyFactory.getInstance(KEY_ALGORITHM);   
                  Key privateKey 
          = keyFactory.generatePrivate(pkcs8KeySpec);   
            
                  
          // 對數(shù)據(jù)加密   
                  Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());   
                  cipher.init(Cipher.ENCRYPT_MODE, privateKey);   
            
                  
          return cipher.doFinal(data);   
              }
             
            
              
          /**  
               * 取得私鑰  
               *   
               * 
          @param keyMap  
               * 
          @return  
               * 
          @throws Exception  
               
          */
            
              
          public static String getPrivateKey(Map<String, Object> keyMap)   
                      
          throws Exception {   
                  Key key 
          = (Key) keyMap.get(PRIVATE_KEY);   
            
                  
          return encryptBASE64(key.getEncoded());   
              }
             
            
              
          /**  
               * 取得公鑰  
               *   
               * 
          @param keyMap  
               * 
          @return  
               * 
          @throws Exception  
               
          */
            
              
          public static String getPublicKey(Map<String, Object> keyMap)   
                      
          throws Exception {   
                  Key key 
          = (Key) keyMap.get(PUBLIC_KEY);   
            
                  
          return encryptBASE64(key.getEncoded());   
              }
             
            
              
          /**  
               * 初始化密鑰  
               *   
               * 
          @return  
               * 
          @throws Exception  
               
          */
            
              
          public static Map<String, Object> initKey() throws Exception {   
                  KeyPairGenerator keyPairGen 
          = KeyPairGenerator   
                          .getInstance(KEY_ALGORITHM);   
                  keyPairGen.initialize(
          1024);   
            
                  KeyPair keyPair 
          = keyPairGen.generateKeyPair();   
            
                  
          // 公鑰   
                  RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();   
            
                  
          // 私鑰   
                  RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   
            
                  Map
          <String, Object> keyMap = new HashMap<String, Object>(2);   
            
                  keyMap.put(PUBLIC_KEY, publicKey);   
                  keyMap.put(PRIVATE_KEY, privateKey);   
                  
          return keyMap;   
              }
             
          }
            


           

          再給出一個測試類:

          import static org.junit.Assert.*;   
            
          import org.junit.Before;   
          import org.junit.Test;   
            
          import java.util.Map;   
            
          /**  
           *   
           * 
          @author 梁棟  http://www.bt285.cn  http://www.guihua.org
           * 
          @version 1.0  
           * 
          @since 1.0  
           
          */
            
          public class RSACoderTest {   
              
          private String publicKey;   
              
          private String privateKey;   
            
              @Before  
              
          public void setUp() throws Exception {   
                  Map
          <String, Object> keyMap = RSACoder.initKey();   
            
                  publicKey 
          = RSACoder.getPublicKey(keyMap);   
                  privateKey 
          = RSACoder.getPrivateKey(keyMap);   
                  System.err.println(
          "公鑰: \n\r" + publicKey);   
                  System.err.println(
          "私鑰: \n\r" + privateKey);   
              }
             
            
              @Test  
              
          public void test() throws Exception {   
                  System.err.println(
          "公鑰加密——私鑰解密");   
                  String inputStr 
          = "abc";   
                  
          byte[] data = inputStr.getBytes();   
            
                  
          byte[] encodedData = RSACoder.encryptByPublicKey(data, publicKey);   
            
                  
          byte[] decodedData = RSACoder.decryptByPrivateKey(encodedData,   
                          privateKey);   
            
                  String outputStr 
          = new String(decodedData);   
                  System.err.println(
          "加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);   
                  assertEquals(inputStr, outputStr);   
            
              }
             
            
              @Test  
              
          public void testSign() throws Exception {   
                  System.err.println(
          "私鑰加密——公鑰解密");   
                  String inputStr 
          = "sign";   
                  
          byte[] data = inputStr.getBytes();   
            
                  
          byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);   
            
                  
          byte[] decodedData = RSACoder   
                          .decryptByPublicKey(encodedData, publicKey);   
            
                  String outputStr 
          = new String(decodedData);   
                  System.err.println(
          "加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);   
                  assertEquals(inputStr, outputStr);   
            
                  System.err.println(
          "私鑰簽名——公鑰驗證簽名");   
                  
          // 產(chǎn)生簽名   
                  String sign = RSACoder.sign(encodedData, privateKey);   
                  System.err.println(
          "簽名:\r" + sign);   
            
                  
          // 驗證簽名   
                  boolean status = RSACoder.verify(encodedData, publicKey, sign);   
                  System.err.println(
          "狀態(tài):\r" + status);   
                  assertTrue(status);   
            
              }
             
            
          }
            


          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. 狀態(tài):   
          58. true  
            簡要總結(jié)一下,使用公鑰加密、私鑰解密,完成了乙方到甲方的一次數(shù)據(jù)傳遞,通過私鑰加密、公鑰解密,同時通過私鑰簽名、公鑰驗證簽名,完成了一次甲方到乙方的數(shù)據(jù)傳遞與驗證,兩次數(shù)據(jù)傳遞完成一整套的數(shù)據(jù)交互!

          類似數(shù)字簽名,數(shù)字信封是這樣描述的:

          數(shù)字信封
            數(shù)字信封用加密技術(shù)來保證只有特定的收信人才能閱讀信的內(nèi)容。
          流程:
              信息發(fā)送方采用對稱密鑰來加密信息,然后再用接收方的公鑰來加密此對稱密鑰(這部分稱為數(shù)字信封),再將它和信息一起發(fā)送給接收方;接收方先用相應(yīng)的私鑰打開數(shù)字信封,得到對稱密鑰,然后使用對稱密鑰再解開信息。

           

          posted on 2009-07-09 21:08 bitmap 閱讀(1235) 評論(0)  編輯  收藏
          主站蜘蛛池模板: 平乡县| 贞丰县| 道孚县| 宜兰县| 南陵县| 潞西市| 多伦县| 平果县| 汽车| 肇州县| 鹤峰县| 比如县| 西和县| 长阳| 平泉县| 安吉县| 新巴尔虎右旗| 德庆县| 德格县| 蒙城县| 吴桥县| 浠水县| 通河县| 武邑县| 屏山县| 杭州市| 喀喇沁旗| 隆安县| 突泉县| 水城县| 锡林浩特市| 汽车| 舞阳县| 宝坻区| 太和县| 炉霍县| 雷波县| 通江县| 西充县| 莱西市| 上饶市|