Antworten:
Wenn der Inhalt eine Zeichenfolge ist:
$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)))
Wenn der Inhalt eine Datei ist:
$someFilePath = "C:\foo.txt"
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($someFilePath)))
Ab PowerShell Version 4 ist dies mit dem Get-FileHash
Cmdlet für Dateien sofort möglich:
Get-FileHash <filepath> -Algorithm MD5
Dies ist sicherlich vorzuziehen, da dadurch die Probleme vermieden werden, die die erste Lösung bietet, wie in den Kommentaren angegeben (verwendet einen Stream, schließt ihn und unterstützt große Dateien).
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."
Als Linux-Neuling bei Powershell ärgere ich mich sehr über die Schwierigkeiten, die ich habe, wenn ich eine MD5-Summe bekomme, die einfach md5sum file.ext
unter Linux wäre.
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)))
Dies gibt Ihnen eine geringe Speichernutzung und keine Beschränkung auf 2 GB .
$stream = [System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
dann $hash = [System.BitConverter]::ToString($md5.ComputeHash($stream))
dann$stream.Close()
Wenn Sie die PowerShell-Community-Erweiterungen verwenden, gibt es ein Get-Hash-Commandlet, das dies auf einfache Weise erledigt:
C:\PS> "hello world" | Get-Hash -Algorithm MD5
Algorithm: MD5
Path :
HashString : E42B054623B3799CB71F0883900F2764
Get-FileHash
in Vanilla PowerShell 4.0 hinzugefügt . Vide TechNet .
Hier sind die beiden Zeilen, ändern Sie einfach "Hallo" in Zeile 2:
PS C:\> [Reflection.Assembly]::LoadWithPartialName("System.Web")
PS C:\> [System.Web.Security.FormsAuthentication]::HashPasswordForStoringInConfigFile("hello", "MD5")
Hier ist eine Funktion, die relative und absolute Pfade verarbeitet:
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()
}
}
Vielen Dank an @davor oben für den Vorschlag, Open () anstelle von ReadAllBytes () zu verwenden, und an @ jpmc26 für den Vorschlag, einen finally-Block zu verwenden.
Dispose
Anruf sollte in einem finally
Block sein.
Ein weiterer integrierter Befehl, der seit 2003 standardmäßig in Windows installiert ist , ist Certutil , das natürlich auch von PowerShell aus aufgerufen werden kann.
CertUtil -hashfile file.foo MD5
(Vorsichtsmaßnahme: MD5 sollte für maximale Robustheit in allen Kappen enthalten sein.)
FipsAlgorithmPolicy
aktiviert ist.
Es gibt viele Beispiele online mit ComputeHash (). Meine Tests haben gezeigt, dass dies beim Ausführen über eine Netzwerkverbindung sehr langsam war. Das folgende Snippet läuft für mich viel schneller, Ihr Kilometerstand kann jedoch variieren:
$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
write-progress
Leitung? Der Syntax-Textmarker scheint es nicht zu mögen.
Diese Site enthält ein Beispiel: Verwenden von Powershell für MD5-Prüfsummen . Es verwendet das .NET-Framework, um eine Instanz des MD5-Hash-Algorithmus zu instanziieren und den Hash zu berechnen.
Hier ist der Code aus dem Artikel, der Stephens Kommentar enthält:
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()
Wie in der akzeptierten Antwort angegeben, Get-FileHash
ist die Verwendung mit Dateien einfach, es ist jedoch auch möglich, sie mit Zeichenfolgen zu verwenden:
$s = "asdf"
Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($s)))
Es gibt jetzt eine Get-FileHash-Funktion, die sehr praktisch ist.
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
Wechseln Sie einfach SHA384
zu MD5
.
Das Beispiel stammt aus der offiziellen Dokumentation von PowerShell 5.1 . Die Dokumentation enthält weitere Beispiele.
Dies wird zu einem Einzeiler, wenn Sie File Checksum Integrity Verifier (FCIV) von Microsoft herunterladen.
Ich habe FCIV von hier heruntergeladen: Verfügbarkeit und Beschreibung des Dienstprogramms File Checksum Integrity Verifier
Führen Sie den folgenden Befehl aus. Ich musste zehn Dateien überprüfen.
Get-ChildItem WTAM*.tar | % {.\fciv $_.Name}
Dadurch wird ein MD5-Hash für eine Datei auf einem Remotecomputer zurückgegeben:
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()
}
PowerShell One-Liner (String zu Hash)
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("-","")
SHA384
([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("-","")
Hier ist ein hübsches Druckbeispiel, das versucht, den SHA256-Fingerabdruck zu überprüfen. Ich habe gpg4win v3.0.3 mit PowerShell v4 heruntergeladen (erforderlich Get-FileHash
).
Laden Sie das Paket von https://www.gpg4win.org/download.html herunter , öffnen Sie PowerShell, holen Sie sich den Hash von der Download-Seite und führen Sie Folgendes aus:
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))
}
Ausgabe:
Hash matches for file gpg4win-3.0.3.exe
Hier ist ein einzeiliges Befehlsbeispiel, bei dem sowohl die richtige Prüfsumme der Datei , wie Sie sie gerade heruntergeladen haben, berechnet als auch mit der veröffentlichten Prüfsumme des Originals verglichen wird.
Zum Beispiel habe ich ein Beispiel für Downloads aus dem Apache JMeter-Projekt geschrieben . In diesem Fall haben Sie:
3a84491f10fb7b147101cf3926c4a855 * apache-jmeter-4.0.zip
Mit diesem PowerShell-Befehl können Sie dann die Integrität der heruntergeladenen Datei überprüfen:
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")
Ausgabe:
True
Erläuterung:
Der erste Operand des -eq
Operators ergibt sich aus der Berechnung der Prüfsumme für die Datei:
(Get-FileHash .\apache-jmeter-4.0.zip -Algorithm MD5).Hash
Der zweite Operand ist der veröffentlichte Prüfsummenwert. Wir erhalten zuerst den Inhalt der Datei.md5, bei der es sich um eine Zeichenfolge handelt, und extrahieren dann den Hashwert basierend auf dem Zeichenfolgenformat:
Get-Content .\apache-jmeter-4.0.zip.md5 | Convert-String -Example "hash path=hash"
Sowohl file als auch file.md5 müssen sich für diese Befehlsarbeit im selben Ordner befinden.
Folgendes verwende ich, um einen konsistenten Hashwert zu erhalten:
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()
}
Hier ist das Snippet, mit dem ich das MD5 für eine bestimmte Zeichenfolge erhalte:
$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")})