menu

有舍才有得

I am back

Avatar

java 加密

由于工作需要,在网上google很多和 java 加密相关的东西,内容大都与Java加密和数字签名编程快速入门相似。

决定采用最简单的消息摘要的方法。

public void testDigest()
	{
		try
		{
			String myinfo = "cws123";
			java.security.MessageDigest alga = java.security.MessageDigest.getInstance("MD5");
			alga.update(myinfo.getBytes());
			byte[] digesta = alga.digest();			
			System.out.println("本信息摘要是:" + digesta);
			System.out.println("本信息摘要是 tostring:" + digesta.toString());
			System.out.println("本信息摘要是 tostring:" + new String(digesta));
			//通过某中方式传给其他人你的信息(myinfo)和摘要(digesta) 对方可以判断是否更改或传输正常
			java.security.MessageDigest algb = java.security.MessageDigest.getInstance("MD5");
			//java.security.MessageDigest algb = java.security.MessageDigest.getInstance("SHA-1");
			algb.update(myinfo.getBytes());	
			byte[] digestb = algb.digest();	
			if (MessageDigest.isEqual(digesta, digestb))
			{
				Log.print("信息检查正常");
				Log.print("1" + digesta.toString());
				Log.print("2" + digestb.toString());
			}
			else
			{
				Log.print("摘要不相同");
			}
			if ((new String(digesta,"UTF8")).equals(new String(digestb,"UTF8")))
			{
				Log.print(" 转换成字符串匹配一样 !");
			}
			//
		}
		catch (java.security.NoSuchAlgorithmException ex)
		{
			Log.print("非法摘要算法");
			ex.printStackTrace();
		} catch (UnsupportedEncodingException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

这个方法是管用的,运行结果是

本信息摘要是:[B@18d107f
本信息摘要是 tostring:[B@18d107f
本信息摘要是 tostring:養驶栓=z>e
6m
信息检查正常
1[B@18d107f
2[B@45a877
转换成字符串匹配一样 !

存入数据库再读取的时候却不知道怎么处理了。
由于最初数据库设计的 password 字段是 varchar2(oracle),而加密以后只提供了 algb.digest() 返回 byte[],所以作了如下尝试
1.把 byte[] toString 存进数据库,rs.getString()以后getBytes(),调用MessageDigest.isEqual 和原始的密码再加密一次匹配,failed!
2.怀疑是编码解码格式的问题,于是都用“UTF8”编码或解码,failed!
3.在网上google搜到一篇关于用 BASE64 编码解码的文章:

Java中提供了计算报文摘要的另一个简单的方法,那就是使用java.security.MessageDigest类。下列代码片断显示了如何将MD5报文摘要算法(128位的摘要)应用到密码字符串:
MassageDigest md=
MessageDigest.getInstance("MD5");
md.update(originalPwd.getByetes());
byte[] digestedBytes=md.digest();

也使用报文摘要创建校验和、文本的唯一ID(也叫做数字指纹)。在签写ARJ文件会发生:校验和是根据ARJ文件的内容计算出来的,然后被加密,并且用 base64的加密格式存放在manifest.mf文件中。base64是编码任意二进制数据的一种方法,得到的结果仅包含可打印字符(注意, base64编码数据占用的空间比转换前多三分之一)。由于报文摘要算法输出的结果是字节数组,可以使用base64编码将哈希字节转换成字符串,以便能将该字符串存放在数据库的varchar字段中。现在有许多base64编码器,但是最简单的方法是使用weblogic.jar库中的编码器: weblogic.apache.xerces.utils.Base64。该类的作用微乎其微,如下面的代码例子所示:

String digestedPwdString =
new String(Base64.encode(digestedPwdBytes));


于是采用,最终还是 failed!

于是将数据库的password 字段改成 Blob,发现存进去和读取出来的byte[]不一样,也许是读写的方式有问题。

如果要把一个二制文件存入ORACLE,用标准的JDBC你就要用LONG ROW类型:
create table tb_file(name varchar(20),detail long row);
然后
File file = new File("aaa.gif");
int fileLength =(int) file.length();
InputStream fin = new FileInputStream(file);
PreparedStatement pstmt = con.prepareStatement("insert into tb_file values('aaa.gif',?)");
pstmt.setBinaryStream (1, fin, fileLength);
pstmt.executeUpdate();

如果你一定要用BLOB存储,你就必须用ORACLE自己的方法:
create table tb_file(name varchar(20),detail BLOB);
con.setAutoCommit(false);
stmt.executeUpdate("insert into tb_file values('aaa.gif',empty_blob())");
下面必须SELECT得到BLOB的对象再向里写:
rs = stmt.executeQuery("select detail from tb_file where name='aaa.gif' for upfdate" );
if(rs.next())
{
Blob blob = rs.getBlob(1);
BinaryOutputStream out = ((oracle.sql.BLOB)blob).getBinaryOutputStream();
byte[] b = new byte[((oracle.sql.BLOB)blob).getBufferSize];
InputStream fin = new FileInputStream(file);
int len = 0;
while( (len = fin.read(b)) != -1)
out.write(b,0,len);
fin.close();
out.close();
con.commit();
}


于是再改程序按这个方式读写,仍然尚未走通
继续摸索中......

我是编程菜鸟,有高手可指点否?

精神支持一下~~~

俺也不懂~~~沙发,等着看高手解答~~~

非常感谢 ss 的大力帮忙,最终把数据库 password 字段换成long RAW,读写的时候直接 rs.getBytes(),pstmt.setBinaryStream()能保证读出来和写进去的二进制数组完全一样,于是问题也就可以解决了。

但是还是有点纳闷,难道别人的软件里都是这么解决,应该还有更好的方式吧

评论已关闭