ChecksumVerify: Downloads per Rechtsklick prüfen
Ein kleines Open-Source-Tool für Windows, das die Prüfsumme eines Downloads per Rechtsklick prüft. Der Beitrag erklärt, warum Prüfsummen wichtig sind und wie das Tool mit .NET und WinUI 3 gebaut ist.
TL;DR
ChecksumVerify ist ein kostenloses Open-Source-Tool (MIT) für Windows: Rechtsklick auf den Download, Verify Checksum wählen, und ein grünes oder rotes Banner zeigt das Ergebnis. Kein Terminal, kein Abgleichen von 64 Zeichen mit bloßem Auge, und im Hintergrund läuft auch nichts.
Ja, ich weiß: Tools, die genau das Gleiche tun, gibt es längst. Get-FileHash steckt schon die ganze Zeit in deinem Terminal, und ein paar ausgereifte Programme erledigen das seit Jahren. Ich habe meins trotzdem gebaut, aus dem edelsten aller Gründe: weil ich es kann. 😄
Im Rest des Beitrags geht es darum, was Prüfsummen beweisen können und was nicht, und wie das Tool gebaut ist.
Warum ich das gebaut habe
Du kennst das vermutlich von Download-Seiten: Neben dem Installer steht eine lange Folge aus Buchstaben und Zahlen, beschriftet mit SHA-256. Damit sollst du die heruntergeladene Datei abgleichen. Ehrlich gesagt vergesse ich das manchmal, und ich vermute, dass ich damit nicht allein bin. Unter Windows heißt Prüfen nämlich: Terminal öffnen, etwas wie Get-FileHash .\setup.exe oder certutil -hashfile setup.exe SHA256 eintippen und dann 64 Zeichen mit bloßem Auge vergleichen.
Deshalb habe ich ChecksumVerify gebaut: ein kleines, kostenloses Open-Source-Tool (MIT) für Windows, das daraus einen Rechtsklick macht.
Der Beitrag hat zwei Teile. Teil 1 ist für alle: was das Tool macht, was eine Prüfsumme ist und was sie beweisen kann und was nicht. Teil 2 richtet sich an Entwicklerinnen und Entwickler: wie das Tool aufgebaut ist, welche Abwägungen ich getroffen habe und wie man es lokal baut und startet.
Teil 1: Was das Tool macht
Der Ablauf
- Auf der Download-Seite kopierst du den veröffentlichten Hash in die Zwischenablage.
- Im Explorer klickst du mit der rechten Maustaste auf die heruntergeladene Datei und wählst Verify Checksum. Unter Windows 11 steckt der Eintrag hinter Weitere Optionen anzeigen (alternativ
Shift+F10). - Ein kleines Fenster öffnet sich. Der kopierte Hash ist schon eingetragen und der passende Algorithmus ausgewählt.
- Du klickst auf Verify. Während die Datei gelesen wird, füllt sich ein Fortschrittsbalken, danach zeigt das Fenster ein Banner: grün, wenn die Datei übereinstimmt, rot, wenn nicht.
Das war's. Kein Terminal, keine Befehle, die man sich merken muss, kein zeichenweises Vergleichen. Stimmt die Datei nicht überein, zeigt das Fenster den tatsächlich berechneten Hash an und kopiert ihn in die Zwischenablage, damit du der Sache nachgehen kannst. Du kannst den erwarteten Hash auch korrigieren und erneut prüfen, ohne irgendetwas neu öffnen zu müssen.
Manche Projekte zeigen den Hash gar nicht auf der Seite an. Stattdessen legen sie eine kleine Datei neben den Download, etwa setup.exe.sha256, oder eine Liste wie SHA256SUMS mit einer Zeile pro Download. Auch damit kommt ChecksumVerify zurecht: Auf Hash file umschalten, die Datei auswählen, und das Tool sucht sich die passende Zeile für deinen Download heraus und wählt den Algorithmus selbst.
Was ist eigentlich eine Prüfsumme?
Eine Prüfsumme (auch Hash) ist ein kurzer Fingerabdruck, der aus jedem einzelnen Byte einer Datei berechnet wird. Die Mathematik dahinter ist so angelegt, dass
- dieselbe Datei immer denselben Fingerabdruck ergibt und
- schon ein einziges geändertes Byte einen völlig anderen Fingerabdruck erzeugt.
Ergibt deine Kopie also denselben Fingerabdruck, den auch der Herausgeber berechnet hat, kannst du dir sehr sicher sein, dass deine Datei Byte für Byte mit seiner übereinstimmt.
Warum das wichtig ist
Auf dem Weg vom Server des Herausgebers auf deine Festplatte kann zweierlei schiefgehen:
- Beschädigung. Downloads gehen öfter kaputt, als man denkt: wacklige Verbindung, abgeschnittene Datei, fehlerhafter Mirror. Ein kaputtes ISO oder ein kaputter Installer kann auf rätselhafte Weise scheitern, manchmal erst lange nach der Installation. Eine Prüfsumme zeigt dir das sofort.
- Manipulation. Hat jemand die Datei auf einem kompromittierten Mirror oder unterwegs gegen eine veränderte Version ausgetauscht, passt der Fingerabdruck nicht mehr.
Was eine Prüfsumme nicht beweist
Hier will ich ehrlich sein, denn an dieser Stelle wird schnell zu viel versprochen. Eine Prüfsumme, die neben dem Download auf derselben Website steht, beweist, dass die Datei unversehrt ist. Sie beweist nicht, dass die Datei echt ist. Kontrolliert ein Angreifer die Website, kann er die Datei und die Prüfsumme austauschen, und alles sieht in Ordnung aus.
Eine passende Prüfsumme heißt: „Das ist die Datei, die mir die Seite angekündigt hat." Sie heißt nicht: „Diese Datei stammt wirklich von denen, die ich dahinter vermute." Dafür brauchst du etwas, das an die Identität des Herausgebers gebunden ist: eine Code-Signatur, eine signierte Prüfsummendatei (zum Beispiel per GPG) oder eine Build-Provenance-Attestierung.
Prüfen lohnt sich trotzdem. Prüfsummen erkennen jede Art von versehentlicher Beschädigung, und sie erkennen Manipulation immer dann, wenn die Prüfsumme von einer anderen Stelle stammt als die Datei (etwa aus den Release Notes eines Projekts auf GitHub statt vom Download-Mirror). Wer meinen Beitrag über sichere .NET-MCP-Server gelesen hat, kennt die Unterscheidung aus einem anderen Zusammenhang: Zu wissen, dass etwas unversehrt ist, ist die eine Frage, zu wissen, von wem es kommt, eine andere.
Algorithmen in aller Kürze
ChecksumVerify unterstützt neun Algorithmen: SHA-256 (mit Abstand der häufigste), SHA-512, SHA3-256, SHA3-512, BLAKE3, BLAKE2b-256, BLAKE2b-512 sowie MD5 und SHA-1 für ältere Download-Seiten. MD5 und SHA-1 reichen, um Beschädigungen zu erkennen, gelten gegen gezielte Angriffe aber als gebrochen. Bietet ein Projekt SHA-256 an, nimm lieber das.
Die SHA-3-Optionen setzen Windows 11 24H2 oder neuer voraus, weil ältere Windows-Versionen SHA-3 in ihrer eingebauten Kryptografie nicht unterstützen. Auf solchen Systemen sind die Optionen ausgegraut, und ein Tooltip erklärt, warum.
Datenschutz
Das Tool hat keinen Netzwerkzugriff und keine Telemetrie, und im Hintergrund läuft nichts. Es liest die Datei lokal, berechnet den Hash und zeigt das Ergebnis an. Mehr nicht.
Herunterladen und den Installer prüfen
Den Installer, ChecksumVerify-<version>-Setup.exe, findest du auf der GitHub-Releases-Seite. Er braucht einmalig Adminrechte, weil er den Rechtsklick-Eintrag für alle Benutzer registriert, und lässt sich ganz normal über Einstellungen → Apps wieder deinstallieren.
Bei einem Prüfsummen-Tool wäre es etwas seltsam, aufs Prüfen zu verzichten, deshalb enthält jedes Release eine SHA256SUMS-Datei. Bei der allerersten Installation hast du das Tool natürlich noch nicht. Nutze dafür Get-FileHash .\ChecksumVerify-<version>-Setup.exe -Algorithm SHA256 und vergleiche das Ergebnis. Bei späteren Releases klickst du mit der rechten Maustaste auf den neuen Installer, wählst Verify Checksum, schaltest auf Hash file um und wählst SHA256SUMS.
Wie im Kasten oben beschrieben, beweist eine Prüfsummendatei auf derselben Seite nur, dass der Download unversehrt ist. Deshalb bringen die Release-Installer zusätzlich eine Build-Provenance-Attestierung mit: einen signierten Nachweis, dass sie vom Release-Workflow des Repositorys selbst gebaut wurden. Mit der GitHub CLI kannst du ihn prüfen:
gh attestation verify .\ChecksumVerify-<version>-Setup.exe --repo hluxenhofer/checksum-verifyDer Installer ist nicht code-signiert, deshalb zeigt Windows SmartScreen möglicherweise „Der Computer wurde durch Windows geschützt". Das README empfiehlt, zuerst den Hash oder die Attestierung zu prüfen und erst dann auf Weitere Informationen → Trotzdem ausführen zu klicken.
Teil 2: Unter der Haube
In diesem Teil geht es darum, wie ChecksumVerify aufgebaut ist und wie du es selbst bauen und starten kannst. Den vollständigen Code findest du auf GitHub.
Kurz noch dazu, wie das Tool entstanden ist: Beim langweiligen Teil, also beim Schreiben des repetitiven Boilerplate-Codes, hat mir ein Coding-Agent geholfen. Die Designentscheidungen und Abwägungen weiter unten stammen von mir, und den Code habe ich selbst gegengelesen.
Aufbau der Solution
Die Solution basiert auf .NET 10 und besteht aus drei Projekten:
| Projekt | Aufgabe |
|---|---|
ChecksumVerify.Core | Einfache Klassenbibliothek mit der gesamten Logik: HashEngine (Algorithmus-Auswahl und Streaming-Berechnung), ClipboardDetector (ist dieser Text ein Hash, und welcher Algorithmus passt?), HashFileParser (Sidecar-Dateien, also kleine Hash-Dateien direkt neben dem Download, und Prüfsummenlisten), dazu AlgorithmSelector und VerifyInputResolver für die Entscheidungsregeln des Fensters. |
ChecksumVerify | Die WinUI-3-App; sie läuft unpackaged auf dem Windows App SDK. Ein Fenster plus ein eigenes Program.Main. |
ChecksumVerify.Tests | xUnit-v3-Tests, ausschließlich gegen Core. |
Die Aufteilung dient dem Testen. Jede Entscheidung des Fensters (welcher Algorithmus automatisch gewählt wird, was als ungültige Eingabe gilt, welcher Fehlertext erscheint) ist eine reine Core-Funktion. Deshalb brauchen die Tests keine Mocks: Sie lassen die echten Hash-Implementierungen gegen kleine Fixture-Dateien mit bekannten Hashes laufen. Von Hand testen muss ich nur noch die Verdrahtung der Controls, die DPI-Skalierung und die Fensterposition.
Null Ressourcen im Leerlauf
Meine wichtigste Designregel: Wenn du gerade nichts prüfst, existiert ChecksumVerify nicht. Kein Tray-Icon, kein Hintergrunddienst, kein Autostart-Eintrag, kein Updater.
Deshalb nutzt der Kontextmenü-Eintrag den einfachsten Mechanismus, den Windows kennt: ein statisches Registry-Verb. Der Inno-Setup-Installer schreibt es nach HKLM:
HKLM\SOFTWARE\Classes\*\shell\ChecksumVerify
(Default) = "Verify Checksum"
Icon = "C:\Program Files\ChecksumVerify\ChecksumVerify.exe,0"
HKLM\SOFTWARE\Classes\*\shell\ChecksumVerify\command
(Default) = "C:\Program Files\ChecksumVerify\ChecksumVerify.exe" "%1"* steht für „alle Dateitypen", %1 für den Pfad der angeklickten Datei. Der Explorer startet die Exe mit genau diesem Pfad als einzigem Argument, und der Prozess beendet sich, sobald du das Fenster schließt. Es wird keine Shell-Extension-DLL in explorer.exe geladen, mein Code kann den Explorer also weder ausbremsen noch zum Absturz bringen.
Der Haken: Unter Windows 11 erscheinen klassische Registry-Verben nur hinter Weitere Optionen anzeigen. Für das neue Kontextmenü der obersten Ebene braucht es eine IExplorerCommand-Implementierung (die Schnittstelle hinter den modernen Kontextmenü-Einträgen von Windows 11) und eine Package Identity, also die Identität, die Windows sonst nur paketierten Apps zuweist. Bei einer nicht paketierten App heißt das: ein Sparse Package (ein minimales Paket, das nur registriert wird, um diese Identität bereitzustellen) und ein Code-Signing-Zertifikat. Ich habe mich für die einfache Variante entschieden.
Streaming-Hashing
Dateien können mehrere Gigabyte groß sein, deshalb lädt HashEngine nie eine ganze Datei in den Speicher. Es liest in 64-KB-Blöcken und übergibt jeden Block an einen inkrementellen Hasher:
private const int BufferSize = 65_536;
private const int ChunksPerProgressReport = 16;
private static async Task ReadChunksAsync(
Stream stream,
Action<byte[], int> consume,
IProgress<long>? progress,
CancellationToken cancellationToken)
{
byte[] buffer = new byte[BufferSize];
int bytesRead;
int chunks = 0;
while ((bytesRead = await stream.ReadAsync(buffer, cancellationToken)) > 0)
{
consume(buffer, bytesRead);
if (++chunks % ChunksPerProgressReport == 0) // 16 chunks = ~1 MiB
progress?.Report(stream.Position);
}
progress?.Report(stream.Position);
}- Dieselbe Schleife funktioniert für alle Algorithmen.
consumeistTransformBlockfür die Algorithmen aus der eingebauten Base Class Library von .NET (BCL: SHA-2, SHA-3, MD5, SHA-1) undUpdatefür BLAKE3 und BLAKE2b. - Der Fortschritt wird etwa einmal pro MiB gemeldet statt nach jedem Block, und der Abbruch wird direkt an
ReadAsyncdurchgereicht: Cancel stoppt die Berechnung, das Fenster bleibt aber offen. - Die Datei wird mit
FileShare.ReadWrite | FileShare.Deletegeöffnet, sodass du auch eine Datei prüfen kannst, die ein anderes Programm noch offen hält.
Den Algorithmus am Hash erkennen
Beim Öffnen liest das Fenster die Zwischenablage und prüft, ob der Text nach einem Hash aussieht. Meistens verrät ihn schon die Länge:
public static HashAlgorithmId? SuggestAlgorithm(string hexString) =>
hexString.Length switch
{
32 => HashAlgorithmId.Md5,
40 => HashAlgorithmId.Sha1,
64 => HashAlgorithmId.Sha256,
128 => HashAlgorithmId.Sha512,
_ => null
};Ein explizites Präfix wie sha256:… oder blake3:… hat immer Vorrang, und Hex-Text ohne Präfix mit einer anderen Länge wird ignoriert, damit 2026 oder deadbeef in der Zwischenablage nicht für einen Hash gehalten wird. Weil 64 Zeichen auch SHA3-256, BLAKE3 oder BLAKE2b-256 sein können, zeigt das Fenster in diesem Fall einen kurzen Hinweis mit den anderen Kandidaten. Bei Hash-Dateien ergibt sich der Algorithmus zuerst aus einer Zeile im BSD-Stil wie SHA256 (file) = …, dann aus der Dateiendung und zuletzt aus der Hash-Länge.
Ein eigenes Main
Die App bekommt ihre einzige Eingabe, den Dateipfad, als Kommandozeilenargument. Ich habe den XAML-generierten Einstiegspunkt abgeschaltet (DISABLE_XAML_GENERATED_MAIN in der csproj) und ein kleines Program.Main geschrieben, das args direkt an den Konstruktor von App weiterreicht:
[STAThread]
static void Main(string[] args)
{
ComWrappersSupport.InitializeComWrappers();
Application.Start(p =>
{
var context = new Microsoft.UI.Dispatching.DispatcherQueueSynchronizationContext(
Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread());
SynchronizationContext.SetSynchronizationContext(context);
_ = new App(args);
});
}App.OnLaunched prüft, ob der Pfad existiert, und beendet sich sofort, wenn nicht. Startest du die Exe ohne gültige Datei, passiert also einfach nichts.
Der resources.pri-Stolperstein
Gut zu wissen, wenn du selbst eine unpackaged WinUI-3-App baust: Zur Laufzeit wird das XAML in einer Datei gesucht, die neben der Exe liegen und resources.pri heißen muss. Der Build erzeugt aber ChecksumVerify.pri, und dotnet publish -o <dir> kopiert sie nicht mit. Unter dotnet run lief die App einwandfrei, nach der Installation konnte sie ihre Oberfläche nicht laden. Inzwischen kopiert ein kleines MSBuild-Target in der csproj die Datei nach dem Publish und benennt sie um.
Lokal ausführen
Du brauchst Windows 10 22H2 oder Windows 11 und das .NET 10 SDK. Inno Setup 7 ist nur nötig, wenn du den Installer bauen willst.
git clone https://github.com/hluxenhofer/checksum-verify.git
cd checksum-verify
.\dev-setup.ps1 # optionales einmaliges Setup: installiert bei Bedarf die WinUI-3-Templates und Inno Setup 7, das .NET 10 SDK aber nur, wenn gar kein dotnet im PATH ist
dotnet build
dotnet test
dotnet run --project src/ChecksumVerify -- "C:\path\to\file.zip"Die letzte Zeile macht genau das, was der Explorer nach einem Rechtsklick tut: Sie startet die App mit einem Dateipfad. Du bekommst das echte Fenster für jede Datei, die du übergibst, ohne etwas zu installieren oder die Registry anzufassen.
Ein einfaches dotnet build / dotnet run ist framework-dependent: Die Windows App SDK Runtime ist nicht mit dabei, sondern muss auf deinem Rechner installiert sein, und dev-setup.ps1 installiert sie nicht. Der Self-contained-Publish weiter unten bringt die Runtime mit, dieser Build läuft also auch ohne.
Hast du bereits ein älteres SDK wie .NET 8 oder 9, gilt das für dev-setup.ps1 als vorhanden, und das SDK wird übersprungen. global.json legt aber SDK 10 fest, also schlägt dotnet build dann fehl. In diesem Fall installierst du das .NET 10 SDK selbst.
Um den echten Rechtsklick-Eintrag auszuprobieren, erstellst du einen Self-contained-Publish und baust den Installer:
dotnet publish src/ChecksumVerify/ChecksumVerify.csproj -c Release -r win-x64 --self-contained -o publish/win-x64/
iscc installer\setup.issMit -r win-x64 landet die Windows App SDK Runtime direkt neben der Exe. Der Installer liegt danach in installer\Output\, braucht einmalig Adminrechte und registriert das oben gezeigte Verify Checksum-Verb. dev-setup.ps1 nimmt iscc in deinen PATH auf; hast du Inno Setup von Hand installiert, sorge selbst dafür, dass iscc im PATH liegt.
Was noch fehlt
Der Installer ist nicht code-signiert, Windows SmartScreen warnt beim ersten Start also möglicherweise. Release-Builds gibt es nur für x64, und unter Windows 11 erscheint der Eintrag nur unter Weitere Optionen anzeigen.
Fazit
ChecksumVerify ist ein kleines Tool für eine kleine, wiederkehrende Aufgabe: sicherzustellen, dass die heruntergeladene Datei auch wirklich die ist, die du haben wolltest. Den Rest der Zeit hält es sich komplett raus: kein Code im Explorer, nichts im Hintergrund, und nach Hause telefoniert es auch nicht.
Wenn du es ausprobierst, freue ich mich über Rückmeldungen. Bugs und Feature-Wünsche sind auf GitHub Issues willkommen, Fragen, Ideen und allgemeines Feedback auf GitHub Discussions.