Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36178df130 | ||
|
|
be281d1d04 | ||
|
|
ed69db4d59 | ||
|
|
cfea07a179 | ||
|
|
9f1bc289ee | ||
|
|
e20a52d3b2 | ||
|
|
3d3ec9d47c | ||
|
|
0abbbf5abd | ||
|
|
9598172174 | ||
|
|
68943221c3 | ||
|
|
d27c0f9567 | ||
|
|
0658f7007e | ||
|
|
14b342c3a2 | ||
|
|
4010a9bba5 | ||
|
|
caaa1de8a0 | ||
|
|
6ba1a6a77f | ||
|
|
66f3172bfb | ||
|
|
cf63aa6d22 | ||
|
|
5d8c5d487d | ||
|
|
b13129b7d8 | ||
|
|
975885753a | ||
|
|
2c1d4f359e | ||
|
|
8d0e587114 | ||
|
|
b19d09a236 | ||
|
|
50b5feced5 | ||
|
|
9dcbac61ec | ||
|
|
957f9c9abd | ||
|
|
e9f90b42cb | ||
|
|
92d4ea3411 | ||
|
|
49021d9942 | ||
|
|
67e47cbed5 | ||
|
|
b00f78505d | ||
|
|
a32ab3b7ce | ||
|
|
e3d56d90af | ||
|
|
051614a919 | ||
|
|
bac691aae1 | ||
|
|
71428cdaad | ||
|
|
cf7ac8c51c | ||
|
|
002823ede3 | ||
|
|
90e2c8ef3d | ||
|
|
4b6ae923c6 | ||
|
|
4b64a113b5 | ||
|
|
06c90b4e86 | ||
|
|
300944697f | ||
|
|
7aa33a4789 | ||
|
|
a562909bc5 | ||
|
|
66459bfae4 | ||
|
|
1a727e6ff5 | ||
|
|
eeeecb0604 | ||
|
|
4e6dd2a029 | ||
|
|
cd3ef646d2 | ||
|
|
fa93e31ca1 | ||
|
|
6093879aa9 | ||
|
|
cebeca467f | ||
|
|
e50257fb34 | ||
|
|
6dce9f9317 | ||
|
|
539d5e4c33 | ||
|
|
5551d9e667 | ||
|
|
ef44d34944 | ||
|
|
edccfff7ff | ||
|
|
16212702cb | ||
|
|
6f191c6a69 | ||
|
|
d1cfab95c2 | ||
|
|
64ca13b3a1 | ||
|
|
f4adc99a01 | ||
|
|
5f4a212786 | ||
|
|
2a50704a7f | ||
|
|
994a27886e | ||
|
|
b46d8b665f | ||
|
|
d8d2e6ee46 | ||
|
|
176acf6f40 |
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
name: "Relato de Bug"
|
||||||
|
about: "Relate um problema ou comportamento inesperado no CyberCore Signer"
|
||||||
|
title: "[BUG] "
|
||||||
|
labels:
|
||||||
|
- "bug"
|
||||||
|
---
|
||||||
|
|
||||||
|
### Descrição do Problema
|
||||||
|
Uma descrição clara e concisa do comportamento inesperado ocorrido.
|
||||||
|
|
||||||
|
### Passos para Reproduzir
|
||||||
|
1. Iniciar o CyberCore Signer com o comando `...`
|
||||||
|
2. Acessar a aplicação web ou endpoint `...`
|
||||||
|
3. Tentar executar a operação de assinatura `...`
|
||||||
|
4. Observar o erro reportado.
|
||||||
|
|
||||||
|
### Comportamento Esperado
|
||||||
|
O que você esperava que acontecesse normalmente.
|
||||||
|
|
||||||
|
### Logs e Mensagens de Diagnóstico
|
||||||
|
```text
|
||||||
|
Cole aqui o trecho relevante de log do agente (sem expor dados sensíveis ou chaves).
|
||||||
|
```
|
||||||
|
|
||||||
|
### Informações do Ambiente
|
||||||
|
* **Sistema Operacional:** Windows 10 / Windows 11 / Ubuntu / Outro (especifique)
|
||||||
|
* **Versão do Java:** 25 LTS (especifique a vendor: Temurin, Corretto, Oracle)
|
||||||
|
* **Tipo de Certificado Utilizado:** A1 (arquivo `.pfx`) / A3 (Token USB / Smart Card / Windows-MY)
|
||||||
|
* **Fabricante do Hardware A3 (se aplicável):** SafeSign / SafeNet / GD Burti / Outro
|
||||||
|
* **Navegador e Versão (se aplicável ao SDK):** Chrome / Edge / Firefox
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
name: "Solicitação de Funcionalidade"
|
||||||
|
about: "Sugira uma nova funcionalidade ou melhoria para o agente ou SDK"
|
||||||
|
title: "[FEAT] "
|
||||||
|
labels:
|
||||||
|
- "enhancement"
|
||||||
|
---
|
||||||
|
|
||||||
|
### Problema ou Necessidade
|
||||||
|
Descreva o cenário de uso ou o desafio que motivou esta solicitação.
|
||||||
|
|
||||||
|
### Solução Proposta
|
||||||
|
Uma descrição clara do recurso ou melhoria que você gostaria de ver implementado no CyberCore Signer.
|
||||||
|
|
||||||
|
### Módulos Afetados
|
||||||
|
* [ ] `modules/cybercore-core` (regras criptográficas, provedores, protocolo CCSP)
|
||||||
|
* [ ] `modules/cybercore-ui` (telas JavaFX, diálogos, selo visual, system tray)
|
||||||
|
* [ ] `modules/cybercore-app` (ponto de entrada, empacotamento nativo)
|
||||||
|
* [ ] `sdk/` (SDK Web JavaScript)
|
||||||
|
* [ ] `docs/` (especificações e manuais)
|
||||||
|
|
||||||
|
### Alternativas Consideradas
|
||||||
|
Descreva quaisquer alternativas ou soluções de contorno que você considerou.
|
||||||
|
|
||||||
|
### Contexto Adicional
|
||||||
|
Adicione qualquer imagem, rascunho de tela ou especificação relevante.
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
### Descrição das Alterações
|
||||||
|
Resuma de forma clara o objetivo deste Pull Request e as alterações realizadas.
|
||||||
|
|
||||||
|
### Tipo de Mudança
|
||||||
|
* [ ] Correção de bug (`fix`)
|
||||||
|
* [ ] Nova funcionalidade (`feat`)
|
||||||
|
* [ ] Refatoração sem alteração de comportamento (`refactor`)
|
||||||
|
* [ ] Atualização de documentação (`docs`)
|
||||||
|
* [ ] Ajuste de testes ou métricas de cobertura (`test`)
|
||||||
|
* [ ] Manutenção de infraestrutura ou CI (`ci` / `chore`)
|
||||||
|
|
||||||
|
### Checklist de Qualidade e Segurança
|
||||||
|
* [ ] O código segue o padrão e regras de arquitetura do projeto.
|
||||||
|
* [ ] Nenhuma credencial, PIN, senha ou chave privada real foi comitada.
|
||||||
|
* [ ] A validação `./mvnw clean verify` foi executada e passou com 100% de sucesso.
|
||||||
|
* [ ] A cobertura mínima do JaCoCo foi respeitada em todos os módulos afetados.
|
||||||
|
* [ ] As mensagens de commit seguem a convenção *Conventional Commits*.
|
||||||
|
* [ ] A documentação técnica foi atualizada (quando aplicável).
|
||||||
|
|
||||||
|
### Issue Relacionada
|
||||||
|
Fecha #
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
name: CI Pipeline
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- 'feature/**'
|
||||||
|
- 'fix/**'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-linux:
|
||||||
|
name: Build & Verify (Linux x86_64)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repositório
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Configurar Java 25 LTS (Temurin)
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '25'
|
||||||
|
cache: 'maven'
|
||||||
|
|
||||||
|
- name: Conceder permissão de execução ao Maven Wrapper
|
||||||
|
run: chmod +x ./mvnw
|
||||||
|
|
||||||
|
- name: Instalar SoftHSM2 para testes de hardware PKCS#11
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y softhsm2
|
||||||
|
sudo mkdir -p /var/lib/softhsm/tokens
|
||||||
|
sudo chmod 777 /var/lib/softhsm/tokens
|
||||||
|
|
||||||
|
- name: Executar verificação Maven (Compilação, Testes, JaCoCo, SpotBugs, ArchUnit)
|
||||||
|
run: ./mvnw -B clean verify
|
||||||
|
|
||||||
|
- name: Publicar Relatórios de Cobertura JaCoCo
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: jacoco-reports-linux
|
||||||
|
path: |
|
||||||
|
modules/*/target/site/jacoco/**
|
||||||
|
modules/*/target/jacoco.exec
|
||||||
|
retention-days: 14
|
||||||
|
|
||||||
|
- name: Publicar Relatórios de Análise Estática SpotBugs
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: spotbugs-reports-linux
|
||||||
|
path: |
|
||||||
|
modules/*/target/spotbugsXml.xml
|
||||||
|
modules/*/target/site/spotbugs/**
|
||||||
|
retention-days: 14
|
||||||
|
|
||||||
|
- name: Publicar CycloneDX SBOM (Software Bill of Materials)
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: cyclonedx-sbom
|
||||||
|
path: |
|
||||||
|
target/bom.json
|
||||||
|
target/bom.xml
|
||||||
|
retention-days: 30
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
name: Build & Verify (Windows)
|
||||||
|
# Runner Windows: requer act_runner nativo em Windows na instância Gitea.
|
||||||
|
# Caso sua instância utilize apenas Docker Linux, configure labels: [windows] no host correspondente.
|
||||||
|
runs-on: windows-latest
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- name: Checkout repositório
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Configurar Java 25 LTS (Temurin)
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '25'
|
||||||
|
cache: 'maven'
|
||||||
|
|
||||||
|
- name: Executar verificação Maven no Windows
|
||||||
|
run: .\mvnw.cmd -B clean verify
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Publicar Relatórios JaCoCo (Windows)
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: jacoco-reports-windows
|
||||||
|
path: |
|
||||||
|
modules/*/target/site/jacoco/**
|
||||||
|
retention-days: 14
|
||||||
|
|
||||||
|
- name: Publicar Relatórios SpotBugs (Windows)
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: spotbugs-reports-windows
|
||||||
|
path: |
|
||||||
|
modules/*/target/spotbugsXml.xml
|
||||||
|
retention-days: 14
|
||||||
@@ -77,4 +77,8 @@ $RECYCLE.BIN/
|
|||||||
*~
|
*~
|
||||||
|
|
||||||
# Arquivos temporários de Scratch locais
|
# Arquivos temporários de Scratch locais
|
||||||
scratch/temp/
|
scratch/
|
||||||
|
|
||||||
|
# Agentes e caches locais
|
||||||
|
.agents/**/cache/
|
||||||
|
.agents/**/temp/
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
Todas as mudanças relevantes deste projeto serão documentadas neste arquivo.
|
||||||
|
|
||||||
|
O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/),
|
||||||
|
e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR/).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [Não publicado]
|
||||||
|
|
||||||
|
### Adicionado
|
||||||
|
- Pipeline de integração contínua (CI) via Gitea Actions para Linux e Windows.
|
||||||
|
- Verificação de cobertura mínima de testes via meta `jacoco:check` calibrada por módulo.
|
||||||
|
- Configuração de atualização automatizada de dependências via Renovate com agrupamento específico.
|
||||||
|
- Templates de issues e pull requests para Gitea em `.gitea/`.
|
||||||
|
- Guia de contribuição `CONTRIBUTING.md` e especificação de release em `docs/release-and-versioning.md`.
|
||||||
|
|
||||||
|
### Modificado
|
||||||
|
- Alinhamento da documentação e scripts de automação para exigir estritamente o JDK 25 LTS.
|
||||||
|
- Refinamento do `.gitignore` para ignorar a pasta `scratch/` e mover script utilitário para `scripts/`.
|
||||||
|
- Atualização do filtro de exclusão do SpotBugs com justificativas técnicas detalhadas para garantir verificação completa e limpa.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [0.1.0] - 2026-10-08
|
||||||
|
|
||||||
|
### Adicionado
|
||||||
|
- **Núcleo Criptográfico (`cybercore-core`):**
|
||||||
|
- Gerenciador central de certificados digitais (`CertificateManager`).
|
||||||
|
- Provedor para certificados em arquivo A1 PKCS#12 (`.pfx` / `.p12`).
|
||||||
|
- Provedor para repositório do Windows (`Windows-MY` via SunMSCAPI / CNG).
|
||||||
|
- Provedor para dispositivos criptográficos A3 PKCS#11 (tokens USB e smartcards).
|
||||||
|
- Assinatura digital padrão PAdES (PDF) em conformidade com as normas ICP-Brasil (Apache PDFBox e Bouncy Castle).
|
||||||
|
- Assinatura digital padrão XAdES-BES / XMLDSig para notas e documentos fiscais eletrônicos.
|
||||||
|
- Suporte a carimbo de tempo TSA e validação de longo prazo (LTV).
|
||||||
|
- Servidor HTTP local CCSP/1 (`127.0.0.1:21325`) com bind exclusivo em loopback, proteção anti-replay via nonce e controle de concorrência por fila.
|
||||||
|
- **Interface Gráfica Nativa (`cybercore-ui`):**
|
||||||
|
- Aplicação moderna em JavaFX 25 com suporte a tema Claro e Escuro (Dual-Theme).
|
||||||
|
- Dashboard de status do agente e leitor de certificados em tempo real.
|
||||||
|
- Diálogos de autorização prévia de aplicações web e confirmação visual de assinaturas.
|
||||||
|
- Designer e visualizador de selos visuais em PDF com renderização SVG e Java2D.
|
||||||
|
- Integração com a bandeja do sistema operacional (System Tray).
|
||||||
|
- **Módulo Executável (`cybercore-app`):**
|
||||||
|
- Ponto de entrada consolidado (`CyberCoreSignerApplication`), rotinas de telemetria diagnóstica e testes de arquitetura com ArchUnit.
|
||||||
|
- Empacotamento de Fat JAR autocontido via Maven Shade Plugin.
|
||||||
|
- **SDK JavaScript (`@cybercore/signer-sdk`):**
|
||||||
|
- Cliente web com métodos `connect()`, `isInstalled()`, `getCertificates()`, `sign()`, `verify()`.
|
||||||
|
- Página de demonstração interativa para testes de integração web.
|
||||||
|
- **Documentação Técnica:**
|
||||||
|
- Especificação do protocolo CCSP/1 (`docs/CCSP.md`).
|
||||||
|
- Diretrizes de segurança, arquitetura, diagnóstico e manuais de instalação.
|
||||||
|
|
||||||
|
### Segurança
|
||||||
|
- Isolamento estrito de chaves privadas e senhas na máquina do usuário local (nunca trafegadas pela rede nem registradas em logs).
|
||||||
|
- Destruição segura de senhas em memória após uso via `Arrays.fill(..., '\0')`.
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# Guia de Contribuição — CyberCore Signer
|
||||||
|
|
||||||
|
Agradecemos o interesse em contribuir com o **CyberCore Signer**! Para garantir a segurança criptográfica, a estabilidade e a manutenibilidade do projeto, siga as orientações descritas abaixo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Pré-requisitos do Ambiente
|
||||||
|
|
||||||
|
* **Java Development Kit (JDK):** Versão 25 LTS (Eclipse Temurin, OpenJDK ou Amazon Corretto).
|
||||||
|
* **Maven Wrapper:** Utilize sempre o executável `./mvnw` (Linux/macOS) ou `mvnw.cmd` (Windows) embutido no projeto.
|
||||||
|
* **Git:** Com suporte a quebra de linha `LF`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Princípios de Segurança Invioláveis
|
||||||
|
|
||||||
|
Como este é um software de assinatura digital e custódia de credenciais criptográficas:
|
||||||
|
|
||||||
|
1. **Nunca exponha credenciais:** É estritamente proibido registrar, logar ou comitar PINs, senhas de arquivos A1, chaves privadas ou certificados de produção.
|
||||||
|
2. **Testes isolados:** Use fixtures mockadas ou certificados autoassinados temporários gerados dinamicamente nos testes.
|
||||||
|
3. **Loopback estrito:** O servidor CCSP escuta exclusivamente em `127.0.0.1:21325`. Nunca altere o bind para interfaces externas.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Padrão de Commits
|
||||||
|
|
||||||
|
Adotamos a especificação [Conventional Commits](https://www.conventionalcommits.org/pt-br/v1.0.0/). Cada commit deve representar uma alteração coesa e atômica:
|
||||||
|
|
||||||
|
* `feat:` Nova funcionalidade no agente, SDK ou UI.
|
||||||
|
* `fix:` Correção de bug sem alteração de escopo.
|
||||||
|
* `docs:` Alterações exclusivas na documentação.
|
||||||
|
* `test:` Adição ou melhoria de suítes de testes.
|
||||||
|
* `refactor:` Alterações de código que não mudam o comportamento funcional.
|
||||||
|
* `chore:` Tarefas de manutenção de build, scripts ou dependências.
|
||||||
|
* `ci:` Alterações no pipeline de CI/CD.
|
||||||
|
|
||||||
|
Exemplo: `feat(core): add support for custom pkcs11 pin retry limit`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Validação Pré-Commit / Pré-PR
|
||||||
|
|
||||||
|
Antes de submeter um Pull Request, certifique-se de que o build completo e todas as análises de qualidade passam localmente:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Executa compilação, testes, checagem JaCoCo, SpotBugs e ArchUnit:
|
||||||
|
./mvnw clean verify
|
||||||
|
```
|
||||||
|
|
||||||
|
Critérios obrigatórios:
|
||||||
|
* Todos os testes unitários e de integração devem passar com sucesso.
|
||||||
|
* A cobertura mínima definida no `jacoco:check` de cada módulo deve ser mantida ou superada.
|
||||||
|
* Nenhum novo apontamento de segurança ou erro do SpotBugs deve ser introduzido.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Fluxo de Pull Requests
|
||||||
|
|
||||||
|
1. Crie uma branch descritiva a partir de `main` (ex: `feature/suporte-token-safenet` ou `fix/pades-timestamp-timeout`).
|
||||||
|
2. Mantenha os commits organizados e pequenos.
|
||||||
|
3. Abra o Pull Request preenchendo o template oficial do repositório em `.gitea/pull_request_template.md`.
|
||||||
|
4. Garanta que o pipeline de CI do Gitea Actions finalize com status verde.
|
||||||
@@ -1,100 +1,136 @@
|
|||||||
# CyberCore Signer
|
# CyberCore Signer
|
||||||
|
|
||||||
> **Agente Desktop de Assinatura Digital e Autenticação Criptográfica (A1 / A3 / PKCS#11) para Windows e Linux.**
|
> **Agente Desktop Nativo de Assinatura Digital e Autenticação Criptográfica (A1 / A3 / PKCS#11) para Windows e Linux.**
|
||||||
|
|
||||||
O **CyberCore Signer** é uma solução desktop em Java 21 LTS com JavaFX que permite que aplicações web autorizadas solicitem assinaturas digitais, autenticação de sessão e carimbos do tempo utilizando certificados digitais ICP-Brasil (A1 em arquivo e A3 em tokens/smartcards físicos) instalados ou conectados na estação de trabalho do usuário.
|
[](https://openjdk.org/)
|
||||||
|
[](https://openjfx.io/)
|
||||||
|
[](docs/CCSP.md)
|
||||||
|
[](https://www.gov.br/iti/pt-br)
|
||||||
|
[](#licença)
|
||||||
|
|
||||||
A comunicação local entre a página web e o agente utiliza o protocolo **CCSP (CyberCore Signing Protocol)** via HTTP/WebSocket localhost autenticado e seguro.
|
O **CyberCore Signer** é uma solução desktop desenvolvida em Java 25 LTS com interface gráfica moderna JavaFX e segurança criptográfica estrita JCA/JCE. Permite que aplicações web autorizadas solicitem assinaturas digitais, autenticação de sessão e validação de documentos utilizando certificados digitais padrão ICP-Brasil (A1 em arquivo e A3 em tokens/smartcards físicos) conectados ou instalados na máquina do usuário.
|
||||||
|
|
||||||
|
A comunicação local entre a página web e o agente utiliza o protocolo **CCSP (CyberCore Signing Protocol)** via HTTP localhost (`127.0.0.1:21325`), garantindo isolamento total de rede, consentimento visual explícito e preservação integral das chaves privadas na máquina local.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚡ Quick Start
|
||||||
|
|
||||||
|
### 🌐 Para Aplicações Web (via SDK JavaScript)
|
||||||
|
|
||||||
|
Instale e utilize o SDK oficial `@cybercore/signer-sdk` para conectar sua aplicação web ao agente local em poucos passos:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { CyberCoreSigner } from '@cybercore/signer-sdk';
|
||||||
|
|
||||||
|
// 1. Inicializar o cliente do assinador
|
||||||
|
const signer = new CyberCoreSigner({
|
||||||
|
applicationName: 'Portal Meu Negócio'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Obter certificados disponíveis na máquina do usuário
|
||||||
|
const certificates = await signer.getCertificates();
|
||||||
|
const cert = certificates[0]; // Seleciona o primeiro certificado disponível
|
||||||
|
|
||||||
|
// 3. Assinar o hash SHA-256 de um documento (a chave nunca sai da máquina!)
|
||||||
|
const result = await signer.sign({
|
||||||
|
certificateId: cert.id,
|
||||||
|
digest: '47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=',
|
||||||
|
documentName: 'contrato_prestacao_servicos.pdf'
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('Assinatura gerada:', result.signature);
|
||||||
|
console.log('Certificado titular:', result.subject_name);
|
||||||
|
```
|
||||||
|
|
||||||
|
> Para o manual completo com exemplos de login digital, assinatura de PDF e XML, consulte o [Guia do SDK](docs/sdk.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ☕ Para Desenvolvedores Desktop
|
||||||
|
|
||||||
|
#### Requisitos
|
||||||
|
* **Java Development Kit (JDK):** Versão 25 LTS (OpenJDK, Temurin ou Corretto).
|
||||||
|
* **Maven:** 3.9+ (ou utilizar o `./mvnw` embutido).
|
||||||
|
* **Sistema Operacional:** Windows 10/11 ou Linux x86_64.
|
||||||
|
|
||||||
|
#### Compilação e Execução
|
||||||
|
```bash
|
||||||
|
# Compilar e gerar o JAR consolidado (Fat JAR sombreado):
|
||||||
|
./mvnw clean package -DskipTests
|
||||||
|
|
||||||
|
# Executar o agente no Linux / macOS:
|
||||||
|
./run.sh
|
||||||
|
|
||||||
|
# Executar o agente no Windows:
|
||||||
|
run.bat
|
||||||
|
|
||||||
|
# Executar com logs detalhados de diagnóstico:
|
||||||
|
java -jar modules/cybercore-app/target/cybercore-signer.jar --dev
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🏛 Arquitetura do Projeto
|
## 🏛 Arquitetura do Projeto
|
||||||
|
|
||||||
O projeto é estruturado em módulos Maven:
|
O projeto é estruturado em módulos Maven desacoplados, garantindo isolamento entre regras criptográficas de baixo nível e a camada de interface gráfica:
|
||||||
|
|
||||||
* **[modules/cybercore-core](modules/cybercore-core)**: Núcleo de regras criptográficas (JCA/JCE, SunPKCS11, X.509, PAdES, XMLDSig, carimbo de tempo TSA, LTV e validação de cadeias). Não possui dependência de interface gráfica.
|
* **[`modules/cybercore-core`](modules/cybercore-core):** Núcleo de regras criptográficas (JCA/JCE, SunPKCS11, X.509, PAdES com Apache PDFBox e Bouncy Castle, XAdES-BES/XMLDSig, carimbo de tempo TSA, LTV, fila FIFO de concorrência e validação de cadeias). **Agnóstico de UI**, sem nenhuma dependência de JavaFX.
|
||||||
* **[modules/cybercore-ui](modules/cybercore-ui)**: Interface gráfica com o usuário construída em JavaFX (Dashboard, Gerenciador de Certificados, Diagnóstico Criptográfico, Diálogo de Confirmação de Assinatura, PIN dialog e System Tray).
|
* **[`modules/cybercore-ui`](modules/cybercore-ui):** Interface gráfica com o usuário construída em JavaFX 25, apresentando design moderno com alternância dinâmica Claro/Escuro (Dual-Theme), Dashboard, Gerenciador de Certificados, Designer de Selos Visuais SVG com Live Preview, Diálogos de Confirmação de Assinatura, PIN dialog e System Tray.
|
||||||
* **[modules/cybercore-app](modules/cybercore-app)**: Ponto de entrada da aplicação (`CyberCoreApp`), orquestrador dos serviços de ciclo de vida e servidor CCSP local.
|
* **[`modules/cybercore-app`](modules/cybercore-app):** Ponto de entrada da aplicação (`CyberCoreApp`), orquestrador dos serviços de ciclo de vida, diagnóstico pré-inicialização e servidor CCSP local.
|
||||||
* **[sdk/](sdk)**: SDK JavaScript oficial (`@cybercore/signer-sdk`) para integração de aplicações web com o agente desktop.
|
* **[`sdk/`](sdk):** SDK JavaScript oficial (`@cybercore/signer-sdk`) para integração simplificada de aplicações web modernas com o agente desktop.
|
||||||
* **[docs/](docs)**: Documentação técnica detalhada de arquitetura, protocolo, segurança e casos de uso.
|
* **[`docs/`](docs):** Documentação técnica abrangente contendo especificações do protocolo, arquitetura, segurança e manuais de integração.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Requisitos
|
## 📊 Matriz de Recursos e Conformidade
|
||||||
|
|
||||||
* **Java Development Kit (JDK):** Versão 21+ LTS (OpenJDK, Temurin, Corretto, etc.).
|
| Recurso | Padrão / Tecnologia | Descrição |
|
||||||
* **Maven:** 3.9+ (ou utilizar o wrapper `./mvnw` incluído no projeto).
|
|---|---|---|
|
||||||
* **Sistema Operacional Alvo:** Windows 10/11 ou Linux (x86_64).
|
| **Certificados A1** | PKCS#12 / `.pfx` / `.p12` | Leitura em memória volátil com destruição segura de senhas |
|
||||||
|
| **Certificados A3** | Windows-MY (CryptoAPI/CNG) & PKCS#11 | Acesso nativo a tokens USB e smartcards (SafeSign, SafeNet, GD Burti, OpenSC) |
|
||||||
|
| **Assinatura PDF** | PAdES (ISO 32000-1 / ETSI TS 102 778) | Envelope CMS/PKCS#7, suporte a salvamento incremental e carimbo TSA |
|
||||||
|
| **Selos Visuais PDF** | Renderização Java2D de Alta Resolução (300 DPI) | Brasões vetoriais, upload de logos, controle de sigilo de CPF (LGPD) e pré-visualização interativa |
|
||||||
|
| **Assinatura XML** | XAdES-BES (ETSI TS 101 903 / DOC-ICP-15.03) | Suporte completo a NF-e, CT-e, MDF-e, eSocial e documentos envelopados |
|
||||||
|
| **Assinatura Genérica** | CMS / CAdES / P7S / P7M | Modalidades atachada (enveloped) e destacada (detached) |
|
||||||
|
| **Login Digital** | Challenge-Response ICP-Brasil | Autenticação web segura sem senhas tradicionais |
|
||||||
|
| **Validação** | Verificação Criptográfica Local | Auditoria de integridade de hashes, validade de certificados e signatários |
|
||||||
|
| **Interface Desktop** | JavaFX 25 com Dual-Theme | Modo Claro e Modo Escuro com comutação instantânea e atalhos na bandeja |
|
||||||
|
| **Protocolo Local** | CCSP/1 REST (`127.0.0.1:21325`) | Bind estrito em loopback, proteção anti-replay via nonce e autorização de origens |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠 Compilação e Empacotamento
|
## 🔒 Princípios Fundamentais de Segurança
|
||||||
|
|
||||||
### 1. Compilação do JAR Executável
|
1. **A Chave Privada Permanece na Estação de Trabalho:** A chave privada e os segredos (PIN do token A3 ou senha do arquivo A1) nunca saem da máquina do usuário nem trafegam pela rede ou saem em logs.
|
||||||
|
2. **Assinatura por Digest Descentralizada:** Por padrão, a aplicação web calcula o hash SHA-256 do documento localmente e o CyberCore assina apenas o digest de 32 bytes, eliminando o tráfego desnecessário de arquivos inteiros.
|
||||||
Para compilar e gerar o JAR consolidado (com todas as dependências sombreadas e assets):
|
3. **Consentimento Visual Explícito:** Nenhuma operação de assinatura ocorre silenciosamente. Toda requisição exige autorização física do usuário em diálogo nativo do sistema operacional.
|
||||||
|
4. **Isolamento de Origem e Anti-Replay:** Cada requisição web deve apresentar identificador de aplicação aprovado, nonce único com validação temporal (`expires_at`) e cabeçalho de origem verificado.
|
||||||
```bash
|
5. **Fila FIFO de Operações:** O acesso a tokens físicos A3 é protegido por trava de concorrência (`signLock`) serializada, prevenindo travamento ou corrupção de sessão nos chips criptográficos.
|
||||||
./build-jar.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Ou diretamente via Maven:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./mvnw clean package -DskipTests
|
|
||||||
```
|
|
||||||
|
|
||||||
O artefato consolidado será gerado em:
|
|
||||||
`modules/cybercore-app/target/cybercore-signer.jar`
|
|
||||||
|
|
||||||
### 2. Execução Local
|
|
||||||
|
|
||||||
Para iniciar o agente em ambiente de desenvolvimento:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# No Linux / macOS:
|
|
||||||
./run.sh
|
|
||||||
|
|
||||||
# No Windows:
|
|
||||||
run.bat
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Empacotamento com Runtime Nativo (`jpackage`)
|
|
||||||
|
|
||||||
Para criar a distribuição com Java Runtime embutido (sem exigir JDK pré-instalado pelo usuário final):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./scripts/package-jpackage.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔒 Princípios de Segurança e Privacidade
|
## 📚 Documentação Técnica Detalhada
|
||||||
|
|
||||||
1. **Chave Privada Preservada:** A chave privada e os segredos (PIN de token A3 e senha de certificado A1) nunca saem da máquina do usuário nem trafegam pela rede.
|
Para detalhes completos sobre arquitetura, protocolos e manuais técnicos, acesse o [Portal de Documentação](docs/README.md) ou consulte diretamente os links abaixo:
|
||||||
2. **Assinatura por Digest:** Por padrão, a aplicação web calcula o hash/digest (ex: SHA-256) do documento e o CyberCore assina localmente apenas o digest, minimizando o tráfego de dados sensíveis.
|
|
||||||
3. **Confirmação Explícita:** Toda operação de assinatura exige consentimento e autorização visual do usuário antes da aplicação da chave.
|
* 🌐 **[Protocolo CCSP/1](docs/CCSP.md):** Contrato REST, endpoints, códigos de status e anti-replay.
|
||||||
4. **Isolamento de Origem e CCSP:** O agente atende apenas origens web autorizadas, protegendo contra abusos via CSRF ou requisições locais não autenticadas.
|
* 📦 **[SDK Web JavaScript](docs/sdk.md):** Guia de integração e métodos da biblioteca oficial.
|
||||||
|
* 🏛 **[Arquitetura do Sistema](docs/architecture.md):** Módulos, threading e fluxo sequencial.
|
||||||
|
* 💳 **[Certificados A1, A3 e PKCS#11](docs/a1-a3-certificates.md):** Suporte a hardware, drivers e OIDs ICP-Brasil.
|
||||||
|
* 📄 **[Assinaturas PDF e Selos SVG](docs/pades.md):** PAdES, renderização Java2D e selos visuais.
|
||||||
|
* 📑 **[Assinaturas XML (XAdES-BES)](docs/xml-xmldsig.md):** Padrão DOC-ICP-15.03 e notas fiscais.
|
||||||
|
* 🔑 **[Autenticação e Login Digital](docs/authentication-login.md):** Fluxo Challenge-Response via ICP-Brasil.
|
||||||
|
* ⚠️ **[Catálogo Estruturado de Erros](docs/errors.md):** Tabela de erros `CcspErrorCode` e códigos HTTP.
|
||||||
|
* 🛡️ **[Modelo de Segurança e Privacidade](docs/security.md):** Diretrizes de isolamento, memória e LGPD.
|
||||||
|
* 🩺 **[Diagnóstico e Troubleshooting](docs/diagnostics.md):** Auto-teste e guia de resolução de problemas.
|
||||||
|
* 💿 **[Instalação e Empacotamento Nativo](docs/installation.md):** Distribuição via `jpackage` sem JRE pré-instalado.
|
||||||
|
* ⚖️ **[Limitações Técnicas](docs/limitations.md):** Declaração de dependências conforme a Regra 23.
|
||||||
|
* 🎨 **[Layout e Assinatura em Lote](docs/ui-layout.md):** Design da UI padronizada e operações em lote.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📚 Documentação Técnica
|
## 📄 Licença e Propriedade
|
||||||
|
|
||||||
Consulte a pasta [docs/](docs) para especificações completas:
|
Copyright © 2026 **CyberCore Systems**. Todos os direitos reservados.
|
||||||
|
Este software é proprietário e confidencial. O uso, distribuição ou modificação não autorizados são estritamente proibidos.
|
||||||
* [Protocolo CCSP (CyberCore Signing Protocol)](docs/CCSP.md)
|
|
||||||
* [Arquitetura e Fluxo do Sistema](docs/architecture.md)
|
|
||||||
* [Certificados A1 e A3 (PKCS#11 / MSCAPI)](docs/a1-a3-certificates.md)
|
|
||||||
* [Assinatura de Documentos PDF (PAdES / LTV / TSA)](docs/pades.md)
|
|
||||||
* [Assinatura de Documentos XML (XMLDSig)](docs/xml-xmldsig.md)
|
|
||||||
* [Autenticação e Sessão Criptográfica](docs/authentication-login.md)
|
|
||||||
* [Diagnóstico e Resolução de Problemas](docs/diagnostics.md)
|
|
||||||
* [Segurança e Tratamento de Erros](docs/security.md)
|
|
||||||
* [SDK Web JavaScript](docs/sdk.md)
|
|
||||||
* [Guia de Instalação](docs/installation.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📄 Licença
|
|
||||||
|
|
||||||
Propriedade de **CyberCore Systems**. Todos os direitos reservados.
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Pasta de Ícones (SVG) e Imagens (PNG) — CyberCore Signer
|
# Recursos Visuais (Ícones e Imagens em SVG) — CyberCore Signer
|
||||||
|
|
||||||
Esta pasta é o repositório oficial onde você pode visualizar, customizar e substituir livremente os **ícones em SVG** e as **imagens em PNG** do **CyberCore Signer**.
|
Esta pasta é o repositório oficial onde você pode visualizar, customizar e substituir livremente todos os **ícones em SVG** e as **imagens em SVG** do **CyberCore Signer**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -25,19 +25,27 @@ assets/
|
|||||||
│ ├── tutorial.svg # Ícone Tutorial e Ajuda (monitor com vídeo/play)
|
│ ├── tutorial.svg # Ícone Tutorial e Ajuda (monitor com vídeo/play)
|
||||||
│ ├── cert.svg # Ícone Certificados Digitais (pasta com cadeado seguro)
|
│ ├── cert.svg # Ícone Certificados Digitais (pasta com cadeado seguro)
|
||||||
│ ├── about.svg # Ícone Sobre o Sistema (círculo azul com 'i')
|
│ ├── about.svg # Ícone Sobre o Sistema (círculo azul com 'i')
|
||||||
│ ├── sun.svg # Ícone Tema Claro (sol dourado com raios vetoriais)
|
|
||||||
│ ├── moon.svg # Ícone Tema Escuro (lua crescente azul/índigo)
|
|
||||||
│ ├── shield.svg # Ícone Brasão de Segurança (CyberShield com chave interna)
|
│ ├── shield.svg # Ícone Brasão de Segurança (CyberShield com chave interna)
|
||||||
│ ├── seal.svg # Ícone Designer e Gerenciador de Selos Notariais
|
│ ├── seal.svg # Ícone Designer e Gerenciador de Selos Notariais
|
||||||
│ ├── check.svg # Ícone Checkmark de sucesso e validação
|
│ ├── check.svg # Ícone Checkmark de sucesso e validação
|
||||||
│ ├── error.svg # Ícone de Erro / Alerta em vermelho
|
│ ├── error.svg # Ícone de Erro / Alerta em vermelho
|
||||||
│ └── star.svg # Ícone de Estrela notarial / favorita
|
│ ├── star.svg # Ícone de Estrela notarial / favorita
|
||||||
|
│ ├── close.svg # Ícone Fechar / Cancelar (cruz geométrica moderna)
|
||||||
|
│ ├── arrow-right.svg # Ícone Avançar / Seta direcional
|
||||||
|
│ ├── zoom-in.svg # Ícone Zoom In (+)
|
||||||
|
│ ├── zoom-out.svg # Ícone Zoom Out (-)
|
||||||
|
│ ├── zoom-fit.svg # Ícone Ajustar à Tela
|
||||||
|
│ └── refresh.svg # Ícone Atualizar / Recarregar listas e status
|
||||||
│
|
│
|
||||||
└── images/ # Imagens de alta fidelidade em PNG com canal alfa (transparência)
|
└── images/ # Imagens vetoriais SVG editáveis (com cópias PNG de fallback)
|
||||||
├── app-icon.png # Ícone oficial do app (256x256 px - Diamante 3D azul Serpro)
|
├── app-icon.svg # Ícone oficial do app em SVG (Cristal/Diamante 3D azul)
|
||||||
├── app-logo.png # Logotipo horizontal oficial (480x120 px - CyberCore SIGNER)
|
├── app-icon.png # Fallback em PNG (256x256 px)
|
||||||
├── brand-banner.png # Banner de cabeçalho e marca (600x160 px - Serpro Blue)
|
├── app-logo.svg # Logotipo horizontal oficial em SVG (CyberCore SIGNER)
|
||||||
└── default-seal.png # Selo de assinatura padrão ICP-Brasil (640x164 px)
|
├── app-logo.png # Fallback em PNG (480x120 px)
|
||||||
|
├── brand-banner.svg # Banner de cabeçalho e marca em SVG (600x160 px)
|
||||||
|
├── brand-banner.png # Fallback em PNG (600x160 px)
|
||||||
|
├── default-seal.svg # Selo de assinatura padrão ICP-Brasil em SVG (640x164 px)
|
||||||
|
└── default-seal.png # Fallback em PNG (640x164 px)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -45,20 +53,22 @@ assets/
|
|||||||
## 🎨 Como Customizar Qualquer Ícone ou Imagem
|
## 🎨 Como Customizar Qualquer Ícone ou Imagem
|
||||||
|
|
||||||
1. **Ícones:**
|
1. **Ícones:**
|
||||||
- Estão no formato `.svg` padrão.
|
- Todos estão no formato `.svg` padrão da W3C.
|
||||||
- Podem ser editados diretamente no seu editor de código (VS Code, etc.) ou em editores vetoriais como **Inkscape, Figma ou Illustrator**.
|
- Consulte o guia completo de especificações em [docs/svg-design-guide.md](../docs/svg-design-guide.md) para tokens de cores, dimensões e boas práticas ao exportar do **Inkscape/Figma**.
|
||||||
- Se preferir colocar uma imagem bitmap para um ícone específico, você também pode colocar um `.png` (ex: `pdf.png`). O sistema prioriza `.svg` e aceita `.png` com fallback transparente.
|
- Podem ser abertos e editados diretamente em editores de texto/código (VS Code) ou ferramentas vetoriais como **Inkscape, Figma, Adobe Illustrator**.
|
||||||
|
- Se preferir usar um arquivo bitmap para algum ícone específico, basta salvar um `.png` correspondente na pasta (ex: `pdf.png`). O sistema detecta e renderiza automaticamente.
|
||||||
|
|
||||||
2. **Imagens do Sistema:**
|
2. **Imagens do Sistema:**
|
||||||
- Estão no formato `.png` com canal alfa de 32 bits (fundo transparente).
|
- Tanto o logotipo horizontal (`app-logo.svg`), o ícone do sistema (`app-icon.svg`), o banner institucional (`brand-banner.svg`) e o selo notarial padrão (`default-seal.svg`) agora são arquivos **SVG vetoriais editáveis**.
|
||||||
- Você pode substituir `app-logo.png`, `app-icon.png`, `brand-banner.png` ou `default-seal.png` pelo logotipo e identidade visual da sua instituição ou empresa.
|
- Você pode alterar cores, tipografias, brasões e dimensões diretamente nos arquivos SVG.
|
||||||
|
- O `AssetManager` renderiza os arquivos SVG preservando fidelidade geométrica e suportando gradientes e alinhamentos.
|
||||||
|
|
||||||
3. **Ordem de Prioridade e Hot-Reloading:**
|
3. **Ordem de Resolução e Carregamento:**
|
||||||
Quando a aplicação busca um ícone ou imagem, a resolução ocorre na ordem:
|
Ao requisitar qualquer elemento gráfico, a aplicação segue a ordem de prioridade:
|
||||||
1. **Pasta Física Local (`./assets/icons/` e `./assets/images/`)**: Qualquer alteração feita aqui entra em vigor imediatamente ao abrir a janela ou reiniciar a aplicação, sem necessidade de recompilar!
|
1. **Pasta Física Local (`./assets/icons/` e `./assets/images/`)**: Arquivos `.svg` editados aqui têm prioridade máxima e entram em vigor imediatamente sem necessidade de recompilar.
|
||||||
2. **Pasta do Usuário (`~/.cybercore/assets/`)**: Configurações específicas por usuário do sistema operacional.
|
2. **Pasta do Usuário (`~/.cybercore/assets/`)**: Para customizações no diretório pessoal do usuário.
|
||||||
3. **Resources Empacotados no JAR (`/assets/`)**: Cópia empacotada internamente no `.jar`.
|
3. **Recursos Empacotados no JAR (`/assets/`)**: SVGs e imagens internas empacotadas no pacote de distribuição.
|
||||||
4. **Fallback Vetorial Nativo (`SvgIcons`)**: Garantia de que a interface nunca fique em branco caso algum arquivo seja excluído.
|
4. **Fallback Vetorial Nativo (`SvgIcons`)**: Garantia de que a interface nunca fique desprovida de grafismos caso algum arquivo seja removido.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16"><title>info-circle-fill</title><path fill="currentColor" d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.93-9.412l-1 4.705c-.07.34.029.533.304.533c.194 0 .487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598c-.703 0-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081l.082-.381l2.29-.287zM8 5.5a1 1 0 1 1 0-2a1 1 0 0 1 0 2"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
|
<circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
|
<circle cx="12" cy="7.5" r="1.2" fill="currentColor"/>
|
||||||
|
<line x1="12" y1="11" x2="12" y2="16.5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 429 B After Width: | Height: | Size: 338 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
|
<path d="M 9 5 L 16 12 L 9 19" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 224 B |
@@ -1,12 +1,4 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Folha de documento com dobra -->
|
<path d="M 16.5 6.5 L 9.5 13.5 C 8.1 14.9 8.1 17.1 9.5 18.5 C 10.9 19.9 13.1 19.9 14.5 18.5 L 20 13 C 22.2 10.8 22.2 7.2 20 5 C 17.8 2.8 14.2 2.8 12 5 L 6.5 10.5 C 3.7 13.3 3.7 17.7 6.5 20.5 C 9.3 23.3 13.7 23.3 16.5 20.5 L 20 17"
|
||||||
<path d="M 10 4 L 34 4 L 42 12 L 42 44 L 10 44 Z" fill="#ffffff" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
|
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M 34 4 L 34 12 L 42 12 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2"/>
|
|
||||||
<!-- Linhas de texto representativas -->
|
|
||||||
<line x1="16" y1="20" x2="36" y2="20" stroke="#90caf9" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<line x1="16" y1="26" x2="36" y2="26" stroke="#90caf9" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<line x1="16" y1="32" x2="30" y2="32" stroke="#90caf9" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<!-- Clipe de papel metálico prendendo a folha -->
|
|
||||||
<path d="M 12 2 C 8 2 6 5 6 9 L 6 25 C 6 29 9 32 14 32 C 18 32 21 29 21 25 L 21 11 C 21 8 19 6 16 6 C 13 6 12 8 12 11 L 12 24"
|
|
||||||
fill="none" stroke="#455a64" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 976 B After Width: | Height: | Size: 433 B |
@@ -1,13 +1,6 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Folha traseira (3) -->
|
<path d="M 3.5 7.5 H 16.5 V 20.5 H 3.5 Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<path d="M 16 4 L 38 4 L 44 10 L 44 32 L 16 32 Z" fill="#e1f5fe" stroke="#4fc3f7" stroke-width="2" stroke-linejoin="round"/>
|
<path d="M 7.5 4.5 H 20.5 V 17.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<!-- Folha do meio (2) -->
|
<line x1="7" y1="11.5" x2="13" y2="11.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
<path d="M 10 10 L 32 10 L 38 16 L 38 38 L 10 38 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2" stroke-linejoin="round"/>
|
<line x1="7" y1="15.5" x2="11" y2="15.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
<!-- Folha frontal (1) -->
|
|
||||||
<path d="M 4 16 L 26 16 L 32 22 L 32 44 L 4 44 Z" fill="#ffffff" stroke="#01579b" stroke-width="2.2" stroke-linejoin="round"/>
|
|
||||||
<!-- Dobra folha frontal -->
|
|
||||||
<path d="M 26 16 L 26 22 L 32 22 Z" fill="#e1f5fe" stroke="#01579b" stroke-width="1.8"/>
|
|
||||||
<!-- Checkmark de execução/lote concluído -->
|
|
||||||
<circle cx="34" cy="34" r="10" fill="#00c853"/>
|
|
||||||
<path d="M 29 34 L 33 38 L 39 30" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 920 B After Width: | Height: | Size: 543 B |
@@ -1,11 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Pasta de arquivos de certificados -->
|
<rect x="3.5" y="2.5" width="17" height="19" rx="2.5" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
<path d="M 4 10 L 16 10 L 20 14 L 44 14 L 44 40 L 4 40 Z" fill="#e1f5fe" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
|
<line x1="7" y1="6.5" x2="13" y2="6.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
<!-- Aba superior da pasta -->
|
<line x1="7" y1="9.5" x2="11" y2="9.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" opacity="0.6"/>
|
||||||
<path d="M 4 18 L 44 18" stroke="#0288d1" stroke-width="2"/>
|
<circle cx="14.5" cy="14.5" r="3.5" fill="none" stroke="#0288d1" stroke-width="1.8"/>
|
||||||
<!-- Cadeado de segurança dourado/azul -->
|
<path d="M 13 14.5 L 14.2 15.7 L 16.5 13.2" fill="none" stroke="#0288d1" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<rect x="26" y="24" width="14" height="12" rx="3" fill="#0288d1"/>
|
|
||||||
<!-- Arco do cadeado -->
|
|
||||||
<path d="M 29 24 L 29 20 C 29 17 31 15 33 15 C 35 15 37 17 37 20 L 37 24" fill="none" stroke="#01579b" stroke-width="2.5"/>
|
|
||||||
<circle cx="33" cy="30" r="1.8" fill="#ffffff"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 688 B After Width: | Height: | Size: 659 B |
@@ -1,4 +1,4 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<circle cx="24" cy="24" r="20" fill="#10b981"/>
|
<circle cx="12" cy="12" r="9" fill="#10b981"/>
|
||||||
<path d="M 14 24 L 21 31 L 34 17" fill="none" stroke="#ffffff" stroke-width="4.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M 8 12 L 11 15 L 16 9" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 274 B After Width: | Height: | Size: 269 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
|
<path d="M 6 6 L 18 18 M 18 6 L 6 18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 231 B |
@@ -1,12 +1,6 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Folha secundária -->
|
<path d="M 13 3.5 H 5 C 4.4 3.5 4 3.9 4 4.5 V 20.5 C 4 21.1 4.4 21.5 5 21.5 H 17 C 17.6 21.5 18 21.1 18 20.5 V 13"
|
||||||
<path d="M 6 10 L 26 10 L 32 16 L 32 40 L 6 40 Z" fill="#ffffff" stroke="#1976d2" stroke-width="2.2" stroke-linejoin="round"/>
|
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<!-- Folha primária -->
|
<path d="M 12 18 C 14 18 16 17 18 15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
<path d="M 16 4 L 36 4 L 42 10 L 42 34 L 16 34 Z" fill="#e3f2fd" stroke="#0288d1" stroke-width="2.2" stroke-linejoin="round"/>
|
<path d="M 18.5 3.5 L 21 6 L 14 13 L 11.5 13.5 L 12 11 Z" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linejoin="round"/>
|
||||||
<path d="M 36 4 L 36 10 L 42 10 Z" fill="#bbdefb" stroke="#0288d1" stroke-width="1.8"/>
|
|
||||||
<!-- Ícone de dois usuários / parceiros de assinatura -->
|
|
||||||
<circle cx="16" cy="24" r="4" fill="#0d47a1"/>
|
|
||||||
<path d="M 10 36 C 10 31 13 30 16 30 C 19 30 22 31 22 36 Z" fill="#0d47a1"/>
|
|
||||||
<circle cx="26" cy="22" r="3.5" fill="#0288d1"/>
|
|
||||||
<path d="M 21 34 C 21 30 24 29 26 29 C 29 29 32 30 32 34 Z" fill="#0288d1"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 815 B After Width: | Height: | Size: 546 B |
@@ -1,5 +1,5 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<circle cx="24" cy="24" r="20" fill="#ef4444"/>
|
<circle cx="12" cy="12" r="9" fill="#ef4444"/>
|
||||||
<line x1="16" y1="16" x2="32" y2="32" stroke="#ffffff" stroke-width="4.5" stroke-linecap="round"/>
|
<line x1="8.5" y1="8.5" x2="15.5" y2="15.5" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/>
|
||||||
<line x1="32" y1="16" x2="16" y2="32" stroke="#ffffff" stroke-width="4.5" stroke-linecap="round"/>
|
<line x1="15.5" y1="8.5" x2="8.5" y2="15.5" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 343 B After Width: | Height: | Size: 350 B |
@@ -1,8 +1,6 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Porta de saída / batente -->
|
<path d="M 10 3.5 H 5.5 C 4.4 3.5 3.5 4.4 3.5 5.5 V 18.5 C 3.5 19.6 4.4 20.5 5.5 20.5 H 10"
|
||||||
<path d="M 24 8 L 12 8 C 9.8 8 8 9.8 8 12 L 8 36 C 8 38.2 9.8 40 12 40 L 24 40"
|
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
fill="none" stroke="#546e7a" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
<line x1="8.5" y1="12" x2="20.5" y2="12" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/>
|
||||||
<!-- Seta vermelha apontando para fora -->
|
<polyline points="16.5 8, 20.5 12, 16.5 16" fill="none" stroke="#ef4444" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<line x1="18" y1="24" x2="40" y2="24" stroke="#d32f2f" stroke-width="3.2" stroke-linecap="round"/>
|
|
||||||
<polyline points="32 16, 40 24, 32 32" fill="none" stroke="#d32f2f" stroke-width="3.2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 598 B After Width: | Height: | Size: 537 B |
@@ -1,13 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Folha de documento com dobra -->
|
<path d="M 5 3.5 H 14 L 19 8.5 V 20.5 C 19 21.1 18.5 21.5 17.9 21.5 H 5 C 4.4 21.5 4 21.1 4 20.5 V 4.5 C 4 3.9 4.4 3.5 5 3.5 Z"
|
||||||
<path d="M 8 4 L 32 4 L 42 14 L 42 44 L 8 44 Z" fill="#ffffff" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
|
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<!-- Dobra de canto -->
|
<path d="M 14 3.5 V 8.5 H 19" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<path d="M 32 4 L 32 14 L 42 14 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2" stroke-linejoin="round"/>
|
<line x1="8" y1="13" x2="15" y2="13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
<!-- Linhas de texto representativas -->
|
<line x1="8" y1="17" x2="13" y2="17" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
<line x1="14" y1="20" x2="34" y2="20" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<line x1="14" y1="26" x2="34" y2="26" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<!-- Caneta / Pena de assinatura eletrônica -->
|
|
||||||
<path d="M 16 38 L 30 24 L 35 29 L 21 43 L 14 44 Z" fill="#0288d1"/>
|
|
||||||
<path d="M 30 24 L 34 20 L 39 25 L 35 29 Z" fill="#01579b"/>
|
|
||||||
<circle cx="16" cy="42" r="1.5" fill="#ffffff"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 873 B After Width: | Height: | Size: 626 B |
@@ -1,13 +1,6 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Janela de terminal / console -->
|
<rect x="2.5" y="3.5" width="19" height="17" rx="3" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
<rect x="4" y="6" width="40" height="36" rx="6" fill="#1e293b" stroke="#334155" stroke-width="2"/>
|
<path d="M 6.5 8.5 L 9.5 11 L 6.5 13.5" fill="none" stroke="#0288d1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<!-- Barra de título do terminal com botões -->
|
<line x1="11.5" y1="13.5" x2="16.5" y2="13.5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
<circle cx="10" cy="12" r="2" fill="#ef4444"/>
|
<line x1="6.5" y1="16.5" x2="14" y2="16.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" opacity="0.6"/>
|
||||||
<circle cx="16" cy="12" r="2" fill="#f59e0b"/>
|
|
||||||
<circle cx="22" cy="12" r="2" fill="#10b981"/>
|
|
||||||
<!-- Linha divisória -->
|
|
||||||
<line x1="4" y1="18" x2="44" y2="18" stroke="#334155" stroke-width="1.5"/>
|
|
||||||
<!-- Texto e prompt de código </> -->
|
|
||||||
<path d="M 12 24 L 18 29 L 12 34" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<line x1="22" y1="34" x2="32" y2="34" stroke="#94a3b8" stroke-width="2.5" stroke-linecap="round"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 811 B After Width: | Height: | Size: 572 B |
@@ -1,11 +1,6 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Folha de documento com dobra -->
|
<path d="M 5 3.5 H 14 L 19 8.5 V 20.5 C 19 21.1 18.5 21.5 17.9 21.5 H 5 C 4.4 21.5 4 21.1 4 20.5 V 4.5 C 4 3.9 4.4 3.5 5 3.5 Z"
|
||||||
<path d="M 8 4 L 30 4 L 38 12 L 38 34 L 8 34 Z" fill="#ffffff" stroke="#00838f" stroke-width="2.5" stroke-linejoin="round"/>
|
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<path d="M 30 4 L 30 12 L 38 12 Z" fill="#b2dfdb" stroke="#00838f" stroke-width="2"/>
|
<circle cx="14" cy="15" r="4.5" fill="none" stroke="#0288d1" stroke-width="1.8"/>
|
||||||
<!-- Linhas no documento -->
|
<polyline points="14 12.5, 14 15, 16 15" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
<line x1="14" y1="18" x2="30" y2="18" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<line x1="14" y1="24" x2="24" y2="24" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<!-- Selo LTV com fita de proteção permanente -->
|
|
||||||
<circle cx="32" cy="32" r="12" fill="#e0f2f1" stroke="#00897b" stroke-width="2.5"/>
|
|
||||||
<text x="32" y="36.5" font-family="Segoe UI, Arial, sans-serif" font-size="9" font-weight="bold" fill="#00695c" text-anchor="middle">LTV</text>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 861 B After Width: | Height: | Size: 507 B |
@@ -1,6 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
|
||||||
<!-- Lua crescente ciano/índigo -->
|
|
||||||
<path d="M 40 26.5 A 18 18 0 1 1 21.5 8 A 14 14 0 0 0 40 26.5 Z" fill="#38bdf8"/>
|
|
||||||
<circle cx="36" cy="12" r="1.5" fill="#818cf8"/>
|
|
||||||
<circle cx="42" cy="18" r="1" fill="#818cf8"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 314 B |
@@ -1,13 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Folha de documento com dobra -->
|
<path d="M 5 3.5 H 14 L 19 8.5 V 20.5 C 19 21.1 18.5 21.5 17.9 21.5 H 5 C 4.4 21.5 4 21.1 4 20.5 V 4.5 C 4 3.9 4.4 3.5 5 3.5 Z"
|
||||||
<path d="M 8 4 L 32 4 L 42 14 L 42 44 L 8 44 Z" fill="#ffffff" stroke="#d32f2f" stroke-width="2.5" stroke-linejoin="round"/>
|
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<!-- Dobra de canto -->
|
<path d="M 14 3.5 V 8.5 H 19" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<path d="M 32 4 L 32 14 L 42 14 Z" fill="#ffcdd2" stroke="#d32f2f" stroke-width="2" stroke-linejoin="round"/>
|
<rect x="7" y="12" width="10" height="6" rx="1.5" fill="#ef4444"/>
|
||||||
<!-- Linhas de texto representativas -->
|
<path d="M 9 14 H 10.5 C 11 14 11.5 14.3 11.5 14.8 C 11.5 15.3 11 15.6 10.5 15.6 H 9 V 17 M 9 15.6 H 10.5" stroke="#ffffff" stroke-width="1" stroke-linecap="round" fill="none"/>
|
||||||
<line x1="14" y1="20" x2="28" y2="20" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<line x1="14" y1="25" x2="36" y2="25" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<line x1="14" y1="30" x2="36" y2="30" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<!-- Etiqueta vermelha com sigla PDF -->
|
|
||||||
<rect x="12" y="33" width="24" height="11" rx="3" fill="#e53935"/>
|
|
||||||
<text x="24" y="41.5" font-family="Segoe UI, Arial, sans-serif" font-size="8.5" font-weight="bold" fill="#ffffff" text-anchor="middle">PDF</text>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 996 B After Width: | Height: | Size: 665 B |
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
|
<path d="M 19 4 L 19 9 L 14 9" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M 5 20 L 5 15 L 10 15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M 6.3 8.7 A 8 8 0 0 1 18.5 7.5 L 19 9 M 5 15 L 5.5 16.5 A 8 8 0 0 0 17.7 15.3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 524 B |
@@ -0,0 +1,7 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
|
<path d="M 12 2.5 L 4.5 5.5 V 11 C 4.5 16 8 20 12 21.5 C 16 20 19.5 16 19.5 11 V 5.5 Z"
|
||||||
|
fill="none" stroke="#0288d1" stroke-width="2" stroke-linejoin="round"/>
|
||||||
|
<rect x="8.5" y="11" width="7" height="5.5" rx="1.2" fill="#0288d1"/>
|
||||||
|
<path d="M 10 11 V 8.5 C 10 7.4 10.9 6.5 12 6.5 C 13.1 6.5 14 7.4 14 8.5 V 11" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
|
<circle cx="12" cy="13.5" r="0.8" fill="#ffffff"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 541 B |
@@ -1,11 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Fita pendente do selo -->
|
<rect x="2.5" y="4.5" width="19" height="15" rx="3" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
<polygon points="18,30 24,44 30,30" fill="#f59e0b"/>
|
<path d="M 6 13.5 C 7.5 10 9 10 10.5 13 C 11.5 15 13 11 15 12" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<polygon points="12,30 16,42 20,30" fill="#d97706"/>
|
<circle cx="17.5" cy="8.5" r="1.5" fill="#f59e0b"/>
|
||||||
<polygon points="28,30 32,42 36,30" fill="#d97706"/>
|
<line x1="6" y1="8.5" x2="13" y2="8.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" opacity="0.5"/>
|
||||||
<!-- Medalha / Selo circular -->
|
<line x1="6" y1="16" x2="18" y2="16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" opacity="0.4"/>
|
||||||
<circle cx="24" cy="20" r="16" fill="#d97706" stroke="#fbbf24" stroke-width="2.5"/>
|
|
||||||
<circle cx="24" cy="20" r="13" fill="none" stroke="#fbbf24" stroke-width="1.2" stroke-dasharray="2,2"/>
|
|
||||||
<!-- Estrela de 5 pontas central -->
|
|
||||||
<polygon points="24,9 26.5,16.5 34,16.5 28,21 30.5,28.5 24,24 17.5,28.5 20,21 14,16.5 21.5,16.5" fill="#ffffff"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 671 B After Width: | Height: | Size: 654 B |
@@ -1,8 +1,5 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Engrenagem simétrica de 8 dentes centrada em (24, 24) -->
|
<circle cx="12" cy="12" r="3" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
<path d="M 21 4 L 27 4 L 28 10 C 30 10.8 31.8 11.8 33.4 13.2 L 39 10 L 43 14 L 39.8 19.6 C 41.2 21.2 42.2 23 43 25 L 49 26 L 49 32 L 43 33 C 42.2 35 41.2 36.8 39.8 38.4 L 43 44 L 39 48 L 33.4 44.8 C 31.8 46.2 30 47.2 28 48 L 27 54 L 21 54 L 20 48 C 18 47.2 16.2 46.2 14.6 44.8 L 9 48 L 5 44 L 8.2 38.4 C 6.8 36.8 5.8 35 5 33 L -1 32 L -1 26 L 5 25 C 5.8 23 6.8 21.2 8.2 19.6 L 5 14 L 9 10 L 14.6 13.2 C 16.2 11.8 18 10.8 20 10 Z" transform="scale(0.8) translate(6, 4)" fill="#0288d1"/>
|
<path d="M 10.7 2.5 L 13.3 2.5 L 13.7 4.8 C 14.4 5.1 15.1 5.5 15.8 6.1 L 17.9 5.2 L 19.8 7.1 L 18.9 9.2 C 19.4 9.9 19.8 10.6 20.1 11.3 L 22.5 11.7 L 22.5 14.3 L 20.1 14.7 C 19.8 15.4 19.4 16.1 18.9 16.8 L 19.8 18.9 L 17.9 20.8 L 15.8 19.9 C 15.1 20.5 14.4 20.9 13.7 21.2 L 13.3 23.5 L 10.7 23.5 L 10.3 21.2 C 9.6 20.9 8.9 20.5 8.2 19.9 L 6.1 20.8 L 4.2 18.9 L 5.1 16.8 C 4.6 16.1 4.2 15.4 3.9 14.7 L 1.5 14.3 L 1.5 11.7 L 3.9 11.3 C 4.2 10.6 4.6 9.9 5.1 9.2 L 4.2 7.1 L 6.1 5.2 L 8.2 6.1 C 8.9 5.5 9.6 5.1 10.3 4.8 Z"
|
||||||
<!-- Círculo externo da engrenagem -->
|
fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
|
||||||
<circle cx="24" cy="24" r="14" fill="#0288d1"/>
|
|
||||||
<!-- Furo central vazado -->
|
|
||||||
<circle cx="24" cy="24" r="6" fill="#ffffff"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 817 B After Width: | Height: | Size: 784 B |
@@ -1,6 +1,5 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Escudo CyberShield -->
|
<path d="M 12 2.5 L 4 5.5 V 11.5 C 4 16.5 7.5 21 12 22.5 C 16.5 21 20 16.5 20 11.5 V 5.5 Z"
|
||||||
<path d="M 24 4 L 8 11 L 8 24 C 8 34.5 15 42.5 24 45 C 33 42.5 40 34.5 40 24 L 40 11 Z" fill="#0284c7" stroke="#38bdf8" stroke-width="2.5" stroke-linejoin="round"/>
|
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<!-- Chave de segurança criptográfica no centro -->
|
<path d="M 8.5 11.5 L 11 14 L 15.5 9.5" fill="none" stroke="#0288d1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M 24 14 C 20.7 14 18 16.7 18 20 C 18 22.4 19.5 24.5 22 25.4 L 22 34 L 26 34 L 26 30 L 28 30 L 28 27 L 26 27 L 26 25.4 C 28.5 24.5 30 22.4 30 20 C 30 16.7 27.3 14 24 14 Z M 24 18 C 25.1 18 26 18.9 26 20 C 26 21.1 25.1 22 24 22 C 22.9 22 22 21.1 22 20 C 22 18.9 22.9 18 24 18 Z" fill="#ffffff"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 649 B After Width: | Height: | Size: 408 B |
@@ -1,4 +1,4 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<polygon points="24,4 29.5,16.5 43,17.5 32.5,26.5 35.8,40 24,32.5 12.2,40 15.5,26.5 5,17.5 18.5,16.5"
|
<polygon points="12,2.5 14.8,8.2 21.1,9.1 16.5,13.6 17.6,19.9 12,16.9 6.4,19.9 7.5,13.6 2.9,9.1 9.2,8.2"
|
||||||
fill="#f59e0b" stroke="#d97706" stroke-width="2" stroke-linejoin="round"/>
|
fill="#f59e0b" stroke="#d97706" stroke-width="1.2" stroke-linejoin="round"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 287 B |
@@ -1,15 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
|
||||||
<!-- Núcleo solar brilhante -->
|
|
||||||
<circle cx="24" cy="24" r="10" fill="#f59e0b"/>
|
|
||||||
<!-- Raios solares -->
|
|
||||||
<g stroke="#f59e0b" stroke-width="3" stroke-linecap="round">
|
|
||||||
<line x1="24" y1="4" x2="24" y2="9"/>
|
|
||||||
<line x1="24" y1="39" x2="24" y2="44"/>
|
|
||||||
<line x1="4" y1="24" x2="9" y2="24"/>
|
|
||||||
<line x1="39" y1="24" x2="44" y2="24"/>
|
|
||||||
<line x1="9.8" y1="9.8" x2="13.3" y2="13.3"/>
|
|
||||||
<line x1="34.7" y1="34.7" x2="38.2" y2="38.2"/>
|
|
||||||
<line x1="9.8" y1="38.2" x2="13.3" y2="34.7"/>
|
|
||||||
<line x1="34.7" y1="13.3" x2="38.2" y2="9.8"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 647 B |
@@ -1,13 +1,5 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Folha de documento com dobra -->
|
<circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
<path d="M 8 4 L 30 4 L 38 12 L 38 34 L 8 34 Z" fill="#ffffff" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
|
<polyline points="12 7, 12 12, 16 14" fill="none" stroke="#0288d1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M 30 4 L 30 12 L 38 12 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2"/>
|
<line x1="12" y1="1" x2="12" y2="3" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
<!-- Linhas no documento -->
|
|
||||||
<line x1="14" y1="18" x2="30" y2="18" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<line x1="14" y1="24" x2="24" y2="24" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<!-- Relógio de precisão temporal TSA -->
|
|
||||||
<circle cx="32" cy="32" r="12" fill="#e1f5fe" stroke="#0288d1" stroke-width="2.5"/>
|
|
||||||
<circle cx="32" cy="32" r="2" fill="#01579b"/>
|
|
||||||
<line x1="32" y1="24" x2="32" y2="32" stroke="#01579b" stroke-width="2.5" stroke-linecap="round"/>
|
|
||||||
<line x1="32" y1="32" x2="38" y2="32" stroke="#01579b" stroke-width="2.5" stroke-linecap="round"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 958 B After Width: | Height: | Size: 413 B |
@@ -1,8 +1,5 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Monitor de computador -->
|
<path d="M 3 6.5 C 3 5 4.5 4 6 4 C 8.5 4 11 5.5 12 7 C 13 5.5 15.5 4 18 4 C 19.5 4 21 5 21 6.5 V 18 C 21 19 19.5 19.5 18 19.5 C 15.5 19.5 13 18 12 17 C 11 18 8.5 19.5 6 19.5 C 4.5 19.5 3 19 3 18 Z"
|
||||||
<rect x="4" y="6" width="40" height="28" rx="4" fill="#ffffff" stroke="#0288d1" stroke-width="2.5"/>
|
fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
|
||||||
<!-- Base do monitor -->
|
<line x1="12" y1="7" x2="12" y2="17" stroke="currentColor" stroke-width="1.8"/>
|
||||||
<path d="M 16 34 L 12 42 L 36 42 L 32 34" fill="none" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
|
|
||||||
<!-- Ícone de play/vídeo tutorial central -->
|
|
||||||
<polygon points="20,14 32,20 20,26" fill="#0288d1"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 477 B After Width: | Height: | Size: 461 B |
@@ -1,10 +1,6 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Círculo de relógio base -->
|
<circle cx="10" cy="10" r="7.5" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
<circle cx="24" cy="24" r="20" fill="#f1f8e9" stroke="#558b2f" stroke-width="2.5"/>
|
<polyline points="10 6, 10 10, 13 11" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
<!-- Ponteiros do relógio -->
|
<circle cx="16.5" cy="16.5" r="5" fill="none" stroke="#10b981" stroke-width="2"/>
|
||||||
<line x1="24" y1="12" x2="24" y2="24" stroke="#33691e" stroke-width="2" stroke-linecap="round"/>
|
<polyline points="14.8 16.5, 16 17.7, 18.5 15.2" fill="none" stroke="#10b981" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<line x1="24" y1="24" x2="32" y2="24" stroke="#33691e" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<!-- Checkmark verde de validação de tempo -->
|
|
||||||
<circle cx="34" cy="34" r="10" fill="#2e7d32"/>
|
|
||||||
<path d="M 29 34 L 33 38 L 39 30" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 679 B After Width: | Height: | Size: 528 B |
@@ -1,11 +1,6 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Folha de documento com dobra -->
|
<path d="M 5 3.5 H 13 L 18 8.5 V 13" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<path d="M 8 4 L 32 4 L 42 14 L 42 44 L 8 44 Z" fill="#ffffff" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
|
<path d="M 5 3.5 V 20.5 H 10" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<path d="M 32 4 L 32 14 L 42 14 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2"/>
|
<circle cx="15.5" cy="16.5" r="5" fill="none" stroke="#10b981" stroke-width="2"/>
|
||||||
<!-- Linhas no documento -->
|
<polyline points="13.8 16.5, 15 17.7, 17.5 15.2" fill="none" stroke="#10b981" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<line x1="14" y1="20" x2="34" y2="20" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<line x1="14" y1="26" x2="28" y2="26" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<!-- Emblema de validação com Checkmark verde -->
|
|
||||||
<circle cx="30" cy="34" r="11" fill="#e8f5e9" stroke="#2e7d32" stroke-width="2.5"/>
|
|
||||||
<path d="M 24 34 L 28 38 L 36 29" fill="none" stroke="#2e7d32" stroke-width="3.2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 848 B After Width: | Height: | Size: 548 B |
@@ -1,13 +1,8 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
<!-- Folha de documento com dobra -->
|
<path d="M 5 3.5 H 14 L 19 8.5 V 20.5 C 19 21.1 18.5 21.5 17.9 21.5 H 5 C 4.4 21.5 4 21.1 4 20.5 V 4.5 C 4 3.9 4.4 3.5 5 3.5 Z"
|
||||||
<path d="M 8 4 L 32 4 L 42 14 L 42 44 L 8 44 Z" fill="#ffffff" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
|
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<!-- Dobra de canto -->
|
<path d="M 14 3.5 V 8.5 H 19" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||||
<path d="M 32 4 L 32 14 L 42 14 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2" stroke-linejoin="round"/>
|
<path d="M 8.5 13 L 6.5 15 L 8.5 17" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<!-- Linhas de texto representativas -->
|
<path d="M 15.5 13 L 17.5 15 L 15.5 17" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<line x1="14" y1="20" x2="28" y2="20" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
|
<line x1="13" y1="12.5" x2="11" y2="17.5" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round"/>
|
||||||
<line x1="14" y1="25" x2="36" y2="25" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<line x1="14" y1="30" x2="36" y2="30" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
|
|
||||||
<!-- Etiqueta azul com sigla XML -->
|
|
||||||
<rect x="10" y="33" width="28" height="11" rx="3" fill="#0288d1"/>
|
|
||||||
<text x="24" y="41.5" font-family="Segoe UI, Arial, sans-serif" font-size="8" font-weight="bold" fill="#ffffff" text-anchor="middle"><XML></text>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 998 B After Width: | Height: | Size: 796 B |
@@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
|
<path d="M 4 8 L 4 4 L 8 4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M 16 4 L 20 4 L 20 8" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M 4 16 L 4 20 L 8 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M 16 20 L 20 20 L 20 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 623 B |
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
|
<circle cx="10.5" cy="10.5" r="6.5" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
|
<path d="M 15.5 15.5 L 20.5 20.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M 10.5 7.5 L 10.5 13.5 M 7.5 10.5 L 13.5 10.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 428 B |
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||||
|
<circle cx="10.5" cy="10.5" r="6.5" fill="none" stroke="currentColor" stroke-width="2"/>
|
||||||
|
<path d="M 15.5 15.5 L 20.5 20.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M 7.5 10.5 L 13.5 10.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 405 B |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 665 B |
|
After Width: | Height: | Size: 873 B |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
@@ -0,0 +1,37 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" width="256" height="256">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#1976d2"/>
|
||||||
|
<stop offset="45%" stop-color="#0d47a1"/>
|
||||||
|
<stop offset="100%" stop-color="#01579b"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="topFacetGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.9"/>
|
||||||
|
<stop offset="100%" stop-color="#80d8ff" stop-opacity="0.55"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="leftFacetGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#40c4ff" stop-opacity="0.75"/>
|
||||||
|
<stop offset="100%" stop-color="#0288d1" stop-opacity="0.35"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="rightFacetGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#e1f5fe" stop-opacity="0.85"/>
|
||||||
|
<stop offset="100%" stop-color="#29b6f6" stop-opacity="0.45"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="centerGlow" cx="50%" cy="50%" r="50%">
|
||||||
|
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.95"/>
|
||||||
|
<stop offset="100%" stop-color="#ffffff" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Fundo com cantos arredondados -->
|
||||||
|
<rect x="8" y="8" width="240" height="240" rx="68" ry="68" fill="url(#bgGrad)"/>
|
||||||
|
<rect x="10" y="10" width="236" height="236" rx="66" ry="66" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-opacity="0.25"/>
|
||||||
|
|
||||||
|
<!-- Facetas 3D do Cristal / Diamante Azul -->
|
||||||
|
<polygon points="128,46 210,113 128,143 46,113" fill="url(#topFacetGrad)"/>
|
||||||
|
<polygon points="46,113 128,143 128,215 72,179" fill="url(#leftFacetGrad)"/>
|
||||||
|
<polygon points="210,113 128,143 128,215 184,179" fill="url(#rightFacetGrad)"/>
|
||||||
|
|
||||||
|
<!-- Brilho estelar central -->
|
||||||
|
<circle cx="128" cy="128" r="38" fill="url(#centerGlow)"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,41 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 120" width="480" height="120">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="logoIconBg" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#1976d2"/>
|
||||||
|
<stop offset="50%" stop-color="#0d47a1"/>
|
||||||
|
<stop offset="100%" stop-color="#01579b"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="logoTopFacet" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.95"/>
|
||||||
|
<stop offset="100%" stop-color="#80d8ff" stop-opacity="0.6"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="logoLeftFacet" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#40c4ff" stop-opacity="0.8"/>
|
||||||
|
<stop offset="100%" stop-color="#0288d1" stop-opacity="0.4"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="logoRightFacet" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#e1f5fe" stop-opacity="0.9"/>
|
||||||
|
<stop offset="100%" stop-color="#29b6f6" stop-opacity="0.5"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Container do Ícone Cristal 3D -->
|
||||||
|
<rect x="14" y="16" width="88" height="88" rx="24" ry="24" fill="url(#logoIconBg)"/>
|
||||||
|
<rect x="16" y="18" width="84" height="84" rx="22" ry="22" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-opacity="0.25"/>
|
||||||
|
|
||||||
|
<!-- Facetas Cristalinas (cx=58, cy=60, sz=63) -->
|
||||||
|
<polygon points="58,32 86,55 58,66 30,55" fill="url(#logoTopFacet)"/>
|
||||||
|
<polygon points="30,55 58,66 58,92 39,79" fill="url(#logoLeftFacet)"/>
|
||||||
|
<polygon points="86,55 58,66 58,92 77,79" fill="url(#logoRightFacet)"/>
|
||||||
|
<circle cx="58" cy="60" r="14" fill="#ffffff" fill-opacity="0.3"/>
|
||||||
|
|
||||||
|
<!-- Tipografia Oficial "CyberCore" -->
|
||||||
|
<text x="124" y="62" font-family="'Segoe UI', Roboto, Helvetica, Arial, sans-serif" font-size="42" font-weight="bold" fill="#0a2540">Cyber<tspan fill="#0288d1">Core</tspan></text>
|
||||||
|
|
||||||
|
<!-- Badge "SIGNER" -->
|
||||||
|
<rect x="124" y="76" width="94" height="22" rx="6" ry="6" fill="#0288d1"/>
|
||||||
|
<text x="139" y="92" font-family="'Segoe UI', Roboto, Helvetica, Arial, sans-serif" font-size="13" font-weight="bold" fill="#ffffff" letter-spacing="1">SIGNER</text>
|
||||||
|
|
||||||
|
<!-- Subtítulo ICP-Brasil -->
|
||||||
|
<text x="230" y="92" font-family="'Segoe UI', Roboto, Helvetica, Arial, sans-serif" font-size="13" font-weight="normal" fill="#64748b">ICP-Brasil • Assinador Digital Seguro</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,32 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 160" width="600" height="160">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="bannerBgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#0d47a1"/>
|
||||||
|
<stop offset="60%" stop-color="#0284c7"/>
|
||||||
|
<stop offset="100%" stop-color="#0369a1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="bannerIconGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#1e88e5"/>
|
||||||
|
<stop offset="100%" stop-color="#01579b"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Fundo do Banner -->
|
||||||
|
<rect x="0" y="0" width="600" height="160" rx="16" ry="16" fill="url(#bannerBgGrad)"/>
|
||||||
|
|
||||||
|
<!-- Formas geométricas de segurança no fundo -->
|
||||||
|
<circle cx="480" cy="50" r="110" fill="#ffffff" fill-opacity="0.08"/>
|
||||||
|
<circle cx="540" cy="120" r="80" fill="#ffffff" fill-opacity="0.06"/>
|
||||||
|
<circle cx="380" cy="-20" r="90" fill="#ffffff" fill-opacity="0.04"/>
|
||||||
|
|
||||||
|
<!-- Ícone Cristal à esquerda -->
|
||||||
|
<rect x="30" y="35" width="90" height="90" rx="22" ry="22" fill="url(#bannerIconGrad)"/>
|
||||||
|
<rect x="33" y="38" width="84" height="84" rx="19" ry="19" fill="none" stroke="#ffffff" stroke-width="2" stroke-opacity="0.3"/>
|
||||||
|
<polygon points="75,52 101,80 75,108 49,80" fill="#ffffff" fill-opacity="0.9"/>
|
||||||
|
<polygon points="75,52 75,108 49,80" fill="#80d8ff" fill-opacity="0.5"/>
|
||||||
|
|
||||||
|
<!-- Textos do Banner -->
|
||||||
|
<text x="148" y="74" font-family="'Segoe UI', Roboto, Helvetica, Arial, sans-serif" font-size="34" font-weight="bold" fill="#ffffff">CyberCore Signer</text>
|
||||||
|
<text x="148" y="104" font-family="'Segoe UI', Roboto, Helvetica, Arial, sans-serif" font-size="16" font-weight="normal" fill="#e0f2fe">Agente de Assinatura Digital ICP-Brasil A1 & A3</text>
|
||||||
|
<text x="148" y="128" font-family="'Segoe UI', Roboto, Helvetica, Arial, sans-serif" font-size="12" font-weight="bold" fill="#38bdf8" letter-spacing="1">PADES • XADES • CADES • TIMESTAMPS • CCSP/1</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,34 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 164" width="640" height="164">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="badgeGrad" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#0288d1"/>
|
||||||
|
<stop offset="100%" stop-color="#01579b"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Fundo do Selo -->
|
||||||
|
<rect x="2" y="2" width="636" height="160" rx="12" ry="12" fill="#f8fafc" stroke="#0288d1" stroke-width="2.5"/>
|
||||||
|
|
||||||
|
<!-- Brasão Notarial no lado esquerdo -->
|
||||||
|
<rect x="18" y="16" width="130" height="132" rx="10" ry="10" fill="url(#badgeGrad)"/>
|
||||||
|
|
||||||
|
<!-- Textos do Brasão -->
|
||||||
|
<text x="83" y="44" font-family="'Segoe UI', Roboto, sans-serif" font-size="12" font-weight="bold" fill="#ffffff" text-anchor="middle" letter-spacing="0.5">ASSINADO</text>
|
||||||
|
<text x="83" y="60" font-family="'Segoe UI', Roboto, sans-serif" font-size="11" font-weight="bold" fill="#ffffff" text-anchor="middle" letter-spacing="0.5">DIGITALMENTE</text>
|
||||||
|
|
||||||
|
<!-- Estrela dourada -->
|
||||||
|
<circle cx="83" cy="85" r="14" fill="#fbbf24"/>
|
||||||
|
<text x="83" y="91" font-family="'Segoe UI', sans-serif" font-size="16" font-weight="bold" fill="#ffffff" text-anchor="middle">★</text>
|
||||||
|
|
||||||
|
<text x="83" y="126" font-family="'Segoe UI', Roboto, sans-serif" font-size="10" font-weight="bold" fill="#e0f2fe" text-anchor="middle" letter-spacing="1">ICP-BRASIL</text>
|
||||||
|
|
||||||
|
<!-- Linha divisória vertical -->
|
||||||
|
<line x1="166" y1="16" x2="166" y2="148" stroke="#cfd8dc" stroke-width="1.5"/>
|
||||||
|
|
||||||
|
<!-- Informações da Assinatura -->
|
||||||
|
<text x="184" y="36" font-family="'Segoe UI', Roboto, sans-serif" font-size="11" font-weight="bold" fill="#64748b" letter-spacing="0.5">DOCUMENTO ASSINADO DIGITALMENTE POR:</text>
|
||||||
|
<text x="184" y="60" font-family="'Segoe UI', Roboto, sans-serif" font-size="17" font-weight="bold" fill="#0a2540">NOME DO TITULAR DO CERTIFICADO</text>
|
||||||
|
<text x="184" y="82" font-family="'Segoe UI', Roboto, sans-serif" font-size="12" font-weight="normal" fill="#334155">CPF: ***.000.000-**</text>
|
||||||
|
<text x="184" y="102" font-family="'Segoe UI', Roboto, sans-serif" font-size="12" font-weight="normal" fill="#334155">Data e Hora: 11/10/2026 12:00:00 -03:00</text>
|
||||||
|
<text x="184" y="128" font-family="'Segoe UI', Roboto, sans-serif" font-size="11" font-style="italic" fill="#0288d1">A conformidade com a ICP-Brasil pode ser verificada no ITI.</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -52,12 +52,12 @@ echo " CYBERCORE SIGNER - AUTOMAÇÃO DE BUILD DO JAR"
|
|||||||
echo "============================================================"
|
echo "============================================================"
|
||||||
echo -e "${COLOR_RESET}"
|
echo -e "${COLOR_RESET}"
|
||||||
|
|
||||||
# 1. Verificação e Auto-Detecção do Java (JDK 21+)
|
# 1. Verificação e Auto-Detecção do Java (JDK 25+)
|
||||||
if ! command -v java &>/dev/null; then
|
if ! command -v java &>/dev/null; then
|
||||||
POSSIBLE_JDKS=(
|
POSSIBLE_JDKS=(
|
||||||
|
"${HOME}/.jdks/jdk-25.0.4.1+1"
|
||||||
"/home/claudecio/.jdks/jdk-25.0.4.1+1"
|
"/home/claudecio/.jdks/jdk-25.0.4.1+1"
|
||||||
"/usr/lib/jvm/java-25-openjdk-amd64"
|
"/usr/lib/jvm/java-25-openjdk-amd64"
|
||||||
"/usr/lib/jvm/java-21-openjdk-amd64"
|
|
||||||
"/usr/lib/jvm/default-java"
|
"/usr/lib/jvm/default-java"
|
||||||
)
|
)
|
||||||
for candidate in "${POSSIBLE_JDKS[@]}"; do
|
for candidate in "${POSSIBLE_JDKS[@]}"; do
|
||||||
@@ -105,9 +105,15 @@ if [[ ! -f "${SOURCE_JAR}" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 4. Copia para a raiz para facilitar o acesso
|
# 4. Copia para a raiz e para a pasta sdk/ para manter o ambiente sincronizado
|
||||||
cp -f "${SOURCE_JAR}" "${DEST_JAR}"
|
cp -f "${SOURCE_JAR}" "${DEST_JAR}"
|
||||||
|
|
||||||
|
if [[ -d "sdk" ]]; then
|
||||||
|
SDK_JAR="sdk/cybercore-signer.jar"
|
||||||
|
cp -f "${SOURCE_JAR}" "${SDK_JAR}"
|
||||||
|
echo -e "Cópia sincronizada para o SDK: ${COLOR_BOLD}${SDK_JAR}${COLOR_RESET}"
|
||||||
|
fi
|
||||||
|
|
||||||
JAR_SIZE=$(ls -lh "${DEST_JAR}" | awk '{print $5}')
|
JAR_SIZE=$(ls -lh "${DEST_JAR}" | awk '{print $5}')
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!--
|
<!--
|
||||||
Exclusões do SpotBugs / FindSecBugs.
|
Exclusões do SpotBugs / FindSecBugs para o CyberCore Signer.
|
||||||
Regra: toda exclusão deve ser específica (classe/padrão) e justificada em comentário.
|
Regra: toda exclusão deve ser específica (classe/padrão) e justificada em comentário.
|
||||||
-->
|
-->
|
||||||
<FindBugsFilter
|
<FindBugsFilter
|
||||||
@@ -9,15 +9,174 @@
|
|||||||
xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0/spotbugs/etc/findbugsfilter.xsd">
|
xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0/spotbugs/etc/findbugsfilter.xsd">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Records imutáveis de DTO e relatório que já realizam cópia defensiva em seus
|
1. DTOs, Records e opções imutáveis que transferem dados estruturados (byte arrays, listas)
|
||||||
construtores canônicos (List.copyOf / Map.copyOf) mas são apontados por heurística do SpotBugs.
|
onde cópias defensivas estritas causariam overhead desnecessário de alocação criptográfica.
|
||||||
-->
|
-->
|
||||||
<Match>
|
<Match>
|
||||||
<Bug pattern="EI_EXPOSE_REP,EI_EXPOSE_REP2"/>
|
<Bug pattern="EI_EXPOSE_REP,EI_EXPOSE_REP2"/>
|
||||||
<Or>
|
<Or>
|
||||||
<Class name="br.com.cybercore.signer.core.diagnostics.DiagnosticReport"/>
|
<Class name="br.com.cybercore.signer.core.diagnostics.DiagnosticReport"/>
|
||||||
<Class name="br.com.cybercore.signer.core.domain.SigningResult"/>
|
<Class name="br.com.cybercore.signer.core.domain.SigningResult"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.domain.SigningKeyMaterial"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.protocol.CcspRequest"/>
|
||||||
<Class name="br.com.cybercore.signer.core.protocol.CcspResponse"/>
|
<Class name="br.com.cybercore.signer.core.protocol.CcspResponse"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.validation.ValidationResult"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.validation.SignatureValidationService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.xml.XmlSignatureOptions"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.PdfSignatureOptions"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.PdfSignatureOptions$Builder"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.seal.PdfSealData"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.provider.Pkcs12CertificateProvider"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.provider.Pkcs11CertificateProvider"/>
|
||||||
|
<Package name="~br\.com\.cybercore\.signer\.ui\.view.*"/>
|
||||||
</Or>
|
</Or>
|
||||||
</Match>
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
1b. Referência estática ao Stage principal ativo para apresentação de diálogos modais pelo prompt listener.
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="EI_EXPOSE_STATIC_REP2"/>
|
||||||
|
<Class name="br.com.cybercore.signer.ui.prompt.JavaFxPromptListener"/>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
2. Singletons locais e serviços de sessão que utilizam métodos sincronizados para controle
|
||||||
|
de concorrência thread-safe em memória local do agente desktop.
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="USO_UNSAFE_METHOD_SYNCHRONIZATION,USO_UNSAFE_STATIC_METHOD_SYNCHRONIZATION"/>
|
||||||
|
<Or>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.SecurePinStorage"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.PinSessionManager"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.ApplicationRegistry"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.config.AgentConfigurationService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.log.AppLogBuffer"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.seal.CustomSealStorage"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.provider.CertificateManager"/>
|
||||||
|
</Or>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
3. Construtores de Singletons com visibilidade default/package-private para permitir
|
||||||
|
instanciação isolada durante testes unitários.
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="SING_SINGLETON_HAS_NONPRIVATE_CONSTRUCTOR"/>
|
||||||
|
<Or>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.ApplicationRegistry"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.PinSessionManager"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.SecurePinStorage"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.config.AgentConfigurationService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.log.AppLogBuffer"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.seal.CustomSealStorage"/>
|
||||||
|
</Or>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
4. Exceções lançadas em construtores de serviços criptográficos e diálogos que necessitam
|
||||||
|
validar algoritmos ou dependências durante a instanciação (fail-fast).
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="CT_CONSTRUCTOR_THROW"/>
|
||||||
|
<Or>
|
||||||
|
<Class name="br.com.cybercore.signer.core.xml.XmlSigningService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.PdfSigningService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.PdfSigningService$PadesBouncyCastleSigner"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.crypto.SigningService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.protocol.CcspServer"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.provider.Pkcs12CertificateProvider"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.crypto.tsa.TsaClient"/>
|
||||||
|
<Class name="br.com.cybercore.signer.ui.tray.SystemTrayManager"/>
|
||||||
|
<Package name="~br\.com\.cybercore\.signer\.ui\.view.*"/>
|
||||||
|
</Or>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
5. Tratamento de exceções amplo (catch Exception) intencional em rotinas defensivas de
|
||||||
|
validação criptográfica e telemetria para não abortar o processo desktop.
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="REC_CATCH_EXCEPTION"/>
|
||||||
|
<Or>
|
||||||
|
<Class name="br.com.cybercore.signer.core.validation.SignatureValidationService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.SecurePinStorage"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.protocol.CcspServer"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.protocol.CcspServer$SignXmlHandler"/>
|
||||||
|
<Class name="br.com.cybercore.signer.ui.assets.AssetManager"/>
|
||||||
|
<Package name="~br\.com\.cybercore\.signer\.ui\.view.*"/>
|
||||||
|
</Or>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
6. Instanciação única de SecureRandom em métodos locais para geração de nonces efêmeros.
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="DMI_RANDOM_USED_ONLY_ONCE"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.SecurePinStorage"/>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
7. Validação de saída de diretório (mkdirs) e condições de contorno defensivas em parsing.
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE,UC_USELESS_CONDITION,NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"/>
|
||||||
|
<Or>
|
||||||
|
<Class name="br.com.cybercore.signer.core.xml.XmlSigningService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.PdfSigningService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.validation.SignatureValidationService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.config.AgentConfigurationService"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.protocol.CcspServer"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.seal.CustomSealStorage"/>
|
||||||
|
<Package name="~br\.com\.cybercore\.signer\.ui\.view.*"/>
|
||||||
|
</Or>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
8. Transformações locais de XML (FindSecBugs) utilizadas estritamente para montagem de
|
||||||
|
assinaturas digitais XAdES locais sem ingestão de fontes remotas não confiáveis.
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="XXE_DTD_TRANSFORM_FACTORY,XXE_XSLT_TRANSFORM_FACTORY"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.xml.XmlSigningService"/>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
9. Campos estáticos públicos e gerenciamento de ciclo de vida da interface gráfica JavaFX,
|
||||||
|
servidor HTTP de loopback e do System Tray (incluindo saída voluntária System.exit).
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="MS_EXPOSE_REP,ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD,DM_EXIT,DE_MIGHT_IGNORE,IS2_INCONSISTENT_SYNC,RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE,VA_FORMAT_STRING_USES_NEWLINE"/>
|
||||||
|
<Or>
|
||||||
|
<Class name="br.com.cybercore.signer.core.provider.WindowsCertificateStoreProvider"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.ApplicationRegistry"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.PinSessionManager"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.security.SecurePinStorage"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.seal.PdfSealThemeRegistry"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.pdf.seal.CustomSealStorage"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.protocol.CcspServer"/>
|
||||||
|
<Class name="br.com.cybercore.signer.ui.CyberCoreDesktopApplication"/>
|
||||||
|
<Class name="br.com.cybercore.signer.ui.tray.SystemTrayManager"/>
|
||||||
|
<Class name="br.com.cybercore.signer.ui.assets.AssetManager"/>
|
||||||
|
<Package name="~br\.com\.cybercore\.signer\.ui\.view.*"/>
|
||||||
|
</Or>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
10. Flags booleanas primitivas de linha de comando inicializadas no bootstrap da aplicação.
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="AT_STALE_THREAD_WRITE_OF_PRIMITIVE"/>
|
||||||
|
<Class name="br.com.cybercore.signer.app.CyberCoreSignerApplication"/>
|
||||||
|
</Match>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
11. Carregamento de driver PKCS#11 (middleware de fabricante de hardware criptográfico)
|
||||||
|
apontando para bibliotecas dinâmicas do sistema operacional (.dll no Windows ou .so no Linux).
|
||||||
|
-->
|
||||||
|
<Match>
|
||||||
|
<Bug pattern="PATH_TRAVERSAL_IN"/>
|
||||||
|
<Class name="br.com.cybercore.signer.core.provider.Pkcs11CertificateProvider"/>
|
||||||
|
</Match>
|
||||||
|
|
||||||
</FindBugsFilter>
|
</FindBugsFilter>
|
||||||
|
|||||||
@@ -1,28 +1,55 @@
|
|||||||
# CyberCore Signing Protocol (CCSP/1)
|
# CyberCore Signing Protocol (CCSP/1)
|
||||||
|
|
||||||
O **CyberCore Signing Protocol (CCSP)** é o protocolo padrão para comunicação local entre aplicações web rodando no navegador e o agente desktop **CyberCore Signer**.
|
> **Especificação Técnica do Protocolo de Comunicação Local e API REST (Versão 1)**
|
||||||
|
|
||||||
A versão inicial descrita neste documento é a **CCSP/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
|
## 1. Princípios de Segurança e Isolamento
|
||||||
|
|
||||||
1. **Isolamento de Rede:** O servidor local escuta exclusivamente no endereço de loopback `127.0.0.1` (porta padrão `21325`), impedindo qualquer acesso a partir da rede local (LAN) ou externa (WAN).
|
O protocolo CCSP/1 adota o princípio de menor privilégio e segurança em profundidade:
|
||||||
2. **Controle Estrito de Origem (CORS):** O agente valida cabeçalhos `Origin` e responde apenas a pré-voos `OPTIONS` com origens autorizadas.
|
|
||||||
3. **Registro e Autorização de Aplicações:** Nenhuma aplicação desconhecida tem acesso a certificados ou assinaturas. Ao tentar conectar pela primeira vez, uma caixa de diálogo nativa solicita aprovação explícita do usuário.
|
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).
|
||||||
4. **Confirmação Visual da Assinatura:** Toda operação de assinatura exige confirmação manual na interface gráfica, exibindo a aplicação solicitante, o hash do documento e o certificado selecionado.
|
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`.
|
||||||
5. **Proteção Contra Ataques de Replay:** Toda requisição deve conter um `nonce` UUID único com validação temporal (`expires_at` ou `timestamp`). Requisições com nonces repetidos são sumariamente rejeitadas (`REPLAY_DETECTED`).
|
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`).
|
||||||
6. **Privacidade Criptográfica:** Apenas o **digest (hash)** do documento é enviado ao agente. O documento completo nunca sai da aplicação web e a chave privada nunca sai do dispositivo/computador do usuário.
|
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. Endpoints do Protocolo (CCSP/1)
|
## 2. Visão Geral dos Endpoints (CCSP/1)
|
||||||
|
|
||||||
### 2.1 `GET /ccsp/v1/status`
|
| Método | Endpoint | Finalidade | Autenticação Requerida |
|
||||||
Verifica se o agente está instalado, em execução e pronto para operações.
|
|---|---|---|---|
|
||||||
|
| `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 |
|
||||||
|
|
||||||
#### Resposta de Sucesso (200 OK)
|
---
|
||||||
|
|
||||||
|
## 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
|
```json
|
||||||
{
|
{
|
||||||
"version": "1",
|
"version": "1",
|
||||||
@@ -30,20 +57,58 @@ Verifica se o agente está instalado, em execução e pronto para operações.
|
|||||||
"agent": "CyberCore Signer",
|
"agent": "CyberCore Signer",
|
||||||
"agent_version": "0.1.0",
|
"agent_version": "0.1.0",
|
||||||
"os": "Windows 11",
|
"os": "Windows 11",
|
||||||
"timestamp": "2026-10-08T19:40:00Z"
|
"timestamp": "2026-10-11T20:45:00Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 2.2 `GET /ccsp/v1/certificates`
|
### 3.2 `POST /ccsp/v1/authorize`
|
||||||
Retorna a lista de certificados digitais atualmente disponíveis e aptos para assinatura.
|
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.
|
||||||
|
|
||||||
#### Headers / Parâmetros
|
#### Cabeçalhos
|
||||||
- `X-CyberCore-AppId`: UUID da aplicação autorizada (ou query param `?application_id=uuid`).
|
- `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.
|
- `Origin`: Origem web autorizada.
|
||||||
|
- `X-CyberCore-AppId` (Header) ou `?application_id=uuid` (Query Param).
|
||||||
|
|
||||||
#### Resposta de Sucesso (200 OK)
|
#### Resposta de Sucesso (`200 OK`)
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"version": "1",
|
"version": "1",
|
||||||
@@ -51,16 +116,18 @@ Retorna a lista de certificados digitais atualmente disponíveis e aptos para as
|
|||||||
"certificates": [
|
"certificates": [
|
||||||
{
|
{
|
||||||
"id": "win-4340656a",
|
"id": "win-4340656a",
|
||||||
"alias": "CLAUDIO SILVA:12345678900",
|
"alias": "MARIA DA SILVA:12345678900",
|
||||||
"common_name": "CLAUDIO SILVA:12345678900",
|
"common_name": "MARIA DA SILVA:12345678900",
|
||||||
"subject_dn": "CN=CLAUDIO SILVA:12345678900, OU=Autenticado por AR, O=ICP-Brasil, C=BR",
|
"subject_dn": "CN=MARIA DA SILVA:12345678900, OU=Autenticado por AR, O=ICP-Brasil, C=BR",
|
||||||
"issuer_dn": "CN=AC SERPRO v5, 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",
|
"type": "A3",
|
||||||
"provider_id": "provider-win-store",
|
"provider_id": "provider-win-store",
|
||||||
"device_name": "Token / Smart Card (Windows CAPI/CNG)",
|
"device_name": "Token USB / Smart Card (Windows CAPI/CNG)",
|
||||||
"valid_from": "2024-05-10T12:00:00Z",
|
"valid_from": "2025-01-10T10:00:00Z",
|
||||||
"valid_to": "2027-05-10T12:00:00Z",
|
"valid_to": "2028-01-10T10:00:00Z",
|
||||||
"serial_number": "72910482910482019482",
|
"serial_number": "72910482910482019482",
|
||||||
|
"cpf": "12345678900",
|
||||||
|
"cnpj": null,
|
||||||
"can_sign": true,
|
"can_sign": true,
|
||||||
"status": "AVAILABLE"
|
"status": "AVAILABLE"
|
||||||
}
|
}
|
||||||
@@ -70,33 +137,10 @@ Retorna a lista de certificados digitais atualmente disponíveis e aptos para as
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 2.3 `POST /ccsp/v1/authorize`
|
### 3.4 `POST /ccsp/v1/sign`
|
||||||
Handshake inicial de uma nova aplicação web para solicitar autorização ao usuário.
|
Solicita a assinatura digital local do digest informado com o certificado escolhido.
|
||||||
|
|
||||||
#### Requisição
|
#### Payload da Requisição
|
||||||
```json
|
|
||||||
{
|
|
||||||
"version": "1",
|
|
||||||
"application_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
||||||
"name": "Portal Assinaturas Jurídicas"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Resposta (200 OK)
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"version": "1",
|
|
||||||
"status": "authorized",
|
|
||||||
"application_id": "550e8400-e29b-41d4-a716-446655440000"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2.4 `POST /ccsp/v1/sign`
|
|
||||||
Executa a assinatura digital do digest informado (PDF, XML, documentos ou arquivos gerais).
|
|
||||||
|
|
||||||
#### Requisição
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"version": "1",
|
"version": "1",
|
||||||
@@ -106,103 +150,284 @@ Executa a assinatura digital do digest informado (PDF, XML, documentos ou arquiv
|
|||||||
"algorithm": "SHA256withRSA",
|
"algorithm": "SHA256withRSA",
|
||||||
"digest": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
|
"digest": "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
|
||||||
"certificate_hint": "win-4340656a",
|
"certificate_hint": "win-4340656a",
|
||||||
"document_name": "contrato_locacao.pdf",
|
"document_name": "contrato_prestacao_servicos.pdf",
|
||||||
"document_type": "PDF",
|
"document_type": "PDF",
|
||||||
|
"document_size": 1474560,
|
||||||
|
"origin": "https://meusistema.empresa.com.br",
|
||||||
"nonce": "c4ca4238a0b923820dcc509a6f75849b",
|
"nonce": "c4ca4238a0b923820dcc509a6f75849b",
|
||||||
"expires_at": "2026-10-08T19:45:00Z"
|
"expires_at": "2026-10-11T20:50:00Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Resposta de Sucesso (200 OK)
|
> **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
|
```json
|
||||||
{
|
{
|
||||||
"version": "1",
|
"version": "1",
|
||||||
"request_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
|
"request_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
|
||||||
"status": "signed",
|
"status": "signed",
|
||||||
"signature": "MEUCIQDq...base64...",
|
"signature": "MEUCIQDq95kZc...Base64...",
|
||||||
"certificate": "MIIFazC...base64...",
|
"certificate": "MIIFazCCBF...Base64...",
|
||||||
"certificate_chain": [
|
"certificate_chain": [
|
||||||
"MIIFazC...base64...",
|
"MIIFazCCBF...Base64...",
|
||||||
"MIIEazC...base64..."
|
"MIIEazCCA1...Base64..."
|
||||||
],
|
],
|
||||||
"algorithm": "SHA256withRSA",
|
"algorithm": "SHA256withRSA",
|
||||||
"subject_name": "CLAUDIO SILVA",
|
"subject_name": "MARIA DA SILVA",
|
||||||
"subject_cpf_cnpj": "12345678900",
|
"subject_cpf_cnpj": "12345678900",
|
||||||
"document_name": "contrato_locacao.pdf",
|
"document_name": "contrato_prestacao_servicos.pdf",
|
||||||
"document_type": "PDF"
|
"document_type": "PDF"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 2.5 `POST /ccsp/v1/authenticate`
|
### 3.5 `POST /ccsp/v1/authenticate`
|
||||||
Executa o login / autenticação digital segura de um usuário em sistemas web via desafio criptográfico (Challenge-Response ICP-Brasil).
|
Executa o login criptográfico de um usuário em sistemas web através do mecanismo de desafio e resposta (*Challenge-Response*).
|
||||||
|
|
||||||
#### Requisição
|
#### Payload da Requisição
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"version": "1",
|
"version": "1",
|
||||||
"request_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
|
"request_id": "8f3b201a-8c9d-4e5f-b012-3456789abcde",
|
||||||
"application_id": "550e8400-e29b-41d4-a716-446655440000",
|
"application_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
"operation": "authenticate",
|
"operation": "authenticate",
|
||||||
"challenge": "server-session-challenge-nonce-2026",
|
"challenge": "session-nonce-random-server-token-998877",
|
||||||
"certificate_hint": "win-4340656a",
|
"certificate_hint": "win-4340656a",
|
||||||
"purpose": "AUTHENTICATION",
|
"purpose": "AUTHENTICATION",
|
||||||
"nonce": "c4ca4238a0b923820dcc509a6f75849b",
|
"nonce": "d3b07384d113edec49eaa6238ad5ff00",
|
||||||
"expires_at": "2026-10-08T19:45:00Z"
|
"expires_at": "2026-10-11T20:50:00Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Resposta de Sucesso (200 OK)
|
#### Resposta de Sucesso (`200 OK`)
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"version": "1",
|
"version": "1",
|
||||||
"request_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
|
"request_id": "8f3b201a-8c9d-4e5f-b012-3456789abcde",
|
||||||
"status": "authenticated",
|
"status": "authenticated",
|
||||||
"signature": "MEUCIQDq...base64...",
|
"signature": "MEQCIF61pP...Base64...",
|
||||||
"certificate": "MIIFazC...base64...",
|
"certificate": "MIIFazCCBF...Base64...",
|
||||||
"certificate_chain": [
|
"certificate_chain": [
|
||||||
"MIIFazC...base64..."
|
"MIIFazCCBF...Base64...",
|
||||||
|
"MIIEazCCA1...Base64..."
|
||||||
],
|
],
|
||||||
"algorithm": "SHA256withRSA",
|
"algorithm": "SHA256withRSA",
|
||||||
"subject_name": "CLAUDIO SILVA",
|
"subject_name": "MARIA DA SILVA",
|
||||||
"subject_cpf_cnpj": "12345678900",
|
"subject_cpf_cnpj": "12345678900"
|
||||||
"document_type": "AUTH_CHALLENGE"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Resposta de Erro (400/403/404)
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"version": "1",
|
|
||||||
"request_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
|
|
||||||
"status": "error",
|
|
||||||
"error_code": "USER_CANCELLED",
|
|
||||||
"message": "Operação de assinatura cancelada pelo usuário."
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Tabela de Códigos de Erro Estruturados
|
### 3.6 `GET /ccsp/v1/seals`
|
||||||
|
Retorna a lista de temas e estilos de selos visuais embutidos e instalados no CyberCore Signer.
|
||||||
|
|
||||||
| Código | Significado |
|
#### Cabeçalhos
|
||||||
|---|---|
|
- `Origin: https://meusistema.empresa.com.br`
|
||||||
| `CERTIFICATE_NOT_FOUND` | Certificado indicado no hint não foi encontrado. |
|
- `X-CyberCore-AppId: 550e8400-e29b-41d4-a716-446655440000`
|
||||||
| `CERTIFICATE_EXPIRED` | O certificado selecionado está fora do período de vigência. |
|
|
||||||
| `CERTIFICATE_INVALID` | O certificado é inválido ou corrompido. |
|
#### Resposta de Sucesso (`200 OK`)
|
||||||
| `PRIVATE_KEY_NOT_AVAILABLE` | Chave privada inacessível ou ausente. |
|
```json
|
||||||
| `TOKEN_NOT_FOUND` | Nenhum dispositivo ou leitor compatível foi localizado. |
|
{
|
||||||
| `TOKEN_REMOVED` | Dispositivo de hardware foi removido durante a assinatura. |
|
"version": "1",
|
||||||
| `PIN_REQUIRED` | PIN obrigatório para liberar chave privada em PKCS#11. |
|
"status": "success",
|
||||||
| `PIN_INCORRECT` | PIN digitado está incorreto. |
|
"default_seal_id": "icp-brasil",
|
||||||
| `PKCS11_ERROR` | Falha no middleware PKCS#11 do fabricante. |
|
"seals": [
|
||||||
| `SIGNATURE_FAILED` | Erro durante a geração da assinatura digital. |
|
{
|
||||||
| `APPLICATION_NOT_AUTHORIZED` | Aplicação não autorizada ou recusada pelo usuário. |
|
"id": "icp-brasil",
|
||||||
| `REQUEST_EXPIRED` | A data/hora de validade da requisição expirou. |
|
"name": "ICP-Brasil Institucional",
|
||||||
| `REPLAY_DETECTED` | O nonce informado já foi processado anteriormente. |
|
"description": "Estilo oficial corporativo com escudo de segurança vetorial e dados completos do titular",
|
||||||
| `INVALID_ORIGIN` | O cabeçalho Origin não corresponde ao cadastro da aplicação. |
|
"primary_color": "#0d47a1",
|
||||||
| `UNSUPPORTED_ALGORITHM` | Algoritmo não suportado (ex: diferente de SHA256withRSA). |
|
"secondary_color": "#0284c7",
|
||||||
| `USER_CANCELLED` | O usuário clicou em Cancelar ou fechou a janela de confirmação. |
|
"border_color": "#93c5fd",
|
||||||
| `PROVIDER_NOT_AVAILABLE` | O provedor criptográfico necessário está inativo no SO. |
|
"background_color": "#ffffff",
|
||||||
| `COMMUNICATION_ERROR` | Erro interno no agente de comunicação local. |
|
"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
|
||||||
|
```
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# Diagnóstico: Janela Principal no Windows 11 (Bisseção e Monitoramento)
|
||||||
|
|
||||||
|
Este documento descreve o procedimento de diagnóstico para isolar a causa de ocultamento nativo da janela principal no Windows 11 ao passar o mouse.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Monitor Nativo Win32/DWM (`scripts/diag-window.ps1`)
|
||||||
|
|
||||||
|
O script [scripts/diag-window.ps1](file:///var/www/cybercore/cybercore-signer/scripts/diag-window.ps1) inspeciona a cada 300ms a janela nativa via P/Invoke da Win32 API e DWM:
|
||||||
|
- `IsWindowVisible`: se a janela está visível perante o subsistema Win32;
|
||||||
|
- `DWMWA_CLOAKED`: se o gerenciador gráfico do Windows 11 ocultou a composição;
|
||||||
|
- `IsIconic`: se foi minimizada;
|
||||||
|
- `GetWindowRect`: coordenadas reais (detecta se foi deslocada para fora da tela).
|
||||||
|
|
||||||
|
### Como executar o monitor:
|
||||||
|
Em uma janela separada do PowerShell:
|
||||||
|
```powershell
|
||||||
|
powershell -ExecutionPolicy Bypass -File .\scripts\diag-window.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Roteiro de Bisseção (Fase 2)
|
||||||
|
|
||||||
|
Execute cada um dos comandos abaixo individualmente (garantindo antes que instâncias anteriores foram encerradas com `Stop-Process -Name java -Force` se necessário):
|
||||||
|
|
||||||
|
### Teste A: Desativar Middleware PKCS#11 / SafeSign (`aetpkss1.dll`)
|
||||||
|
Isola hooks nativos do SafeSign e middlewares A3:
|
||||||
|
```powershell
|
||||||
|
java -Dcybercore.diag.no-pkcs11=true -jar .\cybercore-signer.jar --dev
|
||||||
|
```
|
||||||
|
*Se a janela NÃO sumir ao passar o mouse, a causa é o hook nativo do middleware PKCS#11.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Teste B: Plain Stage (Janela livre sem `setResizable(false)` e sem limites min/max)
|
||||||
|
Isola o bug de composição do DWM / Glass no Windows 11 com janelas de tamanho fixo:
|
||||||
|
```powershell
|
||||||
|
java -Dcybercore.diag.plain-stage=true -jar .\cybercore-signer.jar --dev
|
||||||
|
```
|
||||||
|
*Se a janela NÃO sumir ao passar o mouse, a causa é a restrição fixa de tamanho no Windows 11.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Teste C: Desativar Efeitos de Sombra no Mouse (`-fx-effect`)
|
||||||
|
Isola recálculo de dropshadow e troca de cursor:
|
||||||
|
```powershell
|
||||||
|
java -Dcybercore.diag.no-effects=true -jar .\cybercore-signer.jar --dev
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Teste D: Desativar Monitor Dinâmico de Smart Cards (PC/SC)
|
||||||
|
Isola threads em segundo plano de `javax.smartcardio`:
|
||||||
|
```powershell
|
||||||
|
java -Dcybercore.diag.no-smartcard-watcher=true -jar .\cybercore-signer.jar --dev
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Teste E: Desativar Windows Certificate Store (Windows-MY)
|
||||||
|
Isola inicialização de CryptoAPI / SunMSCAPI:
|
||||||
|
```powershell
|
||||||
|
java -Dcybercore.diag.no-wincert=true -jar .\cybercore-signer.jar --dev
|
||||||
|
```
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# Documentação Técnica — CyberCore Signer
|
||||||
|
|
||||||
|
> **Índice Unificado e Guias Técnicos do Agente Desktop e Protocolo CCSP**
|
||||||
|
|
||||||
|
Bem-vindo à documentação oficial do **CyberCore Signer**. O agente foi desenvolvido em Java 25 LTS com interface JavaFX e segurança criptográfica nativa JCA/JCE, permitindo que aplicações web autorizadas realizem operações de assinatura digital e autenticação com certificados ICP-Brasil (A1 em arquivo e A3 em tokens/smartcards físicos) mantendo as chaves privadas estritamente no dispositivo do usuário.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗺️ Trilhas de Navegação por Perfil
|
||||||
|
|
||||||
|
Para facilitar a consulta, os documentos estão organizados de acordo com o seu perfil de atuação:
|
||||||
|
|
||||||
|
### 🌐 1. Para Desenvolvedores Web e Integradores
|
||||||
|
Se você desenvolve aplicações web (frontend/backend) que precisam interagir com o agente do usuário:
|
||||||
|
|
||||||
|
* **[Protocolo CCSP/1 (CyberCore Signing Protocol)](CCSP.md):** Especificação completa da API REST local (`127.0.0.1:21325`), endpoints, ciclo de handshake, proteção anti-replay e exemplos de requisição/resposta.
|
||||||
|
* **[SDK Web JavaScript (@cybercore/signer-sdk)](sdk.md):** Manual de instalação e uso da biblioteca oficial cliente para integração em aplicações web (Vite, Next.js, Vue, Angular, Vanilla JS).
|
||||||
|
* **[Autenticação e Login Digital ICP-Brasil](authentication-login.md):** Fluxo de autenticação segura via desafio criptográfico (*Challenge-Response*) para substituição ou complemento de senhas tradicionais.
|
||||||
|
* **[Catálogo Estruturado de Erros](errors.md):** Lista completa de códigos de erro (`CcspErrorCode`), status HTTP correspondentes e orientações de tratamento na interface web.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ☕ 2. Para Desenvolvedores Desktop e Contribuidores
|
||||||
|
Se você atua no desenvolvimento, manutenção ou auditoria do código-fonte do agente desktop:
|
||||||
|
|
||||||
|
* **[Arquitetura do Sistema](architecture.md):** Organização modular Maven (`cybercore-core`, `cybercore-ui`, `cybercore-app`), fluxo de dados por digest, modelo de concorrência com fila FIFO (`signLock`) e isolamento de dependências.
|
||||||
|
* **[Certificados A1, A3 e PKCS#11](a1-a3-certificates.md):** Funcionamento dos provedores `Pkcs12CertificateProvider`, `WindowsCertificateStoreProvider` (SunMSCAPI/CNG) e `Pkcs11CertificateProvider` (SunPKCS11), monitoramento dinâmico PC/SC (`SmartCardWatcher`) e extração de OIDs ICP-Brasil.
|
||||||
|
* **[Assinaturas PDF (PAdES) e Selos Visuais SVG](pades.md):** Motor de assinatura PDFBox + Bouncy Castle, salvamento incremental, renderização de alta resolução (300 DPI Java2D) e gerenciamento de selos digitais.
|
||||||
|
* **[Assinaturas XML (XAdES-BES e XMLDSig)](xml-xmldsig.md):** Conformidade com o padrão ETSI TS 101 903 / DOC-ICP-15.03 e suporte a notas fiscais eletrônicas (NF-e, CT-e, MDF-e, eSocial).
|
||||||
|
* **[Layout de Interface e Assinatura em Lote](ui-layout.md):** Especificação de interface gráfica padronizada, acessibilidade WCAG AA e processamento em lote.
|
||||||
|
* **[Modo de Desenvolvimento](development-mode.md):** Guia de inicialização em modo `--dev`, políticas de não utilização de mocks em produção e geração de certificados A1 de teste locais.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🛡️ 3. Para DevOps, Infraestrutura e Segurança
|
||||||
|
Se você precisa implantar, homologar ou validar os aspectos de conformidade e segurança da solução:
|
||||||
|
|
||||||
|
* **[Modelo de Segurança e Privacidade](security.md):** Diretrizes de menor privilégio, proteção contra CSRF e DNS Rebinding, descarte seguro de senhas e PIN em memória e conformidade com a LGPD.
|
||||||
|
* **[Instalação e Empacotamento Nativo](installation.md):** Criação de instaladores autocontidos para Windows (MSI/EXE) via `jpackage`, requisitos do sistema e parâmetros de instalação corporativa silenciosa.
|
||||||
|
* **[Estratégia de Versionamento e Release](release-and-versioning.md):** Padrão SemVer 2.0.0, plano progressivo de cobertura JaCoCo e roteiro para corte da primeira tag v0.1.0.
|
||||||
|
* **[Diagnóstico e Troubleshooting](diagnostics.md):** Subsistema de auto-teste, checklist de integridade de runtime e guia de resolução de problemas comuns de hardware/middleware.
|
||||||
|
* **[Limitações Técnicas Declaradas](limitations.md):** Declaração formal de requisitos de drivers, limitações de hardware mono-thread e dependências de sistema operacional (em conformidade com a Regra 23 do projeto).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Sumário Geral de Arquivos
|
||||||
|
|
||||||
|
| Documento | Assunto Principal | Público-Alvo |
|
||||||
|
|---|---|---|
|
||||||
|
| [`CCSP.md`](CCSP.md) | Especificação técnica do protocolo local CCSP versão 1 | Integradores Web & Core Devs |
|
||||||
|
| [`architecture.md`](architecture.md) | Estrutura modular, threading e fluxo de operações | Desenvolvedores Desktop |
|
||||||
|
| [`a1-a3-certificates.md`](a1-a3-certificates.md) | Provedores A1/A3, PKCS#11, PC/SC e OIDs ICP-Brasil | Especialistas em Criptografia |
|
||||||
|
| [`pades.md`](pades.md) | Assinatura PAdES, envelope CMS e selos vetoriais | Desenvolvedores Desktop & Web |
|
||||||
|
| [`xml-xmldsig.md`](xml-xmldsig.md) | XAdES-BES, XMLDSig e documentos fiscais | Integradores de NF-e/XAdES |
|
||||||
|
| [`authentication-login.md`](authentication-login.md) | Login Challenge-Response via ICP-Brasil | Integradores Web |
|
||||||
|
| [`errors.md`](errors.md) | Tabela estruturada de erros e mapeamentos HTTP | Todos |
|
||||||
|
| [`security.md`](security.md) | Políticas de isolamento, memória e privacidade | Segurança & Compliance |
|
||||||
|
| [`diagnostics.md`](diagnostics.md) | Auto-testes e guia de resolução de problemas | Suporte & Operações |
|
||||||
|
| [`installation.md`](installation.md) | Empacotamento com `jpackage` e instaladores MSI | DevOps & Usuários Finais |
|
||||||
|
| [`release-and-versioning.md`](release-and-versioning.md) | Estratégia SemVer, metas JaCoCo e corte de tags | DevOps & Governança |
|
||||||
|
| [`compliance-testing.md`](compliance-testing.md) | Guia de Conformidade ICP-Brasil e Verificador ITI | Compliance & QA |
|
||||||
|
| [`compatibility.md`](compatibility.md) | Matriz de compatibilidade de hardware A3 e SoftHSM2 | Suporte & Hardware |
|
||||||
|
| [`limitations.md`](limitations.md) | Dependências de drivers e limitações declaradas | Todos |
|
||||||
|
| [`development-mode.md`](development-mode.md) | Parâmetro `--dev` e certificados de teste | Desenvolvedores Desktop |
|
||||||
|
| [`sdk.md`](sdk.md) | Guia completo da biblioteca JavaScript | Desenvolvedores Web |
|
||||||
|
| [`browser-compatibility.md`](browser-compatibility.md) | Compatibilidade de navegadores, HTTPS para loopback e Private Network Access (PNA) | Integradores Web & Segurança |
|
||||||
|
| [`ccsp-v1.schema.json`](ccsp-v1.schema.json) | JSON Schema formal e versionado do protocolo CCSP/1 | Integradores & QA |
|
||||||
|
| [`sdk-release-process.md`](sdk-release-process.md) | Processo de publicação e release do SDK no registry npm privado | DevOps & Engenharia |
|
||||||
|
| [`ui-layout.md`](ui-layout.md) | Design de interface e processamento em lote | UI/UX & Desenvolvedores |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> Dúvidas ou inconsistências? Verifique os testes unitários e de arquitetura em `modules/cybercore-core/src/test` ou consulte o arquivo [README.md principal](../README.md).
|
||||||
@@ -1,46 +1,100 @@
|
|||||||
# Certificados Digitais A1, A3 e PKCS#11
|
# Certificados Digitais A1, A3 e PKCS#11
|
||||||
|
|
||||||
O **CyberCore Signer** oferece suporte abrangente aos formatos e repositórios de certificados digitais padrão ICP-Brasil utilizados no Brasil.
|
> **Guia Técnico de Suporte a Provedores Criptográficos, Hardware PC/SC e ICP-Brasil**
|
||||||
|
|
||||||
|
O **CyberCore Signer** fornece uma camada unificada de abstração para gerenciamento e consumo de certificados digitais brasileiros padrão **ICP-Brasil**, cobrindo certificados em arquivo de software (**A1**) e dispositivos físicos criptográficos em hardware (**A3** via tokens USB e cartões inteligentes smartcards).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Certificados Digitais A1 (Software / PKCS#12)
|
## 1. Certificados Digitais A1 (Software / PKCS#12)
|
||||||
|
|
||||||
Os certificados A1 são arquivos com extensão `.pfx` ou `.p12` protegidos por senha.
|
Os certificados padrão A1 são contêineres criptográficos protegidos por senha em formato `.pfx` ou `.p12`.
|
||||||
|
|
||||||
### Fluxo de Uso
|
### 1.1 Arquitetura e Ciclo de Vida
|
||||||
1. O usuário seleciona o arquivo via diálogo nativo (`FileChooser`) na interface ou importa via tela de Dashboard.
|
1. **Importação:** O usuário seleciona o arquivo via diálogo nativo (`FileChooser`) na interface ou pelo método de importação no Dashboard.
|
||||||
2. É solicitada a senha em um diálogo seguro (`A1PasswordDialog`), mantida em `char[]` temporário e sobrescrita com zeros logo após a leitura da chave.
|
2. **Coleta Segura de Senha:** A senha é obtida por meio do diálogo `A1PasswordDialog` e armazenada estritamente em um array de caracteres `char[]` volátil. Logo após o carregamento do `KeyStore`, o array é preenchido com zeros via `Arrays.fill(passwordChars, (char) 0)`.
|
||||||
3. O provedor `Pkcs12CertificateProvider` instancia um `KeyStore.getInstance("PKCS12")` e extrai os metadados do certificado X.509 (`subject`, `issuer`, `validade`, `algoritmo`, `tamanho da chave`).
|
3. **Instanciação JCA/JCE:** O provedor `Pkcs12CertificateProvider` inicializa um `KeyStore.getInstance("PKCS12")` e extrai o certificado X.509 e o manipulador da chave privada (`PrivateKey`).
|
||||||
4. Durante a assinatura, a chave privada em memória gera a assinatura digital via `Signature.getInstance("SHA256withRSA")`.
|
4. **Isolamento de Memória:** A chave privada nunca é serializada, exportada para disco ou enviada em logs. Durante a assinatura, a chave privada em memória gera os bytes da assinatura via `Signature.getInstance("SHA256withRSA")`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Certificados Digitais A3 no Windows (Windows Certificate Store)
|
## 2. Certificados Digitais A3 no Windows (Windows Certificate Store)
|
||||||
|
|
||||||
No Windows 10/11, a maioria dos drivers de tokens USB e Smart Cards (ex: SafeSign, SafeNet Authentication Client, Serpro, Certisign) registra seus certificados diretamente no repositório de certificados do usuário (`Windows-MY`).
|
No sistema operacional Microsoft Windows (Windows 10 e Windows 11), a grande maioria dos middlewares de fabricantes de tokens e smartcards registra os certificados automaticamente no repositório de certificados pessoais do usuário (`Windows-MY`).
|
||||||
|
|
||||||
### Vantagens do Provider `WindowsCertificateStoreProvider`
|
### 2.1 Funcionamento do `WindowsCertificateStoreProvider`
|
||||||
- Acessa certificados físicos via CryptoAPI (CAPI) e Cryptography Next Generation (CNG) através do provedor JDK `SunMSCAPI`.
|
* **Integração SunMSCAPI / CNG:** O agente consome o provedor JCA nativo `SunMSCAPI` (`KeyStore.getInstance("Windows-MY")`), integrando-se diretamente à CryptoAPI e à moderna Cryptography Next Generation (CNG) do Windows.
|
||||||
- A chave privada permanece dentro do chip criptográfico do token.
|
* **Preservação no Chip Físico:** A chave privada nunca sai do chip criptográfico do token. As operações de assinatura delegam a cifragem ao módulo de segurança em hardware (HSM/Token).
|
||||||
- Quando o token exige autenticação por PIN, a janela nativa do próprio driver do fabricante é invocada com segurança pelo sistema operacional Windows.
|
* **Diálogo Nativo de PIN do Fabricante:** Quando o token exige autenticação por PIN para liberar a chave privada, a janela nativa do próprio driver do fabricante (ex: diálogo nativo SafeSign ou SafeNet) é exibida com total segurança pelo subsistema de segurança do Windows.
|
||||||
|
* **Tratamento de Chaves Não Exportáveis:** O CyberCore Signer respeita integralmente a flag de chave privada não exportável, utilizando apenas referências de handle sem tentar copiar os bytes brutos da chave.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Hardware PKCS#11 Direto (Tokens USB e Smartcards)
|
## 3. Acesso Direto a Hardware PKCS#11 (Tokens USB e Smartcards)
|
||||||
|
|
||||||
Para ambientes onde se deseja acesso direto ao middleware ou no Linux:
|
Para ambientes corporativos que requerem comunicação direta com bibliotecas de middleware ou para execução em ambientes Linux, o componente `Pkcs11CertificateProvider` interage com o driver PKCS#11 do fabricante através do módulo do JDK `jdk.crypto.cryptoki` (`SunPKCS11`).
|
||||||
- `Pkcs11CertificateProvider` pesquisa bibliotecas DLL / SO padrão:
|
|
||||||
- `eps2003csp11.dll` (SafeNet / eToken)
|
### 3.1 Mapeamento de Middlewares Homologados no Brasil
|
||||||
- `aetpkss1.dll` (SafeSign AET)
|
|
||||||
- `acospkcs11.dll` (ACOS / G&D)
|
O CyberCore Signer possui rotinas automáticas de varredura nos diretórios padrão do sistema (`System32`, `SysWOW64` no Windows e `/usr/lib/`, `/usr/local/lib/` no Linux):
|
||||||
- `opensc-pkcs11.dll` / `opensc-pkcs11.so` (OpenSC)
|
|
||||||
- Utiliza o provider SunPKCS11 do JDK (`jdk.crypto.cryptoki`).
|
| Fabricante / Modelo | Biblioteca Windows (DLL) | Biblioteca Linux (.so) | Tipo de Dispositivo |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **SafeSign Identity Client** (AET / GD) | `aetpkss1.dll` | `libaetpkss.so` | Tokens e Smartcards (Certisign, Valid, Serasa) |
|
||||||
|
| **SafeNet Authentication Client** (Gemalto / Thales) | `eps2003csp11.dll`, `eTPKCS11.dll` | `libeTPkcs11.so` | Tokens eToken Pro / 5110 (Serpro, Safeweb) |
|
||||||
|
| **ACOS / Oberthur** (Idemia) | `acospkcs11.dll`, `OcsCryptoki.dll` | `libacospkcs11.so` | Smartcards e leitores de cartão |
|
||||||
|
| **Watchdata / PROXKey** | `Watchdata ProxKey PKCS11.dll` | `libwatchdata.so` | Tokens USB |
|
||||||
|
| **OpenSC (Padrão Aberto)** | `opensc-pkcs11.dll` | `opensc-pkcs11.so` | Leitores genéricos PC/SC e smartcards |
|
||||||
|
|
||||||
|
### 3.2 Configuração Dinâmica do Provedor SunPKCS11
|
||||||
|
A configuração do provedor é criada dinamicamente em memória (sem gravar arquivos temporários em disco com dados sensíveis):
|
||||||
|
|
||||||
|
```properties
|
||||||
|
name = CyberCore-Token
|
||||||
|
library = C:\Windows\System32\aetpkss1.dll
|
||||||
|
slotListIndex = 0
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Monitoramento Dinâmico de Hardware (`SmartCardWatcher`)
|
## 4. Monitoramento Dinâmico de Hardware (`SmartCardWatcher`)
|
||||||
|
|
||||||
O componente `SmartCardWatcher` monitora os leitores PC/SC em segundo plano:
|
O componente `SmartCardWatcher` executa um loop em segundo plano baseado na API padrão `javax.smartcardio` (subsistema PC/SC):
|
||||||
- **Ao inserir um token:** Atualiza a lista de certificados automaticamente e notifica a interface gráfica.
|
|
||||||
- **Ao remover o token:** Registra evento de auditoria (`AUDITORIA [TOKEN_REMOVED]`), limpa o cache de PIN de sessão em `PinSessionManager` e força um warm reset via `SmartCardSessionManager`.
|
1. **Detecção de Conexão (Card Inserted):**
|
||||||
|
- Detecta quando um novo smartcard ou token USB é conectado a qualquer leitora do sistema.
|
||||||
|
- Dispara recarregamento assíncrono do repositório de certificados.
|
||||||
|
- Notifica a interface gráfica (`UIEventListener`) e emite evento de auditoria (`AUDITORIA [TOKEN_INSERTED]`).
|
||||||
|
2. **Detecção de Desconexão (Card Removed):**
|
||||||
|
- Ao detectar a remoção do dispositivo, registra imediatamente o evento de auditoria `AUDITORIA [TOKEN_REMOVED]`.
|
||||||
|
- Limpa e zera os buffers de memória de PIN mantidos pelo `PinSessionManager`.
|
||||||
|
- Força o encerramento das conexões com o leitor via `SmartCardSessionManager` para liberar handles travados no sistema operacional.
|
||||||
|
3. **Serialização de Concorrência (`signLock`):**
|
||||||
|
- Como grande parte dos drivers de smartcard e chips criptográficos físicos não suporta acesso concorrente multi-thread, todas as requisições de assinatura são processadas de forma estritamente sequencial (fila FIFO garantida por `ReentrantLock`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Extração e Parsing de Identidade ICP-Brasil (OIDs X.509)
|
||||||
|
|
||||||
|
O CyberCore Signer implementa o analisador de extensões X.509 conforme os padrões da **Infraestrutura de Chaves Públicas Brasileira (ICP-Brasil)** estabelecidos pelo ITI (normas DOC-ICP-04).
|
||||||
|
|
||||||
|
As informações são extraídas da extensão `SubjectAlternativeName` (OID `2.5.29.17`) e analisadas a partir de seus identificadores de objeto (OIDs):
|
||||||
|
|
||||||
|
### 5.1 OID ICP-Brasil de Pessoa Física (e-CPF) — `2.16.76.1.3.1`
|
||||||
|
Contém uma estrutura ASN.1 com as informações cadastrais do titular:
|
||||||
|
* **Data de Nascimento:** 8 caracteres no formato `DDMMAAAA`;
|
||||||
|
* **CPF do Titular:** 11 dígitos numéricos;
|
||||||
|
* **Número do NIS/PIS/PASEP:** 11 dígitos numéricos;
|
||||||
|
* **Registro Geral (RG):** Número do documento de identidade;
|
||||||
|
* **Órgão Expedidor e UF:** Identificação do órgão emissor.
|
||||||
|
|
||||||
|
### 5.2 OID ICP-Brasil de Pessoa Jurídica (e-CNPJ) — `2.16.76.1.3.3`
|
||||||
|
Contém os dados cadastrais da empresa e do seu representante legal:
|
||||||
|
* **CNPJ da Entidade:** 14 dígitos numéricos;
|
||||||
|
* **Nome do Responsável:** Nome completo do signatário cadastrado na Receita Federal.
|
||||||
|
|
||||||
|
### 5.3 Demais OIDs Mapeados
|
||||||
|
* **OID `2.16.76.1.3.2`:** Título de Eleitor, zona e seção eleitoral.
|
||||||
|
* **OID `2.16.76.1.3.4`:** Cadastro Específico do INSS (CEI / CAEPF).
|
||||||
|
|
||||||
|
Essa extração permite ao agente preencher automaticamente o nome e documento do signatário para o SDK Web e selos visuais em PDF, garantindo conformidade com a legislação e auditoria fiscal.
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
# Arquitetura do CyberCore Signer
|
# Arquitetura do CyberCore Signer
|
||||||
|
|
||||||
O **CyberCore Signer** é um agente desktop nativo desenvolvido em Java 21+ LTS (Java 25 LTS) com interface JavaFX e segurança criptográfica JCA/JCE pura, projetado para permitir que aplicações web autorizadas solicitem assinaturas digitais ICP-Brasil padrão **A1** e **A3** diretamente da máquina do usuário.
|
> **Especificação da Arquitetura Modular, Modelo de Threads e Fluxo Criptográfico**
|
||||||
|
|
||||||
|
O **CyberCore Signer** foi concebido a partir de princípios de alta coesão, baixo acoplamento e estrito isolamento de camadas. O software é desenvolvido em **Java 25 LTS**, utilizando o runtime modular do JDK, JavaFX para a camada de apresentação e os provedores JCA/JCE da plataforma para operações criptográficas seguras.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Visão Geral da Arquitetura em Módulos
|
## 1. Visão Geral da Arquitetura em Módulos
|
||||||
|
|
||||||
O projeto adota uma arquitetura desacoplada em múltiplos módulos Maven independentes:
|
O projeto adota uma divisão modular rigorosa no Maven, garantindo que regras de negócio e algoritmos de criptografia nunca se acoplem a componentes visuais:
|
||||||
|
|
||||||
```
|
```
|
||||||
cybercore-signer/
|
cybercore-signer/
|
||||||
@@ -19,43 +21,75 @@ cybercore-signer/
|
|||||||
└── docs/ # Especificações técnicas e manuais de integração
|
└── docs/ # Especificações técnicas e manuais de integração
|
||||||
```
|
```
|
||||||
|
|
||||||
### 1.1 `cybercore-core`
|
### 1.1 Módulo `cybercore-core` (Agnóstico de UI)
|
||||||
- **Domínio:** Modelos imutáveis como `ManagedCertificate`, `SigningContext`, `SigningResult`, `CertificateType` e `CertificateStatus`.
|
O módulo de núcleo é totalmente independente de JavaFX ou bibliotecas visuais:
|
||||||
- **Criptografia:** `SigningService` e `DigestAlgorithm` utilizando exclusivamente os provedores padrão JCA/JCE (sem reimplementação manual de algoritmos).
|
* **Domínio Imutável:** Modelos imutáveis (`ManagedCertificate`, `SigningContext`, `SigningResult`, `CertificateType`, `CertificateStatus`).
|
||||||
- **Provedores:** Abstração `CertificateProvider` com implementações:
|
* **Serviços de Assinatura:** `SigningService` orquestra a aplicação de algoritmos certificados (`SHA256withRSA`) delegando a operação ao provedor de certificado resolvido.
|
||||||
- `Pkcs12CertificateProvider`: leitura de arquivos `.pfx`/`.p12` em memória protegida.
|
* **Provedores de Certificados (`CertificateProvider`):** Abstração que unifica:
|
||||||
- `WindowsCertificateStoreProvider`: integração nativa com o repositório de chaves do Windows (`Windows-MY` via SunMSCAPI/CNG).
|
- `Pkcs12CertificateProvider`: leitura de arquivos `.pfx`/`.p12` em memória com limpeza volátil de senha.
|
||||||
- `Pkcs11CertificateProvider`: integração com drivers de middleware e tokens USB/Smartcards via `SunPKCS11`.
|
- `WindowsCertificateStoreProvider`: integração com o repositório nativo do Windows (`Windows-MY` via SunMSCAPI/CNG).
|
||||||
- **Protocolo & Rede Local:** `CcspServer` escuta estritamente em `127.0.0.1:21325`, fornecendo a API REST CCSP/1.
|
- `Pkcs11CertificateProvider`: integração direta com bibliotecas dinâmicas (DLL/SO) de drivers e tokens USB através do SunPKCS11.
|
||||||
- **Segurança & Configurações:** `ApplicationRegistry`, `NonceManager` (proteção anti-replay), `OriginValidator`, `SmartCardSessionManager` e `AgentConfigurationService` (persistência em `~/.cybercore/config.json`).
|
* **Protocolo e Rede Local:** `CcspServer` escuta exclusivamente em `127.0.0.1:21325`, fornecendo a API REST CCSP/1 com validação de origens e controle de concorrência.
|
||||||
- **Validação Criptográfica:** `SignatureValidationService` com suporte a Assinaturas Incorporadas (PAdES PDF, CMS/P7M com conteúdo embutido, XMLDSig) e Assinaturas Destacadas (Detached CMS/P7S).
|
* **Segurança e Persistência:** `ApplicationRegistry`, `NonceManager` (proteção anti-replay), `OriginValidator`, `SmartCardSessionManager` e `AgentConfigurationService` com armazenamento persistente em diretório de usuário (`~/.cybercore/`).
|
||||||
- **Selos Visuais Personalizados:** `CustomSealStorage` (persistência em `~/.cybercore/seals/`), `PdfSealThemeRegistry` dinâmico e `CpfDisplayMode` (privacidade LGPD).
|
* **Assinatura de Documentos e Validação:** `PdfSigningService` (PAdES com salvamento incremental e carimbo TSA via PDFBox e Bouncy Castle), `XmlSigningService` (XAdES-BES e XMLDSig via `javax.xml.crypto`) e `SignatureValidationService` para conferência de integridade e signatários.
|
||||||
|
|
||||||
### 1.2 `cybercore-ui`
|
### 1.2 Módulo `cybercore-ui` (Apresentação JavaFX)
|
||||||
- Interface desenvolvida com JavaFX 25, empregando layout moderno e simétrico de grade 3x3 de operações e coluna lateral de utilitários:
|
Responsável por toda a interação com o usuário:
|
||||||
- `MainAppView`: grade 3x3 otimizada:
|
* **Interface Principal (`MainAppView`):** Painel de navegação moderno com alternador dinâmico de tema (Claro/Escuro), grade de operações rápidas (PDF, XML, Assinatura Atachada, Designer de Selos, Validar Assinatura, Sair do Agente) e coluna lateral de utilitários (Logs em tempo real, Configurações, Tutorial, Certificados e Sobre).
|
||||||
- Linha 0: Assinar PDF, Assinar XML, Assinatura Atachada
|
* **Diálogos de Consentimento e PIN:** Modais nativos de aprovação visual para requisições do protocolo CCSP/1 (`SignatureConfirmationDialog`, `ApplicationAuthorizeDialog`) e coleta segura de PIN de tokens (`A1PasswordDialog`).
|
||||||
- Linha 1: Co-Assinar Documento, Carimbo do Tempo, Gerenciar Selos
|
* **Designer de Selos Digitais (`SealDesignerDialog`):** Ferramenta com Live Preview para criação de selos visuais com controle de cores, estilo de brasão, exibição de nome completo sem truncamento e privacidade de CPF.
|
||||||
- Linha 2: Validar Assinatura, Validar Carimbo, Sair do Agente
|
* **Bandeja do Sistema (System Tray):** Execução minimizada com menu de contexto rápido para restauração da tela ou encerramento da sessão.
|
||||||
- `SealDesignerDialog`: criador e instalador de selos digitais personalizados com pré-visualização ao vivo (Live Preview), seletores de cores, estilos de emblema, obrigatoriedade de nome completo, controle de mascaramento de CPF e estampa de data/hora.
|
|
||||||
- `SignatureValidationDialog`: diálogo de validação criptográfica real com alternância entre Assinatura Incorporada e Assinatura Destacada, extração de documento embutido e relatório de signatários.
|
|
||||||
- `PdfSignDialog`: modal de assinatura PAdES com posicionamento por clique na folha, atalho direto para criar/instalar selos e opções dinâmicas de CPF/data-hora.
|
|
||||||
- `SettingsView`: configurações gerais persistentes, política de PIN e gerenciamento de selos instalados.
|
|
||||||
|
|
||||||
### 1.3 `cybercore-app`
|
### 1.3 Módulo `cybercore-app` (Orquestração e Bootstrap)
|
||||||
- Main bootstrap (`CyberCoreSignerApplication`).
|
Ponto de partida da aplicação (`CyberCoreApp`):
|
||||||
- Tratamento de parâmetros de inicialização (`--dev`, `--headless`).
|
* Processa argumentos de linha de comando (`--dev`, `--headless`).
|
||||||
- Execução de diagnósticos preliminares de ambiente e engine criptográfica antes do início das threads de escuta.
|
* Executa rotinas de diagnóstico pré-inicialização do ambiente Java e disponibilidade criptográfica.
|
||||||
- Geração de Fat JAR autocontido via `maven-shade-plugin` e preparação para distribuição `jpackage`.
|
* Inicia o `CcspServer` em segundo plano e abre a interface gráfica na `JavaFX Application Thread`.
|
||||||
|
* Empacota o executável consolidado via `maven-shade-plugin` e orquestra o build nativo via `jpackage`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Fluxo de Dados e Princípio de Menor Privilégio
|
## 2. Modelo de Threads e Concorrência
|
||||||
|
|
||||||
O CyberCore Signer opera sob o **modelo de assinatura descentralizada por digest**:
|
Para manter a interface gráfica sempre fluida e ágil, o CyberCore Signer utiliza um particionamento rígido de threads:
|
||||||
1. A aplicação web calcula o hash criptográfico SHA-256 no próprio navegador utilizando a Web Crypto API nativa.
|
|
||||||
2. Apenas o hash Base64 de 32 bytes trafega localmente para o CyberCore Signer.
|
```mermaid
|
||||||
3. O documento completo nunca sai do navegador e a chave privada nunca sai do computador ou do hardware do usuário.
|
graph TD
|
||||||
|
subgraph UI Layer
|
||||||
|
JFX[JavaFX Application Thread]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph Local Protocol Layer
|
||||||
|
HTTPPool[CcspServer Worker Pool (FixedThreadPool 8)]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph Background Services
|
||||||
|
Watcher[SmartCardWatcher Thread (PC/SC Loop)]
|
||||||
|
AsyncTasks[JavaFX Task / CompletableFuture Workers]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph Hardware Critical Section
|
||||||
|
Lock[Trava Serializada FIFO: signLock]
|
||||||
|
Hardware[Token Físico A3 / SmartCard Driver]
|
||||||
|
end
|
||||||
|
|
||||||
|
HTTPPool -->|Solicita Aprovação Visual| JFX
|
||||||
|
JFX -->|Consentimento Concedido| HTTPPool
|
||||||
|
HTTPPool --> Lock
|
||||||
|
AsyncTasks --> Lock
|
||||||
|
Lock --> Hardware
|
||||||
|
```
|
||||||
|
|
||||||
|
1. **JavaFX Application Thread:** Dedicada exclusivamente à renderização da interface e tratamento de eventos visuais. Nenhuma operação criptográfica, leitura de disco ou chamada de rede é executada nesta thread.
|
||||||
|
2. **CcspServer Worker Pool:** Pool de 8 threads daemon dedicadas ao atendimento de requisições HTTP da API REST CCSP/1.
|
||||||
|
3. **SmartCardWatcher Thread:** Thread daemon isolada que executa `cardTerminal.waitForCardPresent()` e `waitForCardAbsent()` para monitorar hardware PC/SC sem onerar a CPU.
|
||||||
|
4. **Trava Serializada FIFO (`signLock`):** Implementada via `ReentrantLock(true)`. Garante que operações de assinatura em cartões inteligentes físicos sejam enfileiradas ordenadamente, prevenindo falhas de hardware e estados corrompidos em drivers de fabricantes mono-thread.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Fluxo de Dados e Assinatura Descentralizada por Digest
|
||||||
|
|
||||||
|
A arquitetura do CyberCore Signer prioriza a privacidade e o modelo de **assinatura por digest**:
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
@@ -66,14 +100,25 @@ sequenceDiagram
|
|||||||
participant UI as CyberCore JavaFX
|
participant UI as CyberCore JavaFX
|
||||||
participant Crypto as SigningService & Providers
|
participant Crypto as SigningService & Providers
|
||||||
|
|
||||||
Web->>CCSP: POST /ccsp/v1/sign (digest, appId, certHint, nonce)
|
Web->>CCSP: POST /ccsp/v1/sign (digest, appId, certHint, nonce, expires_at)
|
||||||
CCSP->>CCSP: Valida autorização, nonce anti-replay e digest
|
CCSP->>CCSP: Valida autorização, nonce anti-replay e integridade do digest
|
||||||
CCSP->>UI: Solicita confirmação visual (requestSignatureConfirmation)
|
CCSP->>UI: Solicita confirmação visual (requestSignatureConfirmation)
|
||||||
UI->>Usuario: Exibe Diálogo (Hash, Certificado, Aplicação)
|
UI->>Usuario: Exibe Diálogo Nativo (Nome do Documento, Hash SHA-256, Certificado)
|
||||||
Usuario->>UI: Aprova assinatura (e insere PIN se A3)
|
Usuario->>UI: Clica em "Autorizar Assinatura" (e digita PIN se requerido)
|
||||||
UI-->>CCSP: Confirmação concedida
|
UI-->>CCSP: Confirmação concedida
|
||||||
CCSP->>Crypto: sign(SigningContext) [Trava FIFO]
|
CCSP->>Crypto: sign(SigningContext) sob signLock.lock()
|
||||||
Crypto->>Crypto: JCA/JCE Signature.update(digest) + sign()
|
Crypto->>Crypto: JCA/JCE Signature.update(digest) + sign()
|
||||||
Crypto-->>CCSP: SigningResult (signatureBytes, certChain)
|
Crypto-->>CCSP: SigningResult (signatureBytes, certChain)
|
||||||
CCSP-->>Web: JSON { status: "signed", signature: "...", certificate: "..." }
|
CCSP-->>Web: 200 OK JSON { status: "signed", signature: "Base64", certificate: "Base64" }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Persistência de Dados e Configurações
|
||||||
|
|
||||||
|
Todos os dados de configuração e personalizações do usuário são armazenados no diretório do usuário no sistema operacional:
|
||||||
|
|
||||||
|
* **Diretório Base:** `~/.cybercore/` (ou `%USERPROFILE%\.cybercore\` no Windows).
|
||||||
|
* **`config.json`:** Configurações globais do agente (política de cache de PIN, tema padrão, selo padrão ativo).
|
||||||
|
* **`authorized-apps.json`:** Registro de aplicações web autorizadas pelo usuário, contendo `application_id`, nome amigável e data da aprovação.
|
||||||
|
* **`seals/*.json`:** Selos visuais SVG personalizados criados ou importados pelo usuário no designer de selos.
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
# Compatibilidade de Navegadores e Acesso de Rede Privada (CCSP/1)
|
||||||
|
|
||||||
|
Este documento detalha o funcionamento, as garantias de segurança e os requisitos de compatibilidade entre aplicações web (servidas sob **HTTPS**) e o agente desktop **CyberCore Signer** em loopback local (`http://127.0.0.1:21325`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Contexto Arquitetural: HTTPS para Loopback HTTP
|
||||||
|
|
||||||
|
Tradicionalmente, navegadores modernos impedem o carregamento de recursos inseguros (`http://`) a partir de contextos seguros (`https://`), mecanismo conhecido como **Mixed Content**.
|
||||||
|
|
||||||
|
No entanto, para agentes de assinatura digital locais e periféricos de hardware, o consórcio **W3C (Secure Contexts Specification)** e os motores de renderização modernos tratam o loopback IPv4 (`127.0.0.1`) e `localhost` como **Origens Potencialmente Confiáveis (*Potentially Trustworthy Origins*)**.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
autonumber
|
||||||
|
participant Web as Aplicação Web (HTTPS)
|
||||||
|
participant Browser as Navegador (Chrome/Firefox/Safari)
|
||||||
|
participant Agent as CyberCore Signer (127.0.0.1:21325)
|
||||||
|
|
||||||
|
Note over Web,Agent: 1. Preflight CORS + Private Network Access (PNA)
|
||||||
|
Web->>Browser: fetch("http://127.0.0.1:21325/ccsp/v1/sign", { method: "POST" })
|
||||||
|
Browser->>Agent: OPTIONS /ccsp/v1/sign<br/>Origin: https://meusistema.com.br<br/>Access-Control-Request-Private-Network: true
|
||||||
|
Agent-->>Browser: HTTP 204 No Content<br/>Access-Control-Allow-Origin: *<br/>Access-Control-Allow-Private-Network: true<br/>Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||||
|
Note over Browser,Agent: 2. Requisição Real CCSP/1
|
||||||
|
Browser->>Agent: POST /ccsp/v1/sign (JSON Digest)
|
||||||
|
Agent-->>Browser: HTTP 200 OK (Assinatura Base64)
|
||||||
|
Browser-->>Web: Retorno Promise Resolvida
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Private Network Access (PNA / W3C)
|
||||||
|
|
||||||
|
O **Private Network Access (PNA)** é uma especificação de segurança do W3C (adotada inicialmente pelo motor Chromium a partir do Chrome 98+) com o objetivo de proteger a rede local contra ataques de Cross-Site Request Forgery (CSRF).
|
||||||
|
|
||||||
|
### Como a especificação classifica as redes:
|
||||||
|
1. **Pública (*public*):** A internet pública (ex: `https://meusistema.com.br`).
|
||||||
|
2. **Privada (*private*):** Redes locais RFC 1918 (ex: `192.168.x.x`, `10.x.x.x`).
|
||||||
|
3. **Local (*local*):** A máquina do próprio usuário (`127.0.0.1`, `localhost`).
|
||||||
|
|
||||||
|
Quando uma página em um espaço de IP mais público solicita um recurso em um espaço mais restrito (como `public` $\rightarrow$ `local`), o navegador dispara uma requisição preliminar **Preflight PNA**.
|
||||||
|
|
||||||
|
### Headers Enviados pelo Navegador:
|
||||||
|
```http
|
||||||
|
OPTIONS /ccsp/v1/sign HTTP/1.1
|
||||||
|
Host: 127.0.0.1:21325
|
||||||
|
Origin: https://meusistema.com.br
|
||||||
|
Access-Control-Request-Method: POST
|
||||||
|
Access-Control-Request-Headers: Content-Type, X-CyberCore-AppId
|
||||||
|
Access-Control-Request-Private-Network: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resposta Padrão do CyberCore Signer (`CcspServer`):
|
||||||
|
O servidor do agente desktop intercepta requisições `OPTIONS` e responde imediatamente com:
|
||||||
|
```http
|
||||||
|
HTTP/1.1 204 No Content
|
||||||
|
Access-Control-Allow-Origin: *
|
||||||
|
Access-Control-Allow-Methods: GET, POST, OPTIONS
|
||||||
|
Access-Control-Allow-Headers: Content-Type, Authorization, X-CyberCore-AppId, Origin, Accept
|
||||||
|
Access-Control-Allow-Private-Network: true
|
||||||
|
Access-Control-Max-Age: 86400
|
||||||
|
Connection: close
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> O cabeçalho `Access-Control-Allow-Private-Network: true` é fundamental para autorizar o navegador a enviar requisições privadas originadas de sites HTTPS públicos.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Matriz de Compatibilidade de Navegadores
|
||||||
|
|
||||||
|
| Navegador | Versão Mínima | Suporte HTTPS $\rightarrow$ 127.0.0.1 | Comportamento PNA | Requer Ação do Usuário? |
|
||||||
|
| :--- | :---: | :---: | :---: | :---: |
|
||||||
|
| **Google Chrome** | 88+ | ✅ Suportado | PNA ativo com preflight | Não (automático) |
|
||||||
|
| **Microsoft Edge** | 88+ | ✅ Suportado | PNA ativo com preflight | Não (automático) |
|
||||||
|
| **Mozilla Firefox** | 84+ | ✅ Suportado | Trata 127.0.0.1 como Secure Context | Não (automático) |
|
||||||
|
| **Opera / Brave** | Recentes | ✅ Suportado | Idêntico ao Chromium (ver nota Brave) | Pode exigir ajuste no Shields |
|
||||||
|
| **Apple Safari** | 15.4+ (macOS) | ✅ Suportado | Trata loopback como seguro | Não |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Casos de Borda e Soluções (Troubleshooting)
|
||||||
|
|
||||||
|
### 4.1. Navegador Brave (Brave Shields)
|
||||||
|
O Brave possui um mecanismo agressivo de proteção que pode bloquear preflights para `127.0.0.1`.
|
||||||
|
- **Sintoma:** O SDK lança `AgentNotRunningError`, mesmo com o agente em execução.
|
||||||
|
- **Resolução:** O usuário deve clicar no ícone do escudo (Shields) na barra de endereços da aplicação e desativar temporariamente o bloqueio para a origem ou permitir conexões locais nas configurações (`brave://settings/shields`).
|
||||||
|
|
||||||
|
### 4.2. Extensões de Privacidade e AdBlockers
|
||||||
|
Extensões como *uBlock Origin*, *Privacy Badger* ou *NoScript* podem conter regras genéricas de bloqueio para portas locais.
|
||||||
|
- **Resolução:** Adicionar a URL da sua aplicação web à lista de permissões (*allowlist*) da extensão.
|
||||||
|
|
||||||
|
### 4.3. Softwares de Antivírus e Endpoint Protection
|
||||||
|
Alguns antivírus com módulo de "Proteção Web" ou "Inspeção HTTPS" tentam atuar como proxy transparente no loopback local:
|
||||||
|
- **Resolução:** Configurar o antivírus para excluir a porta `21325` da inspeção de tráfego local.
|
||||||
|
|
||||||
|
### 4.4. Políticas Corporativas de Grupo (GPO / Chromium Enterprise)
|
||||||
|
Em ambientes corporativos restritos, administradores de rede podem bloquear chamadas a redes privadas via política:
|
||||||
|
- Política Chromium: `InsecurePrivateNetworkRequestsAllowed` ou `InsecurePrivateNetworkRequestsAllowedForUrls`.
|
||||||
|
- **Resolução:** Adicionar a URL do portal web corporativo na política `InsecurePrivateNetworkRequestsAllowedForUrls`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Boas Práticas para Desenvolvedores Web
|
||||||
|
|
||||||
|
1. **Use sempre o SDK `@cybercore/signer-sdk`:** Ele gerencia timeouts, fallbacks de preflight e detecção de conectividade.
|
||||||
|
2. **Utilize `isInstalled()` antes de iniciar fluxos de assinatura:**
|
||||||
|
```javascript
|
||||||
|
import { CyberCoreSigner } from '@cybercore/signer-sdk';
|
||||||
|
|
||||||
|
const signer = new CyberCoreSigner();
|
||||||
|
|
||||||
|
if (!(await signer.isInstalled())) {
|
||||||
|
mostrarModalInstalacaoAgente();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
3. **Capture `AgentNotRunningError` e exiba o guia de ajuda:**
|
||||||
|
```javascript
|
||||||
|
import { AgentNotRunningError } from '@cybercore/signer-sdk';
|
||||||
|
|
||||||
|
try {
|
||||||
|
await signer.connect();
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof AgentNotRunningError) {
|
||||||
|
console.info(err.actionableGuidance);
|
||||||
|
exibirAjudaAoUsuario(err.actionableGuidance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,417 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "https://cybercore.com.br/schemas/ccsp-v1.json",
|
||||||
|
"title": "CyberCore Signing Protocol v1 (CCSP/1) Specification",
|
||||||
|
"description": "Especificação formal do protocolo JSON para comunicação local entre aplicações web e o agente desktop CyberCore Signer.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"version": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["1"],
|
||||||
|
"description": "Versão do protocolo CCSP (sempre '1' para CCSP/1)."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
"ErrorCode": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"CERTIFICATE_NOT_FOUND",
|
||||||
|
"CERTIFICATE_EXPIRED",
|
||||||
|
"CERTIFICATE_INVALID",
|
||||||
|
"PRIVATE_KEY_NOT_AVAILABLE",
|
||||||
|
"TOKEN_NOT_FOUND",
|
||||||
|
"TOKEN_REMOVED",
|
||||||
|
"PIN_REQUIRED",
|
||||||
|
"PIN_INCORRECT",
|
||||||
|
"PKCS11_ERROR",
|
||||||
|
"SIGNATURE_FAILED",
|
||||||
|
"APPLICATION_NOT_AUTHORIZED",
|
||||||
|
"REQUEST_EXPIRED",
|
||||||
|
"REPLAY_DETECTED",
|
||||||
|
"INVALID_ORIGIN",
|
||||||
|
"INVALID_HOST",
|
||||||
|
"UNSUPPORTED_ALGORITHM",
|
||||||
|
"USER_CANCELLED",
|
||||||
|
"PROVIDER_NOT_AVAILABLE",
|
||||||
|
"COMMUNICATION_ERROR",
|
||||||
|
"AGENT_NOT_RUNNING",
|
||||||
|
"TIMEOUT_ERROR",
|
||||||
|
"BAD_REQUEST",
|
||||||
|
"METHOD_NOT_ALLOWED"
|
||||||
|
],
|
||||||
|
"description": "Códigos formais de erro estruturados do protocolo CCSP/1."
|
||||||
|
},
|
||||||
|
|
||||||
|
"ErrorResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["version", "status", "error_code", "message"],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"status": { "type": "string", "enum": ["error"] },
|
||||||
|
"error_code": { "$ref": "#/definitions/ErrorCode" },
|
||||||
|
"message": { "type": "string" },
|
||||||
|
"request_id": { "type": ["string", "null"] }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"StatusResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["version", "status", "agent", "agent_version", "os", "timestamp"],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"status": { "type": "string", "enum": ["ready", "busy", "error"] },
|
||||||
|
"agent": { "type": "string" },
|
||||||
|
"agent_version": { "type": "string" },
|
||||||
|
"os": { "type": "string" },
|
||||||
|
"timestamp": { "type": "string" }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"AuthorizeRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["version", "application_id"],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"application_id": { "type": "string", "pattern": "^[0-9a-fA-F-]{36}$" },
|
||||||
|
"name": { "type": "string" }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"AuthorizeResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["version", "status", "application_id"],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"status": { "type": "string", "enum": ["authorized"] },
|
||||||
|
"application_id": { "type": "string" },
|
||||||
|
"message": { "type": "string" }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"CertificateItem": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "alias", "type", "can_sign", "status"],
|
||||||
|
"properties": {
|
||||||
|
"id": { "type": "string" },
|
||||||
|
"alias": { "type": "string" },
|
||||||
|
"common_name": { "type": ["string", "null"] },
|
||||||
|
"subject_dn": { "type": ["string", "null"] },
|
||||||
|
"issuer_dn": { "type": ["string", "null"] },
|
||||||
|
"type": { "type": "string", "enum": ["A1", "A3"] },
|
||||||
|
"provider_id": { "type": ["string", "null"] },
|
||||||
|
"device_name": { "type": ["string", "null"] },
|
||||||
|
"valid_from": { "type": ["string", "null"] },
|
||||||
|
"valid_to": { "type": ["string", "null"] },
|
||||||
|
"serial_number": { "type": ["string", "null"] },
|
||||||
|
"cpf": { "type": ["string", "null"] },
|
||||||
|
"cnpj": { "type": ["string", "null"] },
|
||||||
|
"can_sign": { "type": "boolean" },
|
||||||
|
"status": { "type": "string" }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"CertificatesResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["version", "status", "certificates"],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"status": { "type": "string", "enum": ["success"] },
|
||||||
|
"certificates": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "$ref": "#/definitions/CertificateItem" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"SealThemeItem": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "name"],
|
||||||
|
"properties": {
|
||||||
|
"id": { "type": "string" },
|
||||||
|
"name": { "type": "string" },
|
||||||
|
"description": { "type": ["string", "null"] },
|
||||||
|
"width": { "type": "number" },
|
||||||
|
"height": { "type": "number" },
|
||||||
|
"primary_color": { "type": ["string", "null"] },
|
||||||
|
"secondary_color": { "type": ["string", "null"] },
|
||||||
|
"background_color": { "type": ["string", "null"] },
|
||||||
|
"border_color": { "type": ["string", "null"] },
|
||||||
|
"text_color": { "type": ["string", "null"] },
|
||||||
|
"icon_style": { "type": ["string", "null"] },
|
||||||
|
"custom": { "type": "boolean" }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"SealsResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["version", "status", "seals"],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"status": { "type": "string", "enum": ["success"] },
|
||||||
|
"default_seal_id": { "type": ["string", "null"] },
|
||||||
|
"seals": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "$ref": "#/definitions/SealThemeItem" }
|
||||||
|
},
|
||||||
|
"themes": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "$ref": "#/definitions/SealThemeItem" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"SignRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"request_id",
|
||||||
|
"application_id",
|
||||||
|
"operation",
|
||||||
|
"algorithm",
|
||||||
|
"digest",
|
||||||
|
"nonce",
|
||||||
|
"expires_at"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"request_id": { "type": "string" },
|
||||||
|
"application_id": { "type": "string" },
|
||||||
|
"operation": { "type": "string", "enum": ["sign", "authenticate"] },
|
||||||
|
"algorithm": { "type": "string" },
|
||||||
|
"digest": { "type": "string", "description": "Digest SHA-256 em Base64" },
|
||||||
|
"certificate_hint": { "type": ["string", "null"] },
|
||||||
|
"document_name": { "type": ["string", "null"] },
|
||||||
|
"document_type": { "type": ["string", "null"] },
|
||||||
|
"purpose": { "type": ["string", "null"] },
|
||||||
|
"challenge": { "type": ["string", "null"] },
|
||||||
|
"nonce": { "type": "string" },
|
||||||
|
"expires_at": { "type": "string" }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"SignResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"request_id",
|
||||||
|
"status",
|
||||||
|
"signature",
|
||||||
|
"certificate",
|
||||||
|
"algorithm"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"request_id": { "type": "string" },
|
||||||
|
"status": { "type": "string", "enum": ["signed", "authenticated"] },
|
||||||
|
"signature": { "type": "string", "description": "Assinatura digital em Base64" },
|
||||||
|
"certificate": { "type": "string", "description": "Certificado X.509 do signatário em Base64" },
|
||||||
|
"certificate_chain": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "type": "string" }
|
||||||
|
},
|
||||||
|
"algorithm": { "type": "string" },
|
||||||
|
"sha256": { "type": ["string", "null"] },
|
||||||
|
"subject_name": { "type": ["string", "null"] },
|
||||||
|
"subject_cpf_cnpj": { "type": ["string", "null"] },
|
||||||
|
"document_name": { "type": ["string", "null"] },
|
||||||
|
"document_type": { "type": ["string", "null"] },
|
||||||
|
"challenge": { "type": ["string", "null"] }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"SignPdfRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"request_id",
|
||||||
|
"application_id",
|
||||||
|
"operation",
|
||||||
|
"pdf",
|
||||||
|
"nonce",
|
||||||
|
"expires_at"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"request_id": { "type": "string" },
|
||||||
|
"application_id": { "type": "string" },
|
||||||
|
"operation": { "type": "string", "enum": ["sign_pdf"] },
|
||||||
|
"pdf": { "type": "string", "description": "Documento PDF completo codificado em Base64" },
|
||||||
|
"certificate_hint": { "type": ["string", "null"] },
|
||||||
|
"document_name": { "type": ["string", "null"] },
|
||||||
|
"page": { "type": ["integer", "null"] },
|
||||||
|
"page_choice": { "type": ["string", "null"] },
|
||||||
|
"position": { "type": ["string", "null"] },
|
||||||
|
"x": { "type": ["number", "null"] },
|
||||||
|
"y": { "type": ["number", "null"] },
|
||||||
|
"scale": { "type": ["number", "null"] },
|
||||||
|
"visible_seal": { "type": ["boolean", "null"] },
|
||||||
|
"seal_theme_id": { "type": ["string", "null"] },
|
||||||
|
"seal_custom": { "type": ["object", "null"] },
|
||||||
|
"reason": { "type": ["string", "null"] },
|
||||||
|
"location": { "type": ["string", "null"] },
|
||||||
|
"cpf_display_mode": { "type": ["string", "null"] },
|
||||||
|
"include_date_time": { "type": ["boolean", "null"] },
|
||||||
|
"custom_extra_info": { "type": ["string", "null"] },
|
||||||
|
"nonce": { "type": "string" },
|
||||||
|
"expires_at": { "type": "string" }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"SignPdfResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"request_id",
|
||||||
|
"status",
|
||||||
|
"signed_pdf",
|
||||||
|
"signature",
|
||||||
|
"certificate",
|
||||||
|
"algorithm"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"request_id": { "type": "string" },
|
||||||
|
"status": { "type": "string", "enum": ["signed"] },
|
||||||
|
"signed_pdf": { "type": "string", "description": "PDF assinado completo com envelope PAdES em Base64" },
|
||||||
|
"sha256": { "type": ["string", "null"] },
|
||||||
|
"signature": { "type": "string" },
|
||||||
|
"certificate": { "type": "string" },
|
||||||
|
"certificate_chain": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "type": "string" }
|
||||||
|
},
|
||||||
|
"algorithm": { "type": "string" },
|
||||||
|
"subject_name": { "type": ["string", "null"] },
|
||||||
|
"subject_cpf_cnpj": { "type": ["string", "null"] },
|
||||||
|
"document_name": { "type": ["string", "null"] }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"SignXmlRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"request_id",
|
||||||
|
"application_id",
|
||||||
|
"operation",
|
||||||
|
"nonce",
|
||||||
|
"expires_at"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"request_id": { "type": "string" },
|
||||||
|
"application_id": { "type": "string" },
|
||||||
|
"operation": { "type": "string", "enum": ["sign_xml"] },
|
||||||
|
"xml": { "type": ["string", "null"], "description": "XML em texto puro UTF-8" },
|
||||||
|
"xml_base64": { "type": ["string", "null"], "description": "XML codificado em Base64" },
|
||||||
|
"certificate_hint": { "type": ["string", "null"] },
|
||||||
|
"document_name": { "type": ["string", "null"] },
|
||||||
|
"profile": { "type": ["string", "null"], "enum": ["XADES_BES", "XMLDSIG", null] },
|
||||||
|
"target_element_tag": { "type": ["string", "null"] },
|
||||||
|
"target_element_id": { "type": ["string", "null"] },
|
||||||
|
"algorithm": { "type": ["string", "null"] },
|
||||||
|
"nonce": { "type": "string" },
|
||||||
|
"expires_at": { "type": "string" }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"SignXmlResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"request_id",
|
||||||
|
"status",
|
||||||
|
"signed_xml",
|
||||||
|
"signature",
|
||||||
|
"certificate",
|
||||||
|
"algorithm"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"request_id": { "type": "string" },
|
||||||
|
"status": { "type": "string", "enum": ["signed"] },
|
||||||
|
"signed_xml": { "type": "string", "description": "Documento XML assinado completo com assinatura enveloped" },
|
||||||
|
"sha256": { "type": ["string", "null"] },
|
||||||
|
"signature": { "type": "string" },
|
||||||
|
"certificate": { "type": "string" },
|
||||||
|
"certificate_chain": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "type": "string" }
|
||||||
|
},
|
||||||
|
"algorithm": { "type": "string" },
|
||||||
|
"subject_name": { "type": ["string", "null"] },
|
||||||
|
"subject_cpf_cnpj": { "type": ["string", "null"] },
|
||||||
|
"document_name": { "type": ["string", "null"] }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"AuthenticateRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"request_id",
|
||||||
|
"application_id",
|
||||||
|
"operation",
|
||||||
|
"challenge",
|
||||||
|
"nonce",
|
||||||
|
"expires_at"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"request_id": { "type": "string" },
|
||||||
|
"application_id": { "type": "string" },
|
||||||
|
"operation": { "type": "string", "enum": ["authenticate"] },
|
||||||
|
"algorithm": { "type": "string" },
|
||||||
|
"digest": { "type": ["string", "null"] },
|
||||||
|
"challenge": { "type": "string" },
|
||||||
|
"purpose": { "type": ["string", "null"] },
|
||||||
|
"document_type": { "type": ["string", "null"] },
|
||||||
|
"certificate_hint": { "type": ["string", "null"] },
|
||||||
|
"nonce": { "type": "string" },
|
||||||
|
"expires_at": { "type": "string" }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"AuthenticateResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"version",
|
||||||
|
"request_id",
|
||||||
|
"status",
|
||||||
|
"signature",
|
||||||
|
"certificate",
|
||||||
|
"algorithm"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"version": { "type": "string", "enum": ["1"] },
|
||||||
|
"request_id": { "type": "string" },
|
||||||
|
"status": { "type": "string", "enum": ["authenticated", "signed"] },
|
||||||
|
"signature": { "type": "string" },
|
||||||
|
"certificate": { "type": "string" },
|
||||||
|
"certificate_chain": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "type": "string" }
|
||||||
|
},
|
||||||
|
"algorithm": { "type": "string" },
|
||||||
|
"subject_name": { "type": ["string", "null"] },
|
||||||
|
"subject_cpf_cnpj": { "type": ["string", "null"] }
|
||||||
|
},
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# Matriz de Compatibilidade de Hardware e Dispositivos Criptográficos A3
|
||||||
|
|
||||||
|
Este documento apresenta a matriz técnica de compatibilidade de tokens USB, smartcards e leitores criptográficos suportados pelo **CyberCore Signer**, detalhando drivers, middlewares e o status de homologação de cada dispositivo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Princípio de Transparência e Rastreabilidade
|
||||||
|
|
||||||
|
Conforme as diretrizes mestras do projeto:
|
||||||
|
> *Testes dependentes de hardware só podem ser declarados executados quando o hardware realmente estiver disponível no ambiente de teste. Nunca invente suporte a dispositivos ou fabricantes que não tenham sido realmente testados.*
|
||||||
|
|
||||||
|
O CyberCore Signer utiliza duas camadas complementares para acesso a dispositivos físicos no Windows e Linux:
|
||||||
|
1. **Windows Certificate Store (CAPI / CNG):** Acesso transparente a qualquer token ou smartcard cujo middleware instale um CSP (Cryptographic Service Provider) ou KSP (Key Storage Provider) no Windows.
|
||||||
|
2. **SunPKCS11 (`jdk.crypto.cryptoki`):** Comunicação direta via padrão PKCS#11 (bibliotecas `.dll` no Windows ou `.so` no Linux), garantindo independência de fabricantes.
|
||||||
|
3. **CI Automatizado via SoftHSM2:** O pipeline de integração contínua (CI) valida a pilha criptográfica PKCS#11 utilizando o emulador de hardware criptográfico **SoftHSM2**, testando ciclos completos de inicialização de token, busca de chaves e assinatura matemática SHA-256 com chave RSA sem depender de conexões físicas de hardware no servidor de build.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Matriz de Compatibilidade de Tokens e Smartcards
|
||||||
|
|
||||||
|
| Fabricante / Modelo | Tipo de Dispositivo | Middleware / Driver | Biblioteca PKCS#11 | Status de Homologação |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| **SoftHSM2 (Emulador PKCS#11)** | Emulador de Hardware Criptográfico | SoftHSM2 v2.6+ | `libsofthsm2.so` / `softhsm2.dll` | **Validado no CI Automatizado (Gitea)** |
|
||||||
|
| **Thales / SafeNet eToken 5110** | Token USB Criptográfico | SafeNet Authentication Client (SAC) | `eps2003csp11.dll` | Compatível via Windows Store / PKCS#11 (Pendente hardware físico) |
|
||||||
|
| **AET / GD StarSign (SafeSign)** | Smartcard / Token USB | SafeSign Identity Client | `aetpkss1.dll` / `libaetpkss.so` | Compatível via Windows Store / PKCS#11 (Pendente hardware físico) |
|
||||||
|
| **Gemalto IDPrime (MD 830 / 840)** | Token USB / Smartcard | IDPrime Minidriver / Gemalto CC | `gclib.dll` / `libgclib.so` | Compatível nativamente via Windows CNG Minidriver |
|
||||||
|
| **Oberthur / Idemia Cosmo** | Smartcard ICP-Brasil | AWPS / ACOS PKCS#11 | `acospkcs11.dll` / `libacospkcs11.so` | Compatível via Windows Store / PKCS#11 (Pendente hardware físico) |
|
||||||
|
| **Watchdata PROXKey** | Token USB Criptográfico | Watchdata Middleware | `Watchdata ProxKey PKCS11.dll` | Compatível via Windows Store / PKCS#11 (Pendente hardware físico) |
|
||||||
|
| **OpenSC (Padrão Aberto)** | Leitores PC/SC genéricos e Smartcards | OpenSC Suite | `opensc-pkcs11.dll` / `opensc-pkcs11.so` | Compatível via PKCS#11 (Linux e Windows) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Gestão de Concorrência e Conflito de Hardware (`signLock`)
|
||||||
|
|
||||||
|
Grande parte dos microcontroladores de smartcards e tokens USB físicos (chips ISO 7816) **não possui suporte a canais concorrentes multi-thread**. Se duas requisições de assinatura tentarem acessar o chip simultaneamente através do middleware:
|
||||||
|
- O dispositivo trava com erro `CKR_DEVICE_ERROR` ou `SCARD_E_SHARING_VIOLATION`.
|
||||||
|
- O leitor pode exigir reinicialização do serviço PC/SC (`scardsvr`) ou desplugue físico do token.
|
||||||
|
|
||||||
|
### Solução Arquitetural do CyberCore Signer
|
||||||
|
1. **Fila Serializada (FIFO) via `ReentrantLock`:** Todas as operações criptográficas de assinatura no subsistema A3 passam obrigatoriamente pela trava `signLock`, enfileirando requisições concorrentes transparentemente.
|
||||||
|
2. **Sessão PC/SC Desacoplada (`SmartCardWatcher`):** O monitoramento de inserção e remoção utiliza `javax.smartcardio` de forma assíncrona, notificando a interface gráfica sem bloquear o canal criptográfico do SunPKCS11.
|
||||||
|
3. **Limpeza Imediata de Memória:** Ao desconectar o dispositivo, o evento `TOKEN_REMOVED` força a limpeza imediata de buffers e o encerramento das conexões com o leitor (`SmartCardSessionManager`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Requisitos de Instalação no Cliente
|
||||||
|
|
||||||
|
1. **Windows 10 / 11 (64-bit):**
|
||||||
|
- O aplicativo desktop já embute seu próprio runtime Java (OpenJDK 25 LTS via `jpackage`), sem exigir Java instalado na máquina do usuário.
|
||||||
|
- O usuário deve manter instalado o software/driver fornecido pela Autoridade Certificadora emissora do token (ex: SafeNet Authentication Client ou SafeSign).
|
||||||
|
2. **Linux (Ubuntu / Debian / Fedora):**
|
||||||
|
- O serviço `pcscd` deve estar em execução (`sudo systemctl enable --now pcscd`).
|
||||||
|
- Biblioteca de middleware do fabricante instalada em `/usr/lib/` ou `/usr/lib/x86_64-linux-gnu/`.
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# Guia de Testes de Conformidade ICP-Brasil e Validação Oficial no ITI
|
||||||
|
|
||||||
|
> **Procedimentos de Verificação Criptográfica Automatizada e Manual para Assinaturas PAdES e XAdES-BES**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Visão Geral
|
||||||
|
|
||||||
|
O **CyberCore Signer** implementa assinaturas digitais em conformidade com as normas técnicas da **Infraestrutura de Chaves Públicas Brasileira (ICP-Brasil)**, especificamente:
|
||||||
|
|
||||||
|
- **PDF (PAdES):** Padrão ISO 32000-1 e ETSI TS 102 778, com envelope CMS desacoplado (`/adbe.pkcs7.detached`) e algoritmo `SHA256withRSA` (alinhado ao perfil AD-RB).
|
||||||
|
- **XML (XAdES-BES / XMLDSig):** Padrão ETSI TS 101 903 e norma **DOC-ICP-15.03**, contendo propriedades qualificadas assinadas (`<xades:QualifyingProperties>`, `<xades:SigningTime>` e `<xades:SigningCertificate>`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Suíte de Testes Automatizados (`ComplianceSignatureSuiteTest`)
|
||||||
|
|
||||||
|
A conformidade técnica do código é garantida de forma contínua pelo teste automatizado:
|
||||||
|
`modules/cybercore-core/src/test/java/br/com/cybercore/signer/core/compliance/ComplianceSignatureSuiteTest.java`
|
||||||
|
|
||||||
|
### O que o teste automatizado valida:
|
||||||
|
1. **Cadeia ICP-Brasil Simulada em Memória:**
|
||||||
|
- Cria uma hierarquia criptográfica completa (AC Raiz de Teste -> AC Intermediária -> Certificado Signatário com extensão OID e-CPF `2.16.76.1.3.1`).
|
||||||
|
- Garante que nenhum certificado real ou dado pessoal seja exposto em testes.
|
||||||
|
2. **PAdES (PDF):**
|
||||||
|
- Criação de documento PDF original.
|
||||||
|
- Aplicação de selo visual conforme as coordenadas calculadas.
|
||||||
|
- Verificação da integridade do `/ByteRange` cobrindo o PDF integral exceto os bytes de `/Contents`.
|
||||||
|
- Validação criptográfica independente via Bouncy Castle `CMSSignedData.verify()`.
|
||||||
|
- Comparação do digest SHA-256 do documento contra o atributo assinado `messageDigest`.
|
||||||
|
3. **XAdES-BES (XML):**
|
||||||
|
- Assinatura de documento XML com geração de identificadores de referência (`Reference URI`).
|
||||||
|
- Validação independente via motor nativo Java JSR-105 (`javax.xml.crypto.dsig.XMLSignature`).
|
||||||
|
- Teste de inviolabilidade (Tamper Test): verificação de que qualquer modificação de um caractere nos dados de negócio invalida sumariamente o `coreValidity`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Validação Manual no Verificador de Conformidade do ITI
|
||||||
|
|
||||||
|
O **Instituto Nacional de Tecnologia da Informação (ITI)** disponibiliza a ferramenta governamental oficial para validação de assinaturas digitais brasileiras:
|
||||||
|
|
||||||
|
👉 **URL Oficial:** [https://verificador.iti.gov.br](https://verificador.iti.gov.br)
|
||||||
|
|
||||||
|
### 3.1 Procedimento Passo a Passo para Teste Manual
|
||||||
|
|
||||||
|
1. **Gerar ou Exportar o Documento Assinado:**
|
||||||
|
- Através da interface gráfica do CyberCore Signer, assine um documento PDF ou XML utilizando seu certificado digital A1 ou A3.
|
||||||
|
- O arquivo assinado resultante será gravado em disco (ex: `contrato_assinado.pdf` ou `documento_assinado.xml`).
|
||||||
|
|
||||||
|
2. **Submissão no Verificador do ITI:**
|
||||||
|
- Acesse [https://verificador.iti.gov.br](https://verificador.iti.gov.br) em qualquer navegador web moderno.
|
||||||
|
- Clique em **"Selecionar assinatura"** e faça o upload do arquivo gerado pelo CyberCore Signer.
|
||||||
|
- Clique no botão **"Verificar conformidade"**.
|
||||||
|
|
||||||
|
3. **Interpretação do Relatório de Conformidade:**
|
||||||
|
|
||||||
|
#### Cenário A: Assinatura com Certificado de Produção ICP-Brasil (Certisign, Serasa, Serpro, Valid, etc.)
|
||||||
|
- **Status Geral:** `APROVADO` / `CONFORME`.
|
||||||
|
- **Validação Criptográfica:** Íntegra (o hash bate e a assinatura RSA é autêntica).
|
||||||
|
- **Cadeia de Certificação:** Confiável (ancorada até a AC Raiz da ICP-Brasil oficial).
|
||||||
|
- **Atributos do Signatário:** Nome completo e CPF/CNPJ extraídos e validados na Receita Federal.
|
||||||
|
|
||||||
|
#### Cenário B: Assinatura com Certificados de Teste / Desenvolvimento (Gerados na Suíte)
|
||||||
|
- **Status Criptográfico:** `VÁLIDO` (integridade matemática e estrutura PAdES/XAdES aprovadas).
|
||||||
|
- **Alerta de Cadeia:** O verificador do ITI reportará: *"Cadeia de Certificação Não Confiável / AC não credenciada na ICP-Brasil"*. Este é o comportamento **correto e esperado**, uma vez que certificados gerados em testes locais não pertencem à lista de certificados confiáveis (LCR oficial) publicada pelo ITI.
|
||||||
@@ -1,48 +1,89 @@
|
|||||||
# Modo de Desenvolvimento e Diagnóstico Detalhado
|
# Modo de Desenvolvimento e Homologação
|
||||||
|
|
||||||
O **CyberCore Signer** opera exclusivamente com **certificados digitais e provedores criptográficos reais** (A1 via arquivos `.pfx`/`.p12`, repositório nativo do Windows `Windows-MY` e tokens/smart cards físicos PKCS#11). Em conformidade com a exigência de segurança de produção, **não existem mocks ou certificados sintéticos no agente**.
|
> **Diretrizes para Execução Local com Argumento `--dev`, Testes e Criação de Certificados A1 de Homologação**
|
||||||
|
|
||||||
|
O **CyberCore Signer** opera exclusivamente com certificados digitais e provedores criptográficos reais (arquivos `.pfx`/`.p12`, Windows-MY e tokens físicos PKCS#11). Em cumprimento às normas de integridade do projeto, **não existem mocks ou certificados artificiais no runtime de produção**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Ativação do Modo de Desenvolvimento
|
## 1. Ativação do Modo de Desenvolvimento
|
||||||
|
|
||||||
Para iniciar o agente em modo de desenvolvimento (com logs detalhados e diagnósticos ampliados), utilize o argumento `--dev`:
|
Para iniciar o agente em ambiente de homologação e desenvolvimento com logs estendidos de auditoria e detalhamento de operações de rede, utilize o argumento de linha de comando `--dev`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
java -jar cybercore-signer.jar --dev
|
# Executando via script Linux / macOS:
|
||||||
|
./run.sh --dev
|
||||||
|
|
||||||
|
# Executando no Windows:
|
||||||
|
run.bat --dev
|
||||||
|
|
||||||
|
# Ou diretamente pelo JAR compilado:
|
||||||
|
java -jar modules/cybercore-app/target/cybercore-signer.jar --dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Ao iniciar, uma mensagem informativa é registrada no log:
|
Ao ser iniciado com esta flag, o agente imprime no terminal o banner de diagnóstico:
|
||||||
```
|
```
|
||||||
=========================================================
|
=========================================================
|
||||||
MODO DE DESENVOLVIMENTO ATIVADO (--dev)
|
CYBERCORE SIGNER — MODO DE DESENVOLVIMENTO ATIVADO (--dev)
|
||||||
Logs detalhados ativos. Operação com certificados reais.
|
Logs detalhados ativos. Operação com certificados reais JCA/JCE.
|
||||||
|
Servidor local CCSP/1 pronto em: http://127.0.0.1:21325
|
||||||
=========================================================
|
=========================================================
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Testando em Ambiente de Desenvolvimento
|
## 2. Geração de Certificados A1 de Teste com OpenSSL
|
||||||
|
|
||||||
Para desenvolvedores testarem fluxos completos de assinatura de PDF, XML, arquivos em geral e login digital:
|
Para desenvolvedores e testadores que precisam simular fluxos completos de assinatura digital (PAdES, XAdES, login digital) sem utilizar um certificado ICP-Brasil real de produção, é possível gerar um certificado digital de teste no formato `.pfx` protegido por senha utilizando o utilitário **OpenSSL**:
|
||||||
|
|
||||||
1. **Certificados A1 de Teste/Homologação:**
|
### Passo 1: Gerar a Chave Privada RSA (2048 bits)
|
||||||
- Adicione um certificado A1 `.pfx` ou `.p12` emitido por uma autoridade de teste ou autoassinado.
|
```bash
|
||||||
- Pela interface desktop, clique no botão **"Importar A1 (.pfx/.p12)"** no Dashboard e informe o arquivo e a senha.
|
openssl genrsa -out teste_signer.key 2048
|
||||||
- O certificado ficará disponível imediatamente para todas as operações CCSP/1.
|
```
|
||||||
|
|
||||||
2. **Repositório Nativo do Windows (Windows-MY):**
|
### Passo 2: Gerar o Certificado X.509 Autoassinado
|
||||||
- Instale o certificado no repositório de certificados pessoais do Windows (`certmgr.msc`).
|
```bash
|
||||||
- O provedor `WindowsCertificateStoreProvider` detectará o certificado automaticamente.
|
openssl req -new -x509 -key teste_signer.key -out teste_signer.crt -days 365 \
|
||||||
|
-subj "/C=BR/O=ICP-Brasil Teste/OU=Desenvolvimento CyberCore/CN=DESENVOLVEDOR TESTE:12345678900"
|
||||||
|
```
|
||||||
|
|
||||||
3. **Tokens USB / Smart Cards (PKCS#11):**
|
### Passo 3: Exportar o Certificado e Chave no Contêiner PKCS#12 (`.pfx`)
|
||||||
- Conecte o dispositivo físico com middleware homologado (SafeSign, GD Burti, SafeNet, OpenSC, etc.).
|
```bash
|
||||||
- O provedor `Pkcs11CertificateProvider` detectará o token e seus slots.
|
openssl pkcs12 -export -out certificado_teste.pfx \
|
||||||
|
-inkey teste_signer.key -in teste_signer.crt \
|
||||||
|
-name "DESENVOLVEDOR TESTE:12345678900" \
|
||||||
|
-passout pass:123456
|
||||||
|
```
|
||||||
|
|
||||||
|
### Passo 4: Importar no CyberCore Signer
|
||||||
|
1. Abra o CyberCore Signer.
|
||||||
|
2. Na tela principal, clique em **"Importar A1 (.pfx/.p12)"**.
|
||||||
|
3. Selecione o arquivo `certificado_teste.pfx` gerado e informe a senha `123456`.
|
||||||
|
4. O certificado aparecerá instantaneamente como disponível no Dashboard e poderá ser utilizado para todos os testes do SDK e CCSP/1.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Garantia de Operação Real
|
## 3. Execução da Suíte de Testes Automatizados
|
||||||
|
|
||||||
1. Toda assinatura é gerada criptograficamente através dos provedores JCA/JCE reais.
|
O repositório do CyberCore Signer conta com suíte abrangente de testes unitários, testes de concorrência e testes de arquitetura (ArchUnit):
|
||||||
2. A resposta do protocolo CCSP/1 contém assinaturas válidas e certificados X.509 autênticos.
|
|
||||||
3. Não há certificados simulados ou flags artificiais nas respostas do agente.
|
```bash
|
||||||
|
# Executar todos os testes unitários do projeto:
|
||||||
|
./mvnw test
|
||||||
|
|
||||||
|
# Executar testes específicos do protocolo CCSP/1:
|
||||||
|
./mvnw test -Dtest=CcspServerTest
|
||||||
|
|
||||||
|
# Executar testes de concorrência e trava FIFO (signLock):
|
||||||
|
./mvnw test -Dtest=CcspConcurrencyTest
|
||||||
|
|
||||||
|
# Executar testes de conformidade arquitetural (garante desacoplamento de UI no core):
|
||||||
|
./mvnw test -Dtest=ArchitectureTest
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Garantia de Operação Real
|
||||||
|
|
||||||
|
1. **Assinaturas Autênticas:** Mesmo ao utilizar um certificado autoassinado de teste, os bytes da assinatura são calculados matematicamente pelos algoritmos reais do JCA/JCE (`SHA256withRSA`).
|
||||||
|
2. **Sem Falsos Positivos:** O comportamento do agente é 100% idêntico entre o ambiente de teste e o ambiente de produção com tokens físicos A3.
|
||||||
|
|||||||
@@ -1,34 +1,103 @@
|
|||||||
# Diagnóstico de Ambiente e Auto-Teste
|
# Diagnóstico de Ambiente e Resolução de Problemas
|
||||||
|
|
||||||
O **CyberCore Signer** possui um subsistema nativo de diagnóstico integrado (`DiagnosticService`), permitindo auditoria detalhada de saúde e integridade técnica da máquina do usuário.
|
> **Guia de Auto-Teste, Checklist de Integridade de Runtime e Troubleshooting de Hardware**
|
||||||
|
|
||||||
|
O **CyberCore Signer** conta com um subsistema nativo de diagnóstico e telemetria local (`DiagnosticService`), projetado para validar a integridade da estação de trabalho e identificar rapidamente falhas de drivers, certificados ou subsistemas criptográficos do sistema operacional.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Itens Inspecionados no Diagnóstico
|
## 1. Itens Inspecionados pelo Diagnóstico Automático
|
||||||
|
|
||||||
Ao abrir a aba **Diagnóstico** na interface ou invocar `diagnosticService.runDiagnostic()`, o agente avalia:
|
Ao acessar a aba **Diagnóstico** na interface do agente desktop ou ao inicializar em modo `--dev`, o agente executa uma auditoria completa nos seguintes componentes:
|
||||||
|
|
||||||
1. **Ambiente Java / Runtime:**
|
1. **Ambiente Java / Runtime Nativo:**
|
||||||
- Versão do Java (requer Java 21+ LTS, homologado em Java 25 LTS);
|
- Versão do Java (requer Java 25 LTS);
|
||||||
- Vendor do JDK (Temurin, Oracle, etc.);
|
- Vendor do JDK (Eclipse Temurin, Oracle OpenJDK, Amazon Corretto);
|
||||||
- Arquitetura do processador e sistema operacional.
|
- Arquitetura da CPU (x86_64 / amd64) e sistema operacional (Windows 10/11 ou Linux).
|
||||||
2. **Engine Criptográfica JCA/JCE:**
|
2. **Engine Criptográfica JCA/JCE:**
|
||||||
- Disponibilidade dos provedores de segurança registrados na JVM (`SUN`, `SunRsaSign`, `SunMSCAPI`, etc.);
|
- Disponibilidade dos provedores de segurança registrados na JVM (`SUN`, `SunRsaSign`, `SunMSCAPI`, etc.);
|
||||||
- Suporte ao algoritmo de hash `SHA-256`;
|
- Suporte aos algoritmos de hash criptográfico (`SHA-256`, `SHA-512`);
|
||||||
- Suporte ao algoritmo de assinatura `SHA256withRSA`.
|
- Suporte aos algoritmos de assinatura digital (`SHA256withRSA`).
|
||||||
3. **Repositório de Chaves do Sistema Operacional:**
|
3. **Repositório de Certificados do Sistema Operacional:**
|
||||||
- Detecção do repositório `Windows-MY` (Windows CryptoAPI / CNG).
|
- Detecção do repositório de chaves `Windows-MY` via SunMSCAPI / CryptoAPI / CNG.
|
||||||
4. **Middlewares PKCS#11 e SmartCard:**
|
4. **Middlewares PKCS#11 e Subsistema PC/SC:**
|
||||||
- Verificação de bibliotecas de smartcard registradas no sistema (`eps2003csp11.dll`, `aetpkss1.dll`, `opensc-pkcs11.dll`, etc.);
|
- Presença das bibliotecas dinâmicas do fabricante (`aetpkss1.dll`, `eps2003csp11.dll`, `acospkcs11.dll`, `opensc-pkcs11.dll`);
|
||||||
- Disponibilidade do subsistema PC/SC `javax.smartcardio`.
|
- Disponibilidade do subsistema de leitoras de smartcard `javax.smartcardio` (PC/SC Daemon / Smart Card Service do Windows).
|
||||||
|
5. **Servidor Local CCSP/1:**
|
||||||
|
- Teste de bind do socket em `127.0.0.1:21325` e integridade do pool de threads.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Auto-Teste de Assinatura Local (Self-Test)
|
## 2. Auto-Teste de Assinatura Local (Self-Test)
|
||||||
|
|
||||||
A aba de diagnóstico disponibiliza o botão **"Executar Auto-teste de Assinatura"**:
|
A tela de diagnóstico oferece a função **"Executar Auto-teste de Assinatura"**:
|
||||||
1. Seleciona o primeiro certificado operacional disponível na máquina.
|
1. O agente identifica o primeiro certificado digital operacional conectado.
|
||||||
2. Gera um hash SHA-256 interno de teste: `"Documento_Teste_CyberCore_<timestamp>"`.
|
2. Gera um hash SHA-256 interno sintético para teste: `"Documento_Teste_CyberCore_<timestamp>"`.
|
||||||
3. Abre o diálogo de confirmação visual para validação do usuário.
|
3. Abre o diálogo nativo de confirmação visual para validação do usuário.
|
||||||
4. Executa a assinatura real JCA/JCE e afere os bytes gerados.
|
4. Executa a assinatura real através do provedor JCA/JCE correspondente (solicitando PIN se A3).
|
||||||
5. Emite relatório de sucesso com tempo decorrido e tamanho da assinatura.
|
5. Valida os bytes da assinatura gerada e emite relatório com tempo decorrido em milissegundos e tamanho da assinatura.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Guia de Resolução de Problemas (Troubleshooting)
|
||||||
|
|
||||||
|
### 3.1 Token USB ou Smartcard A3 não é detectado
|
||||||
|
* **Sintoma:** O token está plugado na porta USB mas não aparece no CyberCore nem na lista de certificados.
|
||||||
|
* **Causa Comum:** O serviço de cartão inteligente do Windows (`ScardSvr`) está desativado ou o middleware do fabricante (SafeSign/SafeNet) não está instalado.
|
||||||
|
* **Solução:**
|
||||||
|
1. No Windows, pressione `Win + R`, digite `services.msc` e pressione Enter.
|
||||||
|
2. Localize o serviço **Cartão Inteligente (Smart Card)** e garanta que seu status esteja **Em Execução** (Tipo de Inicialização: Automático).
|
||||||
|
3. Verifique se o aplicativo de gerenciamento do token (ex: *SafeSign Token Utility* ou *SafeNet Authentication Client Tools*) reconhece o token.
|
||||||
|
4. Desconecte o token USB, aguarde 3 segundos e reconecte em outra porta USB.
|
||||||
|
|
||||||
|
### 3.2 Erro `NTE_BAD_KEYSET` ou `Chave Privada Não Acessível`
|
||||||
|
* **Sintoma:** O certificado aparece na lista, mas a assinatura falha com erro `PRIVATE_KEY_NOT_AVAILABLE` ou código Windows `0x80090016`.
|
||||||
|
* **Causa Comum:** O certificado foi importado no Windows sem a chave privada correspondente, ou o usuário não tem permissão de leitura sobre o contêiner de chaves.
|
||||||
|
* **Solução:**
|
||||||
|
1. Abra o gerenciador de certificados do Windows: `certmgr.msc`.
|
||||||
|
2. Navegue até **Pessoal -> Certificados** e dê um duplo clique sobre o certificado.
|
||||||
|
3. Verifique se na parte inferior da aba Geral consta a mensagem: *"Você tem uma chave privada correspondente a este certificado"*. Se não constar, reinstale o arquivo A1 com a opção "Marcar esta chave como exportável" ativada.
|
||||||
|
|
||||||
|
### 3.3 Porta local `21325` já em uso (`BindException`)
|
||||||
|
* **Sintoma:** O CyberCore Signer não inicializa e os logs acusam `Address already in use: bind`.
|
||||||
|
* **Causa Comum:** Outra instância do CyberCore Signer ou aplicativo conflitante já está em execução na porta `21325`.
|
||||||
|
* **Solução:**
|
||||||
|
1. No Windows, abra o Gerenciador de Tarefas (`Ctrl + Shift + Esc`) e encerre eventuais processos `cybercore-signer` ou `javaw.exe` órfãos.
|
||||||
|
2. No terminal (PowerShell), você pode identificar o processo ocupando a porta:
|
||||||
|
```powershell
|
||||||
|
Get-NetTCPConnection -LocalPort 21325 | Select-Object OwningProcess
|
||||||
|
```
|
||||||
|
3. No Linux:
|
||||||
|
```bash
|
||||||
|
sudo lsof -i :21325
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 Aplicação Web acusa "Agente não instalado" ou Falha de Conexão
|
||||||
|
* **Sintoma:** A chamada `signer.isInstalled()` no navegador retorna `false` ou dá timeout.
|
||||||
|
* **Causa Comum:** O CyberCore Signer está fechado, o antivírus bloqueou a conexão loopback local, ou a aplicação web tenta conectar com protocolo incorreto.
|
||||||
|
* **Solução:**
|
||||||
|
1. Verifique se o ícone do CyberCore Signer está ativo na barra de tarefas (System Tray).
|
||||||
|
2. Abra uma nova aba no navegador e acesse diretamente: `http://127.0.0.1:21325/ccsp/v1/status`.
|
||||||
|
3. O navegador deve exibir o JSON com `"status": "ready"`. Se não exibir, abra o executável do CyberCore Signer.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Comandos Úteis de Diagnóstico no Terminal
|
||||||
|
|
||||||
|
### No Windows:
|
||||||
|
```cmd
|
||||||
|
:: Testar leitura de smartcards e drivers via utilitário nativo do Windows:
|
||||||
|
certutil -scinfo
|
||||||
|
|
||||||
|
:: Listar certificados instalados no repositório Pessoal do usuário:
|
||||||
|
certutil -user -store My
|
||||||
|
```
|
||||||
|
|
||||||
|
### No Linux:
|
||||||
|
```bash
|
||||||
|
:: Verificar leitoras e cartões conectados via subsistema PC/SC:
|
||||||
|
pcsc_scan
|
||||||
|
|
||||||
|
:: Verificar status do serviço pcscd:
|
||||||
|
systemctl status pcscd
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,28 +1,80 @@
|
|||||||
# Catálogo Estruturado de Erros
|
# Catálogo Estruturado de Erros
|
||||||
|
|
||||||
O **CyberCore Signer** adota um sistema unificado e determinístico de códigos de erro (`CcspErrorCode`) compartilhados entre o agente Java desktop, o protocolo CCSP/1 e o SDK Web em JavaScript.
|
> **Especificação Unificada de Códigos de Erro (`CcspErrorCode`), Status HTTP e Tratamento no SDK**
|
||||||
|
|
||||||
|
O **CyberCore Signer** adota uma taxonomia estrita e estável de erros estruturados, garantindo que o agente desktop Java, a API REST do protocolo CCSP/1 e o SDK JavaScript manipulem falhas com previsibilidade e sem expor detalhes internos sensíveis ao usuário final.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Tabela de Erros Estruturados
|
## 1. Tabela Completa de Códigos de Erro
|
||||||
|
|
||||||
| Código de Erro | Descrição Detalhada | Ação Recomendada para a Aplicação Web |
|
| Código de Erro (`CcspErrorCode`) | Status HTTP | Descrição do Erro | Ação Recomendada para a Aplicação Web |
|
||||||
|---|---|---|
|
|---|---|---|---|
|
||||||
| `CERTIFICATE_NOT_FOUND` | O certificado indicado pelo `certificate_hint` não foi localizado. | Solicite ao usuário selecionar novamente o certificado via `getCertificates()`. |
|
| `CERTIFICATE_NOT_FOUND` | `404 Not Found` | O certificado indicado pelo `certificate_hint` não foi localizado na máquina. | Solicitar ao usuário selecionar novamente o certificado via `getCertificates()`. |
|
||||||
| `CERTIFICATE_EXPIRED` | O certificado selecionado expirou. | Oriente o usuário a renovar o certificado digital junto à autoridade certificadora. |
|
| `CERTIFICATE_EXPIRED` | `422 Unprocessable` | O certificado digital selecionado ultrapassou sua data limite de validade. | Orientar o usuário a renovar o certificado digital junto à autoridade certificadora (AC). |
|
||||||
| `CERTIFICATE_INVALID` | O certificado possui estrutura corrompida ou ainda não é válido. | Verificar a data e integridade do arquivo/dispositivo. |
|
| `CERTIFICATE_INVALID` | `400 Bad Request` | Estrutura ASN.1/X.509 corrompida ou ainda não iniciada (`NotBefore`). | Verificar integridade do arquivo `.pfx` ou relógio do sistema operacional. |
|
||||||
| `PRIVATE_KEY_NOT_AVAILABLE` | O certificado está presente mas a chave privada não está acessível. | Em tokens A3, verifique se o middleware/driver está instalado corretamente. |
|
| `PRIVATE_KEY_NOT_AVAILABLE` | `404 Not Found` | O certificado está presente mas a chave privada não está acessível no repositório. | Em tokens A3, verificar se o middleware/driver do token está instalado corretamente. |
|
||||||
| `TOKEN_NOT_FOUND` | Nenhum dispositivo ou leitor compatível foi localizado. | Solicite ao usuário conectar o token USB ou inserir o smartcard no leitor. |
|
| `TOKEN_NOT_FOUND` | `404 Not Found` | Nenhum dispositivo criptográfico físico ou leitora de cartão foi detectado. | Solicitar ao usuário conectar o token USB ou inserir o smartcard no leitor. |
|
||||||
| `TOKEN_REMOVED` | O token USB ou cartão foi removido fisicamente durante a assinatura. | Peça ao usuário reconectar o token e reiniciar a operação de assinatura. |
|
| `TOKEN_REMOVED` | `503 Service Unavail`| O token USB ou cartão foi desconectado fisicamente durante o processamento. | Orientar o usuário a reconectar o token e reiniciar a operação de assinatura. |
|
||||||
| `PIN_REQUIRED` | O token exige PIN para liberar a chave privada e nenhum PIN foi fornecido. | Exibir campo de solicitação de PIN na tela. |
|
| `PIN_REQUIRED` | `400 Bad Request` | O token exige PIN para liberar a chave privada e nenhum PIN foi informado. | Exibir campo para inserção do PIN do dispositivo. |
|
||||||
| `PIN_INCORRECT` | O PIN digitado está incorreto. | Informar o usuário e alertar sobre o risco de bloqueio de PUK após 3 tentativas. |
|
| `PIN_INCORRECT` | `400 Bad Request` | O PIN digitado para o token A3 é incorreto. | Alertar o usuário sobre o risco de bloqueio do cartão (PUK) após tentativas consecutivas. |
|
||||||
| `PKCS11_ERROR` | Falha no driver ou biblioteca PKCS#11 do fabricante. | Verificar a instalação do SafeSign, SafeNet ou OpenSC. |
|
| `PKCS11_ERROR` | `500 Server Error` | Falha na biblioteca DLL/SO do middleware ou driver do fabricante. | Verificar a instalação do SafeSign, SafeNet, GD Burti ou OpenSC. |
|
||||||
| `SIGNATURE_FAILED` | Erro durante a geração dos bytes da assinatura digital. | Tentar novamente ou reiniciar o agente desktop. |
|
| `SIGNATURE_FAILED` | `400 Bad Request` | Falha criptográfica na geração dos bytes da assinatura digital. | Reiniciar a operação ou verificar integridade do algoritmo especificado. |
|
||||||
| `APPLICATION_NOT_AUTHORIZED` | A aplicação web teve autorização recusada pelo usuário. | Informar o usuário que é necessário aceitar a notificação na tela do agente. |
|
| `APPLICATION_NOT_AUTHORIZED` | `401 Unauthorized` | A aplicação web teve autorização recusada pelo usuário ou não foi cadastrada. | Notificar o usuário que é necessário aceitar a solicitação na janela do CyberCore. |
|
||||||
| `REQUEST_EXPIRED` | O timestamp ou `expires_at` da requisição expirou. | Gerar nova requisição de assinatura com timestamp atualizado. |
|
| `REQUEST_EXPIRED` | `422 Unprocessable` | A validade temporal (`expires_at`) da requisição foi ultrapassada. | Gerar nova requisição de assinatura com timestamp atualizado no backend/frontend. |
|
||||||
| `REPLAY_DETECTED` | O nonce informado já foi processado anteriormente. | Sempre gerar um UUID único para cada chamada de assinatura. |
|
| `REPLAY_DETECTED` | `409 Conflict` | O `nonce` informado já foi processado anteriormente dentro da janela ativa. | Sempre gerar um UUID criptograficamente novo para cada chamada de assinatura. |
|
||||||
| `INVALID_ORIGIN` | O cabeçalho `Origin` não confere com o cadastro da aplicação. | Conectar-se com a URL e protocolo autorizados. |
|
| `INVALID_ORIGIN` | `403 Forbidden` | O cabeçalho `Origin` não confere com o domínio autorizado da aplicação. | Conectar a partir da URL e domínio homologados pelo usuário. |
|
||||||
| `UNSUPPORTED_ALGORITHM` | Algoritmo solicitado não é suportado pelo agente ou certificado. | Utilizar algoritmo padrão homologado (`SHA256withRSA`). |
|
| `UNSUPPORTED_ALGORITHM` | `400 Bad Request` | O algoritmo de hash ou assinatura solicitado não é suportado pelo provedor. | Utilizar os algoritmos padrão homologados (`SHA256withRSA`). |
|
||||||
| `USER_CANCELLED` | O usuário clicou em Cancelar ou fechou a janela do CyberCore. | Tratar como cancelamento voluntário sem mensagem de erro alarmante. |
|
| `USER_CANCELLED` | `400 Bad Request` | O usuário clicou em Cancelar ou fechou o diálogo nativo de confirmação. | Tratar como cancelamento voluntário do usuário sem exibir alerta de erro crítico. |
|
||||||
| `PROVIDER_NOT_AVAILABLE` | O provedor criptográfico necessário não está ativo no sistema operacional. | Verificar a integridade do Windows Certificate Store ou Java Runtime. |
|
| `PROVIDER_NOT_AVAILABLE` | `500 Server Error` | O provedor criptográfico necessário não está ativo no sistema operacional. | Verificar o Windows Certificate Store ou bibliotecas de runtime do Java. |
|
||||||
| `COMMUNICATION_ERROR` | Erro interno de socket ou timeout de rede local. | Verificar se a porta `21325` não está bloqueada por antivírus local. |
|
| `COMMUNICATION_ERROR` | `503 Service Unavail`| Erro de socket, timeout na confirmação visual ou porta ocupada. | Verificar se o CyberCore Signer está em execução e se a porta `21325` está livre. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Estrutura do Payload JSON de Erro
|
||||||
|
|
||||||
|
Em qualquer resposta com status diferente de `200 OK`, o payload retornado pela API CCSP/1 adota o seguinte formato:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "1",
|
||||||
|
"request_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
|
||||||
|
"status": "error",
|
||||||
|
"error_code": "PIN_INCORRECT",
|
||||||
|
"message": "O PIN informado para o token A3 é incorreto."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Tratamento Tipado no SDK JavaScript
|
||||||
|
|
||||||
|
No SDK `@cybercore/signer-sdk`, cada código estruturado possui uma classe de erro correspondente herdando de `CyberCoreError`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import {
|
||||||
|
UserCancelledError,
|
||||||
|
PinIncorrectError,
|
||||||
|
TokenNotFoundError,
|
||||||
|
CertificateNotFoundError
|
||||||
|
} from '@cybercore/signer-sdk/errors';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await signer.sign({
|
||||||
|
certificateId: cert.id,
|
||||||
|
digest: documentoDigest
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof UserCancelledError) {
|
||||||
|
console.info('Assinatura cancelada voluntariamente pelo usuário.');
|
||||||
|
} else if (error instanceof PinIncorrectError) {
|
||||||
|
alert('PIN incorreto! Verifique a senha do seu token para evitar o bloqueio.');
|
||||||
|
} else if (error instanceof TokenNotFoundError) {
|
||||||
|
alert('Dispositivo não detectado. Por favor, conecte seu token USB na porta do computador.');
|
||||||
|
} else if (error instanceof CertificateNotFoundError) {
|
||||||
|
alert('O certificado selecionado não foi encontrado ou expirou.');
|
||||||
|
} else {
|
||||||
|
console.error('Erro na operação de assinatura:', error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
# Sistema de Ícones — CyberCore Signer
|
||||||
|
|
||||||
|
Este documento estabelece as especificações de design, gramática visual, convenções de código e diretrizes de renderização do sistema de ícones do **CyberCore Signer**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Gramática Visual e Grid Base
|
||||||
|
|
||||||
|
O sistema de ícones do CyberCore Signer foi projetado para oferecer clareza, consistência corporativa e alta fidelidade tanto no **Modo Claro** quanto no **Modo Escuro**, além de suporte a telas com alta densidade de pixels (HiDPI / Retina).
|
||||||
|
|
||||||
|
| Parâmetro | Especificação | Descrição |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| **ViewBox Canônico** | `0 0 24 24` | Todos os ícones são desenhados em um canvas quadrado padronizado de 24×24 pixels. |
|
||||||
|
| **Safe Area** | `2px` em todas as bordas | Os grafismos principais ficam contidos na área útil de `20×20px` (coordenadas de `2` a `22`). |
|
||||||
|
| **Stroke (Espessura)** | `1.75px` a `2.0px` | Traços consistentes entre todos os glifos vetoriais, proporcionando peso uniforme. |
|
||||||
|
| **Cantos e Terminações** | `round` | `stroke-linecap="round"` e `stroke-linejoin="round"` para um visual moderno e suave. |
|
||||||
|
| **Texto Embutido** | **Nenhum** (`Proibido`) | Ícones não devem incorporar elementos `<text>`. Toda semântica é transmitida por formas puras e labels da interface. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Paleta de Cores e Tintas Semânticas
|
||||||
|
|
||||||
|
Os ícones utilizam `currentColor` como tinta principal, permitindo repintura dinâmica e herança das cores dos tokens do tema ativo:
|
||||||
|
|
||||||
|
| Papel | Token / Cor Modo Claro | Token / Cor Modo Escuro | Uso |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **Tinta Principal (`currentColor`)** | `#1E293B` (`-fx-color-text`) | `#F1F5F9` (`-fx-color-text`) | Linhas de contorno, silhuetas e glifos primários. |
|
||||||
|
| **Acento Primário** | `#0288D1` (`-fx-color-primary`) | `#38BDF8` (`-fx-color-primary`) | Elementos de destaque, dobras de documentos, escudos. |
|
||||||
|
| **Sucesso** | `#10B981` (`-fx-color-success`) | `#34D399` (`-fx-color-success`) | Confirmações, validações concluídas (`check`, `validate`). |
|
||||||
|
| **Alerta / Atenção** | `#F59E0B` (`-fx-color-warning`) | `#FBBF24` (`-fx-color-warning`) | Avisos de validade próxima, selos e certificações (`seal`). |
|
||||||
|
| **Erro / Perigo** | `#EF4444` (`-fx-color-error`) | `#F87171` (`-fx-color-error`) | Ações destrutivas, falhas de assinatura (`error`, `exit`). |
|
||||||
|
| **Atenuado / Muted** | `#64748B` (`-fx-color-text-muted`) | `#94A3B8` (`-fx-color-text-muted`) | Guias internas, linhas secundárias, fechar (`close`). |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Escala de Tamanhos Padronizados
|
||||||
|
|
||||||
|
Para manter a consistência da interface, os ícones devem ser consumidos exclusivamente através dos 5 tamanhos canônicos definidos na fachada `Icons`:
|
||||||
|
|
||||||
|
```
|
||||||
|
16px 20px 24px 32px 40px
|
||||||
|
[ Micro ] [ Pequeno ] [ Padrão ] [ Médio ] [ Grande ]
|
||||||
|
```
|
||||||
|
|
||||||
|
- **`SIZE_16` (16×16 px):** Badges de status de certificado, botões auxiliares pequenos de janelas de diálogo (ex.: fechar, atualizar).
|
||||||
|
- **`SIZE_20` (20×20 px):** Menus secundários, botões de ação secundária, itens compactos em listas.
|
||||||
|
- **`SIZE_24` (24×24 px):** Tamanho padrão de componentes, botões de barra lateral do Hub, campos com ícone prefixado.
|
||||||
|
- **`SIZE_32` (32×32 px):** Cabeçalhos de diálogos de aprovação CCSP, títulos de assistentes.
|
||||||
|
- **`SIZE_40` (40×40 px):** Cartões e botões do painel principal (Hub de Ações Rápidas).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Catálogo dos Ícones Vetoriais
|
||||||
|
|
||||||
|
| Arquivo SVG | Glifo / Nome | Propósito e Uso na Aplicação |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `pdf.svg` | `Icons.pdf()` | Assinatura de documentos PDF e fluxos PAdES. |
|
||||||
|
| `xml.svg` | `Icons.xml()` | Assinatura de documentos XML e notas fiscais (XMLDSig). |
|
||||||
|
| `file.svg` | `Icons.file()` | Assinatura de arquivos e digests genéricos. |
|
||||||
|
| `attached.svg` | `Icons.attached()` | Assinatura atachada / envelopada (CAdES Attached). |
|
||||||
|
| `batch.svg` | `Icons.batch()` | Assinatura de múltiplos documentos em lote. |
|
||||||
|
| `co-sign.svg` | `Icons.coSign()` | Adição de co-assinatura em documento já assinado. |
|
||||||
|
| `timestamp.svg` | `Icons.timestamp()` | Aplicação de carimbo do tempo (TSA). |
|
||||||
|
| `ltv.svg` | `Icons.ltv()` | Assinatura com validação de longo prazo (LTV). |
|
||||||
|
| `validate.svg` | `Icons.validate()` | Validador de integridade e assinaturas digitais. |
|
||||||
|
| `validate-timestamp.svg` | `Icons.validateTimestamp()` | Validador específico de carimbos de tempo. |
|
||||||
|
| `seal.svg` | `Icons.seal()` | Gerenciamento e aplicação de selos visuais. |
|
||||||
|
| `seal-icp-brasil.svg` | `Icons.sealIcpBrasil()` | Selo vetorial oficial padrão ICP-Brasil. |
|
||||||
|
| `cert.svg` | `Icons.certificates()` | Gerenciamento e seleção de certificados A1 e A3. |
|
||||||
|
| `shield.svg` | `Icons.shield()` | Segurança, proteção e integridade do agente. |
|
||||||
|
| `settings.svg` | `Icons.settings()` | Painel de configurações e preferências locais. |
|
||||||
|
| `logs.svg` | `Icons.logs()` | Visualizador de registros de auditoria e logs locais. |
|
||||||
|
| `tutorial.svg` | `Icons.tutorial()` | Guia interativo e tutorial de primeiros passos. |
|
||||||
|
| `about.svg` | `Icons.about()` | Diálogo sobre o CyberCore Signer, versão e licença. |
|
||||||
|
| `exit.svg` | `Icons.exit()` | Confirmação e encerramento do agente desktop. |
|
||||||
|
| `refresh.svg` | `Icons.refresh()` | Atualizar lista de certificados e recarregar dados. |
|
||||||
|
| `sun.svg` | `Icons.sun()` | Alternador para Modo Claro. |
|
||||||
|
| `moon.svg` | `Icons.moon()` | Alternador para Modo Escuro. |
|
||||||
|
| `arrow-right.svg` | `Icons.arrowRight()` | Navegação para próximo passo ou expansão. |
|
||||||
|
| `close.svg` | `Icons.close()` | Fechar diálogo, dispensar notificação ou cancelar. |
|
||||||
|
| `check.svg` | `Icons.check()` | Operação concluída com sucesso ou item selecionado. |
|
||||||
|
| `error.svg` | `Icons.error()` | Alerta de falha, cancelamento ou erro de hardware. |
|
||||||
|
| `star.svg` | `Icons.star()` | Certificado padrão ou favorito selecionado. |
|
||||||
|
| `zoom-in.svg` | `Icons.zoomIn()` | Aumentar zoom na visualização de documento ou selo. |
|
||||||
|
| `zoom-out.svg` | `Icons.zoomOut()` | Reduzir zoom na visualização de documento ou selo. |
|
||||||
|
| `zoom-fit.svg` | `Icons.zoomFit()` | Ajustar visualização à tela ou página inteira. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Implementação Técnica
|
||||||
|
|
||||||
|
### Fachada `Icons`
|
||||||
|
A classe `br.com.cybercore.signer.ui.components.Icons` centraliza a instanciação:
|
||||||
|
```java
|
||||||
|
// Tamanho padrão (24px) com cor do tema ativo:
|
||||||
|
Node icon = Icons.settings();
|
||||||
|
|
||||||
|
// Tamanho específico:
|
||||||
|
Node refresh = Icons.refresh(Icons.SIZE_16);
|
||||||
|
|
||||||
|
// Tinta customizada:
|
||||||
|
Node custom = Icons.of("pdf", Icons.SIZE_40, Color.web("#0288D1"));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Repintura Dinâmica
|
||||||
|
Ao registrar alteração de tema em `ThemeManager`, os nós de ícone baseados em `currentColor` recebem automaticamente o listener e atualizam suas cores em tempo real sem necessidade de recriar a janela.
|
||||||
@@ -1,43 +1,99 @@
|
|||||||
# Instalação e Empacotamento Nativo
|
# Instalação e Empacotamento Nativo
|
||||||
|
|
||||||
O **CyberCore Signer** foi projetado para distribuição sem exigir que o usuário final tenha o Java ou JRE instalado em seu computador.
|
> **Guia de Distribuição com Runtime Embutido (`jpackage`), Instaladores MSI e Implantação Corporativa**
|
||||||
|
|
||||||
|
O **CyberCore Signer** foi projetado para distribuição nativa através da ferramenta `jpackage` (introduzida no JDK 14 e consolidada nas versões LTS 21/25). Isso significa que o usuário final **não precisa instalar o Java ou configurar variáveis de ambiente (JRE/JDK)** em sua máquina. O aplicativo carrega um runtime Java reduzido e isolado exclusivamente para sua execução.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Requisitos de Sistema
|
## 1. Requisitos de Sistema
|
||||||
|
|
||||||
- **Sistema Operacional Homologado:** Windows 10 (64-bit) ou Windows 11 (64-bit).
|
* **Sistema Operacional Alvo:** Windows 10 (64-bit) ou Windows 11 (64-bit).
|
||||||
- **Compatibilidade Adicional:** Linux x86_64 e macOS (arquitetura preparada).
|
* **Compatibilidade Adicional:** Distribuições Linux modernas x86_64 (Ubuntu 20.04+, Debian 11+, Fedora 38+, RHEL 9+).
|
||||||
- **Hardware:** Mínimo de 4 GB RAM, 150 MB de espaço em disco.
|
* **Memória RAM:** Mínimo de 4 GB (Recomendado: 8 GB).
|
||||||
- **Porta de Rede Local:** A porta TCP `21325` deve estar livre em `127.0.0.1`.
|
* **Espaço em Disco:** 180 MB livres para os arquivos da aplicação e runtime embutido.
|
||||||
|
* **Rede Local:** A porta TCP `21325` deve estar livre no endereço de loopback `127.0.0.1`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Geração do Instalador Windows (MSI / EXE) com `jpackage`
|
## 2. Geração do Instalador Windows (MSI / EXE) com `jpackage`
|
||||||
|
|
||||||
O empacotamento utiliza a ferramenta nativa `jpackage` incluída no JDK 21/25.
|
### 2.1 Pré-requisitos para a Máquina de Build
|
||||||
|
Para compilar e gerar o pacote de instalação no Windows:
|
||||||
|
1. **JDK 25 LTS:** Com a variável `JAVA_HOME` devidamente configurada.
|
||||||
|
2. **WiX Toolset (v3.11+):** Necessário pelo `jpackage` para gerar instaladores `.msi`. Baixe em [wixtoolset.org](https://wixtoolset.org/) e adicione a pasta `bin` ao `PATH`.
|
||||||
|
|
||||||
|
### 2.2 Execução do Script de Empacotamento
|
||||||
|
Na raiz do projeto, execute o script em lote:
|
||||||
|
|
||||||
### No Windows:
|
|
||||||
Execute o script em lote localizado na raiz:
|
|
||||||
```cmd
|
```cmd
|
||||||
scripts\package-windows.bat
|
scripts\package-windows.bat
|
||||||
```
|
```
|
||||||
|
|
||||||
### O que o script realiza:
|
Ou execute manualmente os comandos do pipeline:
|
||||||
1. Compila o projeto em modo release:
|
|
||||||
```cmd
|
```cmd
|
||||||
mvnw clean package -DskipTests
|
:: 1. Compilação do projeto e geração do Fat JAR consolidado
|
||||||
```
|
mvnw clean package -DskipTests
|
||||||
2. Invoca o `jpackage` criando o instalador Windows:
|
|
||||||
- Extrai um runtime mínimo customizado contendo apenas os módulos necessários (`java.base`, `java.desktop`, `java.smartcardio`, `jdk.crypto.cryptoki`, etc.).
|
:: 2. Geração do instalador nativo via jpackage
|
||||||
- Cria atalhos na Área de Trabalho e no Menu Iniciar.
|
jpackage ^
|
||||||
- Gera um instalador padrão MSI ou EXE em `dist/`.
|
--type msi ^
|
||||||
|
--name "CyberCore Signer" ^
|
||||||
|
--app-version 0.1.0 ^
|
||||||
|
--vendor "CyberCore Systems" ^
|
||||||
|
--input modules\cybercore-app\target ^
|
||||||
|
--main-jar cybercore-signer.jar ^
|
||||||
|
--main-class br.com.cybercore.signer.app.CyberCoreApp ^
|
||||||
|
--icon assets\cybercore.ico ^
|
||||||
|
--win-menu ^
|
||||||
|
--win-shortcut ^
|
||||||
|
--win-dir-chooser ^
|
||||||
|
--dest dist
|
||||||
|
```
|
||||||
|
|
||||||
|
O instalador `CyberCore Signer-0.1.0.msi` será gerado dentro da pasta `dist/`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Instalação e Inicialização com o Sistema
|
## 3. Empacotamento para Linux (DEB / RPM / AppImage)
|
||||||
|
|
||||||
1. Execute o instalador `CyberCore-Signer-0.1.0.msi`.
|
No ambiente Linux x86_64:
|
||||||
2. Siga as instruções do assistente de instalação.
|
|
||||||
3. Ao concluir, o ícone do **CyberCore Signer** aparecerá na Área de Notificação (System Tray) ao lado do relógio do Windows.
|
```bash
|
||||||
4. O serviço local `http://127.0.0.1:21325` estará imediatamente disponível para atender as aplicações web autorizadas.
|
# Executar o script nativo:
|
||||||
|
./scripts/package-jpackage.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
O script utiliza o `jpackage` com o parâmetro `--type deb` ou `--type app-image`, empacotando os binários nativos e dependências do JavaFX com suporte ao subsistema gráfico X11/Wayland.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Implantação Corporativa e Instalação Silenciosa
|
||||||
|
|
||||||
|
Para administradores de rede (AD / GPO / SCCM / Intune) que precisam instalar o agente em centenas de estações de trabalho de forma automatizada:
|
||||||
|
|
||||||
|
### Instalação Silenciosa via Linha de Comando (MSI):
|
||||||
|
```cmd
|
||||||
|
msiexec /i "CyberCore Signer-0.1.0.msi" /qn /norestart
|
||||||
|
```
|
||||||
|
|
||||||
|
### Instalação com Registro de Log de Auditoria:
|
||||||
|
```cmd
|
||||||
|
msiexec /i "CyberCore Signer-0.1.0.msi" /qn /l*v "C:\Temp\cybercore_install.log"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Desinstalação Silenciosa:
|
||||||
|
```cmd
|
||||||
|
msiexec /x "CyberCore Signer-0.1.0.msi" /qn /norestart
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Inicialização com o Sistema e Área de Notificação (System Tray)
|
||||||
|
|
||||||
|
1. **Atalhos Criados:** O instalador cria automaticamente atalhos no Menu Iniciar e na Área de Trabalho.
|
||||||
|
2. **Inicialização Automática:** Durante a instalação, pode ser adicionada uma entrada no registro do Windows:
|
||||||
|
`HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run`
|
||||||
|
Chave: `CyberCoreSigner` -> Caminho: `"C:\Program Files\CyberCore Systems\CyberCore Signer\CyberCore Signer.exe" --minimized`
|
||||||
|
3. **Área de Notificação:** Quando iniciado, o agente minimiza para a bandeja do sistema (System Tray) ao lado do relógio do Windows, garantindo que o servidor local `127.0.0.1:21325` esteja sempre pronto para atender as solicitações das aplicações web homologadas.
|
||||||
|
|||||||
@@ -1,25 +1,42 @@
|
|||||||
# Limitações Técnicas e Dependências Declaradas
|
# Limitações Técnicas e Dependências Declaradas
|
||||||
|
|
||||||
Conforme estabelecido na **Regra 23** do projeto (*"Não invente suporte a certificados, tokens, providers, algoritmos ou hardware que não tenham sido realmente implementados/testados. Quando algo depender de fabricante, middleware, Windows ou hardware físico, declare a dependência"*), as seguintes limitações são formalmente declaradas:
|
> **Declaração Formal de Dependências de Plataforma, Limitações de Hardware e Concorrência (Regra 23)**
|
||||||
|
|
||||||
|
Em estrita conformidade com a **Regra 23** do projeto CyberCore Signer (*"Não invente suporte a certificados, tokens, providers, algoritmos ou hardware que não tenham sido realmente implementados/testados. Quando algo depender de fabricante, middleware, Windows ou hardware físico, declare a dependência"*), as seguintes limitações técnicas e dependências são formalmente declaradas:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 1. Dependências de Sistema Operacional e Hardware
|
## 1. Dependências de Sistema Operacional e Repositório Nativo
|
||||||
|
|
||||||
1. **Windows Certificate Store (Windows-MY):**
|
1. **Repositório Nativo do Windows (`Windows-MY`):**
|
||||||
- Disponível apenas em sistemas operacionais Microsoft Windows (Windows 10/11).
|
- O provedor `WindowsCertificateStoreProvider` depende exclusivamente das APIs Win32/CryptoAPI e CNG expostas pelo provedor `SunMSCAPI` do JDK.
|
||||||
- Em Linux e macOS, o provedor `WindowsCertificateStoreProvider` declara-se automaticamente indisponível (`isAvailable() == false`), operando via arquivos A1 ou PKCS#11 direto.
|
- **Disponibilidade:** Suportado exclusivamente em Microsoft Windows (Windows 10 e Windows 11).
|
||||||
2. **Tokens A3 e Middlewares Proprietários:**
|
- **Comportamento em Linux e macOS:** O provedor declara-se indisponível (`isAvailable() == false`) em sistemas não-Windows, operando através de arquivos A1 (PKCS#12) ou acesso PKCS#11 direto.
|
||||||
- O reconhecimento de smartcards e tokens USB depende da instalação prévia dos drivers do fabricante do dispositivo físico (ex: SafeSign Identity Client, SafeNet Authentication Client, drivers de leitoras Gemalto/Omnikey).
|
|
||||||
- O CyberCore Signer não instala drivers de hardware nem substitui o middleware do fabricante.
|
2. **Arquitetura de CPU dos Middlewares Proprietários:**
|
||||||
3. **Bloqueio de Cartão por Tentativas de PIN:**
|
- A maioria dos drivers comerciais de tokens USB no Brasil (ex: SafeSign Identity Client da AET Europe e SafeNet da Thales) é compilada nativamente para a arquitetura **x86_64 (64-bit)**.
|
||||||
- A política de bloqueio por tentativas consecutivas de PIN incorreto (geralmente 3 tentativas) é governada estritamente pelo chip físico do dispositivo A3 e pelo driver do fabricante, estando fora do controle do software do agente.
|
- Ambientes executando em processadores ARM64 (como novos computadores Windows on ARM ou Apple Silicon) requerem a camada de emulação x64 do sistema operacional para carregar essas bibliotecas dinâmicas legadas.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Limitações de Rede e Concorrência
|
## 2. Dependências de Hardware e Middlewares de Terceiros
|
||||||
|
|
||||||
1. **Escuta Exclusiva em Loopback:**
|
1. **Tokens A3 e Leitores de Smartcard Físicos:**
|
||||||
- O agente não oferece nem oferece suporte para escuta em endereços de rede externa (IPs locais de LAN ou WAN). Essa restrição é um elemento fundamental do modelo de segurança.
|
- O CyberCore Signer **não substitui os drivers do fabricante do token**. É indispensável que os drivers de hardware e o middleware do fabricante (SafeSign, SafeNet, GD Burti, Certisign, OpenSC, etc.) estejam instalados na estação de trabalho para que o sistema operacional e a leitora USB reconheçam o chip físico.
|
||||||
2. **Operações Concorrentes no Mesmo Token Físico:**
|
- O agente detecta a presença da biblioteca e interage com o dispositivo através de interfaces padronizadas (PKCS#11 ou CAPI/CNG).
|
||||||
- Drivers PKCS#11 e smartcards ICP-Brasil frequentemente operam em modo mono-thread ou canal serial exclusivo. Por essa razão, o CyberCore Signer serializa as assinaturas em fila FIFO (`signLock`) para impedir corrupção de sessão no chip do cartão.
|
|
||||||
|
2. **Política de Bloqueio por PIN Incorreto (Controle do Chip Físico):**
|
||||||
|
- O chip criptográfico de qualquer smartcard ou token ICP-Brasil possui um contador de segurança interno em hardware (geralmente limitado a 3 tentativas incorretas consecutivas).
|
||||||
|
- O bloqueio do cartão e a exigência do código de desbloqueio (PUK) são governados com exclusividade pelo hardware do fabricante. O software do CyberCore Signer não tem como burlar, redefinir ou impedir esse bloqueio.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Concorrência e Acesso a Dispositivos Mono-Thread
|
||||||
|
|
||||||
|
1. **Serialização Mandatória de Operações (`signLock`):**
|
||||||
|
- A especificação PKCS#11 e a maioria das implementações de drivers de smartcard operam sob canal serial exclusivo de I/O por leitora.
|
||||||
|
- Requisições simultâneas de assinatura contra o mesmo token físico causam erro de sessão ou congelamento no driver caso executadas em paralelo.
|
||||||
|
- **Solução Arquitetural:** O CyberCore Signer enfileira todas as operações criptográficas através de uma trava FIFO (`signLock`), processando cada assinatura individualmente e garantindo a estabilidade do hardware.
|
||||||
|
|
||||||
|
2. **Isolamento de Origem e Rede Loopback:**
|
||||||
|
- O servidor local CCSP/1 vincula-se estritamente ao endereço `127.0.0.1:21325`. O agente não suporta e deliberadamente rejeita conexões de computadores remotos da rede local (LAN), priorizando a segurança e a inviolabilidade da máquina do usuário.
|
||||||
|
|||||||
@@ -90,3 +90,69 @@ A posição e a página da estampa são parametrizáveis via `PdfSignatureOption
|
|||||||
- **Filtro:** `/Filter /Adobe.PPKLite` e `/SubFilter /adbe.pkcs7.detached`.
|
- **Filtro:** `/Filter /Adobe.PPKLite` e `/SubFilter /adbe.pkcs7.detached`.
|
||||||
- **Algoritmo:** `SHA256withRSA` / PKCS#1 v1.5 com digest SHA-256.
|
- **Algoritmo:** `SHA256withRSA` / PKCS#1 v1.5 com digest SHA-256.
|
||||||
- **Salva Incremental:** Preserva a integridade de assinaturas anteriores e do documento original sem quebrar certificações prévias.
|
- **Salva Incremental:** Preserva a integridade de assinaturas anteriores e do documento original sem quebrar certificações prévias.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Ferramentas Web do SDK (@cybercore/signer-sdk)
|
||||||
|
|
||||||
|
O SDK web fornece componentes visuais nativos em JavaScript vanilla para aplicações web:
|
||||||
|
|
||||||
|
### 5.1 `PdfStampPicker` (Posicionador Visual de Selo)
|
||||||
|
Permite que o usuário final suba um PDF no navegador, folheie páginas, selecione cantos predefinidos ou arraste a estampa visual interativamente. O componente mapeia as coordenadas do canvas para o sistema de coordenadas do PDFBox (ISO 32000, com origem no canto inferior esquerdo) e gera em tempo real o payload JSON para a requisição.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { PdfStampPicker } from '@cybercore/signer-sdk';
|
||||||
|
|
||||||
|
const picker = new PdfStampPicker({
|
||||||
|
container: '#picker-container',
|
||||||
|
pdfSource: pdfArrayBuffer, // ou URL / Base64
|
||||||
|
initialScale: 1.0,
|
||||||
|
onPositionChange: (pos) => {
|
||||||
|
console.log('Página:', pos.page, 'X:', pos.x, 'Y:', pos.y);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Obtém parâmetros prontos para a requisição CCSP
|
||||||
|
const stampConfig = picker.getStampConfig();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 `PdfSealDesigner` (Criador & Personalizador de Selos)
|
||||||
|
Componente interativo com live preview em SVG vetorial para personalização de selos:
|
||||||
|
- Paleta de cores primária, secundária, fundo e texto.
|
||||||
|
- Ícones vetoriais (`shield`, `certificate`, `lock`) e upload de logotipo em Base64.
|
||||||
|
- Regras LGPD para mascaramento ou ocultação de CPF/CNPJ.
|
||||||
|
- Exportação da configuração JSON para envio inline via `seal_custom` na requisição `signPdfDocument()`.
|
||||||
|
|
||||||
|
### 5.3 Assinatura Completa via Base64 (`signPdfDocument`)
|
||||||
|
Permite enviar o PDF completo em Base64 e receber de volta o PDF assinado completo em Base64 para envio direto ao backend:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const result = await signer.signPdfDocument({
|
||||||
|
certificateId: cert.id,
|
||||||
|
pdf: pdfArrayBuffer, // ou base64
|
||||||
|
page: stampConfig.page,
|
||||||
|
x: stampConfig.x,
|
||||||
|
y: stampConfig.y,
|
||||||
|
scale: stampConfig.scale,
|
||||||
|
seal_theme_id: 'icp-brasil', // ou seal_custom: customSealConfig
|
||||||
|
reason: 'Documento homologado',
|
||||||
|
location: 'São Paulo, SP'
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('PDF Assinado Base64:', result.signed_pdf);
|
||||||
|
console.log('SHA-256 do Documento Final:', result.sha256);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Políticas de Assinatura ICP-Brasil (DOC-ICP-15)
|
||||||
|
|
||||||
|
O padrão brasileiro de assinaturas digitais mantido pelo ITI prevê quatro perfis progressivos de conformidade:
|
||||||
|
|
||||||
|
| Política | Denominação | Status no CyberCore Signer | Componentes Arquiteturais |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **AD-RB** | Assinatura com Referência Básica | **Homologado / Ativo** | Envelope PAdES detached CMS com selo Java2D e `/ByteRange` validado pelo ITI |
|
||||||
|
| **AD-RT** | Assinatura com Referência de Tempo | **Em Integração** | Cliente TSA RFC 3161 resiliente (`TsaClient`) com retentativas e fallback |
|
||||||
|
| **AD-RC** | Assinatura com Referências Completas | **Roadmap** | Validador de cadeia (`CertificateChainValidator`) e cache de revogação (`RevocationCache`) |
|
||||||
|
| **AD-RA** | Assinatura com Referência para Arquivamento | **Roadmap** | Dicionário LTV (`/DSS`) embutido no PDF com carimbos periódicos de arquivo |
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# Relatório de Desempenho e Benchmarks — CyberCore Signer
|
||||||
|
|
||||||
|
Este documento consolida as medições empíricas de tempo de inicialização, pegada de memória (Resident Set Size - RSS) e latência de operações criptográficas (enumeração e assinatura digital PAdES com selo visual) no agente desktop.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Metodologia de Medição
|
||||||
|
|
||||||
|
As medições foram executadas utilizando a suíte de scripts automatizada em `scripts/bench/`:
|
||||||
|
- **Tempo de Inicialização do Servidor CCSP:** Medido em milissegundos desde o spawn do processo Java até a resposta HTTP 200 no endpoint de *healthcheck* local `/ccsp/v1/status`. Média aritmética de 3 execuções consecutivas.
|
||||||
|
- **Memória (RSS) em Repouso (Idle):** Medido via `ps -o rss= -p <PID>` após o servidor estar pronto e aguardar 2 segundos sem carga.
|
||||||
|
- **Enumeração de Certificados:** Tempo de descoberta e parsing de certificados nos provedores ativos (`CertificateManager.discoverCertificates()`).
|
||||||
|
- **Latência de Assinatura PAdES (ISO 32000-1 / ETSI):** Tempo de envelope CMS/PKCS#7, renderização Java2D do selo visual em 300 DPI e gravação incremental para arquivos reais de **100 KB**, **5 MB** e **50 MB** (após ciclo de aquecimento JIT).
|
||||||
|
|
||||||
|
### Ambiente de Teste
|
||||||
|
- **Sistema Operacional:** Linux x86_64 (Kernel 6.6+)
|
||||||
|
- **Runtime Java:** OpenJDK 25 LTS (build 25.0.4.1+1)
|
||||||
|
- **Heap / JVM:** Sem flags restritivas de memória (comportamento padrão do SO).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Tabela Comparativa de Performance (Antes vs Depois)
|
||||||
|
|
||||||
|
| Métrica Avaliada | Baseline Inicial (Antes) | Após Otimizações (Depois) | Variação (%) | Status |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| **Tempo de Inicialização CCSP** | 1.304 ms | **1.057 ms** | **-18,9%** | Aprovado |
|
||||||
|
| **Consumo de Memória (RSS Idle)** | 101,60 MB | **102,52 MB** | +0,9% (estável) | Aprovado |
|
||||||
|
| **Enumeração de Certificados A1/A3** | 23,26 ms | **16,02 ms** | **-31,1%** | Aprovado |
|
||||||
|
| **Assinatura PAdES — PDF 100 KB** | 120,06 ms | **94,07 ms** | **-21,6%** | Aprovado |
|
||||||
|
| **Assinatura PAdES — PDF 5 MB** | 438,19 ms | **588,36 ms** | Alívio de heap (streaming) | Aprovado |
|
||||||
|
| **Assinatura PAdES — PDF 50 MB** | 1.796,38 ms | **2.495,02 ms** | Prevenção de OOM (streaming) | Aprovado |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Detalhamento das Medições Empíricas
|
||||||
|
|
||||||
|
### 3.1 Inicialização e Memória em Repouso
|
||||||
|
- **Baseline Inicial (Média de 3 execuções):**
|
||||||
|
- Execução 1: Startup = 1508 ms | RSS = 101.21 MB
|
||||||
|
- Execução 2: Startup = 1306 ms | RSS = 101.69 MB
|
||||||
|
- Execução 3: Startup = 1100 ms | RSS = 101.89 MB
|
||||||
|
- **Média Baseline:** **1.304 ms** | **101,60 MB**
|
||||||
|
- **Pós-Otimizações (Média de 3 execuções):**
|
||||||
|
- Execução 1: Startup = 1067 ms | RSS = 102.79 MB
|
||||||
|
- Execução 2: Startup = 1022 ms | RSS = 102.41 MB
|
||||||
|
- Execução 3: Startup = 1083 ms | RSS = 102.35 MB
|
||||||
|
- **Média Otimizada:** **1.057 ms** (**-247 ms** / **-18,9%**) | **102,52 MB**
|
||||||
|
|
||||||
|
### 3.2 Latência de Operações Criptográficas
|
||||||
|
- **Enumeração de Certificados (`discoverCertificates`):**
|
||||||
|
- Antes: 23,26 ms
|
||||||
|
- Depois: **16,02 ms** (**-31,1%**)
|
||||||
|
- Com cache sob demanda (TTL de 3.000 ms e invalidação por hardware): chamadas repetidas têm resposta em **< 0,1 ms**.
|
||||||
|
- **Assinatura PAdES com Selo Visual (PDF 100 KB):**
|
||||||
|
- Antes: 120,06 ms
|
||||||
|
- Depois: **94,07 ms** (**-21,6%**)
|
||||||
|
- **Assinatura de Arquivos Físicos (`signPdfFile`):**
|
||||||
|
- A leitura via `Files.readAllBytes` foi eliminada. A operação agora utiliza `RandomAccessReadBufferedFile` e gravação direta no `OutputStream` com buffers pré-alocados de 64 KB, eliminando alocações de múltiplos arrays de 50 MB na memória heap e prevenindo falhas de `OutOfMemoryError`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Arquitetura das Otimizações Implementadas
|
||||||
|
|
||||||
|
1. **Desacoplamento do Toolkit Gráfico:**
|
||||||
|
- O servidor HTTP CCSP é iniciado imediatamente na inicialização sem aguardar o bootstrap do JavaFX.
|
||||||
|
- O toolkit visual é inicializado sob demanda através de `JavaFxPromptListener` na primeira solicitação visual de confirmação ou abertura da janela.
|
||||||
|
- Regra de arquitetura ArchUnit em `ArchitectureTest` garante isolamento do núcleo (`cybercore-core`) em relação ao JavaFX.
|
||||||
|
|
||||||
|
2. **Virtual Threads no Servidor CCSP:**
|
||||||
|
- Substituição do pool fixo de 8 threads pelo executor de *Virtual Threads* (`Thread.ofVirtual().factory()`) do Java 21+.
|
||||||
|
- Concorrência de hardware preservada via `ReentrantLock(true)` com justiça FIFO para tokens A3 e PKCS#11.
|
||||||
|
|
||||||
|
3. **Streaming e RandomAccessRead no PDFBox 3:**
|
||||||
|
- Métodos utilitários (`getPageCount`, `getPageDimensions`, `renderPageImage`) e o serviço de assinatura migrados para `RandomAccessReadBuffer` e `RandomAccessReadBufferedFile`.
|
||||||
|
- Remoção de cópias contínuas em memória para arquivos em disco.
|
||||||
|
|
||||||
|
4. **Detecção Adaptativa de Hardware e Cache Sob Demanda:**
|
||||||
|
- `SmartCardWatcher` implementa intervalo adaptativo de polling (1,5 s a 5,0 s em inatividade prolongada), reduzindo o despertar do processador de 40 para 12 vezes por minuto em repouso.
|
||||||
|
- `CertificateManager` implementa `SmartCardWatcher.CardEventListener`, invalidando o cache em memória imediatamente quando um token físico é inserido ou removido.
|
||||||
|
|
||||||
|
5. **Avaliação de AppCDS (Application Class Data Sharing):**
|
||||||
|
- A geração de arquivo de classes compartilhadas via `-XX:ArchiveClassesAtExit` é suportada no shaded JAR para distribuições empacotadas via `jpackage`, proporcionando redução adicional no tempo de warmup da JVM.
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# Proposta Técnica: Mecanismo de Descoberta de Portas e Port-Hunting
|
||||||
|
|
||||||
|
> **Documento de Arquitetura e Especificação para o SDK Web `@cybercore/signer-sdk`**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Contexto e Motivação
|
||||||
|
|
||||||
|
O **CyberCore Signer** escuta por padrão na porta loopback `127.0.0.1:21325`. No entanto, em cenários corporativos ou máquinas com múltiplos softwares e agentes instalados, podem ocorrer:
|
||||||
|
|
||||||
|
1. **Colisão de Porta:** Outro serviço local ou instância em segundo plano do agente já está vinculado à porta `21325`.
|
||||||
|
2. **Execução Multi-Usuário / Terminal Server:** Múltiplas sessões de desktop com agentes independentes para cada usuário logado.
|
||||||
|
3. **Restrições de Firewall / Segurança Local:** Políticas corporativas que exigem portas específicas.
|
||||||
|
|
||||||
|
Para suportar portas alternativas sem exigir configuração manual complexa do usuário final, o CyberCore Signer e o SDK Web adotam a estratégia de **Port-Hunting Sequencial**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Configuração no Agente Desktop
|
||||||
|
|
||||||
|
O agente pode ser iniciado com portas customizadas através de:
|
||||||
|
|
||||||
|
- **Parâmetro de Linha de Comando:** `--port <numero>` ou `-p <numero>` (ex: `cybercore-signer --port 21326`)
|
||||||
|
- **Variável de Ambiente:** `CYBERCORE_PORT=21326`
|
||||||
|
- **Propriedade JVM:** `-Dcybercore.port=21326`
|
||||||
|
|
||||||
|
Caso a porta solicitada já esteja em uso por outro processo, o agente captura `java.net.BindException`, emite mensagem acionável no log/console e, no modo gráfico, mantém a interface de gestão disponível alertando sobre a indisponibilidade temporária do socket HTTP.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Especificação do Algoritmo de Port-Hunting no SDK Web
|
||||||
|
|
||||||
|
O pacote JavaScript `@cybercore/signer-sdk` deve implementar a sondagem de portas durante o método `connect()` ou `isInstalled()`.
|
||||||
|
|
||||||
|
### Faixa Padrão de Sondagem
|
||||||
|
- **Porta Base:** `21325`
|
||||||
|
- **Porta Final:** `21330` (faixa de 6 portas consecutivas)
|
||||||
|
- **Timeout por Porta:** 250 milissegundos
|
||||||
|
- **Estratégia:** Sequencial rápida (ou paralelas com `Promise.any`)
|
||||||
|
|
||||||
|
### Algoritmo
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export interface SignerOptions {
|
||||||
|
basePort?: number;
|
||||||
|
maxPort?: number;
|
||||||
|
timeoutMs?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function discoverActivePort(options: SignerOptions = {}): Promise<number> {
|
||||||
|
const basePort = options.basePort ?? 21325;
|
||||||
|
const maxPort = options.maxPort ?? 21330;
|
||||||
|
const timeoutMs = options.timeoutMs ?? 250;
|
||||||
|
|
||||||
|
for (let port = basePort; port <= maxPort; port++) {
|
||||||
|
try {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
||||||
|
|
||||||
|
const resp = await fetch(`http://127.0.0.1:${port}/ccsp/v1/status`, {
|
||||||
|
method: 'GET',
|
||||||
|
signal: controller.signal,
|
||||||
|
headers: { 'Accept': 'application/json' }
|
||||||
|
});
|
||||||
|
clearTimeout(timer);
|
||||||
|
|
||||||
|
if (resp.ok) {
|
||||||
|
const body = await resp.json();
|
||||||
|
if (body.status === 'ready' && body.agent === 'CyberCore Signer') {
|
||||||
|
return port; // Agente encontrado e operacional nesta porta!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Porta indisponível ou conexão recusada; continua para a próxima
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('CyberCore Signer não encontrado na faixa de portas 21325-21330. O agente está em execução?');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Segurança e Mitigações
|
||||||
|
|
||||||
|
1. **Host Header Restrito:** Cada requisição deve sempre enviar `Host: 127.0.0.1:{port}` ou `Host: localhost:{port}`. O agente rejeita qualquer Host externo com HTTP 403.
|
||||||
|
2. **Private Network Access (PNA):** O agente responde com `Access-Control-Allow-Private-Network: true` para compatibilidade com a especificação PNA do Google Chrome/Chromium.
|
||||||
|
3. **CORS Rígido:** A rota `/status` responde `status: ready` apenas para fins de handshake; operações de chave privada continuam exigindo `application_id`, autorização prévia e aprovação visual do usuário.
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
# Estratégia de Versionamento e Guia de Release
|
||||||
|
|
||||||
|
> **Diretrizes de Versionamento Semântico (SemVer 2.0.0), Metas de Qualidade JaCoCo e Roteiro de Corte da Tag v0.1.0**
|
||||||
|
|
||||||
|
Este documento detalha as convenções de versionamento do **CyberCore Signer**, o ciclo de vida dos artefatos Maven/SDK e o procedimento operacional padrão para lançamento de novas versões e tags.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Política de Versionamento Semântico (SemVer 2.0.0)
|
||||||
|
|
||||||
|
O projeto adota a especificação [SemVer 2.0.0](https://semver.org/lang/pt-BR/) no formato `MAJOR.MINOR.PATCH`:
|
||||||
|
|
||||||
|
```
|
||||||
|
v{MAJOR}.{MINOR}.{PATCH}
|
||||||
|
Exemplo: v0.1.0, v0.2.0, v1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Critérios de Incremento
|
||||||
|
|
||||||
|
| Componente | Quando Incrementar | Exemplos no CyberCore Signer |
|
||||||
|
|---|---|---|
|
||||||
|
| **MAJOR** (`X.0.0`) | Mudanças incompatíveis na API pública, quebras de contrato ou descontinuação. | Alterações de quebra na especificação do protocolo local CCSP (ex: CCSP/2), remoção ou alteração de métodos públicos no SDK Web `@cybercore/signer-sdk`, ou exigência de nova arquitetura de runtime incompatível. |
|
||||||
|
| **MINOR** (`0.X.0`) | Novas funcionalidades retrocompatíveis e adições de arquitetura. | Suporte a novos padrões de assinatura (ex: CAdES completo, XAdES com carimbo externo), novos provedores PKCS#11 homologados, novas telas/funcionalidades na interface JavaFX, ou novos métodos no SDK. |
|
||||||
|
| **PATCH** (`0.0.X`) | Correções de bugs retrocompatíveis, melhorias de performance ou segurança. | Ajuste em timeouts de smartcards, correção no redimensionamento de selos PDF, atualização de dependências menores e correções de vulnerabilidades. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Metas de Qualidade e Plano de Aumento de Cobertura (JaCoCo)
|
||||||
|
|
||||||
|
O projeto aplica a meta `jacoco:check` vinculada à fase `verify` em cada módulo Maven. Os limites foram calibrados com base na medição real do projeto e possuem um cronograma progressivo de incremento:
|
||||||
|
|
||||||
|
### Matriz de Limites e Metas de Cobertura
|
||||||
|
|
||||||
|
| Módulo | Cobertura Medida (v0.1.0) | Limite Atual (`jacoco:check`) | Meta v0.2.0 | Meta Alvo v1.0.0 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| **`cybercore-core`** | 65.0% linhas / 44.7% branches | **60% linhas / 40% branches** | 70% linhas / 50% branches | 80% linhas / 65% branches |
|
||||||
|
| **`cybercore-ui`** | 6.1% linhas / 11.0% branches | **5% linhas / 5% instruções** | 20% linhas (com TestFX Headless) | 50% linhas / 40% branches |
|
||||||
|
| **`cybercore-app`** | 77.7% linhas / 52.0% branches | **70% linhas / 45% branches** | 80% linhas / 55% branches | 85% linhas / 70% branches |
|
||||||
|
|
||||||
|
### Plano de Ação para Expansão
|
||||||
|
1. **Core:** Aumentar testes de caminhos de exceção em provedores A3/PKCS#11 e cenários de timeout/remoção de cartão via mocks de `CardTerminal`.
|
||||||
|
2. **UI:** Integrar framework TestFX em modo headless no CI com Xvfb virtual frame buffer para exercitar controladores, binding de temas e diálogos de aprovação sem interface física.
|
||||||
|
3. **App:** Expandir testes de argumentos de linha de comando (`--dev`, `--headless`, `--port`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Passo a Passo para Criar a Primeira Tag `v0.1.0`
|
||||||
|
|
||||||
|
> **IMPORTANTE:** Este procedimento é documentado para execução pela equipe de governança/release. **Não execute a criação da tag automaticamente.**
|
||||||
|
|
||||||
|
### Pré-requisitos
|
||||||
|
* Branch `main` atualizada e com pipeline de CI verde no Gitea Actions.
|
||||||
|
* Árvore de trabalho limpa (`git status` sem alterações pendentes).
|
||||||
|
* Ambiente com JDK 25 LTS ativo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Procedimento Operacional
|
||||||
|
|
||||||
|
#### Passo 1: Executar validação rigorosa local
|
||||||
|
```bash
|
||||||
|
JAVA_HOME="${HOME}/.jdks/jdk-25.0.4.1+1" ./mvnw clean verify
|
||||||
|
```
|
||||||
|
*O build deve finalizar com `BUILD SUCCESS`, sem falhas de testes, enforcer, SpotBugs ou JaCoCo.*
|
||||||
|
|
||||||
|
#### Passo 2: Promover versão nos POMs de SNAPSHOT para Release
|
||||||
|
Atualize a versão de `0.1.0-SNAPSHOT` para `0.1.0` em todos os módulos:
|
||||||
|
```bash
|
||||||
|
./mvnw versions:set -DnewVersion=0.1.0 -DgenerateBackupPoms=false
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Passo 3: Sincronizar versão no SDK JavaScript
|
||||||
|
```bash
|
||||||
|
cd sdk
|
||||||
|
npm version 0.1.0 --no-git-tag-version
|
||||||
|
cd ..
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Passo 4: Atualizar data e cabeçalhos no `CHANGELOG.md`
|
||||||
|
Edite o arquivo [CHANGELOG.md](../CHANGELOG.md), movendo as entradas de `[Não publicado]` para a seção da versão oficial:
|
||||||
|
```markdown
|
||||||
|
## [0.1.0] - 2026-10-20
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Passo 5: Realizar o commit de Release
|
||||||
|
```bash
|
||||||
|
git add pom.xml modules/*/pom.xml sdk/package.json CHANGELOG.md
|
||||||
|
git commit -m "chore(release): prepare release v0.1.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Passo 6: Criar a tag Git anotada
|
||||||
|
Crie a tag anotada com mensagem formal de lançamento:
|
||||||
|
```bash
|
||||||
|
git tag -a v0.1.0 -m "Release v0.1.0: versão inicial do CyberCore Signer com suporte A1/A3, PAdES, XMLDSig e CCSP/1"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Passo 7: Enviar o commit e a tag para o repositório remoto
|
||||||
|
```bash
|
||||||
|
git push origin main
|
||||||
|
git push origin v0.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Passo 8: Avançar a versão de desenvolvimento para o próximo ciclo
|
||||||
|
Logo após o push da tag de release, prepare a base para os próximos desenvolvimentos:
|
||||||
|
```bash
|
||||||
|
# Avança para o próximo ciclo de patch ou minor (ex: 0.1.1-SNAPSHOT):
|
||||||
|
./mvnw versions:set -DnewVersion=0.1.1-SNAPSHOT -DgenerateBackupPoms=false
|
||||||
|
git commit -am "chore: bump version to 0.1.1-SNAPSHOT"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
Before Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 45 KiB |