SefazNfe.Certificate (sefaz_nfe v0.1.0)

Copy Markdown View Source

A1 (PKCS#12) handle.

load/2 decodes the PFX, so a wrong password fails here — before any SOAP call — via the PKCS#12 MAC. The password is never kept on the struct and Inspect never prints the key or the DER.

The fields are shaped for the two consumers: :der + :key + :chain feed :ssl client options for mTLS, and :der + :key feed XMLDSig.

Summary

Functions

DER trust anchors from config :sefaz_nfe, :cacerts.

Decodes an A1 PFX.

Client options for an mTLS connection to SEFAZ.

Types

t()

@type t() :: %SefazNfe.Certificate{chain: [binary()], der: binary(), key: binary()}

Functions

extra_cacerts()

@spec extra_cacerts() :: [binary()]

DER trust anchors from config :sefaz_nfe, :cacerts.

load(pfx, password)

@spec load(binary(), String.t()) :: {:ok, t()} | {:error, term()}

Decodes an A1 PFX.

Returns {:error, :invalid_certificate} for an empty input, a wrong password (the MAC will not verify) or a structurally broken file, and {:error, {:unsupported_pbe, oid}} for a PFX encrypted with an algorithm this reader has not been verified against.

ssl_options(cert)

@spec ssl_options(t()) :: keyword()

Client options for an mTLS connection to SEFAZ.

The private key is handed to :ssl as a PrivateKeyInfo DER, which is what the PKCS#12 shrouded key bag already contains. The A1's own chain goes into :cacerts because that is where :ssl looks when it builds the client chain to present.

Trust anchors

Several SEFAZ endpoints — SP and MT among them — serve certificates issued under Autoridade Certificadora Raiz Brasileira, which no operating system bundle carries. Without that root the handshake fails with {:tls, :unknown_ca}, and the fix is to supply it rather than to stop verifying:

config :sefaz_nfe, :cacerts, "/etc/ssl/icp-brasil.pem"

The value is a path to a PEM bundle or a list of DER binaries. It is added to the trust anchors, never replacing the system bundle, since other UFs chain to ordinary commercial roots.

This library ships no trust anchors of its own on purpose: a CA bundle vendored from an unverified download is a man-in-the-middle waiting to happen. Fetch the roots from the ITI repository and check their fingerprints before installing them.