zoukankan      html  css  js  c++  java
  • 使用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加密解密类
     * 说明:
     * 作者:何杨(heyang78@gmail.com)
     * 创建时间: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;

    /**
     * 信息安全实用类
     * 说明:
     * 作者:何杨(heyang78@gmail.com)
     * 创建时间: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 获得上述代码涉及到的两个实例工程。

    好了,感谢您看到这里,希望此文字没有耽误您太多宝贵时间。
  • 相关阅读:
    sqlplus时报Linux-x86_64 Error: 13: Permission denied
    thrift之TTransport层的缓存传输类TBufferedTransport和缓冲基类TBufferBase
    Java实现 蓝桥杯 算法提高 新建Microsoft world文档
    Java实现 蓝桥杯 算法提高 新建Microsoft world文档
    Java实现 蓝桥杯 算法提高 快乐司机
    Java实现 蓝桥杯 算法提高 快乐司机
    Java实现 蓝桥杯 算法提高 队列操作
    Java实现 蓝桥杯 算法提高 队列操作
    Java实现 蓝桥杯 算法提高 文本加密
    Java实现 蓝桥杯 算法提高 合并石子
  • 原文地址:https://www.cnblogs.com/zmc/p/4112384.html
Copyright © 2011-2022 走看看