需求:用java将字符串通过DES加密。
本地环境:
操作系统:Windows XP SP3 32bit
JDK版本:Sun JDK6
服务器环境:Linux 64bit
JDK版本:Open JDK7
百度了一下,很多相关代码,直接拿来就用(http://blog.csdn.net/shibenjie/article/details/5365355),发现有一个问题:
在本地测试的时候没问题,但发布到服务器后,同一个text和keyStr,每次加密生成的字符串竟然是不同的;
最后把问题代码定位到getKey()方法上,代码如下:
/** * 根据参数生成Key; * * @param keyStr */ private static Key getKey(String keyStr) { Key key = null; try { KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM); keyGenerator.init(new SecureRandom(keyStr.getBytes())); key = keyGenerator.generateKey(); keyGenerator = null; } catch (Exception e) { e.printStackTrace(); } return key; }
for (int i = 0; i < 5; i++) System.out.println(new String(getKey("test").getEncoded()));
为此我怀疑过是不是32位和64位、JDK6和JDK7、SunJDK和OpenJDK之间的问题,用虚拟机虚拟了几个环境测试,发现如下(OK表示没问题,FALSE表示有问题):
1、Win7 32bitSunJDK7OK
2、LinuxMint 32bit OpenJDK7FALSE
3、WinXP 32bitSunJDK6OK(本地环境)
4、Mac 64bitOpenJDK7FALSE
5、SL-Linux 64bitOpenJDK7FALSE(服务器环境)
当时就在纠结上面那3个怀疑方向,google了一番之后,好像也没人提到32位/64位的,于是怀疑JDK6和JDK7和SunJDK和OpenJDK之间的差异问题,就在上面几次测试之后,突然想起,会不会是操作系统之间的差异问题呢?!
因为本人之前认为Java是跨平台的,JVM在不同平台下对代码的解释应该是一样的(差异仅在性能之间),所以没想到是操作系统之间的差异问题。但因为这段代码涉及到随机数的生成问题,而随机数可能是跟操作系统有关系的,所以根据这方面的联想google一番之后,got it!
貌似这是一个著名的linux问题……
后来将getKey()方法里的try块修改如下:
try { KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM); SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); random.setSeed(keyStr.getBytes()); keyGenerator.init(random); key = keyGenerator.generateKey(); keyGenerator = null; } catch (Exception e) { e.printStackTrace(); }