Ich möchte meine Erfahrungen, oder besser meine Odyssee, zur Signierung von Visual Studio Projekten, im speziellen Anwendungen und Office AddIns, zusammenfassen, um möglichst schnell beim nächsten Mal auf die richtigen Informationen zugreifen zu können. Eventuell hilft es ja auch jemanden bei der Fehlersuche.

Es geht hierbei um die Code Signatur, um Anwendern die Echtheit der Software per Zertifikat zu bestätigen. Diese lässt sich in Visual Studio in den Projekteigenschaften unter Signierung auswählen, indem man ein Haken bei „ClickOnce Manifeste signieren“ auswählt. Leider wird beim Veröffentlichen lediglich die Setup.exe signiert und nicht das eigentliche Programm. Dies bleibt weiterhin unsigniert.

Die Option „Assembly signieren“ im gleichen Menü versieht die Anwendungsassemblys mit Strong Names um diese eindeutig identifizieren zu können. Dies hat aber nichts mit der Signierung per Code Signing Zertifikat zu tun und soll nicht weiter Gegenstand dieses Beitrags sein.

Um die Signatur auch auf die EXE oder DLL Datei anzuwenden, ist es erforderlich die Datei manuell zu signieren. Dafür lassen sich perfekt die Build Ereignisse (Projekteigenschaften->Kompilieren->Buildereignisse) verwenden. Da die Signatur erst nach Erstellen der Dateien angewendet werden kann, verwende ich hierfür die POST Buildereignisse.

Um die Signatur anzuwenden benötigt man ein Tool namens signtool.exe. Dieses wird vom Visual Studio normalerweise bei dessen Installation mit installiert, kann sich jedoch je nach .Net Version in unterschiedlichen Ordnern befinden. Auch kann es vorkommen, dass sich das Tool mehrfach auf der Festplatte wiederfinden lässt. Sollte das Tool dennoch nicht auffindbar sein, kann man es durch die Installation einer Windows SDK verfügbar machen. Welche SDK die richtige ist, hängt von der jeweiligen Windows Version ab.

Hat man den Pfad zur signtool.exe gefunden, trägt man in die Post Buildereignisse folgenden Befehl ein:

signtool.exe sign /f Certificate.pfx /p <PFX password>  /t http://timestamp.comodoca.com /v program_name

Certificate.pfx ist dabei der Pfad und  Dateiname des zu verwendenden Code Signing Zertifikat. Diese Angabe muss in “ Anführungszeichen stehen, wenn der Pfad Leerzeichen enthält.
<PFX password> entspricht dem Zertifikatspasswort.
/t http://…  dies ist der Timestamp Server, von dem signtool.exe den aktuellen Timestamp für die Signierung erhält. Ich habe hier den Timestamp Server von Comodo eingetragen, da ich mein Code Signing Zertifikat über Comodo bezogen habe.
/v zeigt ausführliche Informationen zur Signierung an
program_name ist der vollständige Name der EXE oder DLL die aus dem compilierten Projekt erzeugt wird. Bei einem VSTO Projekt ist das Programm eine DLL.

Nach dem erneuten Erstellen des Projekts, dürfte die EXE oder DLL Datei nun signiert sein. Bei der Signierung wird standardmäßig der SHA1 Algorithmus verwendet. Seit 2017 dürften die meisten Zertifikate mit SHA-256 codiert sein. Um explizit auch diesen Algorithmus für die Signierung zu verwenden sieht der Befehl so aus:

signtool.exe sign /f Certificate.pfx /p <PFX password>  /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 /as /v program_name

/fd legt den Algorithmus fest
/tr entspricht /t, hat aber die Möglichkeit weitere Optionen anzugeben
/td fordert vom Timestamp Server einen bestimmten Algorithmus zu verwenden
/as hängt die Signatur an bereits bestehende Signaturen der Datei an

Mit dem /as Schalter ist es möglich mehrere Signaturen auf eine Datei anzuwenden. Wenn man ältere Systeme unterstützen möchte, die bspw. den SHA-256 Algorithmus nicht kennen, kann man die zwei Befehle nacheinander ausführen, um die Signatur in SHA-1 und SHA-256 zu verwenden.
Der /as Schalter steht erst ab Windows 8 zur Verfügung.

Wenn man nun das Projekt veröffentlicht, verwenden Setup und Programm die korrekte Signatur.

