Hessian加密传输

  由于项目需要需要研究下hessian的加密传输。于是翻出hessian源码,发现com.caucho.hessian.security包下面有两个类X509Encryption和X509Signature,一个是用来加密解密的,一个是用来签名认真的。很遗憾hessian虽然提供了这两项功能但是它并没有使用上去,甚至还没有给我们开了口子来使用它。仍然不甘心,于google,baidu,bing多方搜索hessian的内置加密方式如何使用,仍然没有结果。没有办法只能自己来提供对传输的数据进行加密和解密的方式了。在这里提供了两套加密解密方式:非对称密钥的RSA和对称密钥的AES。

       一、 非对称密钥加密算法RSA

       非对称密钥算法需要一对密钥:公开密钥和私有密钥。利用公开密钥进行加密后的信息,只有用对应的私有密钥才能解密。因为加密和解密用的密钥是不一样的,因此,公开密钥是公开的,供所有人使用,并且不会威胁到传递信息和解密密钥的安全,不需要对密钥传递的额外保护。首先,提供RSA的密钥生成算法,生成公有密钥和私有密钥存入文件中:且看 RSAKeyCreater.java

1./**  
2. * @author zhangwei  
3. *  
4. */  
5.public class RSAKeyCreater {   
6.       
7.    /**  
8.     * @param args  
9.     * @throws Exception   
10.     */  
11.    public static void main(String[] args) throws Exception {   
12.        RSAKeyCreater rSAKeyCreater = new RSAKeyCreater();   
13.        rSAKeyCreater.createKeyFile(512, System.getProperty("user.dir"));   
14.    }   
15.  
16.    public void createKeyFile(int in, String url) throws Exception {   
17.        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");   
18.        kpg.initialize(in);   
19.        KeyPair kp = kpg.genKeyPair();   
20.        PublicKey publicKey = kp.getPublic();   
21.        PrivateKey privateKey = kp.getPrivate();   
22.           
23.        File file1 = new File(url + "/src/main/resources/public_key_file.rsa");   
24.        FileOutputStream publicOut = new FileOutputStream(file1);   
25.        ObjectOutputStream publicObjectOutput = new ObjectOutputStream(publicOut);   
26.        publicObjectOutput.writeObject(publicKey);   
27.        publicObjectOutput.flush();   
28.        publicObjectOutput.close();   
29.           
30.        File file2 = new File(url + "/src/main/resources/private_key_file.rsa");   
31.        FileOutputStream privateOut = new FileOutputStream(file2);   
32.        ObjectOutputStream privateObjectOutput = new ObjectOutputStream(privateOut);   
33.        privateObjectOutput.writeObject(privateKey);   
34.        privateObjectOutput.flush();   
35.        privateObjectOutput.close();   
36.    }   
37.}  


    RSAKeyCreater类中createKeyFile()方法生成公钥和私钥分别保存到public_key_file.rsa和private_key_file.rsa文件中,加密和解密时进行使用。

         其次,提供加密解密算法,对byte[] 进行加密和解密:且看RSAEncryptionUtil.java

1./**  
2. * @author zhangwei  
3. *   
4. */  
5.public class AESEncryptionUtil {   
6.    /**  
7.     * 加密  
8.     * @param bytes  
9.     * @param aesKey  
10.     * @return  
11.     */  
12.    public static byte[] encryptMessage(byte[] bytes, String aesKey) {   
13.        try {   
14.            Object obj = KeyUtil.getKey(aesKey);   
15.            SecretKey key = (SecretKey) obj;   
16.            Cipher cipher = Cipher.getInstance("AES");   
17.            cipher.init(Cipher.ENCRYPT_MODE, key);   
18.            byte[] decryptedBytes = cipher.doFinal(bytes);   
19.            return decryptedBytes;   
20.        } catch (Exception e) {   
21.            e.printStackTrace();   
22.            return null;   
23.        }   
24.    }   
25.  
26.    /**  
27.     * 解密  
28.     * @param encryptedBytes  
29.     * @param aesKey  
30.     * @return  
31.     */  
32.    public static byte[] decryptMessage(byte[] encryptedBytes, String aesKey) {   
33.        try {   
34.            Object obj = KeyUtil.getKey(aesKey);   
35.            SecretKey key = (SecretKey) obj;   
36.            Cipher cipher = Cipher.getInstance("AES");   
37.            cipher.init(Cipher.DECRYPT_MODE, key);   
38.            byte[] bytes = cipher.doFinal(encryptedBytes);   
39.            return bytes;   
40.        } catch (Exception e) {   
41.            e.printStackTrace();   
42.            return null;   
43.        }   
44.    }   
45.}  


