apache.commons.Codec

时间:2015-09-25 19:34:43

标签: java hash md5 apache-commons apache-stringutils

我正在针对Linux /etc/shadow file编写针对MD5哈希方案的基本密码破解程序。当我使用commons.codec的{​​{1}}或DigestUtils库时,它们的哈希长度不同(除其他外)。

当我使用Crypt时,输出是一个22个字符的字符串。当我使用Crypt.crypt(passwordToHash, "$1$Jhe937$")(或Java DigestUtils.md5[Hex](passwordToHash + "Jhe937")类)时,输出是一个32个字符的字符串(转换后)。这对我来说毫无意义。

除此之外:没有简单的方法可以将MessageDigest' s DigestUtils.md5(passwordToHash)转换为字符串。我已经尝试了所有方法,但我获得了所有无效输出:byte[]

* all are:`new String(byte []," UTF-8")并转换为char然后转换为String

1 个答案:

答案 0 :(得分:1)

执行摘要是虽然它们将执行相同的散列,但两者之间的输出格式不同,因此长度会有所不同。请继续阅读。

MD5是一种消息摘要算法,它产生一个16字节的哈希值,总是(假设有效输入等)。那些字节不是所有可打印字符,它们可以从0-取任何值255表示任何字节,而ASCII中的可打印字符的范围是32-126。

DigestUtils.md5(String)生成字符串的MD5并返回16个元素的字节数组。 DigestUtils.md5Hex(String)是一个方便的包装器(我假设,我没有查看源代码,但我就是这样写的:-))围绕DigestUtils.md5采用md5产生的16个元素字节数组和base16对其进行编码(也称为十六进制编码)。用等效的两个十六进制字符替换每个字节,这就是为什么你得到一个32个字符的字符串。

Crypt.crypt使用一种特殊格式,可以追溯到存储密码的原始Unix方法。多年来,它一直在使用不同的哈希/加密算法,更长的盐和其他功能。它还将其输出编码为可打印文本,这是长度差异的来源。通过使用“$ 1 $ ...”的盐,你说要使用MD5,所以使用MD5对密码和盐进行哈希处理,得到16个字节,但由于这些字节不一定是可打印的,散列是base64编码的(使用与标准base64编码略有不同的字母表),用4个可打印字符替换3个字节。因此,16个字节变为16/3 * 4 = 21-1 / 3个字符,向上舍入为22。

在你的旁边,DigestUtils.md5产生16个字节,但这些字节可以有0到255之间的任何值,并且(有效)是随机的。 new String(byte [],“UTF-8”)表示字节数组中的字节是UTF-8编码,这是一种非常特殊的格式。 new String最好将字节视为UTF-8编码的字符串,但由于它们实际上并非如此,因此通常会出现乱码。如果你想要一些可打印的东西,你将不得不使用一些随机字节,而不是特定格式的字节(如UTF-8)。两个流行的选项是base16 / hex编码,您可以使用DigestUtils.md5Hex或base64获得,您可以使用Base64.encodeBase64String(DigestUtils.md5(pwd + salt))获得。