声明:因为准备在项目组内部做一次关于序列化的分享,故有如此一系列关于序列化的博文产生。次系列期间参考了一些其他的资料,如《java加密与解密的艺术》,java官方序列化规范文档等资料,来源相对较杂,在此不一一说明,后续也不再说明。仅致以最诚挚的感谢!此为原创,转载请说明出处 -----哲渊2011-4-10
序列化的二进制数据几乎是以明文的形式在网络传输,这样会存在比较大的安全问题。解决方案之一如下:
对整个对象进行加密和签名,最简单的是将它放在一个 javax.crypto.SealedObject 或 java.security.SignedObject 包装器中。两者都是可序列化的,所以将对象包装在 SealedObject 中可以围绕原对象创建一种 “包装盒”。必须有对称密钥才能解密,而且密钥必须单独管理。同样,也可以将 SignedObject 用于数据验证,并且对称密钥也必须单独管理。以下代码解释了以SignedObject为例说明如何进行整个对象的序列化安全加密和解密。
需要序列化的原始类代码:
package zheyuan.experiment4.com;
import java.io.Serializable;
/**
* 用于被密钥包装的类
*
* @author Administrator
*
*/
public class SignedPerson implements Serializable {
private static final long serialVersionUID = 8533862948800025300L;
private String name;
private int age;
private boolean isNB;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isNB() {
return isNB;
}
public void setNB(boolean isNB) {
this.isNB = isNB;
}
}
序列化类的加密解密类代码如下:
package zheyuan.experiment4.com;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignedObject;
public class SignedSerializableTest {
/**
* 如果需要对整个对象进行加密和签名,最简单的是将它放在一个 javax.crypto.SealedObject
* 或 java.security.SignedObject 包装器中。两者都是可序列化的,所以将对象包装在 SealedObject
* 中可以围绕原对象创建一种 “包装盒”。必须有对称密钥才能解密,而且密钥必须单独管理。
* 同样,也可以将 SignedObject 用于数据验证,并且对称密钥也必须单独管理。
*
* 这里以SignedObject为例说明
*/
/**
* 演示如何对序列化数据进行签名加密
* @param args
*/
public static void main(String[] args) throws Throwable{
SignedPerson signedPerson=new SignedPerson();
signedPerson.setAge(18);
signedPerson.setName("zheyuan");
signedPerson.setNB(false);
signedSerializableData(signedPerson);
}
static void signedSerializableData(Object signedPerson) throws Throwable{
//-----------第一步:密钥武装序列化类--------------------
//代做数字签名的原始信息(必须实现Serializable接口)
Serializable o=(Serializable)signedPerson;
//实例化KeyPairGenerator(密钥生成器)对象,并指定DSA算法
KeyPairGenerator keyPairGen=KeyPairGenerator.getInstance("DSA");
//初始化KeyPairGenerator对象
int keysize=1024;
keyPairGen.initialize(keysize);
//生成KeyPair对象
KeyPair keyPair=keyPairGen.generateKeyPair();
//实例化Signature(用来生成和验证数字签名,是一个引擎类)对象
Signature signature=Signature.getInstance(keyPairGen.getAlgorithm());
//实例化SignedObject对象
SignedObject sin=new SignedObject(o,keyPair.getPrivate(),signature);
//----------第二步:将密钥武装后序列化类SignedObject序列化------------
OutputStream out=new FileOutputStream("signed_temp");
ObjectOutputStream oos=new ObjectOutputStream(out);
oos.writeObject(sin);
//-----------第三步:SignedObject反序列化-----------------------
InputStream in=new FileInputStream("signed_temp");
ObjectInputStream ois=new ObjectInputStream(in);
SignedObject sout=(SignedObject)ois.readObject();
//-------------第四步:将原始类信息解密-----------------
//获得签名值
Object sign=sout.getObject();
System.out.println(sign.toString());
//验证签名
boolean status=sout.verify(keyPair.getPublic(), signature);
System.out.println(status);
}
}