Files
cybercore-signer/docs/CCSP.md
T

15 KiB

CyberCore Signing Protocol (CCSP/1)

Especificação Técnica do Protocolo de Comunicação Local e API REST (Versão 1)

O CyberCore Signing Protocol (CCSP) é o protocolo padrão para comunicação local entre aplicações web rodando no navegador do usuário e o agente desktop CyberCore Signer.

A versão atual especificada neste documento é a CCSP/1.


1. Princípios de Segurança e Isolamento

O protocolo CCSP/1 adota o princípio de menor privilégio e segurança em profundidade:

  1. Loopback Estrito (127.0.0.1): O servidor HTTP local vincula seu socket exclusivamente ao endereço IP 127.0.0.1 na porta padrão 21325. O agente rejeita escuta em 0.0.0.0, prevenindo qualquer acesso proveniente da rede local (LAN) ou externa (WAN).
  2. Validação de Cabeçalhos e DNS Rebinding: O agente valida o cabeçalho Host para garantir que as requisições se originem estritamente de 127.0.0.1:21325 ou localhost:21325.
  3. Controle de Origem (CORS): Todas as respostas incluem cabeçalhos CORS restritivos. Métodos HTTP OPTIONS prévios (preflight) são tratados para liberar apenas métodos e headers homologados (Content-Type, Origin, X-CyberCore-AppId).
  4. Handshake de Autorização de Aplicações: Nenhuma página web desconhecida pode listar certificados ou solicitar assinaturas. Uma aplicação deve se identificar (POST /ccsp/v1/authorize) e obter aprovação explícita do usuário via diálogo nativo do sistema operacional.
  5. Proteção Anti-Replay com Nonce e TTL: Todas as chamadas de assinatura exigem um identificador pseudoaleatório nonce único e um timestamp de expiração (expires_at). Requisições com nonces repetidos são sumariamente rejeitadas com erro estruturado REPLAY_DETECTED.
  6. Privacidade Criptográfica por Digest: Por padrão, a aplicação web calcula o hash SHA-256 no próprio navegador utilizando a Web Crypto API nativa e envia apenas o digest de 32 bytes (em Base64). O documento confidencial nunca trafega para o agente e a chave privada nunca sai do computador ou do chip criptográfico do usuário.
  7. Trava FIFO Serializada (signLock): O processamento de assinaturas físicas em smartcards/tokens USB A3 é serializado em fila FIFO para evitar colisões no hardware mono-thread do middleware do fabricante.

2. Visão Geral dos Endpoints (CCSP/1)

Método Endpoint Finalidade Autenticação Requerida
GET /ccsp/v1/status Verifica integridade e status de prontidão do agente local Nenhuma
POST /ccsp/v1/authorize Handshake de autorização inicial de uma aplicação web Consentimento visual do usuário
GET /ccsp/v1/certificates Lista certificados digitais ICP-Brasil válidos e operacionais Aplicação Autorizada
GET /ccsp/v1/seals Lista temas e estilos visuais de selos suportados pelo agente Aplicação Autorizada
POST /ccsp/v1/sign Executa assinatura digital do digest informado (PAdES/CAdES/XMLDSig) Aplicação Autorizada + Diálogo Nativo
POST /ccsp/v1/sign-pdf Assina documento PDF em Base64 com selo posicionado e devolve PDF assinado Aplicação Autorizada + Diálogo Nativo
POST /ccsp/v1/sign-xml Assina documento XML (XAdES-BES / XMLDSig) e devolve XML assinado Aplicação Autorizada + Diálogo Nativo
POST /ccsp/v1/authenticate Realiza login seguro via desafio criptográfico (Challenge-Response) Aplicação Autorizada + Diálogo Nativo

3. Especificação Detalhada dos Endpoints

3.1 GET /ccsp/v1/status

Verifica se o agente desktop está instalado, em execução e pronto para operações criptográficas.

Requisição

GET /ccsp/v1/status HTTP/1.1
Host: 127.0.0.1:21325
Origin: https://meusistema.empresa.com.br

Resposta de Sucesso (200 OK)

{
  "version": "1",
  "status": "ready",
  "agent": "CyberCore Signer",
  "agent_version": "0.1.0",
  "os": "Windows 11",
  "timestamp": "2026-10-11T20:45:00Z"
}

