Beliebige Dateien (z.B. 7z, zip, yaml, …) mittels Catalog-Files und PowerShell signieren

Die Nutzung eines Code-Signing-Zertifikats zur Authenticode-Signatur ist für zahlreiche Datei-Typen die dies unterstützen direkt inline möglich. Als Beispiele seien *.exe, *.dll, *.ps1, … genannt.

Dieses kurze How-To beschäftigt sich allerdings mit Datei-Typen, die keine Signatur unterstützen. Beispielsweise ein YAML-Konfigurationsfile im Textformat, oder ZIP-Container sowie 7zip-Containerfiles.

Eine elegante Variante beliebige Dateien unter Windows zu signieren ist die Nutzung von CatalogFiles (*.cat). Der Vorteil hierbei: Die Werkzeuge zur Signatur-Erstellung und zur Signatur-Prüfung sind in Form der PowerShell-Commandlets New-FileCatalog sowie Test-FileCatalog auf jedem modernen Windows-System bereits vorhanden.

Catalog-Files: *.cat

Eine Catalog-Datei (*.cat) ist eine digital signierte Windows-Sicherheitskatalogdatei (Security Catalog). Diese speichert kryptografische Hashwerte (SHA1 oder SHA256 Fingerprints) einer Sammlung von Dateien. Typischerweise werden Catalog-Files verwendet, um Treiber- und Software-Pakete zu signieren. Man kann damit allerdings beliebige Dateien signieren, die Nutzung ist nicht auf Treiber- und Software-Pakete beschränkt.

Statt jede einzelne Datei separat zu signieren, wird nur die Katalogdatei selbst mit einem Authenticode-Zertifikat digital signiert.

Bei zum Beispiel der Installation von Treibern prüft Windows die Signatur der .cat-Datei und vergleicht die gespeicherten Hashes der Treiber-Dateien mit den tatsächlichen Dateien. Stimmt alles überein, gilt das Paket als unverändert und vertrauenswürdig. Die Datei ist intern eine PKCS#7-Struktur.

Wir machen uns die einfache Möglichkeit Catalog-Files zu erstellen und zu prüfen nun zu Nutze, um damit beliebige Dateien zu signieren sowie deren Signatur zu prüfen.

Ein Catalog-File erstellen

Erstellen wir zur Demonstration mittels New-FileCatalog ein Catalog-File, das nachfolgende 6 Dateien signiert:

PS C:\temp\Demofiles> dir

    Verzeichnis: C:\temp\Demofiles

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        10.09.2026     23:27            748 Config.yaml
-a----        10.09.2026     23:16          38601 Demodokument.pdf
-a----        10.09.2026     23:18          84063 Demofiles.7z
-a----        10.09.2026     23:17          84508 Demofiles.zip
-a----        10.09.2026     21:56          52742 Grafik.png
-a----        10.09.2026     23:27           2646 Readme.txt

Schritt 1: Erstellung des Catalog-Files:

Die Erstellung des Catalog-Files ist unspektakulär, wir wählen bewusst ein Catalog File in Version 2.0 um SHA256 Hashes zu erhalten, andernfalls würde man mit Version 1.0 nur SHA1 Hashes erzeugen, welche heutzutage aber keine akzeptable Kollisionsresistenz mehr bieten.

PS C:\temp\Demofiles> New-FileCatalog -Path . -CatalogFilePath signed-catalog.cat -CatalogVersion 2.0

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        10.09.2026     23:33           2094 signed-catalog.cat

Schritt 2: Authenticode-Signieren des Catalog-Files:

Nun führen wir die Authenticode-Signatur des Catalog-Files durch, das funktioniert wie von *.exe, *.dll, oder *.ps1 Dateien gewohnt:

# Vorbereitung: Wir selektieren unser im Windows Certificate Store hinterlegtes Code-Signing-Zertifikat
PS C:\temp\Demofiles> $CertSubject = "*HITCo Demo-Authenticode-Signer*"
PS C:\temp\Demofiles> $Cert = Get-ChildItem -Path "Cert:\CurrentUser\My" | Where-Object { $_.Subject -like $CertSubject } | Select-Object -First 1
PS C:\temp\Demofiles> $Cert.Subject
CN=HITCo Demo-Authenticode-Signer, OU=Dev-Department, O=HITCo.at, C=AT

# Mit $Cert signieren wir nun das Catalog-File
PS C:\temp\Demofiles> Set-AuthenticodeSignature -FilePath .\signed-catalog.cat -Certificate $Cert -TimestampServer "http://timestamp.sectigo.com"

    Verzeichnis: C:\temp\Demofiles


SignerCertificate                         Status                                                Path
-----------------                         ------                                                ----
B41CCA64A43FCA6B4E0CA1B03D580F1F3BB2DA4D  Valid                                                 signed-catalog.cat

Anmerkung: Wie man sich eine Root-CA und daraus ein Signatur-Zertifikat ausstellt habe ich im Blog-Post Certificate Authority unter Windows mit PowerShell betreiben erläutert.

Das erstellte signed-catalog.cat enthält einen Katalog aller signierten Files mit deren Hashes, sowie eine Authenticode-Signatur mit dem verwendeten Code-Signing-Zertifikat samt Trusted-Timestamp-Signatur vom TimeStampServer Sectigo.

Signatur-Prüfung

Nun möchten wir die Signatur-Prüfung vornehmen. Wenn wir alle Files, die vom Catalog-File umfasst sind, im aktuellen Verzeichnis liegen haben, klappt das sehr einfach wie folgt:

