2017-04-04 57 views
25

我正在为PHP中的加密脚本写一个密钥生成器,我希望它与我在Java中编写的类兼容,以便他们可以共享资源。为什么这些PHP和Java密钥生成器产生不同的输出?

PHP代码:

public function keyGen($key, $rounds) { 
    for($i = 0; $i < $rounds; $i++) { 
     $key = substr(base64_encode(md5($key)), 0, 16); 
     echo $i . " " . $key . PHP_EOL; // debugging // 
    } 
    return $key; 
} 

Java代码:

public static String keyGen(String key, int rounds) { 
    try { 
     for(int i = 0; i < rounds; i++) { 
      byte[] md5 = MessageDigest.getInstance("MD5").digest(key.getBytes("UTF-8")); 
      String md5h = (new BigInteger(1, md5)).toString(16); 
      key = Base64.getEncoder().encodeToString(md5h.getBytes()).substring(0, 16); 
      System.out.println(Integer.toString(i) + " " + key); // debugging // 
     } 
    } catch(Exception ex) { 
     ex.printStackTrace(); 
     return null; 
    } 
    return key; 
} 

PHP调试输出:

0 MWExZGM5MWM5MDcz 
1 NDVkZmMxNWVjNWZi 
2 ODY5YzVkODBhNTRh 
3 ZGE2OTNiOWMxOWM1 
4 OTcxMTY3MzgxMmRk 
5 NWNjNDI2N2IzMDlj 
6 NGVkYzY0YjVkMWUy 
7 MjdhMGU4NjhhNmU3 
8 OWY5OGE3ZGZiODZl 
9 Y2I1ZjBkNjRmMjkx 
10 YTk5NDA1MGI1OWY1 
11 YzRmYWE5ZTk0ZDdl 
12 NDBiZWZkNmQ5Yjhj 
13 MzQyNzcwNGRjMTYw 
14 N2U4ZmUxOGMyNWYx 
15 MjBjOTZhNGE4ZDQ1 
16 MjdmMzkwMzI0NDdj 
17 YjM4NDI0YWU0YzUw 
18 NDRiNjA1MWUwOGZi 
19 MGI1YmIyMDViMGYz 

的Java调试输出:

0 MWExZGM5MWM5MDcz 
1 NDVkZmMxNWVjNWZi 
2 ODY5YzVkODBhNTRh 
3 ZGE2OTNiOWMxOWM1 
4 OTcxMTY3MzgxMmRk 
5 NWNjNDI2N2IzMDlj 
6 NGVkYzY0YjVkMWUy 
7 MjdhMGU4NjhhNmU3 
8 OWY5OGE3ZGZiODZl 
9 Y2I1ZjBkNjRmMjkx 
10 YTk5NDA1MGI1OWY1 
11 YzRmYWE5ZTk0ZDdl 
12 NDBiZWZkNmQ5Yjhj 
13 MzQyNzcwNGRjMTYw 
14 N2U4ZmUxOGMyNWYx 
15 MjBjOTZhNGE4ZDQ1 
16 MjdmMzkwMzI0NDdj 
17 YjM4NDI0YWU0YzUw 
18 NDRiNjA1MWUwOGZi 
19 YjViYjIwNWIwZjMy 

它按预期工作,直到第19个循环。为什么之后会产生不同的输出?

+0

你可能想看看[你如何在PHP中创建“良好”的随机MD5散列?](http://stackoverflow.com/a/24037589/1255289) – miken32

+1

我不知道你的密钥,所以我可以不测试它,但是你的问题可能是由这个造成的:'md5h.getBytes()'。在您发布的Java代码的第四行中,您使用的是UTF-8编码,但不在第6行。 –

+0

给出密钥,以便我们可以尝试重现。 –

回答

31

在Java中,使用toString(int base)方法将BigDecimal转换为十六进制字符串不会输出前导零。

您可以通过打印中间步骤的输出(将md5哈希码转换为十六进制字符串)来发现此问题 - 在Java中,给出b5bb205b0f32a7bf2a80fc870cbd2b7,而在PHP中给出0b5bb205b0f32a7bf2a80fc870cbd2b7。它只是一个前导零的差异,但是在应用base64编码之后,它们看起来非常不同。

获得前导零的更简单方法是使用String.format方法。

替换此行:

String md5h = (new BigInteger(1, md5)).toString(16); 

这一行:

String md5h = String.format("%032x", new BigInteger(1, md5)); 

,你会得到相同的输出与你的PHP代码。

相关问题