Isox.Xmldsig.Signer (Isox v0.1.0)

Copy Markdown View Source

Núcleo do XMLDSig do Pix (Manual de Segurança do SFN Vol. II §3), comum aos dois perfis que o manual define: SPI (3 <ds:Reference> — tabela 3) e DICT (2 <ds:Reference> — tabela 4). Hoje só o perfil SPI está implementado (sign/4); sign_references/3 e key_info_xml/2 já são o suficiente para montar o perfil do DICT quando existir um simulador para ele — a diferença entre os dois perfis é só a lista de referências, não o resto do mecanismo (§3.2 do manual: os passos são os mesmos).

RSA-SHA256, digest SHA-256, canonicalização exclusiva.

Summary

Functions

Nome do emissor (DN, renderizado) e número de série do certificado DER dado.

Monta <ds:KeyInfo> com <ds:X509IssuerSerial> (tabela 2, item 1.2.3.1 do manual) — nome do emissor (DN) e número de série do certificado, não o certificado inteiro embutido. É assim que o manual descreve: quem verifica é responsável por manter sua própria base de números de série e chaves públicas dos certificados (§3.3, nota de rodapé), não por confiar num certificado que veio dentro da própria mensagem.

Perfil SPI (tabela 3): três <ds:Reference>KeyInfo por Id, AppHdr (sem <Sgntr> preenchido, transformação enveloped-signature) e Document (sem atributo URI — fora do processamento padrão de XMLDSig, "deve ser interpretada pela aplicação de forma a referenciar a mensagem ISO 20.022 propriamente dita", manual §3.1).

Monta <ds:Signature> a partir de uma lista arbitrária de referências já canônicas — o núcleo comum aos dois perfis do manual. key_info_xml entra pronto (já contém o Id que a referência correspondente usa em URI="#...") porque quem monta a lista de referências é quem sabe qual delas aponta pro KeyInfo.

Types

reference_spec()

@type reference_spec() ::
  {uri :: String.t() | nil, transforms :: [String.t()], binary()}

Functions

digest(canonical_xml)

@spec digest(binary()) :: binary()

issuer_and_serial(certificate_der)

@spec issuer_and_serial(binary()) :: {String.t(), integer()}

Nome do emissor (DN, renderizado) e número de série do certificado DER dado.

key_info_xml(id, certificate_der)

@spec key_info_xml(String.t(), binary()) :: binary()

Monta <ds:KeyInfo> com <ds:X509IssuerSerial> (tabela 2, item 1.2.3.1 do manual) — nome do emissor (DN) e número de série do certificado, não o certificado inteiro embutido. É assim que o manual descreve: quem verifica é responsável por manter sua própria base de números de série e chaves públicas dos certificados (§3.3, nota de rodapé), não por confiar num certificado que veio dentro da própria mensagem.

otp_certificate(args \\ [])

(macro)

otp_certificate(record, args)

(macro)

otp_tbs_certificate(args \\ [])

(macro)

otp_tbs_certificate(record, args)

(macro)

rsa_sign(canonical_signed_info, private_key_der)

@spec rsa_sign(binary(), binary()) :: binary()

sign(app_hdr_xml, document_xml, private_key_der, certificate_der)

@spec sign(binary(), binary(), binary(), binary()) :: binary()

Perfil SPI (tabela 3): três <ds:Reference>KeyInfo por Id, AppHdr (sem <Sgntr> preenchido, transformação enveloped-signature) e Document (sem atributo URI — fora do processamento padrão de XMLDSig, "deve ser interpretada pela aplicação de forma a referenciar a mensagem ISO 20.022 propriamente dita", manual §3.1).

app_hdr_xml e document_xml precisam já vir em forma canônica exclusiva — quem chama é o caminho de template da lib de codec (ADR 0006), e essa é justamente a razão de existir dele: sem isso, assinar não paga canonicalização no caminho quente. Passar XML não-canônico aqui produz uma assinatura que não bate na verificação (que sempre canonicaliza de verdade, porque não pode confiar no que chegou de terceiro) — não é validado nesta função porque validar seria a mesma canonicalização que o caminho de template existe pra evitar.

sign_references(references, private_key_der, key_info_xml)

@spec sign_references([reference_spec()], binary(), binary()) :: binary()

Monta <ds:Signature> a partir de uma lista arbitrária de referências já canônicas — o núcleo comum aos dois perfis do manual. key_info_xml entra pronto (já contém o Id que a referência correspondente usa em URI="#...") porque quem monta a lista de referências é quem sabe qual delas aponta pro KeyInfo.