分享

Hessian加密传输

 老年图书馆 2012-09-21
Hessian加密传输
2012-09-17 20:38:36 来源:开发界 作者:admin 栏目:Java 责任编辑:admin
[导读]由于项目需要需要研究下hessian的加密传输。于是翻出hessian源码,发现com.caucho.hessian.security包下面有两个类X509Encryption和X509Signature,一个是用来加密解密的,一个是用来签名认真的。

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

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

       非对称密钥算法需要一对密钥:公开密钥和私有密钥。利用公开密钥进行加密后的信息,只有用对应的私有密钥才能解密。因为加密和解密用的密钥是不一样的,因 此,公开密钥是公开的,供所有人使用,并且不会威胁到传递信息和解密密钥的安全,不需要对密钥传递的额外保护。首先,提供RSA的密钥生成算法,生成公有 密钥和私有密钥存入文件中:且看 RSAKeyCreater.java
Java代码 
/** 
 * @author zhangwei 
 * 
 */ 
public class RSAKeyCreater {  
      
    /** 
     * @param args 
     * @throws Exception  
     */ 
    public static void main(String[] args) throws Exception {  
        RSAKeyCreater rSAKeyCreater = new RSAKeyCreater();  
        rSAKeyCreater.createKeyFile(512, System.getProperty("user.dir"));  
    }  
 
    public void createKeyFile(int in, String url) throws Exception {  
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");  
        kpg.initialize(in);  
        KeyPair kp = kpg.genKeyPair();  
        PublicKey publicKey = kp.getPublic();  
        PrivateKey privateKey = kp.getPrivate();  
          
        File file1 = new File(url + "/src/main/resources/public_key_file.rsa");  
        FileOutputStream publicOut = new FileOutputStream(file1);  
        ObjectOutputStream publicObjectOutput = new ObjectOutputStream(publicOut);  
        publicObjectOutput.writeObject(publicKey);  
        publicObjectOutput.flush();  
        publicObjectOutput.close();  
          
        File file2 = new File(url + "/src/main/resources/private_key_file.rsa");  
        FileOutputStream privateOut = new FileOutputStream(file2);  
        ObjectOutputStream privateObjectOutput = new ObjectOutputStream(privateOut);  
        privateObjectOutput.writeObject(privateKey);  
        privateObjectOutput.flush();  
        privateObjectOutput.close();  
    }  

/**
 * @author zhangwei
 *
 */
public class RSAKeyCreater {
 
 /**
  * @param args
  * @throws Exception
  */
 public static void main(String[] args) throws Exception {
  RSAKeyCreater rSAKeyCreater = new RSAKeyCreater();
  rSAKeyCreater.createKeyFile(512, System.getProperty("user.dir"));
 }

 public void createKeyFile(int in, String url) throws Exception {
  KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
  kpg.initialize(in);
  KeyPair kp = kpg.genKeyPair();
  PublicKey publicKey = kp.getPublic();
  PrivateKey privateKey = kp.getPrivate();
  
  File file1 = new File(url + "/src/main/resources/public_key_file.rsa");
  FileOutputStream publicOut = new FileOutputStream(file1);
  ObjectOutputStream publicObjectOutput = new ObjectOutputStream(publicOut);
  publicObjectOutput.writeObject(publicKey);
  publicObjectOutput.flush();
  publicObjectOutput.close();
  
  File file2 = new File(url + "/src/main/resources/private_key_file.rsa");
  FileOutputStream privateOut = new FileOutputStream(file2);
  ObjectOutputStream privateObjectOutput = new ObjectOutputStream(privateOut);
  privateObjectOutput.writeObject(privateKey);
  privateObjectOutput.flush();
  privateObjectOutput.close();
 }
}

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

