【问题标题】:Unix md5sum vs Powershell Get-hashUnix md5sum vs Powershell Get-hash
【发布时间】:2018-09-29 06:45:16
【问题描述】:

我正在尝试从 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 出了什么问题?

【问题讨论】:

    标签: md5sum


    【解决方案1】:

    区别并不明显,但您没有散列相同的数据。 MD5 是一种散列算法,它没有文本编码的概念——这就是为什么您可以像创建文本散列一样容易地创建二进制数据散列。考虑到这一点,我们可以找出 MD5 计算散列的 bytes(或八位字节;严格来说是每个 8 位的值流)。为此,我们可以使用xxd,或任何其他十六进制编辑器。

    首先,您的 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 - 这是正常的(例如,这也是 Internet 上使用 UTF-8 而不是 UTF-16 的原因),因为 Unicode 代码点基本的 ASCII 字符与它们的 ASCII 表示相同。现在让我们看看哈希:

    $ md5 < thefile.txt
    e42b054623b3799cb71f0883900f2764
    

    这与 PS 为您制作的内容相匹配。

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

    【讨论】:

    • 在您的解释和同事的帮助下,使用 Get-Hash 和“-StringEncoding ascii”得到正确的结果。 PS U:\&gt; echo "hello world" | Get-Hash -Algorithm md5 -StringEncoding ascii Path Algorithm HashString Hash ---- --------- ---------- ---- MD5 5EB63BBBE01EEED093CB22BB8F5ACDC3 {94, 182, 59, 187...}
    【解决方案2】:

    这个问题肯定与How to get an MD5 checksum in PowerShell有关,但它有所不同,而且很重要。

    Md5sums 是根据 bytes 计算得出的。 事实上,你的 Ubuntu 结果在某种意义上是错误的:

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

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

    (顺便说一句,有趣的是,这里的字符串包含一个回车:)

    $ 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  -
    

    【讨论】:

      【解决方案3】:

      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 *-
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多