當(dāng)柳上原的風(fēng)吹向天際的時(shí)候...

          真正的快樂(lè)來(lái)源于創(chuàng)造

            BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            368 Posts :: 1 Stories :: 201 Comments :: 0 Trackbacks
          按:以下文字涉及RSA對(duì)WebService傳遞的數(shù)據(jù)的加密解密,如果您已經(jīng)熟知RSA或是有其它更好的方法請(qǐng)不要往下看以免浪費(fèi)時(shí)間.

          WebService采用的協(xié)議是SOAP,它基于HTTP,而HTTP是明文方式,也就是說(shuō),采用WebService傳遞的數(shù)據(jù)是明文的。如果是天氣預(yù)報(bào)這種公開的只讀信息的WebService無(wú)所謂,如果涉及寫入或是和私密數(shù)據(jù)相關(guān),那么明文傳遞就有很大的潛在危險(xiǎn)性,必須加以遏止。

          一般來(lái)說(shuō)有兩種方法,一是采用https加密的方式,另一種是用非對(duì)稱加密算法對(duì)數(shù)據(jù)加密,下文提到的RSA就是第二種。

          使用RSA對(duì)WebService傳遞的信息加密解密的基本思想是:服務(wù)器端提供一個(gè)WebService方法byte[] getServerPublicKey(),客戶端可以以此得到服務(wù)器端的公鑰,然后使用服務(wù)器端的公鑰對(duì)要傳出去的數(shù)據(jù)進(jìn)行RSA加密,并附帶以自己的公鑰;服務(wù)器端得到客戶端的請(qǐng)求后,先用自己的私鑰解密客戶端送來(lái)的數(shù)據(jù),得到處理結(jié)果后用客戶端提供的公鑰加密,然后傳回;客戶端得到服務(wù)器端的返回?cái)?shù)據(jù)后,用自己的私鑰進(jìn)行解密,最終得到了服務(wù)器端的真實(shí)數(shù)據(jù)。服務(wù)器端和客戶端各自保存自己的RSA私鑰用于解密,提供給對(duì)方RSA公鑰進(jìn)行加密,這樣中間傳遞的信息就安全了。

          加密解密示意順序圖:


          下面是服務(wù)器端實(shí)現(xiàn)類的代碼:
          package com.heyang;


          public class ServiceImpl implements IService{
              @Override
              
          public byte[] getResonse(byte[] params, byte[] clientPublicKey) {
                  
          try {
                      
          // 使用自己的私鑰解密客戶端用服務(wù)器端公鑰加密的數(shù)據(jù)
                      String decryptString=SecurityUtil.getCoder().getDecryptString(params);
                      
                      
          // 要返回的結(jié)果
                      String response="你好!"+decryptString;
                      
                      
          // 使用客戶端提供的公鑰對(duì)返回的數(shù)據(jù)進(jìn)行加密
                      byte[] retval=SecurityUtil.getCoder().getEncryptArray(response, clientPublicKey);
                      
                      
          return retval;
                  } 
          catch (Exception e) {
                      e.printStackTrace();
                      
                      
          return null;
                  }
              }

              @Override
              
          public byte[] getServerPublicKey() {
                  
          return SecurityUtil.getCoder().getPublicKey();
              }
          }


          客戶端調(diào)用服務(wù)器端的代碼:
          package com.heyang;

          import org.codehaus.xfire.XFireFactory;
          import org.codehaus.xfire.client.XFireProxyFactory;
          import org.codehaus.xfire.service.Service;
          import org.codehaus.xfire.service.binding.ObjectServiceFactory;

          public class Test {
              
          public static void main(String[] args) {
                  Service srvcModel 
          = new ObjectServiceFactory().create(IService.class);
                  XFireProxyFactory factory 
          = new XFireProxyFactory(XFireFactory
                          .newInstance().getXFire());

                  String helloWorldURL 
          = "http://localhost:8080/XfireSample/services/hello";
                  
          try {
                      IService srvc 
          = (IService) factory.create(srvcModel, helloWorldURL);

                      
          // 得到服務(wù)器端的公鑰
                      byte[] serverPublicKey=srvc.getServerPublicKey();
                      System.out.print(
          "從服務(wù)器端得到的公鑰為:");
                      
          for(byte b:serverPublicKey){
                          System.out.print(b);
                      }
                      System.out.println();
                      
                      
                      RSASecurityCoder coder
          =SecurityUtil.getCoder();
                      String requestString
          ="世界";
                      
                      
          // 使用服務(wù)器端的公鑰對(duì)要傳出去的數(shù)據(jù)進(jìn)行加密
                      byte[] params=coder.getEncryptArray(requestString, serverPublicKey);
                      
                      
          // 得到服務(wù)器端的返回結(jié)果
                      byte[] responseArray=srvc.getResonse(params, coder.getPublicKey());
                      
                      
          // 使用自己的私鑰進(jìn)行解密
                      String responseString=coder.getDecryptString(responseArray);
                      System.out.println(
          "從服務(wù)器端返回的字符串結(jié)果是:"+responseString);
                  } 
          catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }

          輸出的結(jié)果為:
          從服務(wù)器端得到的公鑰為:48-127-9748136942-12272-122-913111503-127-115048-127-1192-127-1270-575108-121578675121-687-32-1165359-2586-50-127114-24-6769-17-128115114982868-11550-121-111-69-494021-48-22-5844-37-8645-115-125-984651-344761-117-7875-34115-101-119164666123-4211-13-103-62-30-587926842-12338-32-91-24-75-1177128103-12-71108-121-122112-712-1089753-2691-7863-6385-41-10210782-8784120344-69-90474108-3661-47089-1261812510046-123-3910723101
          從服務(wù)器端返回的字符串結(jié)果是:你好!世界

          服務(wù)器端和客戶端使用的RSA加密解密類代碼:
          package com.heyang;

          import java.security.KeyFactory;
          import java.security.KeyPair;
          import java.security.KeyPairGenerator;
          import java.security.PrivateKey;
          import java.security.PublicKey;
          import java.security.interfaces.RSAPrivateKey;
          import java.security.interfaces.RSAPublicKey;
          import java.security.spec.PKCS8EncodedKeySpec;
          import java.security.spec.X509EncodedKeySpec;

          import javax.crypto.Cipher;

          /**
           * RSA加密解密類
           * 說(shuō)明:
           * 作者:何楊(heyang78@gmail.com)
           * 創(chuàng)建時(shí)間:2010-12-1 下午06:14:38
           * 修改時(shí)間:2010-12-1 下午06:14:38
           
          */
          public class RSASecurityCoder{
              
          // 非對(duì)稱加密密鑰算法
              private static final String Algorithm="RSA";
              
              
          // 密鑰長(zhǎng)度,用來(lái)初始化
              private static final int Key_Size=1024;
              
              
          // 公鑰
              private final byte[] publicKey;
              
              
          // 私鑰
              private final byte[] privateKey;
              
              
          /**
               * 構(gòu)造函數(shù),在其中生成公鑰和私鑰
               * 
          @throws Exception
               
          */
              
          public RSASecurityCoder() throws Exception{
                  
          // 得到密鑰對(duì)生成器
                  KeyPairGenerator kpg=KeyPairGenerator.getInstance(Algorithm);
                  kpg.initialize(Key_Size);
                  
                  
          // 得到密鑰對(duì)
                  KeyPair kp=kpg.generateKeyPair();
                  
                  
          // 得到公鑰
                  RSAPublicKey keyPublic=(RSAPublicKey)kp.getPublic();
                  publicKey
          =keyPublic.getEncoded();
                  
                  
          // 得到私鑰
                  RSAPrivateKey keyPrivate=(RSAPrivateKey)kp.getPrivate();
                  privateKey
          =keyPrivate.getEncoded();
              }
              
              
          /**
               * 用公鑰對(duì)字符串進(jìn)行加密
               * 
               * 說(shuō)明:
               * 
          @param originalString
               * 
          @param publicKeyArray
               * 
          @return
               * 
          @throws Exception
               * 創(chuàng)建時(shí)間:2010-12-1 下午06:29:51
               
          */
              
          public byte[] getEncryptArray(String originalString,byte[] publicKeyArray) throws Exception{
                  
          // 得到公鑰
                  X509EncodedKeySpec keySpec=new X509EncodedKeySpec(publicKeyArray);
                  KeyFactory kf
          =KeyFactory.getInstance(Algorithm);
                  PublicKey keyPublic
          =kf.generatePublic(keySpec);
                  
                  
          // 加密數(shù)據(jù)
                  Cipher cp=Cipher.getInstance(Algorithm);
                  cp.init(Cipher.ENCRYPT_MODE, keyPublic);
                  
          return cp.doFinal(originalString.getBytes());
              }
              
              
              
          /**
               * 使用私鑰進(jìn)行解密
               * 
               * 說(shuō)明:
               * 
          @param encryptedDataArray
               * 
          @return
               * 
          @throws Exception
               * 創(chuàng)建時(shí)間:2010-12-1 下午06:35:28
               
          */
              
          public String getDecryptString(byte[] encryptedDataArray) throws Exception{
                  
          // 得到私鑰
                  PKCS8EncodedKeySpec keySpec=new PKCS8EncodedKeySpec(privateKey);
                  KeyFactory kf
          =KeyFactory.getInstance(Algorithm);
                  PrivateKey keyPrivate
          =kf.generatePrivate(keySpec);
                  
                  
          // 解密數(shù)據(jù)
                  Cipher cp=Cipher.getInstance(Algorithm);
                  cp.init(Cipher.DECRYPT_MODE, keyPrivate);
                  
          byte[] arr=cp.doFinal(encryptedDataArray);
                  
                  
          // 得到解密后的字符串
                  return new String(arr);
              }

              
          public byte[] getPublicKey() {
                  
          return publicKey;
              }
              
              
          public static void main(String[] arr) throws Exception{
                  String str
          ="你好,世界! Hello,world!";
                  System.out.println(
          "準(zhǔn)備用公鑰加密的字符串為:"+str);
                  
                  
          // 用公鑰加密
                  RSASecurityCoder rsaCoder=new RSASecurityCoder();
                  
          byte[] publicKey=rsaCoder.getPublicKey();        
                  
          byte[] encryptArray=rsaCoder.getEncryptArray(str, publicKey);
                  
                  System.out.print(
          "用公鑰加密后的結(jié)果為:");
                  
          for(byte b:encryptArray){
                      System.out.print(b);
                  }
                  System.out.println();
                  
                  
          // 用私鑰解密
                  String str1=rsaCoder.getDecryptString(encryptArray);
                  System.out.println(
          "用私鑰解密后的字符串為:"+str1);
              }
          }

          用于初始化RSASecurityCoder實(shí)例的SecurityUtil類代碼:
          package com.heyang;

          /**
           * 信息安全實(shí)用類
           * 說(shuō)明:
           * 作者:何楊(heyang78@gmail.com)
           * 創(chuàng)建時(shí)間:2010-12-2 上午10:57:49
           * 修改時(shí)間:2010-12-2 上午10:57:49
           
          */
          public class SecurityUtil{
              
          // 用于加密解密的RSA編碼類
              private static RSASecurityCoder coder;
              
              
          /**
               * 初始化coder的靜態(tài)構(gòu)造子
               
          */
              
          static{
                  
          try {
                      coder
          =new RSASecurityCoder();
                  } 
          catch (Exception e) {
                      e.printStackTrace();
                  }
              }

              
          public static RSASecurityCoder getCoder() {
                  
          return coder;
              }
          }


          您可以從http://www.box.net/shared/cyg98xgz78 獲得上述代碼涉及到的兩個(gè)實(shí)例工程。

          好了,感謝您看到這里,希望此文字沒(méi)有耽誤您太多寶貴時(shí)間。
          posted on 2010-12-02 11:44 何楊 閱讀(11057) 評(píng)論(16)  編輯  收藏

          Feedback

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例[未登錄](méi) 2010-12-02 13:22 zz
          支持一下,幸苦了  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2010-12-09 09:59 mashiguang
          謝謝,先收藏再細(xì)讀。  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2010-12-09 10:06 mashiguang
          學(xué)習(xí)了。我感覺(jué)這樣做解決了明文的問(wèn)題,是不是還不能解決假冒客戶端的問(wèn)題?  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2010-12-09 14:12 何楊
          @mashiguang

          是的,還需要用數(shù)字證書等。  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例[未登錄](méi) 2010-12-10 09:41 mashiguang
          @何楊
          謝謝
          期待你出一篇https加密的方式的文章。  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2010-12-10 09:55 何楊
          @mashiguang

          客氣了,我也是初學(xué)。盡力吧!  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例[未登錄](méi) 2011-03-06 15:13 s
          客戶端的密鑰怎么產(chǎn)生的?是不是也在服務(wù)器端產(chǎn)生然后返回到了客戶端?那傳輸過(guò)程中被人截取了私鑰怎么辦?再說(shuō)你定義的方法都是在服務(wù)器端執(zhí)行,加密也是先把明文發(fā)送到服務(wù)器加密 ,然后返回加密的數(shù)據(jù),再發(fā)送到服務(wù)器  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例[未登錄](méi) 2011-03-07 23:04 何楊
          @s

          服務(wù)器和客戶端都是各自產(chǎn)生自己的私鑰和公鑰,公鑰用于發(fā)給對(duì)方來(lái)給要發(fā)給自己的數(shù)據(jù)加密,收到數(shù)據(jù)后再用自己這邊的私鑰解密。  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2011-04-18 08:41 柳寄悠
          你好,我是一名大四的學(xué)生,現(xiàn)在正在做畢業(yè)設(shè)計(jì),你的文章“使用RSA進(jìn)行信息加密解密的WebService示例 ”對(duì)我很有幫助,我還有問(wèn)題要問(wèn)你,希望加qq:912614339  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例[未登錄](méi) 2011-12-09 23:13 Ruby
          @mashiguang
          @何楊
          不僅客戶端,服務(wù)端也有被假冒的危險(xiǎn)。
          公鑰傳輸過(guò)程不可靠。
          使用RSA進(jìn)行常規(guī)通訊還有低效問(wèn)題。
          直接上有可信數(shù)字證書的HTTPS更靠譜。
            回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2011-12-10 09:05 何楊
          @Ruby

          說(shuō)的沒(méi)錯(cuò),這篇文章只是學(xué)習(xí)過(guò)程中的一步,還會(huì)前進(jìn)的。  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2012-02-08 16:13 ss
          您好,我想問(wèn)一下那個(gè)XfireSample導(dǎo)進(jìn)去怎么會(huì)有錯(cuò)的,我的QQ:414038013,希望您能加我,你這篇文章對(duì)我非常有幫助,謝謝  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2012-02-13 11:06 何楊
          @ss

          庫(kù)導(dǎo)入進(jìn)去了?  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2012-09-04 18:21 魏燕
          這個(gè)是java的 有.net的嗎?有的話 麻煩解答一下~  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2012-09-05 09:09 何楊
          @魏燕

          沒(méi)。  回復(fù)  更多評(píng)論
            

          # re: 使用RSA進(jìn)行信息加密解密的WebService示例 2014-05-08 09:57 tanjun
          實(shí)例怎么下載不了  回復(fù)  更多評(píng)論
            


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 道真| 拜城县| 吕梁市| 化德县| 阿克苏市| 南平市| 长治县| 竹溪县| 宜君县| 三门县| 洛扎县| 灵丘县| 大田县| 湖州市| 竹山县| 分宜县| 山东省| 双桥区| 广饶县| 偏关县| 鲜城| 汉阴县| 平舆县| 长春市| 阿克| 沂南县| 和龙市| 皋兰县| 射阳县| 托克逊县| 安吉县| 会同县| 探索| 新昌县| 莱州市| 宜章县| 区。| 塔城市| 新丰县| 拉萨市| 河津市|