使用RSA进行信息加密解密的WebService示例

 
按:以下文字涉及RSA对WebService传递的数据的加密解密,如果您已经熟知RSA或是有其它更好的方法请不要往下看以免浪费时间.

WebService采用的协议是SOAP,它基于HTTP,而HTTP是明文方式,也就是说,采用WebService传递的数据是明文的。如果是天气预报这种公开的只读信息的WebService无所谓,如果涉及写入或是和私密数据相关,那么明文传递就有很大的潜在危险性,必须加以遏止。

一般来说有两种方法,一是采用https加密的方式,另一种是用非对称加密算法对数据加密,下文提到的RSA就是第二种。

使用RSA对WebService传递的信息加密解密的基本思想是:服务器端提供一个WebService方法byte[] getServerPublicKey(),客户端可以以此得到服务器端的公钥,然后使用服务器端的公钥对要传出去的数据进行RSA加密,并附带以自己的公钥;服务器端得到客户端的请求后,先用自己的私钥解密客户端送来的数据,得到处理结果后用客户端提供的公钥加密,然后传回;客户端得到服务器端的返回数据后,用自己的私钥进行解密,最终得到了服务器端的真实数据。服务器端和客户端各自保存自己的RSA私钥用于解密,提供给对方RSA公钥进行加密,这样中间传递的信息就安全了。

加密解密示意顺序图:


下面是服务器端实现类的代码:
package  com.heyang;


public   class  ServiceImpl  implements  IService{
    @Override
    
public   byte [] getResonse( byte [] params,  byte [] clientPublicKey) {
        
try  {
            
//  使用自己的私钥解密客户端用服务器端公钥加密的数据
            String decryptString = SecurityUtil.getCoder().getDecryptString(params);
            
            
//  要返回的结果
            String response = " 你好! " + decryptString;
            
            
//  使用客户端提供的公钥对返回的数据进行加密
             byte [] retval = SecurityUtil.getCoder().getEncryptArray(response, clientPublicKey);
            
            
return  retval;
        } 
catch  (Exception e) {
            e.printStackTrace();
            
            
return   null ;
        }
    }

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


客户端调用服务器端的代码:
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);

            
//  得到服务器端的公钥
             byte [] serverPublicKey = srvc.getServerPublicKey();
            System.out.print(
" 从服务器端得到的公钥为: " );
            
for ( byte  b:serverPublicKey){
                System.out.print(b);
            }
            System.out.println();
            
            
            RSASecurityCoder coder
= SecurityUtil.getCoder();
            String requestString
= " 世界 " ;
            
            
//  使用服务器端的公钥对要传出去的数据进行加密
             byte [] params = coder.getEncryptArray(requestString, serverPublicKey);
            
            
//  得到服务器端的返回结果
             byte [] responseArray = srvc.getResonse(params, coder.getPublicKey());
            
            
//  使用自己的私钥进行解密
            String responseString = coder.getDecryptString(responseArray);
            System.out.println(
" 从服务器端返回的字符串结果是: " + responseString);
        } 
catch  (Exception e) {
            e.printStackTrace();
        }
    }
}

输出的结果为:
从服务器端得到的公钥为: 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
从服务器端返回的字符串结果是:你好!世界

服务器端和客户端使用的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加密解密类
 * 说明:
 * 作者:何杨([email protected])
 * 创建时间:2010-12-1 下午06:14:38
 * 修改时间:2010-12-1 下午06:14:38
 
*/
public   class  RSASecurityCoder{
    
//  非对称加密密钥算法
     private   static   final  String Algorithm = " RSA " ;
    
    
//  密钥长度,用来初始化
     private   static   final   int  Key_Size = 1024 ;
    
    
//  公钥
     private   final   byte [] publicKey;
    
    
//  私钥
     private   final   byte [] privateKey;
    
    
/**
     * 构造函数,在其中生成公钥和私钥
     * 
@throws  Exception
     
*/
    
public  RSASecurityCoder()  throws  Exception{
        
//  得到密钥对生成器
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(Algorithm);
        kpg.initialize(Key_Size);
        
        
//  得到密钥对
        KeyPair kp = kpg.generateKeyPair();
        
        
//  得到公钥
        RSAPublicKey keyPublic = (RSAPublicKey)kp.getPublic();
        publicKey
= keyPublic.getEncoded();
        
        
//  得到私钥
        RSAPrivateKey keyPrivate = (RSAPrivateKey)kp.getPrivate();
        privateKey
= keyPrivate.getEncoded();
    }
    
    
/**
     * 用公钥对字符串进行加密
     * 
     * 说明:
     * 
@param  originalString
     * 
@param  publicKeyArray
     * 
@return
     * 
@throws  Exception
     * 创建时间: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);
        
        
//  加密数据
        Cipher cp = Cipher.getInstance(Algorithm);
        cp.init(Cipher.ENCRYPT_MODE, keyPublic);
        
return  cp.doFinal(originalString.getBytes());
    }
    
    
    
/**
     * 使用私钥进行解密
     * 
     * 说明:
     * 
@param  encryptedDataArray
     * 
@return
     * 
@throws  Exception
     * 创建时间: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);
        
        
//  解密数据
        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(
" 准备用公钥加密的字符串为: " + str);
        
        
//  用公钥加密
        RSASecurityCoder rsaCoder = new  RSASecurityCoder();
        
byte [] publicKey = rsaCoder.getPublicKey();        
        
byte [] encryptArray = rsaCoder.getEncryptArray(str, publicKey);
        
        System.out.print(
" 用公钥加密后的结果为: " );
        
for ( byte  b:encryptArray){
            System.out.print(b);
        }
        System.out.println();
        
        
//  用私钥解密
        String str1 = rsaCoder.getDecryptString(encryptArray);
        System.out.println(
" 用私钥解密后的字符串为: " + str1);
    }
}

用于初始化RSASecurityCoder实例的SecurityUtil类代码:
package  com.heyang;

/**
 * 信息安全实用类
 * 说明:
 * 作者:何杨([email protected])
 * 创建时间:2010-12-2 上午10:57:49
 * 修改时间:2010-12-2 上午10:57:49
 
*/
public   class  SecurityUtil{
    
//  用于加密解密的RSA编码类
     private   static  RSASecurityCoder coder;
    
    
/**
     * 初始化coder的静态构造子
     
*/
    
static {
        
try  {
            coder
= new  RSASecurityCoder();
        } 
catch  (Exception e) {
            e.printStackTrace();
        }
    }

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


您可以从 http://www.box.net/shared/cyg98xgz78 获得上述代码涉及到的两个实例工程。

好了,感谢您看到这里,希望此文字没有耽误您太多宝贵时间。

猜你喜欢

转载自a52071453.iteye.com/blog/2267110