         其次,提供加密解密算法,对byte[] 进行加密和解密:且看RSAEncryptionUtil.java
Java代码 
/** 
 * @author zhangwei 
 *  
 */ 
public class AESEncryptionUtil {  
    /** 
     * 加密 
     * @param bytes 
     * @param aesKey 
     * @return 
     */ 
    public static byte[] encryptMessage(byte[] bytes, String aesKey) {  
        try {  
            Object obj = KeyUtil.getKey(aesKey);  
            SecretKey key = (SecretKey) obj;  
            Cipher cipher = Cipher.getInstance("AES");  
            cipher.init(Cipher.ENCRYPT_MODE, key);  
            byte[] decryptedBytes = cipher.doFinal(bytes);  
            return decryptedBytes;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
 
    /** 
     * 解密 
     * @param encryptedBytes 
     * @param aesKey 
     * @return 
     */ 
    public static byte[] decryptMessage(byte[] encryptedBytes, String aesKey) {  
        try {  
            Object obj = KeyUtil.getKey(aesKey);  
            SecretKey key = (SecretKey) obj;  
            Cipher cipher = Cipher.getInstance("AES");  
            cipher.init(Cipher.DECRYPT_MODE, key);  
            byte[] bytes = cipher.doFinal(encryptedBytes);  
            return bytes;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  

/**
 * @author zhangwei
 *
 */
public class AESEncryptionUtil {
 /**
  * 加密
  * @param bytes
  * @param aesKey
  * @return
  */
 public static byte[] encryptMessage(byte[] bytes, String aesKey) {
  try {
   Object obj = KeyUtil.getKey(aesKey);
   SecretKey key = (SecretKey) obj;
   Cipher cipher = Cipher.getInstance("AES");
   cipher.init(Cipher.ENCRYPT_MODE, key);
   byte[] decryptedBytes = cipher.doFinal(bytes);
   return decryptedBytes;
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }

 /**
  * 解密
  * @param encryptedBytes
  * @param aesKey
  * @return
  */
 public static byte[] decryptMessage(byte[] encryptedBytes, String aesKey) {
  try {
   Object obj = KeyUtil.getKey(aesKey);
   SecretKey key = (SecretKey) obj;
   Cipher cipher = Cipher.getInstance("AES");
   cipher.init(Cipher.DECRYPT_MODE, key);
   byte[] bytes = cipher.doFinal(encryptedBytes);
   return bytes;
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }
}

         RSAEncryptionUtil的encryptWithPublicKey()方法对信息进行加
密,decryptWithPrivateKey()方法对加密后的信息进行解密,分别需要传入公有和私有密钥。
            由于提供的算法是对byte[]数组进行加密和解密返回新的byte[],因此我们需要提供一个普通object对象到byte[]之间转化的工具:且看SerializationUtil.java
Java代码 
/** 
 * @author zhangwei 
 *  
 */ 
public class SerializationUtil {  
 
    public static byte[] serialize(Object obj) {  
        try {  
            if (obj == null)  
                throw new NullPointerException();  
              
            ByteArrayOutputStream os = new ByteArrayOutputStream();  
            ObjectOutputStream out = new ObjectOutputStream(os);  
            out.writeObject(obj);  
            out.flush();  
            out.close();  
            return os.toByteArray();  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
 
    public static Object deserialize(byte[] by) {  
        try {  
            if (by == null)  
                throw new NullPointerException();  
 
            ByteArrayInputStream is = new ByteArrayInputStream(by);  
            ObjectInputStream in = new ObjectInputStream(is);  
            Object obj = in.readObject();  
            in.close();  
            return obj;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  

/**
 * @author zhangwei
 *
 */
public class SerializationUtil {

 public static byte[] serialize(Object obj) {
  try {
   if (obj == null)
    throw new NullPointerException();
   
   ByteArrayOutputStream os = new ByteArrayOutputStream();
   ObjectOutputStream out = new ObjectOutputStream(os);
   out.writeObject(obj);
   out.flush();
   out.close();
   return os.toByteArray();
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }

 public static Object deserialize(byte[] by) {
  try {
   if (by == null)
    throw new NullPointerException();

   ByteArrayInputStream is = new ByteArrayInputStream(by);
   ObjectInputStream in = new ObjectInputStream(is);
   Object obj = in.readObject();
   in.close();
   return obj;
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }
}

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

       二、 对称密钥加密算法AES
           对称密钥算法中,信息的加密和解密都是使用相同的密钥,使用起来简单,速度快,但在使用之前,需要通过额外安全的途径交换加密密钥。首先,提供AES密钥生成算法,生成密钥保存在文件中,且看AESKeyCreater.java
Java代码 
/** 
 * @author zhangwei 
 * 
 */ 
public class AESKeyCreater {  
      
    /** 
     * @param args 
     */ 
    public static void main(String[] args) throws Exception{  
        String url = System.getProperty("user.dir");  
        AESKeyCreater aESKeyCreater = new AESKeyCreater();  
        aESKeyCreater.createKeyFile(url);  
    }  
 
    public void createKeyFile(String url) throws Exception{  
        Security.addProvider(new SunJCE());  
        KeyGenerator keygen = KeyGenerator.getInstance("AES");  
        SecretKey key = keygen.generateKey();  
        File file = new File(url + "/src/main/resources/AES_Secret_Key_File.aes");  
        FileOutputStream out = new FileOutputStream(file);  
        ObjectOutputStream objectOutput = new ObjectOutputStream(out);  
        objectOutput.writeObject(key);  
        objectOutput.flush();  
        objectOutput.close();  
    }  

/**
 * @author zhangwei
 *
 */
public class AESKeyCreater {
 
 /**
  * @param args
  */
 public static void main(String[] args) throws Exception{
  String url = System.getProperty("user.dir");
  AESKeyCreater aESKeyCreater = new AESKeyCreater();
  aESKeyCreater.createKeyFile(url);
 }

 public void createKeyFile(String url) throws Exception{
  Security.addProvider(new SunJCE());
  KeyGenerator keygen = KeyGenerator.getInstance("AES");
  SecretKey key = keygen.generateKey();
  File file = new File(url + "/src/main/resources/AES_Secret_Key_File.aes");
  FileOutputStream out = new FileOutputStream(file);
  ObjectOutputStream objectOutput = new ObjectOutputStream(out);
  objectOutput.writeObject(key);
  objectOutput.flush();
  objectOutput.close();
 }
}

          AESKeyCreater类中createKeyFile()方法生成AES算法的密钥,保存在AES_Secret_Key_File.aes文件中,供加密和解密时使用。
            其次,提供加密解密算法,对byte[] 进行加密和解密:且看AESEncryptionUtil.java
Java代码 
/** 
 * @author zhangwei 
 *  
 */ 
public class AESEncryptionUtil {  
    /** 
     * 加密 
     * @param bytes 
     * @param aesKey 
     * @return 
     */ 
    public static byte[] encryptMessage(byte[] bytes, String aesKey) {  
        try {  
            Object obj = KeyUtil.getKey(aesKey);  
            SecretKey key = (SecretKey) obj;  
            Cipher cipher = Cipher.getInstance("AES");  
            cipher.init(Cipher.ENCRYPT_MODE, key);  
            byte[] decryptedBytes = cipher.doFinal(bytes);  
            return decryptedBytes;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
 
    /** 
     * 解密 
     * @param encryptedBytes 
     * @param aesKey 
     * @return 
     */ 
    public static byte[] decryptMessage(byte[] encryptedBytes, String aesKey) {  
        try {  
            Object obj = KeyUtil.getKey(aesKey);  
            SecretKey key = (SecretKey) obj;  
            Cipher cipher = Cipher.getInstance("AES");  
            cipher.init(Cipher.DECRYPT_MODE, key);  
            byte[] bytes = cipher.doFinal(encryptedBytes);  
            return bytes;  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  

/**
 * @author zhangwei
 *
 */
public class AESEncryptionUtil {
 /**
  * 加密
  * @param bytes
  * @param aesKey
  * @return
  */
 public static byte[] encryptMessage(byte[] bytes, String aesKey) {
  try {
   Object obj = KeyUtil.getKey(aesKey);
   SecretKey key = (SecretKey) obj;
   Cipher cipher = Cipher.getInstance("AES");
   cipher.init(Cipher.ENCRYPT_MODE, key);
   byte[] decryptedBytes = cipher.doFinal(bytes);
   return decryptedBytes;
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }

 /**
  * 解密
  * @param encryptedBytes
  * @param aesKey
  * @return
  */
 public static byte[] decryptMessage(byte[] encryptedBytes, String aesKey) {
  try {
   Object obj = KeyUtil.getKey(aesKey);
   SecretKey key = (SecretKey) obj;
   Cipher cipher = Cipher.getInstance("AES");
   cipher.init(Cipher.DECRYPT_MODE, key);
   byte[] bytes = cipher.doFinal(encryptedBytes);
   return bytes;
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }
}

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

         下面给出AES算法对hessian进行加密和解密传输,思路:客户端通过Hessian工厂获取到Hessian服务之后,将传入参数对象序列化成 byte[],然后对byte[]进行加密,然后调用hessian服务的方法,服务端获取到客户端传过来的加密之后的byte[]参数,首先进行AES 解密,然后将byte[]反序列化成参数对象,再调用相应的业务逻辑,再然后将返回结果进行序列化成byte[],然后进行AES加密,然后客户端获得返 回结果之后进行AES解密,然后反序列化成结果对象,至此一轮调用完成。且看hessian服务接口:EncryptionService.java
Java代码 
/** 
 * @author zhangwei 
 * 
 */ 
public interface EncryptionService {  
      
    public static final String publicKeyFile = EncryptionService.class.getResource("/").getPath() + "/public_key_file.rsa";  
    public static final String privateKeyFile = EncryptionService.class.getResource("/").getPath() + "/private_key_file.rsa";  
    public static final String aesKeyFile = EncryptionService.class.getResource("/").getPath() + "AES_Secret_Key_File.aes";  
      
    public byte[] testHessianEncrypt(byte[] encryptedBytes);  
 

/**
 * @author zhangwei
 *
 */
public interface EncryptionService {
 
 public static final String publicKeyFile = EncryptionService.class.getResource("/").getPath() + "/public_key_file.rsa";
 public static final String privateKeyFile = EncryptionService.class.getResource("/").getPath() + "/private_key_file.rsa";
 public static final String aesKeyFile = EncryptionService.class.getResource("/").getPath() + "AES_Secret_Key_File.aes";
 
 public byte[] testHessianEncrypt(byte[] encryptedBytes);

}       
        由于hessian是一个二进制协议,非常适合传输二进制数据,以byte[]作为参数和返回结果是非常合适的,将来这部分完全可以做在框架之中。且看hessian服务实现类:EncryptionServiceImpl.java
Java代码 
/** 
 * @author zhangwei 
 * 
 */ 
public class EncryptionServiceImpl implements EncryptionService{  
 
    public byte[] testHessianEncrypt(byte[] encryptedBytes) {  
        //解密参数  
        byte[] decryptedBytes = AESEncryptionUtil.decryptMessage(encryptedBytes, aesKeyFile);  
        //将参数反序列化  
        Secret secret = (Secret)SerializationUtil.deserialize(decryptedBytes);  
        //业务逻辑  
        System.out.println(secret.getMessage());  
        secret.setMessage("I love you too!");  
        System.out.println(secret.getMessage());  
        //将结果序列化  
        byte[] returnBytes = SerializationUtil.serialize(secret);  
        //加密返回结果  
        byte[] encryptedReturnBytes = AESEncryptionUtil.encryptMessage(returnBytes,aesKeyFile);  
        return encryptedReturnBytes;  
    }  

/**
 * @author zhangwei
 *
 */
public class EncryptionServiceImpl implements EncryptionService{

 public byte[] testHessianEncrypt(byte[] encryptedBytes) {
  //解密参数
  byte[] decryptedBytes = AESEncryptionUtil.decryptMessage(encryptedBytes, aesKeyFile);
  //将参数反序列化
  Secret secret = (Secret)SerializationUtil.deserialize(decryptedBytes);
  //业务逻辑
  System.out.println(secret.getMessage());
  secret.setMessage("I love you too!");
  System.out.println(secret.getMessage());
  //将结果序列化
  byte[] returnBytes = SerializationUtil.serialize(secret);
  //加密返回结果
  byte[] encryptedReturnBytes = AESEncryptionUtil.encryptMessage(returnBytes,aesKeyFile);
  return encryptedReturnBytes;
 }
}
             代码一目了然,没啥好说的。且看客户端调用:TestClient.java
Java代码 
/** 
 * @author zhangwei 
 * 
 */ 
public class TestClient {  
 
    /** 
     * @param args 
     * @throws MalformedURLException  
     */ 
    public static void main(String[] args) throws MalformedURLException {  
        String hessianServiceUrl = "http://localhost:8089/HessianEncryption/hessianService";  
        String aesKeyFile = System.getProperty("user.dir") + "/lib/AES_Secret_Key_File.aes";  
          
        HessianProxyFactory factory = new HessianProxyFactory();  
        EncryptionService service = (EncryptionService)factory.create(EncryptionService.class, hessianServiceUrl);  
        Secret secret = new Secret();  
        secret.setMessage("I love you!");  
        System.out.println(secret.getMessage());  
        //序列化參數  
        byte[] paramBytes = SerializationUtil.serialize(secret);  
        //加密參數  
        byte[] encryptedParamBytes = AESEncryptionUtil.encryptMessage(paramBytes, aesKeyFile);  
        //調用方法  
        byte[] encryptedReturnBytes = service.testHessianEncrypt(encryptedParamBytes);  
        //解密返回結果  
        byte[] decryptedReturnBytes = AESEncryptionUtil.decryptMessage(encryptedReturnBytes, aesKeyFile);  
        //反序列化結果  
        Secret returnResult = (Secret)SerializationUtil.deserialize(decryptedReturnBytes);  
        System.out.println(returnResult.getMessage());  
    }  
 


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多