Powershell unterstützt mit dem Cmdlet Get-Filehash von Haus aus die Möglichkeit, Hashes über Dateien zu erzeugen. Ein Hash ist dabei eine komplexe Prüfsumme, die die Eindeutigkeit einer Datei garantiert - die Prüfsumme kann die Datei also identifizieren. Ein kryptographischer Hash-Algorithmus wie SHA-1 oder SHA-2 (gesprochen Schah oder mit den Einzahlbuchstaben S-H-A) muss aber noch weitere Kriterien erfüllen - zwei fast identische Dateien müssen vollkommen unterschiedliche Hashes erzeugen. Das ist notwendig, damit man vom Hash keine Rückschlüsse auf den Original-Text ziehen kann. Den Algorithmus kann man bei Get-Filehash mit dem Parameter -Algorithm bestimmen.
Get-FileHash -Path C:\windows\notepad.exe -Algorithm SHA256
Get-FileHash unterstützt 3 Gruppen von Algorithmen: MD5 (Message Digest 5), SHA1 und SHA2. SHA2 gibt es in 3 Versionen: SHA256, SHA384 und SHA512, wobei die Zahl am Ende die Länge des generierten Hashes in Bit angibt. Für kryptographische Zwecke sind MD5 und SHA1 nicht mehr geeignet, da sie inzwischen als unsicher gelten, aber sie können natürlich weiterhin verwendet werden, wenn man einfach nur Dateien eindeutig identifizieren möchte, weshalb Sie Get-Filehash auch nach wie vor angeboten werden.
Wenn man große Mengen von Daten hashen möchte, z.B. um doppelte Dateien zu finden, kann das Hashen aber ein ziemlich langwieriger Prozess werden. Für diesen Zweck wurden schnellere Hash-Algorithmen entwickelt, die von Powershell nativ allerdings nicht unterstützt werden. Für aktuellere Versionen des .net-Frameworks gibt es aber Implementierungen von z.B. XxHash3, auf die man Powershell 7 aus zugreifen kann. Die entsprechenden Klassen werden allerdings nicht mit Windows ausgeliefert, sondern müssen erst installiert werden.
Um Codebibliotheken zu installieren, wurde ein spezieller Paketmanager namens nuget entwickelt, der nicht nur das Installieren von Klassen erledigt, sondern sich auch um Abhängigkeiten kümmert. Nuget ist in Visual Studio standardmäßig implementiert, kann aber auch von Powershell aus über die Kommandozeile gestartet werden. Dazu muss im Powershell Paketmanager nuget zuerst als Paketquelle hinzugefügt werden. Anschließend kann die System.IO.Hashing-Bibliothek installiert werden.
Register-PackageSource -Name NuGet -Location https://www.nuget.org/api/v2 -ProviderName NuGet Install-Package -Name "system.io.hashing" -Source nuget
Ist die Bibliothek installieren, muss man sie mit Hilfe von Add-Type in die Powershell nachladen. Mit Admin-Rechten wurde die Datei bei mir dabei unter "C:\Program Files\PackageManagement\NuGet\Packages" abgelegt. Um die Benutzung einfacher zu machen, habe ich einen kleine Funktion gestrickt, die die Generierung des Hashes sehr einfach z.B. über die Pipeline erlaubt.
Add-Type -AssemblyName "C:\Program Files\PackageManagement\NuGet\Packages\System.IO.Hashing.9.0.8\lib\net8.0\System.IO.Hashing.dll" Function Get-FileHashFast { Param ( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelinebyPropertyName)] [Alias('Fullname')] [String]$Path ) Process { $bufferSize = 16MB $hasher = [System.IO.Hashing.XxHash3]::new() $buffer = New-Object byte[] $bufferSize $fs = [System.IO.File]::OpenRead($path) while (($read = $fs.Read($buffer, 0, $bufferSize)) -gt 0) { if ($read -eq $bufferSize) { $hasher.Append($buffer) } else { # PowerShell: create subarray for last chunk $chunk = $buffer[0..($read-1)] $hasher.Append($chunk) } } $fs.Close() $hash = $hasher.GetHashAndReset() [PSCustomObject]@{ Path = $Path Hash = ( $hash | ForEach-Object { $_.ToString("x2") }) -join '' } } }
Nachdem man den obenstehenden Code ausgeführt hat, kann man die Dateien, für die Hashes generiert werden sollen, einfach in die Funktion Get-FileHashFast pipen.
Get-Childitem C:\Bilder\* -Recurse | Get-FilehashFast
Die Funktion Get-FilehashFast ist in meinen Tests ca. 3 mal schneller gewesen als SHA1 bzw. SHA2. Man sollte allerdings beachten, dass schon SHA1 und SHA2 so schnell sind, dass eine 1GBit-Netzwerkverbindung die Daten nicht schnell genug ausliefert, um die volle Leistung des Hash-Algorithmus auszureizen. Auf einer SSD kann man mit XXHash3 aber problemlos die 3-fache Menge an Daten im gleichen Zeitraum hashen.