Files
cybercore-signer/docs/CCSP.md
T

434 lines
18 KiB
Markdown

# 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
```http
GET /ccsp/v1/status HTTP/1.1
Host: 127.0.0.1:21325
Origin: https://meusistema.empresa.com.br
```
#### Resposta de Sucesso (`200 OK`)
```json
{
"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
```json
{
"version": "1",
"application_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Portal Jurídico e Tributário"
}
```
#### Resposta de Sucesso (`200 OK`)
```json
{
"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`)
```json
{
"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`)
```json
{
"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
```json
{
"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`)
```json
{
"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
```json
{
"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`)
```json
{
"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`)
```json
{
"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
```json
{
"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`)
```json
{
"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
```json
{
"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`)
```json
{
"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:
```json
{
"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."
}
```
### Lista Completa de Códigos de Erro Estruturados
Todos os códigos de erro são estáveis, estruturados e interoperáveis entre o backend Java e o SDK JavaScript:
| Código de Erro (`error_code`) | Descrição e Causa Raiz | Mapeamento no SDK |
|---|---|---|
| `CERTIFICATE_NOT_FOUND` | Certificado não encontrado pelo ID ou hint especificado | `CertificateNotFoundError` |
| `CERTIFICATE_EXPIRED` | Certificado ultrapassou a data limite de validade (`notAfter`) | `CertificateExpiredError` |
| `CERTIFICATE_INVALID` | Certificado corrompido, revogado ou com estrutura X.509 inválida | `CertificateInvalidError` |
| `PRIVATE_KEY_NOT_AVAILABLE` | Chave privada inacessível, protegida por hardware desconectado ou ausente | `PrivateKeyNotAvailableError` |
| `TOKEN_NOT_FOUND` | Nenhum token USB, smart card ou leitora física detectada | `TokenNotFoundError` |
| `TOKEN_REMOVED` | O dispositivo físico foi desconectado durante a operação | `TokenNotFoundError` |
| `PIN_REQUIRED` | O hardware criptográfico A3 exige digitação de PIN para desbloqueio | `PinRequiredError` |
| `PIN_INCORRECT` | O PIN digitado pelo usuário foi rejeitado pelo token (risco de bloqueio de PUK) | `PinIncorrectError` |
| `PKCS11_ERROR` | Falha interna no driver, middleware PKCS#11 ou DLL do fabricante | `CyberCoreError` |
| `SIGNATURE_FAILED` | Erro matemático na cifra assimétrica ou payload malformado | `SignatureFailedError` |
| `APPLICATION_NOT_AUTHORIZED` | A aplicação web solicitante não possui autorização concedida pelo usuário | `ApplicationNotAuthorizedError` |
| `REQUEST_EXPIRED` | O timestamp `expires_at` da requisição foi ultrapassado (timeout) | `RequestExpiredError` |
| `REPLAY_DETECTED` | O identificador `nonce` já foi processado anteriormente (ataque de replay) | `ReplayDetectedError` |
| `INVALID_ORIGIN` | O cabeçalho `Origin` não confere com os domínios homologados para o AppId | `InvalidOriginError` |
| `INVALID_HOST` | O cabeçalho `Host` foi adulterado (tentativa de DNS Rebinding) | `CyberCoreError` |
| `UNSUPPORTED_ALGORITHM` | Algoritmo criptográfico solicitado não é suportado pelo provider | `UnsupportedAlgorithmError` |
| `USER_CANCELLED` | O usuário clicou explicitamente em 'Cancelar' no diálogo nativo do sistema | `UserCancelledError` |
| `PROVIDER_NOT_AVAILABLE` | Provedor criptográfico nativo indisponível na plataforma atual | `ProviderNotAvailableError` |
| `COMMUNICATION_ERROR` | Falha na camada de transporte HTTP local do loopback | `CyberCoreError` |
| `AGENT_NOT_RUNNING` | O agente desktop não está rodando em 127.0.0.1:21325 (lado SDK) | `AgentNotRunningError` |
---
## 5. Especificação JSON Schema e Versionamento
O contrato canônico e exaustivo de todos os endpoints e payloads do protocolo CCSP/1 está formalizado no arquivo:
- [docs/ccsp-v1.schema.json](file:///var/www/cybercore/cybercore-signer/docs/ccsp-v1.schema.json)
### Política de Versionamento e Retrocompatibilidade
1. **Identificador de Versão Maior (`version: "1"`):**
- O campo `version` em todos os requests e responses identifica a versão maior do protocolo. O agente desktop garante compatibilidade retroativa com todas as revisões do CCSP/1.
2. **Evolução Aditiva (Não Quebrante):**
- Novos campos opcionais de requisição e novos metadados informativos de resposta podem ser adicionados dentro da versão CCSP/1 sem quebrar clientes existentes. Clientes e servidores devem ignorar propriedades adicionais desconhecidas (`additionalProperties` tolerantes).
3. **Mudança Quebrante (Nova Versão Maior):**
- Qualquer alteração na semântica de autenticação, remoção de campos obrigatórios ou mudança estrutural de URLs exigirá a introdução de uma nova versão de protocolo (ex: CCSP/2 com prefixo `/ccsp/v2/`). O agente manterá os endpoints `/ccsp/v1/` operacionais em paralelo para garantir transição suave.
---
## 6. Diagrama de Sequência Completo
```mermaid
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
```