Pular para conteúdo

🧾 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:

    eyJhbGciOiJSUzI1NiIsImtpZCI6ImFkNDZmOTBhLTYxMzgtNDVhMy05NjY3LTFiYzFmZGIzMjcxYyIsInR5cCI6IkpXVCJ9.eyJ0ZW1wbGF0ZUlkIjoiMTIyMjAyNC0wMDAwMSIsImlzQ29uc2VudGltZW50byI6dHJ1ZSwiaWRDb25zZW50aW1lbnRvIjoiMTIzNDU2ODciLCJjbnBqVXN1YXJpbyI6IjA1ODg0NzY1MDAwMTY0IiwiY25wakFudWVudGUiOiIwMzQ1MjMwNzAwMDExMSIsImNucGpHY2MiOiIwNTg4NDc2NTAwMDE2NCIsImRhdGFDcmlhY2FvIjoiMjAyNS0xMC0yMVQxMDo0NTowMCIsImRhdGFFeHBpcmFjYW8iOiIyMDI1LTEyLTMxVDIzOjU5OjU5In0.
    
    Essas partes combinadas devem ser assinadas por uma Chave Privada por meio do algoritmo RSA SHA256. Exemplo de Chave em formato PEM:
    -----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:

  1. O sistema identifica a GCC pelo certificado usado na requisição (mTLS) que deve estar previamente cadastrado no Credencia;
  2. Recupera a Chave Pública correspondente à assinatura por meio do identificador no Cabeçalho;
  3. Valida a assinatura digital (RSA-SHA256);
  4. 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.