Sat.Certificados.Certificate (sat_certificados v4.0.1)

Copy Markdown

Certificado X.509 (.cer) del SAT en formato DER con parseo OTP para consultas (RFC, vigencia, etc.).

Summary

Functions

Versión de la Autoridad Certificadora del SAT (4 o 5) que emitió el cert.

Detecta el tipo de certificado por extensiones X.509 estándar

true si la fecha actual es posterior a valid_to/1.

Huella SHA-1 del DER, formato AA:BB:CC:... en mayúsculas (estilo Node).

Huella SHA-256 del DER (hex mayúsculas, sin separadores).

Crea un certificado a partir del contenido DER binario (.cer).

Lee un archivo .cer (DER o PEM).

Crea un certificado a partir de un string PEM.

true si es CSD. Equivalente a certificate_type/1 == :csd.

true si es FIEL (e.firma). Equivalente a certificate_type/1 == :fiel.

Verifica que este certificado fue firmado por el issuer dado. Útil para validar la cadena de confianza contra AC4_SAT.cer / AC5_SAT.cer.

Issuer como mapa atributo => valor.

Nombre legal (CN o, en su defecto, givenName).

Número de certificado en formato SAT (ver Clir.Openssl.X509.no_certificado/1).

Llave pública RSA decodificada ({:RSAPublicKey, modulus, exponent}).

Llave pública del certificado en formato PEM -----BEGIN PUBLIC KEY-----.

RFC del titular, inferido del subject (OIDs típicos del SAT).

