🧾 API PGCC - Módulo de Hash JWT
📘 Visão Geral
O módulo PGCC Hash é responsável por receber, validar e consultar hashes digitais assinados e enviados pelas Gerenciadoras de Consentimento e Ciência (GCC). Os hashes são codificados como chaves JWT (chaves web em formato JSON) e assinados via algoritmos de criptografia por meio de chaves assimétricas (RSA usando SHA-256).
- A integridade, autenticidade e não repúdio dos dados é garantido pela assinatura digital do hash JWT.
- A validação da assinatura é realizada com base em uma chave pública previamente cadastrada pela GCC, assegurando que o conteúdo do JWT não tenha sido alterado e que a origem da assinatura seja confiável.
🔐 Funcionamento do Hash JWT
1️⃣ Codificação do conteúdo do Hash
A GCC converte o conteúdo (ou payload) do Hash em formato JSON para uma versão compacta e, em seguida, eu um texto codificado em Base64. Esse processo garante que o conteúdo original seja representado de forma ofuscada e permita seu tráfego via HTTP, preservando sua estrutura e integridade.
Exemplo de conteúdo original
O payload do Hash deve ser representado como um JSON contendo todos os dados especificados abaixo.
{
"templateId": "1222024-00001",
"isConsentimento": true,
"idConsentimento": "12345687",
"cnpjUsuario": "87587279000130",
"cnpjAnuente": "84432367000174",
"cnpjGcc": "20211917000142",
"dataCriacao": "2025-07-01T12:34:56",
"dataExpiracao": "2025-12-01T12:34:56"
}
Exemplo do conteúdo em versão compacta
O JSON em formato compacto retira todos os espaços em branco não significantes.
{
"templateId": "1222024-00001",
"isConsentimento": true,
"idConsentimento": "12345687",
...
}
Exemplo do conteúdo codificado
O JSON codificado no formato Base64 para URLs permite que seja trafegado via HTTP.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZW1wbGF0ZUlkIjoiMTIyMjAyNC0wMDAwMSIsImlzQ29uc2VudGltZW50byI6dHJ1ZSwiaWRDb25zZW
50aW1lbnRvIjoiMTIzNDU2ODciLCJjbnBqUmVxdWVyZW50ZSI6IjA1ODg0NzY1MDAwMTY0IiwiY25wakFudWVudGUiOiIwMzQ1MjMwNzAwMDExMSIsImNuc
GpHY2MiOiIwNTg4NDc2NTAwMDE2NCIsImRhdGFDcmlhY2FvIjoiMjAyNS0xMC0yMVQxMDo0NTowMCIsImRhdGFFeHBpcmFjYW8iOiIyMDI1LTEyLTMxVDIz
OjU5OjU5In0.s6EEXxWus8sNCYiQhnoKox3OOy5UV6DDouo3act5lNQ
💡 Essa sequência representa os bytes do JSON original e serve como base para a assinatura digital.
Existem bibliotecas em várias linguagens que podem gerar e assinar um JWT automaticamente: https://www.jwt.io/libraries
2️⃣ Assinatura do Hash
A assinatura digital do Hash em formato JWT deve ser realizada por meio de chaves assimétricas. A GCC deve gerar um par de chaves (RSA SHA256) e manter uma delas em segurança, isto é, a Chave Privada. Já a outra chave deve ser compartilhada com a PGCC (via Módulo Admin) para que a assinatura do Hash possa ser verificada, ou seja, uma Chave Pública.
Com um par de chaves gerado e a Chave Pública cadastrada, o conteúdo codificado do Hash deve ser concatenado com um cabeçalho (outro JSON codificado) e assinados digitalmente com RSA-SHA256 ( RS256) usando a Chave Privada da GCC.
Estrutura do JWT
O Cabeçalho (header), o conteúdo (payload) e a assinatura (signature) concatenados por um ponto (.) compõem o
Hash:
<Cabeçalho>.<Conteúdo>.<Assinatura>
-
Header: No Cabeçalho, é necessário informar o identificador da Chave Pública pareada com a Chave Privada que foi usada para assinar o Hash, por exemplo:
{ "alg": "RS256", "kid": "ad46f90a-6138-45a3-9667-1bc1fdb3271c", "typ": "JWT" } -
Payload: O Conteúdo do Hash é um objeto JSON comum:
{ "templateId": "1222024-00001", "isConsentimento": true, "idConsentimento": "12345687", "cnpjUsuario": "05884765000164", "cnpjAnuente": "03452307000111", "cnpjGcc": "05884765000164", "dataCriacao": "2025-10-21T10:45:00", "dataExpiracao": "2025-12-31T23:59:59" } -
Signature: A Assinatura deve ser gerada a partir do Cabeçalho e Conteúdo codificados e concatenados por um ponto, por exemplo:
Essas partes combinadas devem ser assinadas por uma Chave Privada por meio do algoritmo RSA SHA256. Exemplo de Chave em formato PEM:eyJhbGciOiJSUzI1NiIsImtpZCI6ImFkNDZmOTBhLTYxMzgtNDVhMy05NjY3LTFiYzFmZGIzMjcxYyIsInR5cCI6IkpXVCJ9.eyJ0ZW1wbGF0ZUlkIjoiMTIyMjAyNC0wMDAwMSIsImlzQ29uc2VudGltZW50byI6dHJ1ZSwiaWRDb25zZW50aW1lbnRvIjoiMTIzNDU2ODciLCJjbnBqVXN1YXJpbyI6IjA1ODg0NzY1MDAwMTY0IiwiY25wakFudWVudGUiOiIwMzQ1MjMwNzAwMDExMSIsImNucGpHY2MiOiIwNTg4NDc2NTAwMDE2NCIsImRhdGFDcmlhY2FvIjoiMjAyNS0xMC0yMVQxMDo0NTowMCIsImRhdGFFeHBpcmFjYW8iOiIyMDI1LTEyLTMxVDIzOjU5OjU5In0.-----BEGIN PRIVATE KEY----- MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDg9HHM4gYlzbDD GVFqGHMJsh+xqVkefSYwhGUKiks3xaSBnqMP5micR2iUkodNd/c3eWafWyRJxIFl ivS0hrB5uI6dAbkCuovt1oIq33j8uLtSydTO5/uvusbTAgdcxPW6W/TQGtYpoWov ICIh6AvVI8QXzW9/lB62dpsKNgm2RYXRJuEAhKatEKP1UgNiGlKYI6EXJDH/PrDG dvZU7uxM0ZEjL5beYf3z0A+BECqVAhm8HLL1KdtvRSAFKBulcND2pHtlVg8hTH+9 uznedeLTDChEa7HdR8AkLqMcC0fCjKLfvawnkj2N58IMwu9XaGFYP7Aj9TAUMXfJ X1IVs/n5AgMBAAECggEAMBTXYQ8beMeM5Tp7XhWxOuyNXSwg7gUaXUrjDNxvxNEz /veBC2Q4TlTt+7mQ/WQrnToPzvZMXI8JiEJp2M8kF7Q0mUb1vClSwMh1ZIQE6GF0 unaEy5+melJN7mpz1+aKTiWa/0MJLPdBCqcP3JbsNoeRQXQpxYdLhDz4GPfhXgl5 3NbnfedDoTwUy4YsiaJ8O/Ubn+idQV1sG1yB2uEAzCedOwalJOQmUc3GSpUBs3cV LOQSkPDyn7vfcWXnt9NA5gTiXe+N/S6Iv6XRhhL/hKEFfdHrvW7DesB1T1vrm+4z VM0/XlIax1N2w7DUut8PQW4iOJItagYBa2AjcK0N3QKBgQDjnngbQw/vD2BCgAXU Jc7zyCZIMMn29kTW3EEvin1nTbPoE/tAMhvXQbyAgDcxOJFyK2kvS9MWSE0WqTQ6 bn0lZlEnLFWCnHZJfUpdnX/outnYME2meM8Lqgn+onerAMqt4nZIg3ShWvNcgQEf 1yrp5tMUf/9sGgFeNYqO08JQtQKBgQD9AO+sEiicy+r2a7CUk8P8tJ2dFfS+Q2wz wKY2k1hYolwUBh6Cg/PjivOBi8OZo3szmjyPKUERENP8Fg5LhQQ99vAUtF0l7dfm LIKVpd+sqJKyNAKHjOf8mM+LrHcijPjY9+CCGcZClyobY84MKcAHmeXIFBLS8icU +o/OxSGCtQKBgHSJpBDBKx1IkA48Ib/Wg7jI1uDLKfxpZiFjr3Q5wa7sV5oQ8OiT PzHclDhubNOklMMRes8eUTrtVZqukvD/tM87LX2S80zl8qH5peN8SgrL79ECGh+L ZuYf7vISGJbS1vJkKg9CTqp2OHc6DWtR7MTIy3WJeyrLvbuQShqKTMipAoGAERUk GaEsPtIB7lt9E7saa5CiZ73YxZP11VS3pE20lF96ChwTqUpRiFaUdHXEYjZIlkZe umfVrdpOBeJTWsQDck+fDDbVZz806aStuH73qEfFh+S9GvvnmgWTVeHyNVIBZ1zt OruUyGA+hpTpj6auAZVhj23Ti4ywGNmGJjbnOVUCgYAWknLiGptiRKUOnr0ucljF GsSYzIkqB7C5CLbXSSjbThPaI7ep6UBjP351asK5KbcNa6KOC3TvG6TAlz0ooDo+ tbSeUaeEEVLga7wSrqAFdcJck1NyK5BKHX5FtiUavV5JV+ij+D5cSwcrUekQPF7W De1OvzKWrNnAmShL0cDgyg== -----END PRIVATE KEY----- -
Exemplo de Hash completo:
eyJhbGciOiJSUzI1NiIsImtpZCI6ImFkNDZmOTBhLTYxMzgtNDVhMy05NjY3LTFiYzFmZGIzMjcxYyIsInR5cCI6IkpXVCJ9.eyJ0ZW1wbGF0ZUlkIjoiMTIyMjAyNC0wMDAwMSIsImlzQ29uc2VudGltZW50byI6dHJ1ZSwiaWRDb25zZW50aW1lbnRvIjoiMTIzNDU2ODciLCJjbnBqVXN1YXJpbyI6IjA1ODg0NzY1MDAwMTY0IiwiY25wakFudWVudGUiOiIwMzQ1MjMwNzAwMDExMSIsImNucGpHY2MiOiIwNTg4NDc2NTAwMDE2NCIsImRhdGFDcmlhY2FvIjoiMjAyNS0xMC0yMVQxMDo0NTowMCIsImRhdGFFeHBpcmFjYW8iOiIyMDI1LTEyLTMxVDIzOjU5OjU5In0.qshzgKGzjRVg5CdkHi21-B6IM8chPonbKltYMMEaHHH4B-Ou3vyo2XIpB1WHnSJUEvU3aVqCkT8_-p6EDuC4UbkDI14pmsmWTQlacOE8WWBgI4Gi6cpsRyJRJY1wtJV2ebTlCXez97BhoXTJoBNuL6hm4O4niQd8V1pB92Rh-R97w9RmRpLMoTLHZ8ZjbXpMuQT_sigqr5BAl_SWbVT5Ns5j9NsHGDnfdrOCOZmx-M3g4mx08RHASW7lTocn4cVQaYzOQLtm1WWDbJ15qzXZHNLkYX-RdeOozCLWPK1zm-jXkTMYULsHETPgb9-Ye2vbS6Pvm3SC7g3D4Mn7WVOG3Q
💡 A assinatura é gerada com a Chave Privada da GCC, e validada pela PGCC usando a Chave Pública previamente cadastrada no sistema cuja ID deve ser informada no Cabeçalho do JWT do Hash.
⚙️ Validação na PGCC
Quando o JWT é recebido pela PGCC:
- O sistema identifica a GCC pelo certificado usado na requisição (mTLS) que deve estar previamente cadastrado no Credencia;
- Recupera a Chave Pública correspondente à assinatura por meio do identificador no Cabeçalho;
- Valida a assinatura digital (RSA-SHA256);
- Decodifica o payload em Base64, reconstrói o JSON original e armazena as informações do Hash para processamento e auditoria.
Se a assinatura for inválida ou o CNPJ não possuir Chave Pública cadastrada, a requisição é rejeitada com erro 401.
🔄 Diagrama de Sequência – Fluxo de Criação e Validação do JWT (GCC → PGCC)
sequenceDiagram
title Fluxo de criação e validação do JWT (GCC → PGCC)
participant GCC
participant JwtBuilder
participant ChavePrivada
participant API_PGCC
participant JwtValidator
participant RepositorioChavesPublicas
participant FilaProcessamento
participant HashService
participant HashInfoDTO
GCC ->> JwtBuilder: Monta header (alg=RS256, typ=JWT)
GCC ->> JwtBuilder: Adiciona payload (idTemplate, cnpjs, etc)
JwtBuilder ->> ChavePrivada: Solicita assinatura digital
ChavePrivada -->> JwtBuilder: Retorna assinatura RSA-SHA256
JwtBuilder -->> GCC: Retorna JWT (header.payload.signature)
GCC ->> API_PGCC: Envia JWT via requisição HTTP POST
API_PGCC ->> JwtValidator: Recebe JWT e inicia validação
JwtValidator ->> RepositorioChavesPublicas: Busca chave pública do remetente (por CNPJ)
RepositorioChavesPublicas -->> JwtValidator: Retorna chave pública
JwtValidator ->> JwtValidator: Verifica assinatura (RSA)
alt Assinatura inválida
JwtValidator -->> API_PGCC: Retorna erro de autenticação
API_PGCC -->> GCC: HTTP 401 Unauthorized\n(assinatura inválida)
else Assinatura válida
JwtValidator -->> API_PGCC: Retorna payload validado
API_PGCC ->> FilaProcessamento: Enfileira requisição\npara processamento posterior
API_PGCC -->> GCC: HTTP 202 Accepted\n("Hash validado e aceito para processamento")
end
Note right of FilaProcessamento: Processamento assíncrono posterior\n(Worker, Batch ou Job Scheduler)
FilaProcessamento ->> HashService: Inicia processamento do hash validado
HashService ->> HashInfoDTO: Cria DTO com os campos do payload
HashInfoDTO -->> HashService: Retorna objeto DTO
HashService ->> API_PGCC: Atualiza status do processamento\n(SUCCESS ou FAILURE)
API_PGCC ->> GCC: Opcional: envia callback HTTP 200\ncom DTO processado
📡 Endpoints da API
🔸 1. Enviar Hash JWT Assinado
POST /api/v1/hash
Recebe um JWT assinado digitalmente pela GCC.
A PGCC valida a assinatura e aceita o hash para processamento.
Headers
| Header | Obrigatório | Descrição |
|---|---|---|
x-cnpj-consulta |
✅ | CNPJ do GCC remetente |
x-cpf-operador |
✅ | CPF do operador que envia o hash |
Corpo da Requisição
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
Respostas
| Código | Descrição |
|---|---|
| 202 | Hash validado e aceito |
| 401 | Assinatura JWT inválida |
| 422 | Campos obrigatórios ausentes no payload |
| 500 | Erro interno durante validação |
🔸 2. Consultar Hash por Campos do Payload
GET /api/v1/hash/payload
Consulta registros de hash com base em campos do payload decodificado, sem precisar reenviar o JWT original.
Parâmetros
| Nome | Local | Obrigatório | Descrição |
|---|---|---|---|
x-cnpj-consulta |
Header | ✅ | CNPJ da GCC responsável |
x-cpf-operador |
Header | ❌ | CPF do operador (para auditoria) |
idTemplate |
Query | ❌ | ID do template |
idConsentimento |
Query | ❌ | ID do consentimento |
cnpjUsuario |
Query | ❌ | CNPJ do usuário vinculado |
Respostas
| Código | Descrição |
|---|---|
| 200 | Hash encontrado |
| 404 | Hash não encontrado |
| 400 | Erro de validação nos parâmetros |
🔸 3. Consultar Hashes por CNPJ com Filtros
GET /api/v1/hash/cnpjGcc/{cnpjGcc}
Consulta hashes vinculados a um determinado CNPJ GCC, com filtros opcionais por campos e intervalo de datas.
Parâmetros
| Nome | Local | Tipo | Descrição |
|---|---|---|---|
x-cnpj-consulta |
Header | String | CNPJ do consultante |
x-cpf-operador |
Header | String | CPF do operador |
cnpjGcc |
Path | String | CNPJ do GCC |
idTemplate |
Query | String | ID do template |
idConsentimento |
Query | String | ID do consentimento |
cnpjUsuario |
Query | String | CNPJ do usuário |
status |
Query | String | Status do hash (PENDENTE, PROCESSADO, EXCLUIDO, etc.) |
dataInicial |
Query | Date | Data inicial (yyyy-MM-dd) |
dataFinal |
Query | Date | Data final (yyyy-MM-dd) |
Respostas
| Código | Descrição |
|---|---|
| 200 | Lista de hashes encontrados |
| 404 | Nenhum hash encontrado |
| 400 | Parâmetros inválidos |
🔸 4. Exclusão Lógica de Hash
DELETE /api/v1/hash/id/{id}
Marca o hash como excluído logicamente.
O registro é mantido para auditoria, alterando apenas o status para EXCLUIDO.
Parâmetros
| Nome | Local | Tipo | Descrição |
|---|---|---|---|
x-cnpj-consulta |
Header | String | CNPJ do GCC responsável |
x-cpf-operador |
Header | String | CPF do operador |
id |
Path | String | id do hash |
Respostas
| Código | Descrição |
|---|---|
| 200 | Hash marcado como excluído |
| 404 | Hash não encontrado |
| 400 | Erro de validação |
🧠 Exemplo Completo de Fluxo
1️⃣ GCC gera o JWT
jwt=$(jwt-sign --alg RS256 --key private_key.pem '{
"templateId": "1222024-00001",
"isConsentimento": true,
"idConsentimento": "12345687",
"cnpjUsuario": "05884765000164",
"cnpjAnuente": "03452307000111",
"cnpjGcc": "05884765000164",
"dataCriacao": "2025-10-21T10:45:00",
"dataExpiracao": "2025-12-31T23:59:59"
}')
2️⃣ GCC envia para a PGCC
curl -X POST https://pgcc.gov.br/api/v1/hash -H "x-cnpj-consulta: 03452307000111" -H "x-cpf-operador: 10973787724" -H "Content-Type: application/json" -d ""$jwt""
3️⃣ Resposta
HTTP/1.1 202 Accepted
🔎 Auditoria e Logs
Cada requisição:
- Registra os headers e campos do payload em
HttpServletRequest; - Mantém histórico de todas as ações (
CRIADO,VALIDADO,EXCLUIDO); - Permite auditoria completa de origem (CNPJ remetente, operador, timestamps e assinatura).
📋 Resumo dos Endpoints
| Método | Caminho | Descrição |
|---|---|---|
POST |
/api/v1/hash |
Recebe e valida JWT assinado |
GET |
/api/v1/hash/payload |
Consulta por campos do payload |
GET |
/api/v1/hash/cnpjGcc/{cnpjGcc} |
Consulta com filtros flexíveis |
DELETE |
/api/v1/hash/id/{id} |
Exclusão lógica do hash |
📖 Swagger UI
A documentação interativa está disponível em:
🧾 Versão e Manutenção
- Versão: 1.1 (modelo JWT assinado)
- Data: 21/10/2025
- Responsável: SERPRO – Projeto PGCC
- Descrição: Migração do cálculo SHA-256 para modelo JWT (RS256) com validação por chave pública.