3.2 POST /ccsp/v1/authorize

Inicia o handshake para autorizar uma nova aplicação web. Quando a aplicação ainda não foi homologada pelo usuário, o CyberCore Signer suspende a requisição e exibe um modal nativo na tela do desktop para confirmação.

Cabeçalhos

  • Content-Type: application/json
  • Origin: https://meusistema.empresa.com.br

Payload da Requisição

{
  "version": "1",
  "application_id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Portal Jurídico e Tributário"
}

Resposta de Sucesso (200 OK)

{
  "version": "1",
  "status": "authorized",
  "application_id": "550e8400-e29b-41d4-a716-446655440000",
  "message": "Aplicação autorizada pelo usuário com sucesso."
}

Resposta de Recusa do Usuário (403 Forbidden)

{
  "version": "1",
  "status": "error",
  "error_code": "APPLICATION_NOT_AUTHORIZED",
  "message": "O usuário recusou a autorização para esta aplicação."
}

3.3 GET /ccsp/v1/certificates

Retorna a lista de certificados digitais atualmente disponíveis e aptos para assinatura no sistema (A1 importados e A3 conectados via Windows Store ou PKCS#11).

Cabeçalhos / Parâmetros

  • Origin: Origem web autorizada.
  • X-CyberCore-AppId (Header) ou ?application_id=uuid (Query Param).

Resposta de Sucesso (200 OK)

{
  "version": "1",
  "status": "success",
  "certificates": [
    {
      "id": "win-4340656a",
      "alias": "MARIA DA SILVA:12345678900",
      "common_name": "MARIA DA SILVA:12345678900",
      "subject_dn": "CN=MARIA DA SILVA:12345678900, OU=Autenticado por AR, O=ICP-Brasil, C=BR",
      "issuer_dn": "CN=AC SERPRO v5, OU=Servico Federal de Processamento de Dados, O=ICP-Brasil, C=BR",
      "type": "A3",
      "provider_id": "provider-win-store",
      "device_name": "Token USB / Smart Card (Windows CAPI/CNG)",
      "valid_from": "2025-01-10T10:00:00Z",
      "valid_to": "2028-01-10T10:00:00Z",
      "serial_number": "72910482910482019482",
      "cpf": "12345678900",
      "cnpj": null,
      "can_sign": true,
      "status": "AVAILABLE"
    }
  ]
}

3.4 POST /ccsp/v1/sign

Solicita a assinatura digital local do digest informado com o certificado escolhido.

Payload da Requisição

{
  "version": "1",
  "request_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
  "application_id": "550e8400-e29b-41d4-a716-446655440000",
  "operation": "sign",
  "algorithm": "SHA256withRSA",
  "digest": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
  "certificate_hint": "win-4340656a",
  "document_name": "contrato_prestacao_servicos.pdf",
  "document_type": "PDF",
  "document_size": 1474560,
  "origin": "https://meusistema.empresa.com.br",
  "nonce": "c4ca4238a0b923820dcc509a6f75849b",
  "expires_at": "2026-10-11T20:50:00Z"
}

Garantia WYSIWYS (What You See Is What You Sign): O agente CyberCore Signer apresenta ao usuário, antes de qualquer operação criptográfica:

  • Aplicação Solicitante e Origem Web: Exibe a URL de origem da página web chamadora para prevenir ataques de personificação (Spoofing).
  • Nome e Tamanho do Documento: Se informados via document_name e document_size (em bytes), são apresentados de forma legível (ex: 1.4 MB).
  • Hash do Documento (SHA-256 Digest): Formatado em blocos legíveis de 4 caracteres (ex: A1B2 C3D4 ...) em tipografia monoespaçada para fácil conferência humana.
  • Certificado e Dispositivo: Exibe titular, CPF/CNPJ, tipo A1/A3 e algoritmo de assinatura.

Resposta de Sucesso (200 OK)

{
  "version": "1",
  "request_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
  "status": "signed",
  "signature": "MEUCIQDq95kZc...Base64...",
  "certificate": "MIIFazCCBF...Base64...",
  "certificate_chain": [
    "MIIFazCCBF...Base64...",
    "MIIEazCCA1...Base64..."
  ],
  "algorithm": "SHA256withRSA",
  "subject_name": "MARIA DA SILVA",
  "subject_cpf_cnpj": "12345678900",
  "document_name": "contrato_prestacao_servicos.pdf",
  "document_type": "PDF"
}

3.5 POST /ccsp/v1/authenticate

Executa o login criptográfico de um usuário em sistemas web através do mecanismo de desafio e resposta (Challenge-Response).

Payload da Requisição

{
  "version": "1",
  "request_id": "8f3b201a-8c9d-4e5f-b012-3456789abcde",
  "application_id": "550e8400-e29b-41d4-a716-446655440000",
  "operation": "authenticate",
  "challenge": "session-nonce-random-server-token-998877",
  "certificate_hint": "win-4340656a",
  "purpose": "AUTHENTICATION",
  "nonce": "d3b07384d113edec49eaa6238ad5ff00",
  "expires_at": "2026-10-11T20:50:00Z"
}

Resposta de Sucesso (200 OK)

{
  "version": "1",
  "request_id": "8f3b201a-8c9d-4e5f-b012-3456789abcde",
  "status": "authenticated",
  "signature": "MEQCIF61pP...Base64...",
  "certificate": "MIIFazCCBF...Base64...",
  "certificate_chain": [
    "MIIFazCCBF...Base64...",
    "MIIEazCCA1...Base64..."
  ],
  "algorithm": "SHA256withRSA",
  "subject_name": "MARIA DA SILVA",
  "subject_cpf_cnpj": "12345678900"
}

3.6 GET /ccsp/v1/seals

Retorna a lista de temas e estilos de selos visuais embutidos e instalados no CyberCore Signer.

Cabeçalhos

  • Origin: https://meusistema.empresa.com.br
  • X-CyberCore-AppId: 550e8400-e29b-41d4-a716-446655440000

Resposta de Sucesso (200 OK)

{
  "version": "1",
  "status": "success",
  "default_seal_id": "icp-brasil",
  "seals": [
    {
      "id": "icp-brasil",
      "name": "ICP-Brasil Institucional",
      "description": "Estilo oficial corporativo com escudo de segurança vetorial e dados completos do titular",
      "primary_color": "#0d47a1",
      "secondary_color": "#0284c7",
      "border_color": "#93c5fd",
      "background_color": "#ffffff",
      "text_color": "#0f172a",
      "icon_style": "shield",
      "width": 320,
      "height": 82,
      "default_cpf_mode": "FULL",
      "default_include_date_time": true
    },
    {
      "id": "gov-br",
      "name": "Governamental (Padrão Gov.br / ITI)",
      "description": "Faixa verde e ouro com declaração expressa de validade pela MP nº 2.200-2/2001",
      "primary_color": "#047857",
      "secondary_color": "#eab308"
    }
  ]
}

3.7 POST /ccsp/v1/sign-pdf

Recebe um documento PDF em Base64, a página e as coordenadas desejadas (x, y, scale), aplica o selo visual e a assinatura digital PAdES (ISO 32000-1 / RFC 5652) e retorna o PDF assinado completo em Base64.

Payload da Requisição

{
  "version": "1",
  "request_id": "b1b74288-7264-44a5-9271-bf10d32c5f11",
  "application_id": "550e8400-e29b-41d4-a716-446655440000",
  "operation": "sign-pdf",
  "certificate_hint": "cert-1",
  "pdf": "JVBERi0xLjQKJ...Base64...",
  "page": 1,
  "x": 60.0,
  "y": 60.0,
  "scale": 1.0,
  "visible_seal": true,
  "seal_theme_id": "icp-brasil",
  "reason": "Aprovado e assinado digitalmente",
  "location": "Curitiba, PR",
  "nonce": "c301d011-8012-4261-bcfa-e7912ab5a420"
}

Selo Customizado Inline (seal_custom): Em vez de seal_theme_id, a requisição pode fornecer um objeto seal_custom com cores hexadecimais, título customizado, ícone vetorial (shield, certificate, lock) e política de privacidade LGPD (FULL, MASKED, HIDDEN).

Resposta de Sucesso (200 OK)

{
  "version": "1",
  "request_id": "b1b74288-7264-44a5-9271-bf10d32c5f11",
  "status": "signed",
  "signed_pdf": "JVBERi0xLjQKJ...PDF_ASSINADO_BASE64...",
  "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "certificate": "MIIFazCCBF...Base64...",
  "algorithm": "SHA256withRSA"
}

3.8 POST /ccsp/v1/sign-xml

Executa a assinatura digital de documentos XML em conformidade com o padrão XMLDSig W3C ou XAdES-BES ICP-Brasil (Padrão NF-e / NFC-e / CT-e / NFS-e). O documento assinado completo é devolvido diretamente ao sistema web.

Payload da Requisição

{
  "version": "1",
  "request_id": "e44d32e1-455b-4357-9351-41c10d3b6f22",
  "application_id": "550e8400-e29b-41d4-a716-446655440000",
  "operation": "sign-xml",
  "certificate_hint": "cert-1",
  "xml": "<nfeProc versao=\"4.00\" xmlns=\"http://www.portalfiscal.inf.br/nfe\">...</nfeProc>",
  "profile": "XADES_BES",
  "target_element_tag": "infNFe",
  "target_element_id": "NFe35261012345678000199550010000001001234567890",
  "nonce": "d80b0322-8012-4261-bcfa-e7912ab5a420"
}

Resposta de Sucesso (200 OK)

{
  "version": "1",
  "request_id": "e44d32e1-455b-4357-9351-41c10d3b6f22",
  "status": "signed",
  "signed_xml": "<nfeProc versao=\"4.00\" ...><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">...</Signature></nfeProc>",
  "certificate": "MIIFazCCBF...Base64...",
  "algorithm": "SHA256withRSA"
}

4. Estrutura Padrão de Erro e Códigos HTTP

Quando qualquer operação falha, o servidor local CCSP/1 responde com um objeto JSON padronizado e o código de status HTTP correspondente:

{
  "version": "1",
  "request_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
  "status": "error",
  "error_code": "PIN_INCORRECT",
  "message": "O PIN informado para o token A3 é inválido."
}

Mapeamento de Status HTTP

Código HTTP Erro Típico Descrição
400 Bad Request USER_CANCELLED, PIN_INCORRECT, SIGNATURE_FAILED Requisição malformada, cancelamento pelo usuário ou falha de PIN
401 Unauthorized APPLICATION_NOT_AUTHORIZED Aplicação não autorizada ou sem cabeçalho X-CyberCore-AppId
403 Forbidden INVALID_ORIGIN Cabeçalho Origin não confere com o domínio cadastrado
404 Not Found CERTIFICATE_NOT_FOUND, TOKEN_NOT_FOUND Certificado ou dispositivo físico ausente
409 Conflict REPLAY_DETECTED Nonce já utilizado anteriormente na janela de validação
422 Unprocessable REQUEST_EXPIRED, CERTIFICATE_EXPIRED Parâmetros sintaticamente válidos mas expirados temporalmente
500 Server Error PKCS11_ERROR, PROVIDER_NOT_AVAILABLE Falha interna no middleware do fabricante ou driver criptográfico
503 Service Unavail TOKEN_REMOVED, COMMUNICATION_ERROR Hardware desconectado ou serviço em recuperação

5. Diagrama de Sequência Completo

sequenceDiagram
    autonumber
    actor User as Usuário
    participant Browser as Aplicação Web (Browser)
    participant SDK as @cybercore/signer-sdk
    participant CCSP as CyberCore CcspServer (127.0.0.1)
    participant UI as CyberCore Desktop UI
    participant HW as Hardware Token / Windows MY

    Browser->>SDK: signer.sign({ digest, certId })
    SDK->>CCSP: POST /ccsp/v1/sign (Headers, AppId, Nonce, Digest)
    CCSP->>CCSP: Valida Origin, AppId e Nonce (anti-replay)
    CCSP->>UI: Solicita confirmação visual (requestSignatureConfirmation)
    UI->>User: Exibe Diálogo Nativo (Aplicação, Documento, Certificado)
    User->>UI: Clica em "Assinar"
    opt Certificado A3 exige PIN
        UI->>User: Solicita PIN do Hardware
        User->>UI: Digita PIN
    end
    UI-->>CCSP: Confirmação concedida
    CCSP->>HW: signLock.lock() -> JCA/JCE Signature.sign()
    HW-->>CCSP: Bytes da assinatura + Cadeia X.509
    CCSP->>CCSP: signLock.unlock()
    CCSP-->>SDK: 200 OK (signature Base64, cert, subject)
    SDK-->>Browser: Retorna resultado para a página web