CodeSigning — Kode-Signierung (Windows)

Ein Versuch, Windows-Programme über ein Zertifikat des Rechenzentrums der TU Chemnitz zu signieren.

Die Idee dazu kam von der Anleitung der Humboldt-Uni.

Zertifikat beschaffen

Da die ganze Prozedur im der o.g. Webseite für Unix angegeben war, habe ich es genauso gemacht. Also per putty und Kommandozeile.

Die meisten Tutorials im WWW verwenden openssl. Wahrscheinlich geht es damit leichter.

Geheimen Schlüssel erstellen

Habe ich damit gemacht:
keytool -genkey -keyalg RSA -alias heha-cs -keySize 2048
Das Programm fragt einige zu setzende Bezeichner ab. Dabei habe ich, in Absprache mit dem URZ, folgendes eingegeben:
CN=PN: Henrik Haftmann (CodeSigning)
OU=IWP
O=Technische Universitaet Chemnitz
L=Chemnitz
ST=Sachsen
C=DE
Außerdem möchte es ein Passwort für die ~/.keystore-Datei haben. Da diese immerhin einen privaten (geheimen) Schlüssel enthalten wird, habe ich dafür ein paar Sonderzeichen spendiert, obwohl die Datei im einigermaßen geschützten AFS-Bereich liegt.

Mit dem alias gibt man dem Schlüssel bzw. dem künftigen Schlüsselpaar einen Namen.

Zertifikatantrag exportieren

keytool -certreq -file heha-cs.csr -alias heha-cs
Die entstehende Datei heha-cs.csr sieht etwa so aus:
-----BEGIN NEW CERTIFICATE REQUEST-----
 kryptischer Text
-----END NEW CERTIFICATE REQUEST-----

Zertifikatantrag einreichen

Die Datei heha-cs.csr muss man nun zur Universität bringen, und zwar durch den Besuch dieser Webseite. Als „Zertifikatsprofil“ (Einsatzzweck) legt man „User“ fest.

Die anderen Angaben füllt man wahrheitsgemäß aus, und das angegebene Passwort zum Löschen des Zertifikats schreibt man sich am besten irgendwo auf. (Ich benutze für das mit der Zeit anfallende Passwort-Sammelsurium eine passwortgeschützte ZIP-Datei.)

Dann druckt man den Antrag (PDF-Datei, 1 A4-Seite) aus, füllt den aus und marschiert damit und dem Personalausweis zum Nutzerservice.

Der Mitarbeiter dort macht einen Gesichts- und Unterschriftenvergleich, und dann geht der Zettel per Hauspost ans URZ.

Zertifikat importieren (zum geheimen Schlüssel hinzufügen)

Nach 1-2 Tagen kommt eine E-Mail vom URZ mit einer cert-??????.pem-Datei als Anhang.
Sehr geehrte Nutzerin, sehr geehrter Nutzer,

die Bearbeitung Ihres Zertifizierungsantrags ist nun abgeschlossen.

Ihr Zertifikat mit der Seriennummer XXXXXXXXXXXXXXXX ist auf den Namen
CN=PN: Henrik Haftmann (CodeSigning),OU=IWP,O=Technische Universitaet Chemnitz,L=Chemnitz,ST=Sachsen,C=DE
erstellt worden.

Sie benötigen die Seriennummer, um Ihr Zertifikat gegebenenfalls sperren zu können.

Um Ihr Zertifikat nutzen zu können, müssen Sie alle folgenden Zertifikate in Ihre Anwendung importieren.
1. Für die CA-Zertifikate wählen Sie bitte die Seite

https://pki.pca.dfn.de:443/tu-chemnitz-ca/cgi-bin/pub/pki?cmd=getStaticPage;name=index;id=2
und folgen den Anweisungen.

2. Ihr eigenes Zertifikat finden Sie im Anhang dieser Mail.

Mit freundlichen Grüßen

Ihr PKI-Team der Technische Universitaet Chemnitz
Bevor man das angehängte Zertifikat in die ~/.keystore-Datei importieren kann, muss man die Zertifikatkette der Uni installieren. Das ging so: Man klickt auf den Link in der E-Mail, klickt auf „Zertifikatkette anzeigen“ und speichert diese. Heraus kommt eine Datei mit 3 Sektionen, die so aussehen:
-----BEGIN CERTIFICATE-----
 kryptischer Text
