Introdução & Motivação

Ao implementar assinaturas digitais em sistemas de nível empresarial, a segurança é inegociável.
Armazenar um certificado em um arquivo PFX ou P12 local é conveniente, mas expõe a chave privada à extração ou comprometimento. Em contraste, tokens de hardware PKCS#11 (como dongles USB, cartões inteligentes e HSMs) mantêm as chaves dentro de um limite à prova de violação, garantindo que nunca deixem o dispositivo.

Esta postagem demonstra como usar GroupDocs.Signature for .NET em conjunto com Pkcs11Interop para assinar documentos PDF com tokens de hardware. A abordagem combina conveniência e conformidade: o GroupDocs cuida de todo o empacotamento em nível de PDF (campos de assinatura, cálculo de digest, incorporação), enquanto o token realiza a assinatura criptográfica propriamente dita.

⚠️ Aviso de Implementação Precoce
Esta solução está atualmente disponível como uma implementação precoce para usar dongles de assinatura digital PKCS#11 com o GroupDocs.Signature.
Embora permita a assinatura de documentos com tokens de hardware, recomendamos fortemente a realização de testes adicionais em seu próprio ambiente para garantir que atenda aos seus requisitos de conformidade e segurança.
Agradecemos imensamente seu feedback, resultados de testes e sugestões de melhorias.

O Desafio: Conectando PKCS#11 à Assinatura de PDF

Integrar tokens PKCS#11 nos fluxos de trabalho de assinatura de documentos apresenta vários desafios não triviais:

  1. Complexidade de Baixo Nível – A API PKCS#11 (Cryptoki) requer o gerenciamento de slots, sessões, identificadores e atributos para encontrar a chave privada correta.
  2. Empacotamento em Nível de PDF – Assinar um PDF é mais do que assinar bytes: a biblioteca deve calcular os digests corretos sobre os intervalos de bytes selecionados, envolver assinaturas em contêineres CMS/PKCS#7, incluir carimbos de tempo e incorporar informações de validação.
  3. Variações de Vendedor – Diferentes tokens/módulos de fornecedor podem exigir mapeamento customizado de atributos ou middleware adicional.
  4. Conformidade & Auditabilidade – Sistemas de produção precisam de manipulação robusta de PIN, controle do ciclo de vida da sessão, recuperação de erros e registro de logs.

O Que o Projeto de Exemplo Faz

  • Demonstra assinatura de documentos PDF usando tokens PKCS#11 (dongle, cartão inteligente, HSM).
  • Suporta fallback para repositório de certificados do Windows: se um certificado estiver instalado no Windows, o código pode usá‑lo em vez do token.
  • Implementa assinatura personalizada de hash: o GroupDocs calcula o digest; o token apenas assina o hash.
  • Mantém a chave privada no hardware o tempo todo — nunca exportada.
  • Encapsula a lógica do token (sessão, procura de chave, assinatura) em Pkcs11DigitalSigner.cs
  • Fornece lógica auxiliar em Helpers.cs (por exemplo, busca de certificados no repositório do Windows).
  • Configuração centralizada em Settings.cs.
  • Atua como implementação de referência que pode ser adaptada ao seu ambiente.
Bridging PKCS#11 with PDF Signing

Configuração & Pré‑requisitos

Pré‑requisitos

  • .NET 6.0 ou superior (ou .NET Framework 4.6.2)
  • Uma biblioteca PKCS#11 (DLL) válida do fornecedor do seu token
  • Um token de hardware (dongle USB, cartão inteligente ou HSM) com um certificado válido
  • GroupDocs.Signature for .NET (versão de avaliação ou licenciada)
  • A biblioteca Pkcs11Interop

Instalação

git clone https://github.com/groupdocs-signature/esign-documents-with-pkcs11-using-groupdocs-signature-dotnet.git
cd esign-documents-with-pkcs11-using-groupdocs-signature-dotnet
dotnet restore

Abra a solução no Visual Studio ou na IDE de sua preferência e certifique‑se de que as dependências foram resolvidas.

Estrutura do Repositório – Visão Detalhada

GroupDocs.Signature-for-.NET-PKCS11-Sample/
├── GroupDocs.Signature-for-.NET-PKCS11-Sample.csproj      # Arquivo de projeto
├── Program.cs                                             # Ponto de entrada e fluxo de uso
├── Settings.cs                                            # Configuração PKCS#11 / token
├── Helpers.cs                                             # Funções utilitárias (repositório Windows, filtragem de certificados)
├── Pkcs11DigitalSigner.cs                                 # Implementa ICustomSignHash via PKCS#11
└── README.md                                              # Explicação & instruções de uso
  • Program.cs – orquestra a assinatura; demonstra tanto o fluxo baseado em token quanto o fluxo de certificado do Windows.
  • Settings.cs – contém constantes/placeholders para Pkcs11LibraryPath, TokenPin e CertificateSubject.
  • Helpers.cs – contém código para encontrar certificados no repositório do Windows por nome do assunto (usado no fluxo de fallback).
  • Pkcs11DigitalSigner.cs – lógica central: carrega o módulo PKCS#11, abre sessões, localiza o objeto da chave privada, assina um digest e retorna um X509Certificate2 ou uma implementação de callback de assinatura.
  • README.md – fornece visão geral, desafios e instruções de uso (que complementa este blog).

Explicação do Código & Passo a Passo

Settings.cs

