Entonces La tarea ha llegado. Con un navegador, invite al usuario a firmar el PDF con una firma electrónica (en lo sucesivo, EP). El usuario debe tener un token que contenga el certificado, las claves públicas y privadas. A continuación, en el servidor debe insertar la firma en el documento PDF. Después de eso, debe verificar la validez de la firma. Usamos ASP.NET y, en consecuencia, C # como back-end.
Toda la sal es que necesita usar una firma en el formato CAdES-X Long Type 1 y el ruso GOST R 34.10-2001, GOST R 34.10-2012, etc. Además, puede haber más de una firma, es decir, los usuarios pueden turnarse para firmar un archivo. Sin embargo, las firmas anteriores deben seguir siendo válidas.
En el proceso de resolver el problema, decidieron complicarnos y reducir la cantidad de datos transmitidos al cliente. Solo transmita el hash del documento, pero no el documento en sí.
En el código fuente omitiré los momentos que son de poca importancia para el tema, dejaré solo eso con respecto a la criptografía. Daré el código JS solo para navegadores normales cuyos motores JS admiten Promise y generador de funciones. Creo que quién necesita escribir para IE ellos mismos (tuve que "no quiero").
Lo que necesitas
- El usuario debe recibir un par de claves y un certificado.
- El usuario debe instalar el complemento desde Crypto PRO. Sin esto, no podremos trabajar con un proveedor de servicios criptográficos utilizando herramientas JS.
Observaciones:
- Para las pruebas, tenía un certificado emitido por la prueba Crypto PRO CA y un token normal recibido por uno de nuestros empleados (al momento de escribir ~ 1500r con una licencia anual para Crypto PRO y dos certificados: pero el "nuevo" y el "antiguo" GOST)
- Dicen que el complemento puede funcionar con ViPNet, pero no lo he probado.
Ahora suponemos que en nuestro servidor hay un PDF listo para firmar.
Agregue un script de Crypto PRO a la página:
<script src="/Scripts/cadesplugin_api.js" type="text/javascript"></script>
Luego tenemos que esperar hasta que se forme el objeto cadesplugin
window.cadespluginLoaded = false; cadesplugin.then(function () { window.cadespluginLoaded = true; });
Le preguntamos al servidor hash. Anteriormente, para esto todavía necesitamos saber qué certificado, y por lo tanto el algoritmo, firmará el usuario. Un pequeño comentario: combiné todas las funciones y "variables" para trabajar con criptografía en el lado del cliente en un CryptographyObject.
Método para llenar el campo de certificados del objeto 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); } }); }
Comentario: intente abrir un almacén de certificados. En este punto, el sistema del usuario le advertirá que el sitio está tratando de hacer algo con certificados, criptografía y otras tonterías mágicas e incomprensibles. El usuario deberá hacer clic en "Sí"
A continuación, obtenemos certificados que son válidos a tiempo (no caducados) y los colocamos en la matriz de certificados. Esto debe hacerse debido a la naturaleza asincrónica de cadesplugin (para IE, todo es diferente;)).
Método hash:
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;
Comentario: preste atención a cadesplugin.async_spawn, se le pasa la función de generador, a la que next () se llama secuencialmente, lo que conduce a la transición al rendimiento.
Por lo tanto, obtenemos un cierto análogo de async-wait de C #. Todo parece síncrono, pero funciona de forma asíncrona.
Ahora, qué sucede en el servidor cuando se ha solicitado hash.
Primero, debe instalar el paquete nuget iTextSharp (en el momento de la redacción, la versión actual 5.5.13 debería ser)
En segundo lugar, se necesita CryptoPro.Sharpei, va a la carga de Crypto PRO .NET SDK
Ahora puedes obtener hash
En el cliente, que tiene hash del servidor, lo firmamos
Comentario: envíe la firma recibida al servidor (ver arriba)
Bueno, finalmente, inserte la firma en el documento en el lado del servidor
Comentario: SimpleExternalSignatureContainer es la clase más simple que implementa la interfaz IExternalSignatureContainer.
En realidad, con la firma del PDF, eso es todo. La verificación se describirá en la continuación del artículo. Espero que ella sea ...
Se hicieron correcciones del comentario al recibir el algoritmo de firma de Oid. Gracias