RSAEncryptionUtil的encryptWithPublicKey()方法对信息进行加
密,decryptWithPrivateKey()方法对加密后的信息进行解密,分别需要传入公有和私有密钥。
            由于提供的算法是对byte[]数组进行加密和解密返回新的byte[],因此我们需要提供一个普通object对象到byte[]之间转化的工具:且看SerializationUtil.java

1./**  
2. * @author zhangwei  
3. *   
4. */  
5.public class SerializationUtil {   
6.  
7.    public static byte[] serialize(Object obj) {   
8.        try {   
9.            if (obj == null)   
10.                throw new NullPointerException();   
11.               
12.            ByteArrayOutputStream os = new ByteArrayOutputStream();   
13.            ObjectOutputStream out = new ObjectOutputStream(os);   
14.            out.writeObject(obj);   
15.            out.flush();   
16.            out.close();   
17.            return os.toByteArray();   
18.        } catch (Exception e) {   
19.            e.printStackTrace();   
20.            return null;   
21.        }   
22.    }   
23.  
24.    public static Object deserialize(byte[] by) {   
25.        try {   
26.            if (by == null)   
27.                throw new NullPointerException();   
28.  
29.            ByteArrayInputStream is = new ByteArrayInputStream(by);   
30.            ObjectInputStream in = new ObjectInputStream(is);   
31.            Object obj = in.readObject();   
32.            in.close();   
33.            return obj;   
34.        } catch (Exception e) {   
35.            e.printStackTrace();   
36.            return null;   
37.        }   
38.    }   
39.}  


   SerializationUtil类中的serialize()方法将普通java对象序列化成byte[],deserialize()方法将byte[]反序列化成原来的对象。
          RSA加密算法有个特点,就是对加密明文和密文的长度有限制,当我们加密的明文过长时,我们需要对明文分块进行加密,因此那种长度较短的信息进行加密适合使用RSA算法。一般来说,我们进行加密的对象序列化成byte[]数组之后长度都超过了RSA加密算法的要求,因此我们可以选用另一种加密算法:AES。

       二、 对称密钥加密算法AES
           对称密钥算法中,信息的加密和解密都是使用相同的密钥,使用起来简单,速度快,但在使用之前,需要通过额外安全的途径交换加密密钥。首先,提供AES密钥生成算法,生成密钥保存在文件中,且看AESKeyCreater.java

1./**  
2. * @author zhangwei  
3. *  
4. */  
5.public class AESKeyCreater {   
6.       
7.    /**  
8.     * @param args  
9.     */  
10.    public static void main(String[] args) throws Exception{   
11.        String url = System.getProperty("user.dir");   
12.        AESKeyCreater aESKeyCreater = new AESKeyCreater();   
13.        aESKeyCreater.createKeyFile(url);   
14.    }   
15.  
16.    public void createKeyFile(String url) throws Exception{   
17.        Security.addProvider(new SunJCE());   
18.        KeyGenerator keygen = KeyGenerator.getInstance("AES");   
19.        SecretKey key = keygen.generateKey();   
20.        File file = new File(url + "/src/main/resources/AES_Secret_Key_File.aes");   
21.        FileOutputStream out = new FileOutputStream(file);   
22.        ObjectOutputStream objectOutput = new ObjectOutputStream(out);   
23.        objectOutput.writeObject(key);   
24.        objectOutput.flush();   
25.        objectOutput.close();   
26.    }   
27.}  


      AESKeyCreater类中createKeyFile()方法生成AES算法的密钥,保存在AES_Secret_Key_File.aes文件中,供加密和解密时使用。
            其次,提供加密解密算法,对byte[] 进行加密和解密:且看AESEncryptionUtil.java
1./**  
2. * @author zhangwei  
3. *   
4. */  
5.public class AESEncryptionUtil {   
6.    /**  
7.     * 加密  
8.     * @param bytes  
9.     * @param aesKey  
10.     * @return  
11.     */  
12.    public static byte[] encryptMessage(byte[] bytes, String aesKey) {   
13.        try {   
14.            Object obj = KeyUtil.getKey(aesKey);   
15.            SecretKey key = (SecretKey) obj;   
16.            Cipher cipher = Cipher.getInstance("AES");   
17.            cipher.init(Cipher.ENCRYPT_MODE, key);   
18.            byte[] decryptedBytes = cipher.doFinal(bytes);   
19.            return decryptedBytes;   
20.        } catch (Exception e) {   
21.            e.printStackTrace();   
22.            return null;   
23.        }   
24.    }   
25.  
26.    /**  
27.     * 解密  
28.     * @param encryptedBytes  
29.     * @param aesKey  
30.     * @return  
31.     */  
32.    public static byte[] decryptMessage(byte[] encryptedBytes, String aesKey) {   
33.        try {   
34.            Object obj = KeyUtil.getKey(aesKey);   
35.            SecretKey key = (SecretKey) obj;   
36.            Cipher cipher = Cipher.getInstance("AES");   
37.            cipher.init(Cipher.DECRYPT_MODE, key);   
38.            byte[] bytes = cipher.doFinal(encryptedBytes);   
39.            return bytes;   
40.        } catch (Exception e) {   
41.            e.printStackTrace();   
42.            return null;   
43.        }   
44.    }   
45.} 