-----END CERTIFICATE------
Diese Datei zerstückelt man mit einem beliebigen Texteditor in 3 Teile, benannt c1, c2 und c3.

Dann importiert man diese folgendermaßen:

keytool -import -file c3 -alias c3 -trustcacerts
keytool -import -file c2 -alias c2 -trustcacerts
keytool -import -file c1 -alias c1 -trustcacerts
Dabei kann es passieren, dass eine Warnung erscheint, weil eins der Zertifikate (bei mir war's c3) bereits global installiert ist. Dann braucht man es nicht zu laden.

Jetzt die Datei aus dem Attachment. Ihr Inhalt entspricht dem der Dateien c1 bis c3. Wichtig beim Import ist der gleiche Alias!

keytool -import -file cert-??????.pem -alias heha-cs -trustcacerts
Nun kann man sich mit
keytool -list
die nun fertige ~/.keystore-Datei angucken. Die Datei selbst ist eine kryptische Binärdatei.

Man kann nun sofort mittels jarsigner Java-Archive signieren.

Schlüsselpaar exportieren und aufbewahren

Jetzt steckt der private (geheime) Schlüssel in der ~/.keystore-Datei, und nur dort. Irgendwie muss dieser auch nach Windows exportiert werden. Das kann keytool nicht erledigen, aber dafür tun es zwei kleine Java-Programme, ExportPriv.java und Base64Coder.java, und ein Text-Editor. Dabei kommen die Tipps von dieser Webseite. Auch die Java-Progrämmchen kann man sich da runterladen. Die Kommandozeilen sind wie folgt:
javac ExportPriv.java Base64Coder.java
java ExportPriv ~/.keystore heha-cs <password> > heha-cs.p8
Dummerweise spuckt ExportPriv alle Base64-Zeichen in einer Zeile aus. Damit der nächste Schritt diese Daten schluckt, habe ich diese mit einem Texteditor auf 64 Zeichen pro Zeile umgebrochen.

In der Windows-Welt werden pkcs12-Dateien erwartet. Das sind Binärdateien für den privaten Schlüssel. Zum Umwandeln muss man starten:

openssl pkcs8 -inform PEM -nocrypt -in heha-cs.p8 -out heha-cs.p12

Diese Datei kann man unter Windows doppelklicken. Dabei wird die Datei im Windows-Zertifikatspeicher unter „Eigene Zertifikate“ installiert. Jener Zertifikatspeicher wird automatisch von Internet Explorer, Outlook (Express?) und signtool verwendet, nicht jedoch von Mozilla Firefox und Thunderbird.

Irgendwie sieht das Zertifikat unter Windows komisch aus:

Dazu später mehr.

Da das Zertifikat auch das Unterschreiben von E-Mail zulässt, ich aber dafür ein anderes Zertifikat von der Uni habe, habe ich im Zertifikat-Manager die Verwendung „Sichere E-Mail“ ausgeschaltet.

Im übrigen gibt es unter Windows zwei Zertifikat-Manager, die auf den gleichen Speicher zugreifen:

Beide Programme sehen etwas unterschiedlich aus!

Software zertifizieren

JAR-Dateien mit jarsigner

Java 8 (ab 2015) erfordert Kode-Signierung. Mit Zeitstempel. Oder man muss in den Java-Einstellungen den HTTP-Server zu den Ausnahmen hinzufügen. Auch bei HTTPS. Da der Zugang zu http- und so auch Zeitstempelservern von login.tu-chemnitz.de versperrt ist, muss man diese Kommandozeile auf dem lokalen Rechner mit einer genügend modernen Java-Entwicklungsumgebung ausführen. Eine Manifestdatei wird obendrein noch benötigt.
echo "Permissions: sandbox" > t.mf
jar cfmv t.jar t.mf t.class …
jarsigner t.jar heha-cs -tsa https://timestamp.geotrust.com/tsa
Und trotzdem wird dann noch gemeckert: Bild 1 Bild 2 Bild 3. Laut Java-Dokumentation ist ein blaues Schutzschild OK. Trotzdem eine eher verwirrende Warnung, die keine ist. Sondern ein Hinweis, dass alles absolut korrekt ist. Da sollte besser nichts hochkommen, ist ja nur Geschwafel.

Hinweis: .class-Dateien lassen sich nicht signieren. Einfache Java-Applets muss man trotzdem einpacken und die HTML-Zeile mit <embed … erweitern um archive=jarname. Im Prinzip das Ende von kleinen Spielereien, Riesenhürden für Anfänger, der Sargdeckel für selbstgemachte Java-Applets. Hier das Beispiel.

Windows-Programme (EXE- und DLL-Dateien) mit signtool signwizard

Am einfachsten geht das Signieren mit der Kommandozeile
signtool signwizard
Dann startet ein Dialog, und man kann die Datei mit ein paar Mausklicks mit dem Zertifikat versehen lassen. signtool entnimmt das Zertifikat automatisch aus dem Windows-Zertifikatspeicher, da es nur eines für Kodesignatur geeignetes findet (es setzt dazu ein Filter). Heraus kommt „Authenticode“.

Bemerkenswerterweise wird nicht nach einem Passwort gefragt! Nur ein kleiner Dialog fordert zum Bestätigen des Signiervorgangs auf. Das war die Einstellung „Hohe Sicherheit“ beim Importieren des geheimen Schlüssels gewesen. Man kann nachträglich noch den Passwortschutz aktivieren.

Die Kommandozeilenoption signwizard steht übrigens erst bei einem relativ neuen SDK, nicht jedoch bei einem DDK zur Verfügung! Offenbar geht Microsoft davon aus, dass Treiberentwickler alles per makefile machen, auch das Signieren.

Ergebnis

Das Endergebnis ist frustierend: Startet man mit dem Internet Explorer eine unsignierte Datei, kommt folgende Warnung:

Startet man hingegen die signierte Datei, sieht es so aus:

Die Signierung führt also dazu, dass die Datei gar nicht mehr gestartet werden kann! Microsoft hat m.E. damit den Sinn der Zertifizierung komplett verfehlt.

From: Jan Mönnich (DFN-Cert)
To: CA TU Chemnitz

ja, leider sind die Code-Signing-Zertifikate der DFN-PKI etwas ungeeignet für Signaturen im Bereich "Microsoft". Denn die zugrundeliegende Wurzel Deutsche Telekom Root CA2 wird in Windows-Systemen nicht für den Verwendungszweck "Codesigning" gelistet :( Diesen Zweck kann der Nutzer zwar selbst setzen, dieser wird jedoch bald wieder von Windows Update überschrieben. Die einzige Möglichkeit ist, den Zweck von einem Domaincontroller an alle Rechner im AD zu verteilen. Das geht. Alles andere ist eher schwierig...

Patcht man, wie angegeben, das Wurzelzertifikat „Deutsche Telekom Root CA 2“ und aktiviert den Zweck „Codesignatur“ (interessant, dass das überhaupt geht!), ist die Folge, dass das Zertifikat nun ganz anders aussieht:
,
dann sieht das Bild beim Download einer EXE-Datei so aus:

Auch nicht viel besser. Obwohl der Zertifizierungspfad ordnungsgemäß und komplett ist, kommt eine Warnung, die den User sicherlich ebenso zurückschreckt. Auch bleibt „Nicht ausführen“ der Standard-Knopf.

Die Moral von der Geschicht': Zertifiziere Deine Windows-Programme nicht!

Wie man nun eine Signatur à la Microsoft hinbekommt, dass keine Warnung erscheint, bleibt weiterhin unklar. Wahrscheinlich kostet es Geld, viel Geld.

Keine Warnung erscheint, wenn man das Zertifikat nach „Vertraute Herausgeber“ kopiert. Dies passiert, wenn man im erweiterten Download-Dialog die Auswahl „Immer Software von … ausführen“ trifft.

Erkenntnisse

Das Microsoft-Programm signtool kennt 3 verschiedene Verifizierungsmodi: Die Fehlermeldungen beziehen sich auf eine signierte Datei mit aktivierter CodeSigning-Verwendung (OID = 1.3.6.1.5.5.7.3.3) im Stammzertifikat (Deutsche Telekom Root CA2).