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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值