如何在PowerShell中获取MD5校验和


Answers:


324

如果内容是字符串:

$someString = "Hello, World!"
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$utf8 = New-Object -TypeName System.Text.UTF8Encoding
$hash = [System.BitConverter]::ToString($md5.ComputeHash($utf8.GetBytes($someString)))

如果内容是文件:

$someFilePath = "C:\foo.txt"
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($someFilePath)))

从PowerShell版本4开始,对于使用Get-FileHashcmdlet 开箱即用的文件,这很容易做到:

Get-FileHash <filepath> -Algorithm MD5

这无疑是可取的,因为它避免了第一个解决方案在注释中指出的问题(使用流,关闭流并支持大文件)。


12
Exception calling "ReadAllBytes" with "1" argument(s): "The file is too long. This operation is currently limited to supporting files less than 2 gigabytes in size."作为刚接触Powershell的Linux专家,我对获得md5 sum的挣扎感到非常恼火,而这md5sum file.ext在Linux上就很简单。
–StockB

@StockB Keith在下面的答案可能会更好地解决这个问题。我同意,powershell有一些缺点。
vcsjones

5
我安装了没有扩展的Vanilla PowerShell,所以我崩溃了,而是下载了命令行md5sum克隆,效果很好。我想喜欢微软的东西,但我不喜欢。
13年

23
@StockB vcsjones的方法未缓冲... =非常大的内存需求。我建议您使用流:$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)))这样可以降低内存使用量,并且没有2GB的限制
Davor Josipovic

20
@davor使流在不确定的时间内保持打开状态,因此在Powershell关闭之前,您无法删除文件。 $stream = [System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)然后$hash = [System.BitConverter]::ToString($md5.ComputeHash($stream))$stream.Close()
Joe Amenta

57

如果您使用的是PowerShell社区扩展,则可以使用Get-Hash命令集轻松执行此操作:

C:\PS> "hello world" | Get-Hash -Algorithm MD5


Algorithm: MD5


Path       :
HashString : E42B054623B3799CB71F0883900F2764

10
Get-Hash来自PowerShell社区扩展。当您不能使用或不使用该程序包时,他们已Get-FileHash在香草PowerShell 4.0中添加了一个cmdlet 。威德TechNet
TomaszCudziło2014年

请注意,此字符串(可能还有大多数PS解决方案)会将字符串编码为UTF-16(小尾数?)。
Christian Mann

PowerShell社区扩展的链接重定向到CodePlex存档(CodePlex在2017年关闭)。也许更改为GitHub之一?(是GitHub上的新主目录吗?)
Peter Mortensen

16

这是两行,只需在第2行中更改“ hello”即可:

PS C:\> [Reflection.Assembly]::LoadWithPartialName("System.Web")
PS C:\> [System.Web.Security.FormsAuthentication]::HashPasswordForStoringInConfigFile("hello", "MD5")

1
这样的结果不等于我从接受的答案中得到的输出。它计算出STRING“ hello”的哈希,而不是由我用“ hello”替换的任何路径定义的FILE的哈希,对吗?
RobertG 2014年

1
没错,但是OP并不需要文件,我来这里是寻找字符串解决方案
克里斯·卡罗尔

16

这是我使用的用于处理相对和绝对路径的函数:

