An X.509 certificate: who a signature names as its signer, and the window the issuer vouched for that name.
PdfElixide.Signature.certificate/1 reads the one a signature carries;
parse/1 reads DER from another source:
{:ok, [signature]} = PdfElixide.Signature.list(doc)
{:ok, certificate} = PdfElixide.Signature.certificate(signature)
certificate.subject_common_name
#=> "pdf_elixide test signer"The "The signer's certificate" section of the Signatures guide puts this in sequence with the rest of a signature check.
Nothing here is a trust decision
The fields are claims read from the certificate. They are not checked against
a trusted root, a revocation source or a list of accepted signers. Use :der
with :public_key or another library to make those decisions.
Names
:subject and :issuer use RFC
4514 form, with the most
specific attribute first. Values that cannot be rendered as text appear as
oid=#hex rather than being dropped.
:subject_common_name is the unescaped common name nearest the leaf. It is
nil when the subject has no textual common name and may contain text that
the full :subject renders as hexadecimal.
A certificate is a plain value with no handle behind it, so it survives
PdfElixide.Document.close/1 and can be passed between processes freely.
Summary
Functions
Parses a DER-encoded X.509 certificate.
Same as parse/1, but raises PdfElixide.Error on failure.
Whether the certificate's validity window covers instant.
Types
@type t() :: %PdfElixide.Signature.Certificate{ der: binary(), issuer: String.t() | nil, not_after: DateTime.t(), not_before: DateTime.t(), serial: String.t(), subject: String.t() | nil, subject_common_name: String.t() | nil }
One parsed X.509 certificate.
:der— the certificate's DER without trailing padding, suitable for OTP's:public_keyor another certificate library.:subject— who the certificate is about, in RFC 4514 form.nilfor a certificate that names no subject at all, which is legal for one identified only by an extension.:subject_common_name— the common name nearest the leaf of:subject, unescaped. See "Names" in the module documentation for when it isnil.:issuer— who issued it, in RFC 4514 form.nilonly for a certificate that names no issuer, which is not a conforming one.:serial— the issuer's serial number as uppercase hexadecimal DER content bytes, without a0xprefix or fixed width. Any sign octet is preserved. This matchesPdfElixide.Signature.Timestamp's:serial.:not_before,:not_after— the window the issuer vouched for, asDateTimes in UTC with one-second resolution.valid_at?/2compares an instant against them.
Functions
@spec parse(binary()) :: {:ok, t()} | {:error, PdfElixide.Error.t()}
Parses a DER-encoded X.509 certificate.
Tolerates trailing zero padding, so a PdfElixide.Signature.DSS entry can be
passed straight in:
{:ok, dss} = PdfElixide.Signature.dss(doc)
[der | _] = dss.certificates
{:ok, certificate} = PdfElixide.Signature.Certificate.parse(der)
certificate.issuer
#=> "CN=pdf_elixide test signer,O=pdf_elixide,C=UA"Reports %PdfElixide.Error{reason: :invalid_pdf} for a malformed or
unsupported certificate, an unrepresentable validity date, or trailing bytes
other than zero padding. A second concatenated certificate is a trailing
value, not a chain, and is rejected.
Same as parse/1, but raises PdfElixide.Error on failure.
@spec valid_at?(t(), DateTime.t()) :: boolean()
Whether the certificate's validity window covers instant.
Both ends are inclusive.
PdfElixide.Signature.Certificate.valid_at?(certificate, DateTime.utc_now())
#=> trueFor a signature, compare against its claimed signing time from
PdfElixide.Signature.signing_time_utc/1, or against the :time of a
PdfElixide.Signature.Timestamp whose attachment was confirmed by
PdfElixide.Signature.verify_timestamp/2 and whose authenticity was checked
by PdfElixide.Signature.Timestamp.verify/1. Only the latter is evidence
rather than the signer's claim, and it is still only as trustworthy as the
timestamp authority. A true result does not establish trust or rule out
revocation.