Alors. La tâche est venue. À l'aide d'un navigateur, invitez l'utilisateur à signer le PDF avec une signature électronique (ci-après dénommé EP). L'utilisateur doit avoir un jeton contenant le certificat, les clés publiques et privées. Ensuite, sur le serveur, vous devez insérer la signature dans le document PDF. Après cela, vous devez vérifier la validité de la signature. Nous utilisons ASP.NET et, par conséquent, C # comme back-end.
Tout le sel est que vous devez utiliser une signature au format CAdES-X Long Type 1, et russe GOST R 34.10-2001, GOST R 34.10-2012, etc. De plus, il peut y avoir plusieurs signatures, c'est-à-dire que les utilisateurs peuvent signer à tour de rôle un fichier. Cependant, les signatures précédentes doivent rester valables.
Dans le processus de résolution du problème, ils ont décidé de nous compliquer la tâche et de réduire la quantité de données transmises au client. Ne transmettez que le hachage du document, mais pas le document lui-même.
Dans le code source j'oublierai les moments qui ont peu d'importance pour le sujet, je ne laisserai que cela comme pour la cryptographie. Je ne donnerai le code JS qu'aux navigateurs normaux dont les moteurs JS prennent en charge Promise et le générateur de fonctions. Je pense qui a besoin d'écrire pour IE eux-mêmes (je devais "ne pas vouloir").
Ce dont vous avez besoin:
- L'utilisateur doit recevoir une paire de clés et un certificat.
- L'utilisateur doit installer le plug-in depuis Crypto PRO. Sans cela, nous ne pourrons pas travailler avec un fournisseur de services cryptographiques à l'aide des outils JS.
Remarques:
- Pour les tests, j'avais un certificat émis par le test Crypto PRO CA et un jeton normal reçu par l'un de nos employés (au moment de la rédaction ~ 1500r avec une licence annuelle pour Crypto PRO et deux certificats: mais le "nouveau" et l '"ancien" GOST)
- Ils disent que le plug-in peut fonctionner avec ViPNet, mais je ne l'ai pas testé.
Nous supposons maintenant que sur notre serveur, un PDF est prêt à être signé.
Ajoutez un script de Crypto PRO à la page:
<script src="/Scripts/cadesplugin_api.js" type="text/javascript"></script>
Ensuite, nous devons attendre que l'objet cadesplugin soit formé
window.cadespluginLoaded = false; cadesplugin.then(function () { window.cadespluginLoaded = true; });
Nous demandons au serveur de hachage. Auparavant, pour cela, nous devons encore savoir quel certificat, et donc l'algorithme, l'utilisateur signera. Une petite remarque: j'ai combiné toutes les fonctions et "variables" pour travailler avec la cryptographie côté client dans un CryptographyObject.
Méthode de remplissage du champ des certificats de l'objet CryptographyObject:
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); } }); }
Commentaire: essayez d'ouvrir un magasin de certificats. À ce stade, le système de l'utilisateur vous avertira que le site essaie de faire quelque chose avec des certificats, de la cryptographie et d'autres non-sens magiques et incompréhensibles. L'utilisateur devra cliquer sur "Oui"
Ensuite, nous obtenons des certificats qui sont valides dans le temps (non expirés) et les mettons dans le tableau des certificats. Cela doit être fait en raison de la nature asynchrone du cadesplugin (pour IE, tout est différent;)).
Méthode de hachage:
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;
Commentaire: faites attention à cadesplugin.async_spawn, la fonction générateur lui est passée, sur laquelle next () est appelée séquentiellement, ce qui conduit à la transition vers yield.
Ainsi, nous obtenons un certain analogue d'async-wait de C #. Tout semble synchrone, mais fonctionne de manière asynchrone.
Maintenant, que se passe-t-il sur le serveur quand le hachage a été demandé.
Tout d'abord, vous devez installer le package de nuget iTextSharp (au moment de la rédaction, la version actuelle 5.5.13 devrait être)
Deuxièmement, CryptoPro.Sharpei est nécessaire, il va à la charge du SDK Crypto PRO .NET
Maintenant, vous pouvez obtenir du hachage
Sur le client, ayant le hachage du serveur, nous le signons
Commentaire: envoyez la signature reçue au serveur (voir ci-dessus)
Enfin, insérez la signature dans le document côté serveur
Commentaire: SimpleExternalSignatureContainer est la classe la plus simple qui implémente l'interface IExternalSignatureContainer.
En fait avec la signature du PDF, c'est tout. La vérification sera décrite dans la suite de l'article. J'espère qu'elle sera ...
Correction du commentaire sur la réception de l'algorithme de signature Oid. Je vous remercie