function md5hash($path)
{
    $fullPath = Resolve-Path $path
    $md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
    $file = [System.IO.File]::Open($fullPath,[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
    try {
        [System.BitConverter]::ToString($md5.ComputeHash($file))
    } finally {
        $file.Dispose()
    }
}

感谢上面的@davor提供使用Open()而不是ReadAllBytes()的建议,以及@ jpmc26提供使用finally块的建议。


2
这种方法比vcsjones和Keith更好,因为它可以接受大于2GB的文件输入,并且不需要任何扩展名或PowerShell 4.0。
Chirag Bhatia-chirag64

1
Dispose呼叫应处于finally阻塞状态。
jpmc26

12

可以早在2003年默认在Windows中安装的另一个内置命令是Certutil,它当然也可以从PowerShell调用。

CertUtil -hashfile file.foo MD5

(注意:MD5应该全部大写,以确保最大的鲁棒性)


FipsAlgorithmPolicy启用后,这是一个不错的选择。
威廉·约翰·霍尔顿

9

在线上有很多使用ComputeHash()的示例。我的测试表明,通过网络连接运行时这非常慢。下面的代码段对我来说运行得快得多,但是您的里程可能会有所不同:

$md5 = [System.Security.Cryptography.MD5]::Create("MD5")
$fd = [System.IO.File]::OpenRead($file)
$buf = New-Object byte[] (1024*1024*8) # 8 MB buffer
while (($read_len = $fd.Read($buf,0,$buf.length)) -eq $buf.length){
    $total += $buf.length
    $md5.TransformBlock($buf,$offset,$buf.length,$buf,$offset)
    Write-Progress -Activity "Hashing File" `
       -Status $file -percentComplete ($total/$fd.length * 100)
}

# Finalize the last read
$md5.TransformFinalBlock($buf, 0, $read_len)
$hash = $md5.Hash

# Convert hash bytes to a hexadecimal formatted string
$hash | foreach { $hash_txt += $_.ToString("x2") }
Write-Host $hash_txt

1
您的方法从其他答案中克服了ReadAllBytes的2Gb限制,这正是我所需要的。
杰伊

write-progress线路上的反引号有什么作用?语法荧光笔似乎不喜欢它。
mwfearnley


6

该站点有一个示例:使用Powershell进行MD5校验和。它使用.NET框架实例化MD5哈希算法的实例以计算哈希。

这是本文的代码,其中包含了Stephen的评论:

param
(
  $file
)

$algo = [System.Security.Cryptography.HashAlgorithm]::Create("MD5")
$stream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open,
    [System.IO.FileAccess]::Read)

$md5StringBuilder = New-Object System.Text.StringBuilder
$algo.ComputeHash($stream) | % { [void] $md5StringBuilder.Append($_.ToString("x2")) }
$md5StringBuilder.ToString()

$stream.Dispose()

1
很好,除了它不适用于只读文件!它需要$ stream = New-Object System.IO.FileStream($ Path,[System.IO.FileMode] :: Open,[System.IO.FileAccess] :: Read)
Stephen Connolly

1
如果链接消失了,答案将毫无用处。stackoverflow.com/help/how-to-answer
我和Monica在一起

1
为了响应我认为是您的不赞成,我在此处剪切并粘贴了本文中的代码。去年我没有这么做,因为我觉得这是窃。添加Stephen的只读改编版使我觉得值得发布。
neontapir

@neontapir只是说:逐字发布(或带有改编内容)只是if窃,如果您不承认来源。版权(从法律上或道德上)是一个单独的问题,但对于大多数代码段,我都不会担心。
mwfearnley

6

如已接受的答案所述,该Get-FileHash文件易于使用,但也可以与字符串一起使用:

$s = "asdf"
Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($s)))

5

现在有一个非常方便的Get-FileHash函数。

PS C:\> Get-FileHash C:\Users\Andris\Downloads\Contoso8_1_ENT.iso -Algorithm SHA384 | Format-List

Algorithm : SHA384
Hash      : 20AB1C2EE19FC96A7C66E33917D191A24E3CE9DAC99DB7C786ACCE31E559144FEAFC695C58E508E2EBBC9D3C96F21FA3
Path      : C:\Users\Andris\Downloads\Contoso8_1_ENT.iso

只需更改SHA384MD5

该示例来自PowerShell 5.1的官方文档。该文档包含更多示例。



3

PowerShell单行代码(从字符串到哈希)

MD5

([System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider).ComputeHash((New-Object -TypeName System.Text.UTF8Encoding).GetBytes("Hello, World!")))).Replace("-","")

SHA1

([System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.SHA1CryptoServiceProvider).ComputeHash((New-Object -TypeName System.Text.UTF8Encoding).GetBytes("Hello, World!")))).Replace("-","")

SHA256

([System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.SHA256CryptoServiceProvider).ComputeHash((New-Object -TypeName System.Text.UTF8Encoding).GetBytes("Hello, World!")))).Replace("-","")

SHA3​​84

([System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.SHA384CryptoServiceProvider).ComputeHash((New-Object -TypeName System.Text.UTF8Encoding).GetBytes("Hello, World!")))).Replace("-","")

SHA512

([System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.SHA512CryptoServiceProvider).ComputeHash((New-Object -TypeName System.Text.UTF8Encoding).GetBytes("Hello, World!")))).Replace("-","")

1

这将返回远程计算机上文件的MD5哈希值:

Invoke-Command -ComputerName RemoteComputerName -ScriptBlock {
    $fullPath = Resolve-Path 'c:\Program Files\Internet Explorer\iexplore.exe'
    $md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
    $file = [System.IO.File]::OpenRead($fullPath)
    $hash = [System.BitConverter]::ToString($md5.ComputeHash($file))
    $hash -replace "-", ""
    $file.Dispose()
}

1

右键菜单选项的示例:

[HKEY_CLASSES_ROOT\*\shell\SHA1 PS check\command]
@="C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -NoExit -Command Get-FileHash -Algorithm SHA1 '%1'"

0

这是一个漂亮的打印示例,试图验证SHA256指纹。我使用PowerShell v4下载了gpg4win v3.0.3(需要Get-FileHash)。

https://www.gpg4win.org/download.html下载该软件包,打开PowerShell,从下载页面获取哈希,然后运行:

cd ${env:USERPROFILE}\Downloads
$file = "gpg4win-3.0.3.exe"

# Set $hash to the hash reference from the download page:
$hash = "477f56212ee60cc74e0c5e5cc526cec52a069abff485c89c2d57d1b4b6a54971"

# If you have an MD5 hash: # $hashAlgo="MD5"
$hashAlgo = "SHA256"

$computed_hash = (Get-FileHash -Algorithm $hashAlgo $file).Hash.ToUpper()
if ($computed_hash.CompareTo($hash.ToUpper()) -eq 0 ) {
    Write-Output "Hash matches for file $file" 
} 
else { 
    Write-Output ("Hash DOES NOT match for file {0}: `nOriginal hash: {1} `nComputed hash: {2}" -f ($file, $hash.ToUpper(), $computed_hash)) 
}

输出:

Hash matches for file gpg4win-3.0.3.exe

0

这是一个单行命令示例,两个示例都计算文件的正确校验和如您刚刚下载,又可以将其与原始发布的校验和进行比较。

例如,我写了一个Apache JMeter项目下载示例。在这种情况下,您可以:

  1. 下载的二进制文件
  2. 原始文件的校验和,以一个字符串的形式发布在file.md5中,格式为:

3a84491f10fb7b147101cf3926c4a855 * apache-jmeter-4.0.zip

然后使用此PowerShell命令,可以验证下载文件的完整性:

PS C:\Distr> (Get-FileHash .\apache-jmeter-4.0.zip -Algorithm MD5).Hash -eq (Get-Content .\apache-jmeter-4.0.zip.md5 | Convert-String -Example "hash path=hash")

输出:

True

说明:

运算-eq符的第一个操作数是计算文件校验和的结果:

(Get-FileHash .\apache-jmeter-4.0.zip -Algorithm MD5).Hash

第二个操作数是已发布的校验和值。我们首先获取file.md5的内容,它是一个字符串,然后根据字符串格式提取哈希值:

Get-Content .\apache-jmeter-4.0.zip.md5 | Convert-String -Example "hash path=hash"

这两个文件file.md5必须在此命令的工作相同的文件夹。


0

这是我用来获取一致的哈希值的方法:

function New-CrcTable {
    [uint32]$c = $null
    $crcTable = New-Object 'System.Uint32[]' 256

    for ($n = 0; $n -lt 256; $n++) {
        $c = [uint32]$n
        for ($k = 0; $k -lt 8; $k++) {
            if ($c -band 1) {
                $c = (0xEDB88320 -bxor ($c -shr 1))
            }
            else {
                $c = ($c -shr 1)
            }
        }
        $crcTable[$n] = $c
    }

    Write-Output $crcTable
}

function Update-Crc ([uint32]$crc, [byte[]]$buffer, [int]$length, $crcTable) {
    [uint32]$c = $crc

    for ($n = 0; $n -lt $length; $n++) {
        $c = ($crcTable[($c -bxor $buffer[$n]) -band 0xFF]) -bxor ($c -shr 8)
    }

    Write-Output $c
}

function Get-CRC32 {
    <#
        .SYNOPSIS
            Calculate CRC.
        .DESCRIPTION
            This function calculates the CRC of the input data using the CRC32 algorithm.
        .EXAMPLE
            Get-CRC32 $data
        .EXAMPLE
            $data | Get-CRC32
        .NOTES
            C to PowerShell conversion based on code in https://www.w3.org/TR/PNG/#D-CRCAppendix

            Author: Øyvind Kallstad
            Date: 06.02.2017
            Version: 1.0
        .INPUTS
            byte[]
        .OUTPUTS
            uint32
        .LINK
            https://communary.net/
        .LINK
            https://www.w3.org/TR/PNG/#D-CRCAppendix

    #>
    [CmdletBinding()]
    param (
        # Array of Bytes to use for CRC calculation
        [Parameter(Position = 0, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [byte[]]$InputObject
    )

    $dataArray = @()
    $crcTable = New-CrcTable
    foreach ($item  in $InputObject) {
        $dataArray += $item
    }
    $inputLength = $dataArray.Length
    Write-Output ((Update-Crc -crc 0xffffffffL -buffer $dataArray -length $inputLength -crcTable $crcTable) -bxor 0xffffffffL)
}

function GetHash() {
    [CmdletBinding()]
    param(
        [Parameter(Position = 0, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$InputString
    )

    $bytes = [System.Text.Encoding]::UTF8.GetBytes($InputString)
    $hasCode = Get-CRC32 $bytes
    $hex = "{0:x}" -f $hasCode
    return $hex
}

function Get-FolderHash {
    [CmdletBinding()]
    param(
        [Parameter(Position = 0, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$FolderPath
    )

    $FolderContent = New-Object System.Collections.ArrayList
    Get-ChildItem $FolderPath -Recurse | Where-Object {
        if ([System.IO.File]::Exists($_)) {
            $FolderContent.AddRange([System.IO.File]::ReadAllBytes($_)) | Out-Null
        }
    }

    $hasCode = Get-CRC32 $FolderContent
    $hex = "{0:x}" -f $hasCode
    return $hex.Substring(0, 8).ToLower()
}

您从哪里复制了PowerShell代码?https://communary.net/
彼得·莫滕森

0

这是我用来获取给定字符串的MD5的代码段:

$text = "text goes here..."
$md5  = [Security.Cryptography.MD5CryptoServiceProvider]::new()
$utf8 = [Text.UTF8Encoding]::UTF8
$bytes= $md5.ComputeHash($utf8.GetBytes($text))
$hash = [string]::Concat($bytes.foreach{$_.ToString("x2")}) 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.