AESEncryptionUtil类中encryptMessage()方法对信息进行加密,decryptMessage()方法对信息进行解密,都需要传入AES密钥文件。由于都是对byte[]数组进行加密和解密,因此也需要RSA算法中提供的普通Object对象和byte[]之间的映射工具。

         下面给出AES算法对hessian进行加密和解密传输,思路:客户端通过Hessian工厂获取到Hessian服务之后,将传入参数对象序列化成byte[],然后对byte[]进行加密,然后调用hessian服务的方法,服务端获取到客户端传过来的加密之后的byte[]参数,首先进行AES解密,然后将byte[]反序列化成参数对象,再调用相应的业务逻辑,再然后将返回结果进行序列化成byte[],然后进行AES加密,然后客户端获得返回结果之后进行AES解密,然后反序列化成结果对象,至此一轮调用完成。且看hessian服务接口:EncryptionService.java


1./**  
2. * @author zhangwei  
3. *  
4. */  
5.public interface EncryptionService {   
6.       
7.    public static final String publicKeyFile = EncryptionService.class.getResource("/").getPath() + "/public_key_file.rsa";   
8.    public static final String privateKeyFile = EncryptionService.class.getResource("/").getPath() + "/private_key_file.rsa";   
9.    public static final String aesKeyFile = EncryptionService.class.getResource("/").getPath() + "AES_Secret_Key_File.aes";   
10.       
11.    public byte[] testHessianEncrypt(byte[] encryptedBytes);   
12.  
13.}  


由于hessian是一个二进制协议,非常适合传输二进制数据,以byte[]作为参数和返回结果是非常合适的,将来这部分完全可以做在框架之中。且看hessian服务实现类:EncryptionServiceImpl.java

1./**  
2. * @author zhangwei  
3. *  
4. */  
5.public class EncryptionServiceImpl implements EncryptionService{   
6.  
7.    public byte[] testHessianEncrypt(byte[] encryptedBytes) {   
8.        //解密参数   
9.        byte[] decryptedBytes = AESEncryptionUtil.decryptMessage(encryptedBytes, aesKeyFile);   
10.        //将参数反序列化   
11.        Secret secret = (Secret)SerializationUtil.deserialize(decryptedBytes);   
12.        //业务逻辑   
13.        System.out.println(secret.getMessage());   
14.        secret.setMessage("I love you too!");   
15.        System.out.println(secret.getMessage());   
16.        //将结果序列化   
17.        byte[] returnBytes = SerializationUtil.serialize(secret);   
18.        //加密返回结果   
19.        byte[] encryptedReturnBytes = AESEncryptionUtil.encryptMessage(returnBytes,aesKeyFile);   
20.        return encryptedReturnBytes;   
21.    }   
22.} 


  代码一目了然,没啥好说的。且看客户端调用:TestClient.java
1./** 
2. * @author zhangwei 
3. * 
4. */ 
5.public class TestClient {  
6.  
7.    /**  
8.     * @param args  
9.     * @throws MalformedURLException   
10.     */  
11.    public static void main(String[] args) throws MalformedURLException {   
12.        String hessianServiceUrl = "http://localhost:8089/HessianEncryption/hessianService";   
13.        String aesKeyFile = System.getProperty("user.dir") + "/lib/AES_Secret_Key_File.aes";   
14.           
15.        HessianProxyFactory factory = new HessianProxyFactory();   
16.        EncryptionService service = (EncryptionService)factory.create(EncryptionService.class, hessianServiceUrl);   
17.        Secret secret = new Secret();   
18.        secret.setMessage("I love you!");   
19.        System.out.println(secret.getMessage());   
20.        //序列化參數   
21.        byte[] paramBytes = SerializationUtil.serialize(secret);   
22.        //加密參數   
23.        byte[] encryptedParamBytes = AESEncryptionUtil.encryptMessage(paramBytes, aesKeyFile);   
24.        //調用方法   
25.        byte[] encryptedReturnBytes = service.testHessianEncrypt(encryptedParamBytes);   
26.        //解密返回結果   
27.        byte[] decryptedReturnBytes = AESEncryptionUtil.decryptMessage(encryptedReturnBytes, aesKeyFile);   
28.        //反序列化結果   
29.        Secret returnResult = (Secret)SerializationUtil.deserialize(decryptedReturnBytes);   
30.        System.out.println(returnResult.getMessage());   
31.    }   
32.  
33.}  


【转载地址】http://zwustudy.iteye.com/blog/1679850

猜你喜欢

转载自hck.iteye.com/blog/2030346