Also. Die Aufgabe ist gekommen. Laden Sie den Benutzer mit einem Browser ein, das PDF mit einer elektronischen Signatur (im Folgenden als EP bezeichnet) zu signieren. Der Benutzer muss über ein Token verfügen, das das Zertifikat sowie öffentliche und private Schlüssel enthält. Als Nächstes müssen Sie auf dem Server die Signatur in das PDF-Dokument einfügen. Danach müssen Sie die Signatur auf Gültigkeit überprüfen. Wir verwenden ASP.NET und dementsprechend C # als Backend.
Das ganze Salz ist, dass Sie eine Signatur im CAdES-X Long Type 1-Format und Russisch GOST R 34.10-2001, GOST R 34.10-2012 usw. verwenden müssen. Darüber hinaus kann es mehr als eine Signatur geben, dh Benutzer können abwechselnd eine Datei signieren. Vorherige Signaturen müssen jedoch gültig bleiben.
Bei der Lösung des Problems haben sie beschlossen, für uns zu komplizieren und die an den Kunden übertragene Datenmenge zu reduzieren. Übertragen Sie nur den Hash des Dokuments, nicht aber das Dokument selbst.
Im Quellcode werde ich die Momente weglassen, die für das Thema von geringer Bedeutung sind, ich werde nur das für die Kryptographie belassen. Ich werde den JS-Code nur für normale Browser geben, deren JS-Engines Promise und Funktionsgenerator unterstützen. Ich denke, wer muss für IE selbst schreiben (ich musste "nicht wollen").
Was Sie brauchen:
- Der Benutzer muss ein Schlüsselpaar und ein Zertifikat erhalten.
- Der Benutzer muss das Plug-In von Crypto PRO installieren. Ohne dies können wir mit JS-Tools nicht mit einem Kryptografiedienstanbieter zusammenarbeiten.
Anmerkungen:
- Für die Tests hatte ich ein Zertifikat, das vom Test Crypto PRO CA ausgestellt wurde, und einen normalen Token, den einer unserer Mitarbeiter erhalten hatte (zum Zeitpunkt des Schreibens von ~ 1500r mit einer jährlichen Lizenz für Crypto PRO und zwei Zertifikaten: aber das „neue“ und das „alte“ GOST).
- Sie sagen, dass das Plug-In mit ViPNet funktionieren kann, aber ich habe es nicht getestet.
Jetzt gehen wir davon aus, dass auf unserem Server ein PDF zum Signieren bereitsteht.
Fügen Sie der Seite ein Skript von Crypto PRO hinzu:
<script src="/Scripts/cadesplugin_api.js" type="text/javascript"></script>
Dann müssen wir warten, bis das Cadesplugin-Objekt gebildet ist
window.cadespluginLoaded = false; cadesplugin.then(function () { window.cadespluginLoaded = true; });
Wir fragen den Hash-Server. Zuvor müssen wir dazu noch wissen, welches Zertifikat und damit welcher Algorithmus der Benutzer signiert. Eine kleine Bemerkung: Ich habe alle Funktionen und "Variablen" für die Arbeit mit Kryptographie auf der Clientseite in einem CryptographyObject zusammengefasst.
Methode zum Ausfüllen des Zertifikatsfelds des CryptographyObject-Objekts:
fillCertificates: function (failCallback) { cadesplugin.async_spawn(function*() { try { let oStore = yield cadesplugin.CreateObjectAsync("CAPICOM.Store"); oStore.Open(cadesplugin.CAPICOM_CURRENT_USER_STORE, cadesplugin.CAPICOM_MY_STORE, cadesplugin.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED); let certs = yield oStore.Certificates; certs = yield certs.Find(cadesplugin.CAPICOM_CERTIFICATE_FIND_TIME_VALID); let certsCount = yield certs.Count; for (let i = 1; i <= certsCount; i++) { let cert = yield certs.Item(i); CryptographyObject.certificates.push(cert); } oStore.Close(); } catch (exc) { failCallback(exc); } }); }
Kommentar: Versuchen Sie, einen Zertifikatspeicher zu öffnen. An diesem Punkt warnt Sie das System des Benutzers, dass die Site versucht, etwas mit Zertifikaten, Kryptografie und anderem magischen, unverständlichen Unsinn zu tun. Der Benutzer muss auf "Ja" klicken.
Als nächstes erhalten wir zeitlich gültige (nicht abgelaufene) Zertifikate und fügen sie in das Zertifikatsarray ein. Dies muss aufgrund der asynchronen Natur von Cadesplugin erfolgen (für IE ist alles anders;)).
Hash-Methode:
getHash: function (certIndex, successCallback, failCallback, - ) { try { cadesplugin.async_spawn(function*() { let cert = CryptographyObject.certificates[certIndex]; let certPublicKey = yield cert.PublicKey(); let certAlgorithm = yield certPublicKey.Algorithm; let algorithmValue = yield certAlgorithm.Value; let hashAlgorithm;
Kommentar: Achten Sie auf cadesplugin.async_spawn, die Generatorfunktion wird an cadesplugin.async_spawn übergeben, worauf next () nacheinander aufgerufen wird, was zum Übergang zum Yield führt.
Somit erhalten wir von C # ein bestimmtes Analogon von asynchronem Warten. Alles sieht synchron aus, funktioniert aber asynchron.
Was passiert nun auf dem Server, wenn ein Hash angefordert wurde?
Zunächst müssen Sie das iTextSharp-Nuget-Paket installieren (zum Zeitpunkt des Schreibens sollte die aktuelle Version 5.5.13 sein).
Zweitens wird CryptoPro.Sharpei benötigt, es geht zum Laden für Crypto PRO .NET SDK
Jetzt können Sie Hash bekommen
Auf dem Client, der Hash vom Server hat, signieren wir ihn
Kommentar: Senden Sie die empfangene Signatur an den Server (siehe oben)
Nun, schließlich fügen Sie die Signatur in das Dokument auf der Serverseite ein
Kommentar: SimpleExternalSignatureContainer ist die einfachste Klasse, die die IExternalSignatureContainer-Schnittstelle implementiert.
Mit der Unterzeichnung des PDF ist das alles. Die Überprüfung wird in der Fortsetzung des Artikels beschrieben. Ich hoffe sie wird ...
Korrekturen aus dem Kommentar zum Empfang des Oid-Signaturalgorithmus. Vielen Dank