Encripta un mensaje con la llave pública del certificado (RSA PKCS#1 v1.5). Solo el dueño de la llave privada puede desencriptar. Retorna Base64.

Número de serie en hexadecimal (mayúsculas).

Subject como mapa atributo => valor.

Tipo de sujeto (titular)

Contenido del certificado en Base64 (sin cabeceras PEM ni saltos).

DER crudo del certificado.

Proyecta toda la metadata útil del certificado a un mapa con llaves snake_case (átomos por default).

PEM del certificado (incluye cabeceras).

true si el certificado está vigente: valid_from <= now <= valid_to. A diferencia de expired?/1, también verifica que el inicio de vigencia ya esté en el pasado.

Inicio de vigencia (UTC).

Fin de vigencia (UTC).

Verifica una firma Base64 contra data con la llave pública del cert. Default SHA-256 (lo que exige el SAT).

Alias de issued_by?/2 por compatibilidad con e.firma.

Types

t()

@type t() :: %Sat.Certificados.Certificate{
  parsed: Clir.Openssl.X509.otp_cert(),
  raw_der: binary()
}

Functions

ac_version(cert)

@spec ac_version(t()) :: integer() | nil

Versión de la Autoridad Certificadora del SAT (4 o 5) que emitió el cert.

El SAT codifica el número de AC en el dígito 12 (índice 11) del no_certificado (20 dígitos decimales).

Retorna nil si no se puede determinar.

certificate_type(cert)

@spec certificate_type(t()) :: :csd | :fiel | :unknown

Detecta el tipo de certificado por extensiones X.509 estándar:

  • :csd (Certificado de Sello Digital): keyUsage con digitalSignature y nonRepudiation activos, sin dataEncipherment ni keyAgreement.
  • :fiel (e.firma / FIEL): extKeyUsage con emailProtection y clientAuth activos.

Si las extensiones no resuelven el tipo, hace fallback a la heurística del OU del subject (Prueba_CFDI, FIEL, etc.). Retorna :unknown si no se puede determinar.

expired?(cert)

@spec expired?(t()) :: boolean()

true si la fecha actual es posterior a valid_to/1.

fingerprint(certificate)

@spec fingerprint(t()) :: String.t()

Huella SHA-1 del DER, formato AA:BB:CC:... en mayúsculas (estilo Node).

fingerprint_sha256(certificate)

@spec fingerprint_sha256(t()) :: String.t()

Huella SHA-256 del DER (hex mayúsculas, sin separadores).

from_der(binary)

@spec from_der(binary()) :: {:ok, t()} | {:error, term()}

Crea un certificado a partir del contenido DER binario (.cer).

from_file(path)

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

Lee un archivo .cer (DER o PEM).

from_pem(pem)

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

Crea un certificado a partir de un string PEM.

is_csd?(cert)

@spec is_csd?(t()) :: boolean()

true si es CSD. Equivalente a certificate_type/1 == :csd.

is_fiel?(cert)

@spec is_fiel?(t()) :: boolean()

true si es FIEL (e.firma). Equivalente a certificate_type/1 == :fiel.

issued_by?(subject, issuer)

@spec issued_by?(t(), t()) :: boolean()

Verifica que este certificado fue firmado por el issuer dado. Útil para validar la cadena de confianza contra AC4_SAT.cer / AC5_SAT.cer.

Retorna true si la firma del cert es válida bajo la pública del emisor.

issuer(certificate)

@spec issuer(t()) :: %{required(String.t()) => String.t()}

Issuer como mapa atributo => valor.

no_certificado(certificate)

@spec no_certificado(t()) :: String.t()

Número de certificado en formato SAT (ver Clir.Openssl.X509.no_certificado/1).

public_key(certificate)

@spec public_key(t()) :: {:RSAPublicKey, integer(), integer()}

Llave pública RSA decodificada ({:RSAPublicKey, modulus, exponent}).

public_key_pem(cert)

@spec public_key_pem(t()) :: String.t()

Llave pública del certificado en formato PEM -----BEGIN PUBLIC KEY-----.

rfc(certificate)

@spec rfc(t()) :: String.t()

RFC del titular, inferido del subject (OIDs típicos del SAT).

rsa_encrypt(cert, message)

@spec rsa_encrypt(t(), iodata()) :: String.t()

Encripta un mensaje con la llave pública del certificado (RSA PKCS#1 v1.5). Solo el dueño de la llave privada puede desencriptar. Retorna Base64.

serial_number(certificate)

@spec serial_number(t()) :: String.t()

Número de serie en hexadecimal (mayúsculas).

subject(certificate)

@spec subject(t()) :: %{required(String.t()) => String.t()}

Subject como mapa atributo => valor.

subject_type(cert)

@spec subject_type(t()) :: :moral | :fisica | :unknown

Tipo de sujeto (titular):

  • :moral — persona moral / empresa: el OID 2.5.4.45 contiene RFC / CURP.
  • :fisica — persona física: RFC de 13 caracteres sin /.
  • :unknown — no se pudo determinar.

to_base64(certificate)

@spec to_base64(t()) :: String.t()

Contenido del certificado en Base64 (sin cabeceras PEM ni saltos).

to_der(certificate)

@spec to_der(t()) :: binary()

DER crudo del certificado.

to_map(cert)

@spec to_map(t()) :: map()

Proyecta toda la metadata útil del certificado a un mapa con llaves snake_case (átomos por default).

Incluye: tipo (CSD/FIEL), persona física o moral, RFC, nombre legal, número de certificado SAT, número de serie hex, fechas de vigencia, estado de expiración, fingerprints (SHA-1 y SHA-256), versión de la AC, issuer, y subject completo (mapa con códigos LDAP estándar como llaves: "CN", "O", "OU", "RFC", etc.).

La llave privada NO se incluye (es PII y vive en PrivateKey).

Opciones:

  • :keys:atom (default), :string o :existing. Misma semántica que CFDI.to_map/2. Aplica al primer nivel y al mapa anidado bajo :subject.

to_map(cert, opts)

@spec to_map(
  t(),
  keyword()
) :: map()

to_pem(certificate)

@spec to_pem(t()) :: String.t()

PEM del certificado (incluye cabeceras).

valid?(cert)

@spec valid?(t()) :: boolean()

true si el certificado está vigente: valid_from <= now <= valid_to. A diferencia de expired?/1, también verifica que el inicio de vigencia ya esté en el pasado.

valid_from(certificate)

@spec valid_from(t()) :: DateTime.t()

Inicio de vigencia (UTC).

valid_to(certificate)

@spec valid_to(t()) :: DateTime.t()

Fin de vigencia (UTC).

verify(cert, data, signature_b64, algo \\ :sha256)

@spec verify(t(), iodata(), String.t(), atom()) :: boolean()

Verifica una firma Base64 contra data con la llave pública del cert. Default SHA-256 (lo que exige el SAT).

verify_integrity(subject, issuer)

@spec verify_integrity(t(), t()) :: boolean()

Alias de issued_by?/2 por compatibilidad con e.firma.