# Validação HSM RTM - PIX e SPB

Data: 2026-06-21
Escopo: integração HSM RTM para assinaturas das cabines PIX e SPB
Status: implementação preparada e validada por contrato; assinatura real Monetarie depende de vHSM, chaves, certificados e RSFN liberados

## Regra arquitetural definitiva

O Core Bancário nunca assina mensagens TED, PIX, SPB, DICT, ICOM-SPI ou qualquer mensagem operacional de rede financeira BACEN.

O Core publica intenções e eventos internos via NATS. A partir desses eventos, cada cabine especializada executa o trabalho que pertence ao seu domínio:

- PIX assina e valida mensagens SPI e DICT.
- SPB assina C15, decifra C14 de entrada e valida mensagens SPB.
- Core mantém contas, cadastro, crédito, tarifas, tesouraria, ledger e eventos internos.

Qualquer implementação futura que tente colocar assinatura BACEN no Core deve ser rejeitada.

## Evidência documental do HSM RTM

Endpoints públicos de teste analisados:

- `http://200.160.162.200:63351/index.html`
- `http://200.160.162.200:63351/swagger/v1/swagger.json`
- `http://200.160.162.200:63351/help/tr31-help-v1.html`
- `http://200.160.162.200:63351/v1/health`

Resultado empírico coletado:

- `index.html`: HTTP 200, Swagger UI carregado.
- `swagger.json`: HTTP 200, contrato da API disponível.
- `tr31-help-v1.html`: HTTP 200, documentação TR-31 disponível.
- `/v1/health`: HTTP 200, status saudável.
- `get-session-credential` no vHSM de teste: HTTP 200, sessão recebida.
- `sign-rsa` com UID de chave de exemplo informado pelo parceiro: HTTP 422, `OperationFailed, ItemNotFound`. O UID de exemplo não existe ou não está disponível no vHSM de teste atual.

Validação a partir de EC2s AWS:

- EC2 `bastion`: `index.html`, TR-31, Swagger e health responderam HTTP 200.
- EC2 `monetarie-rsfn-egress-homolog`: `index.html`, TR-31, Swagger e health responderam HTTP 200.

Essas evidências confirmam acesso ao endpoint de teste do HSM a partir da AWS. Elas não substituem a validação do vHSM real da Monetarie.

Conclusão objetiva do teste vivo: o caminho HTTP, o contrato de sessão e a autenticação de API estão funcionais no ambiente de teste. A assinatura real ainda não pode ser marcada como concluída porque depende de UIDs de chave válidos da Monetarie.

## Contrato Swagger confirmado

Sessão:

- `POST /v1/kmip/{vhsm}/get-session-credential`
- Corpo: `cryptoUser`, `token`
- Retorno esperado: `returnValue`

Assinatura RSA:

- `POST /v1/kmip/{vhsm}/sign-rsa`
- Corpo: `session`, `cryptographicAlgorithm`, `privateKeyUid`, `dataSignHex`
- Header: `Authorization: Bearer <sessão>`

Verificação RSA:

- `POST /v1/kmip/{vhsm}/signature-verify-rsa`
- Corpo: `session`, `cryptographicAlgorithm`, `publicKeyUid`, `dataSignHex`, `signatureDataHex`
- Header: `Authorization: Bearer <sessão>`

Cifra e decifra RSA:

- `POST /v1/kmip/{vhsm}/cipher/rsa/encrypt`
- `POST /v1/kmip/{vhsm}/cipher/rsa/decrypt`
- Corpo correto: `session`, `identifierKey`, `paddingMode`, `dataList`
- Retorno esperado para lista de dados: `dataListReturn`

Ponto importante: o contrato real de `cipher/rsa/encrypt` e `cipher/rsa/decrypt` não usa `publicKeyUid`, `privateKeyUid` nem `dataHex` no corpo. A integração foi ajustada para `identifierKey`, `paddingMode` e `dataList`.

## Implementação PIX

Arquivos principais:

- `pix/backend/apps/shared/lib/shared/crypto/rtm_hsm.ex`
- `pix/backend/apps/shared/lib/shared/crypto/rtm_hsm/client.ex`
- `pix/backend/apps/shared/lib/shared/crypto/rtm_hsm/pkcs1.ex`
- `pix/backend/apps/shared/lib/shared/crypto/xml_signer.ex`
- `pix/backend/config/runtime.exs`

Comportamento:

- O `Shared.Crypto.XmlSigner` segue responsável pelo XMLDSig de SPI e DICT.
- Com `RTM_HSM_ENABLED=true`, a assinatura RSA-SHA256 é delegada ao HSM RTM.
- O conteúdo assinado é o `SignedInfo` canonicalizado.
- O bloco enviado ao HSM é EMSA-PKCS1-v1.5 em hexadecimal no campo `dataSignHex`.
- Sem HSM habilitado, o fluxo atual continua usando a chave local configurada, preservando compatibilidade de desenvolvimento.

