序列化揭秘(一)
?? 声明:因为准备在项目组内部做一次关于序列化的分享,故有如此一系列关于序列化的博文产生。次系列期间参考了一些其他的资料,如《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(密钥生成器)对象,并指—SA算法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);}}?