# Alle Dateien im aktuellen Verzeichnis gegen das CatalogFile prüfen
PS C:\temp\Demofiles> $SignTest = Test-FileCatalog -Detailed -CatalogFilePath .\signed-catalog.cat -Path .
PS C:\temp\Demofiles> $SignTest | Format-List

Status        : Valid
HashAlgorithm : SHA256
CatalogItems  : {[Demofiles.zip, F3AA0DEC172207FFCED86AE63B2C5A48FD2B1FC206A1952A5114C5241F629245], [Demodokument.pdf,
                E8877A3D8ABB380ADB31D0BD68A2528EE438FDD19026D5CFE9A3C39ADBB91681], [Demofiles.7z,
                DA9F3D66C1AD8F043EBE86B44DB2C2C09934EDF2699E82FB54A055C3CAA18139], [Grafik.png,
                9E5C13BF40ACAEB7B887C68A3EA852D548767149DF470B57BFBD1B2E3C694E84]...}
PathItems     : {[Config.yaml, 04AB91927E7829A6816CA2515004301C9BB7FEE1319D15A11D848F93FA1A6EF6], [Demodokument.pdf,
                E8877A3D8ABB380ADB31D0BD68A2528EE438FDD19026D5CFE9A3C39ADBB91681], [Demofiles.7z,
                DA9F3D66C1AD8F043EBE86B44DB2C2C09934EDF2699E82FB54A055C3CAA18139], [Demofiles.zip,
                F3AA0DEC172207FFCED86AE63B2C5A48FD2B1FC206A1952A5114C5241F629245]...}
Signature     : System.Management.Automation.Signature

# Prüfung erfolgreich?
PS C:\temp\Demofiles> $SignTest.Status -eq "Valid" -and $SignTest.HashAlgorithm -eq "SHA256"
True

# Welche Files wurden geprüft?
PS C:\temp\Demofiles> $SignTest.PathItems

Key              Value
---              -----
Config.yaml      04AB91927E7829A6816CA2515004301C9BB7FEE1319D15A11D848F93FA1A6EF6
Demodokument.pdf E8877A3D8ABB380ADB31D0BD68A2528EE438FDD19026D5CFE9A3C39ADBB91681
Demofiles.7z     DA9F3D66C1AD8F043EBE86B44DB2C2C09934EDF2699E82FB54A055C3CAA18139
Demofiles.zip    F3AA0DEC172207FFCED86AE63B2C5A48FD2B1FC206A1952A5114C5241F629245
Grafik.png       9E5C13BF40ACAEB7B887C68A3EA852D548767149DF470B57BFBD1B2E3C694E84
Readme.txt       679A0DB2BA2B5B8BECEC22AC1F892E1246371F637C246723DA8CD06292140B2F

# Wer hat das unterschrieben?
PS C:\temp\Demofiles> $SignTest.Signature.SignerCertificate.Subject
CN=HITCo Demo-Authenticode-Signer, OU=Dev-Department, O=HITCo.at, C=AT

Wenn wir allerdings nur einige Files prüfen möchten, muss das -FilesToSkip Argument verwendet werden, weil die Catalog-File-Prüfung sonst fehlschlägt:

# Wir möchten nur zwei Files aus dem Catalog-File prüfen, das schlägt auf diese Weise aber fehl:
PS C:\temp\Demofiles> $SignTest = Test-FileCatalog -Detailed -CatalogFilePath .\signed-catalog.cat `
                                  -Path "Config.yaml", "Demofiles.zip"
PS C:\temp\Demofiles> $SignTest.Status
ValidationFailed

# Es schlägt deshalb fehl, weil wir nur zwei PathItems geprüft haben, aber sechs CatalogItems zur Prüfung vorhanden sind:
PS C:\temp\Demofiles> $SignTest.PathItems

Key           Value
---           -----
Config.yaml   04AB91927E7829A6816CA2515004301C9BB7FEE1319D15A11D848F93FA1A6EF6
Demofiles.zip F3AA0DEC172207FFCED86AE63B2C5A48FD2B1FC206A1952A5114C5241F629245


PS C:\temp\Demofiles> $SignTest.CatalogItems

Key              Value
---              -----
Demofiles.zip    F3AA0DEC172207FFCED86AE63B2C5A48FD2B1FC206A1952A5114C5241F629245
Demodokument.pdf E8877A3D8ABB380ADB31D0BD68A2528EE438FDD19026D5CFE9A3C39ADBB91681
Demofiles.7z     DA9F3D66C1AD8F043EBE86B44DB2C2C09934EDF2699E82FB54A055C3CAA18139
Grafik.png       9E5C13BF40ACAEB7B887C68A3EA852D548767149DF470B57BFBD1B2E3C694E84
Readme.txt       679A0DB2BA2B5B8BECEC22AC1F892E1246371F637C246723DA8CD06292140B2F
Config.yaml      04AB91927E7829A6816CA2515004301C9BB7FEE1319D15A11D848F93FA1A6EF6

# Um dies zu bewerkstelligen, ermitteln wir die zu skippenden Files:
PS C:\temp\Demofiles> $MissingFiles = $SignTest.CatalogItems.Keys | Where-Object { $SignTest.PathItems.Keys -notcontains $_ }
PS C:\temp\Demofiles> $MissingFiles
Demodokument.pdf
Demofiles.7z
Grafik.png
Readme.txt

# Und nun teilen wir mit, welche Dateien im Zuge der Prüfung zu überspringen sind: 
PS C:\temp\Demofiles> $SignTest = Test-FileCatalog -Detailed -CatalogFilePath .\signed-catalog.cat `
                                  -Path "Config.yaml", "Demofiles.zip" -FilesToSkip $MissingFiles
PS C:\temp\Demofiles> $SignTest.Status
Valid

You May Also Like

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert