最近在做一个使用RSA+MD5算法实现数字签名的一个软件。因为考虑到RSA密钥对的管理与分发,所以采用数据库管理RSA密钥对。由于在java中RSA密钥使用java.security.interfaces.RSAPrivateKey;与java.security.interfaces.RSAPublicKey;两个类,因此需要将这两个对象持久化。
考虑到方便用户使用,因而不采用类似JDataStroe,MySQL甚至MS SQL SERVER啦,所以采用Access。
Access只支持文本,数字与OLE对象。而JDBC没有提供相应的方法操作OLE对象,但可以往OLE对象中写入2进制流。
因此,主要思想采用将对象Serialize到BtyeArray流,在将BtyeArray流写入到2进制流。取出对象时,方法相同。
代码如下:
//连接Access,我的文件名为:db/MyRSAStore.mdb,密码123,表:MyRSAKeys(name[文本],description[文本],RSApublicKey[OLE对象],RSAprivateKey[OLE对象],create_data[文本])
String conURL="jdbc:odbc:driver={MicroSoft Access Driver (*.mdb)};DBQ=db//MyRSAStore.mdb";
String password="123";
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con=DriverManager.getConnection(conURL,password,password);//这里只user或password用密码不行
//RSA密钥对象
KeyPair keyPair = lyRSA.generateKeyPair(1024);
RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();
//得到各个流
ByteArrayOutputStream bout1 = new ByteArrayOutputStream();
ObjectOutputStream oout1 = new ObjectOutputStream(bout1);
oout1.writeObject(pubKey);
oout1.flush();
oout1.close();//将pubKey对象写入ByteArrayOutputStream
ByteArrayOutputStream bout2 = new ByteArrayOutputStream();
ObjectOutputStream oout2 = new ObjectOutputStream(bout2);
oout2.writeObject(priKey);
oout2.flush();
oout2.close();//将priKey对象写入ByteArrayOutputStream
//得到ByteArrayInputStream,主要因为PreparedStatement.setBinaryStream()方法要求InputStream作为参数,如果采用pst.setBytes()方法向OLE对象写入byte将得到JDBC的Access数据不匹配异常
ByteArrayInputStream pubin=new ByteArrayInputStream(bout1.toByteArray());
ByteArrayInputStream priin=new ByteArrayInputStream(bout2.toByteArray());
//写入数据:
pst=con.prepareStatement("insert into MyRSAKeys(name,description,RSApublicKey,RSAprivateKey,create_data) values (?,?,?,?,?)");
pst.setString(1,"test");
pst.setString(2,"no");
pst.setBinaryStream(3,pubin,pubin.available());//pubin.available()获得流长度
pst.setBinaryStream(4,priin,priin.available());
pst.setString(5,new java.sql.Date(new java.util.Date().getTime()).toString());
pst.executeUpdate();
//读出数据
pst=con.prepareStatement("select * from MyRSAKeys");
ResultSet rs=pst.executeQuery();
while(rs.next()){
System.out.println(rs.getInt(1));
System.out.println(rs.getString(2));
System.out.println(rs.getString(3));
//从数据库中读出Bytes然后包装成ObjectInputStream,读出对象。
RSAPublicKey r=(RSAPublicKey)(new ObjectInputStream(new ByteArrayInputStream(rs.getBytes(4))).readObject());
RSAPrivateKey p = (RSAPrivateKey)(new ObjectInputStream(new ByteArrayInputStream(rs.getBytes(5))).readObject());
System.out.println(r);
System.out.println(p);
System.out.println(rs.getString(6));
}
//使用RSA密钥对象,加密test.txt文件得到密文encrypt_result.txt,解密得到明文decrypt_result.txt
File file = new File("test.txt");
FileInputStream in = new FileInputStream(file);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] tmpbuf = new byte[1024];
int count = 0;
while ((count = in.read(tmpbuf)) != -1) {
bout.write(tmpbuf, 0, count);
tmpbuf = new byte[1024];
}
in.close();
byte[] orgData = bout.toByteArray();
byte[] raw = lyRSA.encrypt(p, orgData);
file = new File("encrypt_result.txt");
OutputStream out = new FileOutputStream(file);
out.write(raw);
out.close();
byte[] data = lyRSA.decrypt(r, raw);
File = new File("decrypt_result.txt");
out = new FileOutputStream(file);
out.write(data);
out.flush();
//程序完,测试通过,平台jdk1.5,Access2003,winXp sp3
结语:
一般的,通过保存对象,我们可以保存各种类型数据到Access。
以上工作,欢迎大家指正其中错误
盘子060525