none
Erro ao usar um certificado instalado ou exportado do Windows RRS feed

  • Pergunta

  • Saudações a todos.

    Estou com problemas para utilizar um certificado digital (eCPF) para assinar documentos PDF.

    Aparentemente uma vez que o certificado (arquivo pfx fornecido pela certificadora) é instalado no Windows ele deixa de ser utilizavel.
    Escrevi uma aplicação para assinar os arquivos PDF gerados pelo sistema da empresa, que funciona lendo um arquivo de certificado (.pfx) e tutilizando o certificado para assinar o documento gerado.

    Tudo muito bonitinho, SE, o arquivo pfx for o arquivo original (repito, fornecido pela certificadora), quando o arquivo é exportado do Windows não funciona, da erro de validação.
    Então quando um cliente não tem mais o arquivo original não é possivel assinar os documentos.

    Ok, etntão vamos assinar os documentos lendo o certificado diretamente do storage de certificados do windows e esta tudo resolvido, né ?
    Não ! Quando um certificado instalado é usado para assinar (estou usando a API do .NET com o C#) o sistema gera uma excessão com a seguinte mensagem:
    'Chave inválida para uso no estado especificado'

    Então recorro aos senhores grandes conhecedores desta grande "caixa preta" chamada Windows na tentativa de elucidar os mistérios envolvidos.

    Que "estado" ? A assinatura digital não serve para assinar ?.

    Desde já agradeço qualquer ajuda ou pista, pois não tenho idéia de onde definir o tal "estado" indicado na mensagem.

    Informações complementares para a boa alma que se imiscuir nesta aventura:

    1 - Os certificados foram instalados no windows com a opção "Permitir a exportação da Chave Privada" ativa.

    2 - Nas tentativa de exportação para pfx, todas as combinações de opção (disponiveis na guia de exportação) foram testadas para o certificado do assinante.
    (selecionando o certificado do assinante e clicando em Exportar no gerenciador de certificados do windows)

    3 - Caso ajude, segue também o código da aplicação que assina usando um certificado instalado, o erro ocorre no momento da geração da PK na linha destacada:

    teste.cs:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Windows.Forms;
    using System.Security.Permissions;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using iTextSharp.text.pdf;
    using iTextSharp.text.xml.xmp;
    using iTextSharp.text.pdf.security;
    using iTextSharp.text;
    
    using Org.BouncyCastle.Pkcs;
    using Org.BouncyCastle.Asn1.X509;
    using BcX509 = Org.BouncyCastle.X509;
    
    .....
    
    //Open certificate collection
    X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
    X509Certificate2Collection findCollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, true);
    
    //Create a collection of certificates in a windows form object
    log("Selecionar certificado...");
    X509Certificate2Collection selectCollection = X509Certificate2UI.SelectFromCollection(findCollection
                                             , "Selecionar Certificado para Assinatura"
                                             , "Selecione um certificado qualquer na lista abaixo para obter informações do certificado."
                                             , X509SelectionFlag.MultiSelection);
    
    if (openDlg.ShowDialog() == DialogResult.OK)
    {
        AssinaPDF(openDlg.FileName, selectCollection[0]);
    }
    .....
    
    private void AssinaPDF(string aFileName, X509Certificate2 cert)
    {
    
        PdfReader reader = new PdfReader(aFileName);
        //Activate MultiSignatures
        PdfStamper st = PdfStamper.CreateSignature(reader, new FileStream(aFileName+".assinado.pdf", FileMode.Create, FileAccess.Write), '\0', null, true);
    
        PdfSignatureAppearance sap = st.SignatureAppearance;
    
        sap.Acro6Layers = true;
        sap.Reason = "Razao - Teste";
        sap.Contact = "Contato Fulano de Tal";
        sap.Location = "Aqui";
    
        // iTextSharp needs this cert as a BouncyCastle X509 object; this converts it.
        BcX509.X509Certificate bcCert = DotNetUtilities.FromX509Certificate(cert);
        var chain = new List<BcX509.X509Certificate> { bcCert };
    
        X509Certificate2 signatureCert = new X509Certificate2(cert);
        
        // ####### Esta linha gera uma excessão com a mensagem 'Chave inválida para uso no estado especificado' ########
        var pk = DotNetUtilities.GetKeyPair(signatureCert.PrivateKey).Private;
        
        IExternalSignature es = new PrivateKeySignature(pk, "SHA-256");
        MakeSignature.SignDetached(sap, es, chain, null, null, null, 0, CryptoStandard.CMS);
    
        st.Close();
    
    }
    

    quinta-feira, 26 de maio de 2016 13:19

Respostas