public static class Settings
{
    public const string Pkcs11LibraryPath = "<PKCS11_LIBRARY_PATH>";
    public const string TokenPin = "<TOKEN_PIN>";
    public const string CertificateSubject = "<CERT_SUBJECT>";
}

Isso isola os detalhes de configuração para que possam ser facilmente substituídos no seu ambiente de implantação.

Pkcs11DigitalSigner.cs — Fluxo de Alto Nível

public class Pkcs11DigitalSigner : ICustomSignHash
{
    public byte[] SignHash(byte[] hash)
    {
        // This method is invoked by GroupDocs.Signature when it needs the token to sign a hash
        using (var pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath, AppType.SingleThreaded))
        {
            // Load module, open session, login with PIN, find key and perform signing
        }
    }

    public X509Certificate2 GetCertificateFromPkcs11()
    {
        // Retrieves the public certificate from the token so the signing options can be configured
    }
}
  • SignHash é o método central: ele recebe o digest calculado pelo GroupDocs e, em seguida, usa as APIs PKCS#11 para assiná‑lo.
  • GetCertificateFromPkcs11 obtém o certificado (com chave pública) armazenado no token para que os metadados da assinatura estejam corretos.

Program.cs — Fluxo de Uso

class Program
{
    static void Main()
    {
        string inputFile = "sample.pdf";
        string outputFile = "signed.pdf";

        // (1) PKCS#11 signing
        var tokenSigner = new Pkcs11DigitalSigner();
        var cert = tokenSigner.GetCertificateFromPkcs11();

        using (var signature = new Signature(inputFile))
        {
            var options = new DigitalSignOptions(cert)
            {
                Comments = "Signed with PKCS#11 token",
                SignTime = DateTime.Now,
                CustomSignHash = tokenSigner  // link token-based signing
            };
            signature.Sign(outputFile, options);
        }

        // (2) Windows certificate store fallback (optional)
        // var storeCert = Helpers.GetCertificateFromWindowsStore(Settings.CertificateSubject);
        // using (var signature2 = new Signature(inputFile))
        // {
        //     var options2 = new DigitalSignOptions(storeCert) { ... };
        //     signature2.Sign("signed_store.pdf", options2);
        // }
    }
}

Pontos principais:

  • A propriedade CustomSignHash de DigitalSignOptions recebe tokenSigner, permitindo que o GroupDocs delegue a assinatura real do hash ao token.
  • O fluxo de fallback (comentado) mostra como mudar para o certificado do repositório Windows quando o token de hardware não estiver disponível.

Casos de Uso & Cenários Reais

  • Índia & Dongles de Assinatura USB Emitidos por AC
    Na Índia, muitas e‑signatures juridicamente vinculativas exigem certificados armazenados em dongles USB emitidos por autoridades certificadoras reconhecidas. Este exemplo permite que aplicativos (ex.: portais de documentos, gateways) integrem diretamente com esses dongles.
  • Fluxos de Trabalho Empresariais de Documentos
    Para sistemas internos como gerenciamento de contratos ou processos de aprovação, a assinatura em hardware garante que usuários não autorizados não possam falsificar assinaturas de documentos.
  • Assinatura Regulada / Conformidade
    Governos e indústrias reguladas frequentemente exigem que as assinaturas provêm de chaves controladas por hardware. Esta integração ajuda a atender a exigências estritas de auditoria e conformidade.

Armadilhas Comuns & Solução de Problemas

  • Caminho da biblioteca incorreto → O caminho da DLL PKCS#11 deve corresponder ao módulo do fornecedor do seu token (ex.: softhsm2.dll, cryptoki.dll).
  • Bloqueio ou falha de PIN → Entradas de PIN erradas repetidas podem bloquear o token; verifique a política do fornecedor.
  • Chave não encontrada → Certifique‑se de que o assunto do certificado informado está correto; o token deve conter o certificado com o assunto correspondente.
  • Driver ou middleware ausente → Alguns tokens requerem a instalação de drivers do fornecedor antes que o Pkcs11Interop consiga se comunicar.
  • Problemas de threading → Operações PKCS#11 podem não ser thread‑safe; use contexto single‑threaded a menos que o fornecedor suporte múltiplas threads.
  • Timeouts ou reinicializações de sessão → Operações longas podem fazer com que sessões sejam fechadas ou expiradas; garanta o tratamento adequado de sessões e limpeza.

Segurança & Melhores Práticas

  • Nunca codifique segredos de produção (PINs, caminhos de bibliotecas); use configuração segura ou gerenciamento de segredos.
  • Use PINs fortes e rotacione‑os quando a política permitir.
  • Registre operações e erros (sem registrar PINs sensíveis).
  • Limite sessões ao token e faça logout imediato após a assinatura.
  • Valide a assinatura após a assinatura (verificações de cadeia, carimbo de tempo).
  • Teste em diferentes ambientes e tipos de token (dongle/cartão inteligente/HSM).

Próximos Passos & Recursos

Pronto para experimentar? Clone o repositório, atualize os placeholders e execute o exemplo.
Tópicos que você pode querer explorar a seguir:

  • Assinatura Personalizada de Hash (delegando digest + assinatura ao token)
  • Timestamping & LTV / DSS embedding
  • Assinatura iterativa (múltiplas assinaturas em um único documento)
  • Integração com serviços de HSM remoto ou armazenamento de tokens em nuvem