## Implementação SPB

Arquivos principais:

- `spb/services/bacen_gateway/lib/bacen_gateway/crypto/rtm_hsm.ex`
- `spb/services/bacen_gateway/lib/bacen_gateway/crypto/rtm_hsm/client.ex`
- `spb/services/bacen_gateway/lib/bacen_gateway/crypto/rtm_hsm/pkcs1.ex`
- `spb/services/bacen_gateway/lib/bacen_gateway/crypto/message_packer.ex`
- `spb/services/bacen_gateway/config/runtime.exs`

Comportamento:

- A assinatura C15 de saída usa HSM RTM quando `RTM_HSM_ENABLED=true`.
- A decifragem C14 de entrada usa `cipher/rsa/decrypt` quando `RTM_HSM_ENABLED=true`.
- A cifragem C14 de saída continua localmente com a chave pública do destinatário. Isso está correto porque não envolve chave privada da Monetarie.
- A verificação de assinatura de mensagens recebidas continua com certificado público do emissor e falha fechada quando a assinatura não confere.

## Core fora do caminho de assinatura

Arquivos do Core revisados:

- `core/backend/lib/monetarie/infra/rtm_hsm/client.ex`
- `core/backend/lib/monetarie/use_cases/kms/rtm_hsm_adapter.ex`
- `core/backend/test/monetarie/infra/rtm_hsm/rtm_hsm_adapter_test.exs`

Conclusão:

- O Core não contém configuração runtime ativa para assinar TED, PIX, SPB, DICT ou ICOM-SPI via HSM.
- O adaptador KMS do Core fica classificado como genérico e não operacional para mensagens BACEN.
- A documentação no próprio módulo registra que o Core publica por NATS e que as assinaturas BACEN pertencem às cabines PIX e SPB.
- Exemplo de teste que usava nomenclatura de PIX foi renomeado para não sugerir acoplamento indevido.

## Variáveis de ambiente esperadas

Não registrar valores reais neste documento.

PIX e SPB usam:

- `RTM_HSM_ENABLED`
- `RTM_HSM_BASE_URL`
- `RTM_HSM_VHSM`
- `RTM_HSM_CRYPTO_USER`
- `RTM_HSM_TOKEN`
- `RTM_HSM_PRIVATE_KEY_UID`
- `RTM_HSM_PUBLIC_KEY_UID`, quando aplicável
- `RTM_HSM_KEY_SIZE_BITS`
- `RTM_HSM_TIMEOUT_MS`

Em AWS, os valores reais devem vir do Secrets Manager ou de configuração segura equivalente. Não gravar token, sessão, UIDs sensíveis, chave privada, PFX ou senha em Markdown, relatório, `.env` versionado ou log.

## Testes executados

PIX:

- `mix test apps/shared/test/shared/crypto/rtm_hsm_test.exs apps/shared/test/shared/crypto/xml_signer_test.exs`
- Resultado: 16 testes, 0 falhas.

SPB:

- Teste isolado sem start de aplicação, porque o teste completo depende do PostgreSQL local.
- Resultado: 2 testes, 0 falhas.

Core:

- Testes isolados do adaptador genérico sem start de aplicação, porque o teste completo depende do PostgreSQL local.
- Resultado: 7 testes, 0 falhas.

Bloqueio local conhecido:

- Testes completos de Core e SPB não foram executados nesta estação porque o PostgreSQL local rejeitou a senha do usuário `monetarie`.
- Isso não invalida os testes focados do contrato HSM, que não dependem de banco.

## Critério para declarar assinatura real Monetarie validada

A assinatura real Monetarie somente poderá ser declarada validada quando todos os itens abaixo estiverem completos:

1. Receber vHSM real da Monetarie.
2. Receber `cryptoUser` e token do ambiente Monetarie.
3. Receber UIDs das chaves PIX e SPB.
4. Confirmar certificados vinculados às chaves.
5. Executar `get-session-credential` no vHSM Monetarie.
6. Executar `sign-rsa` e `signature-verify-rsa` com chave Monetarie.
7. Executar C15 SPB com assinatura por HSM.
8. Executar C14 de entrada SPB com decifragem por HSM.
9. Executar XMLDSig PIX SPI e DICT com assinatura por HSM.
10. Repetir testes de mensagem quando RSFN estiver liberada para DICT, ICOM-SPI, ARQ e SPB.

Até isso acontecer, a conclusão correta é: integração preparada, contrato validado, endpoint de teste acessível e código das cabines pronto para receber credenciais reais. Não afirmar que a chave real Monetarie já assinou mensagem em HSM.
