Então A tarefa chegou. Usando um navegador, convide o usuário a assinar o PDF com uma assinatura eletrônica (a seguir denominada EP). O usuário deve ter um token contendo o certificado, chaves públicas e privadas. Em seguida, no servidor, você precisa inserir a assinatura no documento PDF. Depois disso, você precisa verificar a assinatura quanto à validade. Usamos o ASP.NET e, consequentemente, o C # como back-end.
Todo o sal é que você precisa usar uma assinatura no formato CAdES-X Long Type 1 e o russo GOST R 34.10-2001, GOST R 34.10-2012, etc. Além disso, pode haver mais de uma assinatura, ou seja, os usuários podem se revezar na assinatura de um arquivo. No entanto, assinaturas anteriores devem permanecer válidas.
No processo de solução do problema, eles decidiram nos complicar e reduzir a quantidade de dados transmitidos ao cliente. Transmita apenas o hash do documento, mas não o próprio documento.
No código-fonte, omitirei os momentos que são pouco significativos para o tópico, deixarei apenas isso para a criptografia. Darei o código JS apenas para navegadores normais cujos mecanismos JS suportam o Promise e o gerador de funções. Eu acho que quem precisa escrever para o IE (eu tinha que "não querer").
O que você precisa:
- O usuário deve receber um par de chaves e um certificado.
- O usuário deve instalar o plug-in do Crypto PRO. Sem isso, não poderemos trabalhar com um provedor de serviços criptográficos usando ferramentas JS.
Observações:
- Para testes, eu tinha um certificado emitido pelo teste Crypto PRO CA e um token normal recebido por um de nossos funcionários (no momento em que escrevi ~ 1500r com uma licença anual para o Crypto PRO e dois certificados: mas o GOST “novo” e o “antigo”)
- Eles dizem que o plug-in pode funcionar com o ViPNet, mas eu não o testei.
Agora assumimos que em nosso servidor existe um PDF pronto para assinatura.
Adicione um script do Crypto PRO à página:
<script src="/Scripts/cadesplugin_api.js" type="text/javascript"></script>
Então precisamos esperar até que o objeto cadesplugin seja formado
window.cadespluginLoaded = false; cadesplugin.then(function () { window.cadespluginLoaded = true; });
Pedimos ao servidor de hash. Anteriormente, para isso, ainda precisamos saber qual certificado e, portanto, o algoritmo, o usuário assinará. Uma pequena observação: eu combinei todas as funções e "variáveis" para trabalhar com criptografia no lado do cliente em um CryptographyObject.
Método para preencher o campo de certificados do 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); } }); }
Comentário: tente abrir um armazenamento de certificados. Nesse momento, o sistema do usuário avisa que o site está tentando fazer algo com certificados, criptografia e outras bobagens mágicas e incompreensíveis. O usuário precisará clicar em "Sim"
Em seguida, obtemos certificados válidos a tempo (não expirados) e os colocamos na matriz de certificados. Isso deve ser feito devido à natureza assíncrona do cadesplugin (para o IE, tudo é 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;
Comentário: preste atenção em cadesplugin.async_spawn, a função do gerador é passada para ela, na qual next () é chamado seqüencialmente, o que leva à transição para o rendimento.
Assim, obtemos um certo análogo de async-waiting do C #. Tudo parece síncrono, mas funciona de forma assíncrona.
Agora, o que acontece no servidor quando o hash foi solicitado.
Primeiro, você precisa instalar o pacote de nuget iTextSharp (no momento da redação, a versão atual 5.5.13 deveria ser)
Em segundo lugar, o CryptoPro.Sharpei é necessário, ele vai para o carregamento do Crypto PRO .NET SDK
Agora você pode obter hash
No cliente, tendo hash do servidor, assinamos
Comentário: envie a assinatura recebida para o servidor (veja acima)
Bem, finalmente, insira a assinatura no documento no lado do servidor
Comentário: SimpleExternalSignatureContainer é a classe mais simples que implementa a interface IExternalSignatureContainer.
Na verdade, com a assinatura do PDF, é tudo. A verificação será descrita na continuação do artigo. Espero que ela seja ...
Correções do comentário sobre o recebimento do algoritmo de assinatura Oid. Obrigada