我想计算一些内容的MD5校验和。如何在PowerShell中做到这一点?


当前回答

团队! 看看我的哈希计算函数。

Function Get-StringHash {
<#
    .DESCRIPTION
        Get string persistant hash.        
#>
    [OutputType([string])]
    [CmdletBinding()]
    Param(
        [Parameter( Mandatory = $True, Position = 0, HelpMessage = "String to calculate hash." )]
        [string] $String,
        [Parameter( Mandatory = $false, Position = 0, HelpMessage = "String encoding." )]
        [ValidateSet( 'UTF8' )]
        [string] $StringEncoding = 'UTF8',
        [Parameter( Mandatory = $false, Position = 2, HelpMessage = "Hash algoritm." )]
        [ValidateSet( 'md5', 'sha256', 'sha512' )]
        [string] $Algoritm = 'sha256'
    )
    try {
        #region functions
        #endregion

        $Result = $null

        switch ( $Algoritm ) {
            'md5' {  
                $HashProvider = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
            }
            'sha256' {  
                $HashProvider = New-Object -TypeName System.Security.Cryptography.SHA256CryptoServiceProvider
            }
            'sha512' {  
                $HashProvider = New-Object -TypeName System.Security.Cryptography.SHA512CryptoServiceProvider
            }
            Default {}
        }

        switch ( $StringEncoding ) {
            'UTF8' {  
                $Encoding = New-Object -TypeName System.Text.UTF8Encoding
            }
            Default {}
        }
        
        
        $Result = [System.BitConverter]::ToString( $HashProvider.ComputeHash( $Encoding.GetBytes( $String ) )).replace('-','')

    }
    catch {
        Get-ErrorReporting -Trap $_
    }

    return $Result
}

$String   = 'Some text'
$Algoritm = 'MD5'

$Hash = Get-StringHash -String $String -Algoritm $Algoritm

write-host "$String has $Algoritm hash $hash"

其他回答

下面是一个单行命令示例,它计算文件的正确校验和(就像您刚刚下载的那样),并将其与原始文件的已发布的校验和进行比较。

例如,我编写了一个从Apache JMeter项目下载的示例。在这种情况下,你有:

下载的二进制文件 在文件中发布的原始文件的校验和。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

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

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

文件和文件。Md5必须在此命令工作的同一文件夹中。

现在有一个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

只需将SHA384更改为MD5即可。

示例来自PowerShell 5.1的官方文档。文档中有更多示例。

正如已接受的答案中所述,Get-FileHash很容易用于文件,但也可以用于字符串:

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

这将返回远程计算机上文件的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()
}

网上有很多使用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