Unix md5sum vs Powershell Get-hash

时间:2018-04-18 21:58:26

标签: md5sum

我正在尝试从Powershell生成md5哈希。我安装了Powershell Community Extension(Pscx)来获取命令:Get-Hash

但是当我使用Get-Hash生成md5哈希时,它似乎与在Ubuntu机器上使用md5sum生成的哈希相匹配。

Powershell的:

PS U:\> "hello world" | get-hash -Algorithm MD5

Path Algorithm HashString                       Hash
---- --------- ----------                       ----
     MD5       E42B054623B3799CB71F0883900F2764 {228, 43, 5, 70...}

的Ubuntu:

root@LT-A03433:~# echo "hello world" | md5sum
6f5902ac237024bdd0c176cb93063dc4  -

我知道Ubuntu生成的那个是正确的,因为几个在线网站显示相同的结果。

Powershell Get-Hash我出了什么问题?

3 个答案:

答案 0 :(得分:2)

差异并不明显,但您没有散列相同的数据。 MD5是一种散列算法,它没有文本编码的概念 - 这就是为什么你可以像创建文本散列一样轻松创建二进制数据的散列。考虑到这一点,我们可以找出 bytes (或八位字节;严格来说是每个8位的值的流)MD5正在计算哈希值。为此,我们可以使用xxd或任何其他hexeditor。

首先,你的Ubuntu例子:

$ echo "hello world" | xxd
0000000: 6865 6c6c 6f20 776f 726c 640a            hello world.

注意最后的0a,Unix风格的换行符,在右侧视图中显示为.echo默认情况下会为其打印的内容添加换行符,您可以使用printf,但这会导致不同的哈希值。

$ echo "hello world" | md5
6f5902ac237024bdd0c176cb93063dc4

现在让我们考虑一下PowerShell正在做什么。它将自己的字符串直接传递给get-hash cmdlet。事实证明,许多Windows中字符串数据的自然表示与Unix不同--Windows使用宽字符串,其中每个字符(在内存中)表示为两个字节。更具体地说,我们可以打开一个文本编辑器,粘贴在:

hello world

没有尾随换行符,并将其保存为UTF-16,little-endian。如果我们检查它产生的实际字节,我们会看到差异:

$ xxd < test.txt
0000000: 6800 6500 6c00 6c00 6f00 2000 7700 6f00  h.e.l.l.o. .w.o.
0000010: 7200 6c00 6400                           r.l.d.

每个字符现在占用两个字节,第二个字节为00 - 这是正常的(这就是为什么UTF-8在互联网上使用而不是UTF-16的原因),因为基本ASCII字符的Unicode代码点与其ASCII表示相同。现在让我们看看哈希:

$ md5 < thefile.txt
e42b054623b3799cb71f0883900f2764

哪个匹配PS为你制作的东西。

所以,回答你的问题 - 你没有做错任何事。您只需要以相同的方式对字符串进行编码以获得相同的哈希值。很遗憾,我无法访问PS,但这应该是朝着正确方向迈出的一步:UTF8Encoding class

答案 1 :(得分:0)

这个问题肯定与How to get an MD5 checksum in PowerShell有关,但它有所不同,并提出了重要观点。

Md5sums是从字节计算的。事实上,从某种意义上说,你的Ubuntu结果是错误的:

$ echo "hello world" | md5sum
6f5902ac237024bdd0c176cb93063dc4  -

$ echo -n "hello world" | md5sum
5eb63bbbe01eeed093cb22bb8f5acdc3  -

在第一种情况下,您将构成字符串ASCII表示形式的12个字节加上最后一个回车符。在第二种情况下,您不包括回车。

(顺便说一下,有趣的是, here string 包含一个回车符:)

$ md5sum <<<"hello world"
6f5902ac237024bdd0c176cb93063dc4 

在Windows PowerShell中,您的字符串以UTF-16LE表示,每个字符2个字节。要在Ubuntu和Windows中获得相同的结果,您必须使用重新编码程序。 Ubuntu的一个不错的选择是iconv

$ echo -n "hello world" | iconv -f UTF-8 -t UTF-16LE | md5sum
e42b054623b3799cb71f0883900f2764  -

答案 2 :(得分:0)

md5sum是错误的,尽管其他人也同意。它将在 unix lf上,在 windows cr-lf上向输入字符串添加特定于平台的行尾字符。

在具有powershellbash的计算机上进行验证,例如已安装postgres进行比较:

'A string with no CR or LF at the end' | %{  psql -c "select md5('$_' || Chr(13) || Chr(10) )"   }
echo 'A string with no CR or LF at the end' | md5sum.exe
'A string with no CR or LF at the end' | %{  psql -c "select md5('$_' || Chr(10) )"   }
bash -c "echo 'A string with no CR or LF at the end' | md5sum.exe"

输出前两行:

PS> 'A string with no CR or LF at the end' | %{  psql -c "select md5('$_' || Chr(13) || Chr(10) )"   }
               md5
----------------------------------
 1b16276b75aba6ebb88512b957d2a198

PS> echo 'A string with no CR or LF at the end' | md5sum.exe

1b16276b75aba6ebb88512b957d2a198 *-

输出后两行:

PS> 'A string with no CR or LF at the end' | %{  psql -c "select md5('$_' || Chr(10) )"   }
               md5
----------------------------------
 68a1fcb16b4cc10bce98c5f48df427d4

PS> bash -c "echo 'A string with no CR or LF at the end' | md5sum.exe"

68a1fcb16b4cc10bce98c5f48df427d4 *-