• 使用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 获得上述代码涉及到的两个实例工程。

    好了,感谢您看到这里,希望此文字没有耽误您太多宝贵时间。
  • 相关阅读:
    文件加密二进制版本
    文件复制二进制版
    C语言里的文件函数
    文件加密2——基础版(限文本)
    文件加密——可执行,较复杂的抽取(限文本)
    typedef的使用3——使用经过typedef定义的函数构成的函数数组
    typedef的使用2——定义函数
    typedef的使用1——引入
    C语言枚举
    HanLP极致简繁转换详细讲解
  • 原文地址:https://www.cnblogs.com/zmc/p/4112384.html
Copyright © 2020-2023  润新知