Bei normalen Anwendung ist hier Schluss, bei Office AddIns, die als VSTO veröffentlicht werden, erhält man jedoch nach der Installation eine Fehlermeldung.
Zum einen müssen die Prüfsummen der Manifeste noch korrigiert werden und zum anderen muss Office noch über unser Zertifikat informiert werden.
Um die Prüfsummen der Manifeste zu korrigieren benötigt man das Tool mage.exe, welches ebenfalls mit Visual Studio installiert wird bzw. über die Windows SDK verfügbar ist.

Für die Prüfsummen verwende ich eine Batch Datei, die nach dem Veröffentlichen im Projektordner ausgeführt wird:

@echo off
REM Pfad zum Publishing Verzeichnis
set AppPublishPath=bin\Release\app.publish
REM Pfad zu den Programmdateien innerhalb der Publishing Verzeichnis
set AppPublishVersionPath=bin\Release\app.publish\Application Files\ProgramName_1_0_0_0
REM Pfad und Dazteiname des zu verwendenden Code Signing Zertifikats in Form einer PFX Datei
set CertificatePath=<Filename including path for Pfx Certificate>
REM das Password für das Zertifikat
set CertificatePassword=<PFX password>
REM Pfad zur mage.exe ohne Dateiname und abschließendes \
set MageToolPath=<Path to mage.exe>

rem kopiert alle notwendigen DLL ins Publishing Verzeichnis
copy bin\release\*.dll "%AppPublishVersionPath%"

"%MageToolPath%\mage.exe" -update "%AppPublishVersionPath%\BirthdayGreetings.dll.manifest"  -certfile "%CertificatePath%"  -Password %CertificatePassword%
"%MageToolPath%\mage.exe" -update "%AppPublishVersionPath%\BirthdayGreetings.vsto"  -appmanifest "%AppPublishVersionPath%\BirthdayGreetings.dll.manifest" -certfile "%CertificatePath%"  -Password %CertificatePassword%
"%MageToolPath%\mage.exe" -update "%AppPublishPath%\BirthdayGreetings.vsto"  -appmanifest "%AppPublishVersionPath%\BirthdayGreetings.dll.manifest"  -certfile "%CertificatePath%"  -Password %CertificatePassword%

set MageToolPath=
set AppPublishPath=
set AppPublishVersionPath=
set CertificatePath=
set CertificatePassword=
REM am Ende warten, um die Ausgabe zu kontrollieren
pause

Die Batch Datei wird nach dem Veröffentlichen ausgeführt und sollte 3 erfolgreiche Signierungen vermelden.

In meiner Office Installation, sowie in den meisten Firmeninstallationen, werden Makros und AddIns nur zugelassen, wenn diese digital signiert sind, um Schadsoftware bspw. Makroviren das ungehinderte Ausbreiten zu erschweren. Wenn man nun mit dieser Einstellung das Setup ausführt wird das AddIn erfolgreich installiert, man erhält jedoch noch eine Fehlermeldung, dass dem Herausgeber nicht vertraut wird.
Um diese letzte Klippe zu umschiffen, benötigt man eine öffentliche Signatur des verwendeten Code Signing Zertifikats sowie das Tool certutil.exe, um dieses dem Office bekannt zu machen.
Um die öffentliche Signatur zu erhalten, muss das Zertifikat im Zertifikatsspeicher installiert sein. Dies sollte bereits der Fall sein. Wenn nicht, das Zertifikat doppelklicken und Zertifikat installieren.
Mittels dem Zertifikatsmanager (erreichbar über Start->Ausführen->certmgr.msc) sucht man das Zertifikat aus. Mittels Rechtsklick->Alle Aufgaben->Exportieren kommt man zum Export Assistent.
Hier ist zu beachten, dass man den privaten Schlüssel nicht exportiert und als Dateiformat das Base64 kodierte .CER auswählt.
Nun wählt man noch den Dateinamen und hat das öffentliche Zertifikat erfolgreich erstellt.
Dieses Zertifikat kann nun an alle Rechner verteilt werden, die das AddIn ausführen sollen. Eine Signierung, wie mit dem Original, ist damit nicht möglich, es dient lediglich zur Verifizierung der Signatur.
In der Eingabeaufforderung, die im Administrator Modus gestartet werden muss, wird das Zertifikat nun wie folgt dem Zertifikatsspeicher von Office hinzugefügt:

certutil -addstore "TrustedPublisher" PublicCertificateName.cer

PublicCertificateName entspricht hierbei dem gerade vergebenen Dateinamen inklusive Pfad.

Nach dem erfolgreichen Hinzufügen, kann die Office Anwendung gestartet werden und das AddIn sollte ohne Probleme ausgeführt werden.