X509_PRINT_EX(3)

πŸ“¦ version 4.4.0, in alpine 3.24, arch rolling

πŸ’… X509_PRINT_EX πŸ’…

okay so this is a page from the libcrypto manual, section 3 β€” yes that libcrypto, bestie, the crypto library. it's all about pretty-printing an X.509 certificate so you can actually read it with your human eyes instead of staring at DER bytes like πŸ‘οΈπŸ‘„πŸ‘οΈ


🌸 NAME 🌸

X509_print_ex, X509_CERT_AUX_print, X509_print_ex_fp, X509_print, X509_print_fp β€” pretty-print an X.509 certificate ✨


πŸŽ€ SYNOPSIS πŸŽ€

library β€œlibcrypto”

#include <openssl/x509.h>

int
X509_print_ex(BIO *bio, X509 *x, unsigned long nameflags,
    unsigned long skipflags);

int
X509_CERT_AUX_print(BIO *bio, X509_CERT_AUX *aux, int indent);

int
X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nameflags,
    unsigned long skipflags);

int
X509_print(BIO *bio, X509 *x);

int
X509_print_fp(FILE *fp, X509 *x);

πŸ¦‹ DESCRIPTION πŸ¦‹

the main character: X509_print_ex()

X509_print_ex() prints the info inside x to bio in human-readable form. it's giving "make it make sense" energy fr fr πŸ’–

printing gets aborted the second any operation fails β€” with one iconic exception: if something goes wrong while trying to decode or print the public key, the X.509 version 3 extensions, or the non-standard auxiliary data, that is not counted as an error. those three are just built different. πŸ’…

the blocks, in order 🧚

by default it prints these blocks in this exact order. you can skip any of them by setting the matching bit in skipflags β€” the flag name is in parentheses after each one, iykyk.

  • A pair of lines reading "Certificate:" and "Data:" that contain literally no information. iconic but useless. (X509_FLAG_NO_HEADER)
  • The certificate version number as defined by the standard, followed in parentheses by the value sitting in the version field in hexadecimal notation. see X509_get_version(3) for the deets. (X509_FLAG_NO_VERSION)
  • The serial number of the certificate, as returned by X509_get_serialNumber(3). if it's not -1 and converting it to long actually succeeds, it gets printed in both decimal and hexadecimal format. if it is -1, too wide to fit in a long, or the conversion just flops, it's printed byte-by-byte in hexadecimal notation. (X509_FLAG_NO_SERIAL)
  • The name of the signature algorithm, printed with X509_signature_print(3). (X509_FLAG_NO_SIGNAME)
  • The issuer name returned by X509_get_issuer_name(3), printed with X509_NAME_print_ex(3). (X509_FLAG_NO_ISSUER)
  • The validity period, from X509_get_notBefore(3) to X509_get_notAfter(3), printed using ASN1_TIME_print(3). (X509_FLAG_NO_VALIDITY)
  • The subject name returned from X509_get_subject_name(3), printed with X509_NAME_print_ex(3). (X509_FLAG_NO_SUBJECT)
  • The public key algorithm, printed with i2a_ASN1_OBJECT(3), and the public key returned from X509_get_pubkey(3) printed with EVP_PKEY_print_public(3). (X509_FLAG_NO_PUBKEY)
  • If an issuer or subject unique identifier is present, its hex dump gets printed with X509_signature_dump(3). (X509_FLAG_NO_IDS)
  • All X.509 extensions contained in the certificate, printed with X509V3_extensions_print(3). (X509_FLAG_NO_EXTENSIONS)
  • The signature, printed with X509_signature_print(3). (X509_FLAG_NO_SIGDUMP)
  • Non-standard auxiliary data associated with the certificate, printed using X509_CERT_AUX_print() β€” which is documented right down below πŸ‘‡ (X509_FLAG_NO_AUX)

nameflags β€” the glow-up for names πŸ’«

the nameflags argument modifies the format used for printing X.501 Name objects contained in x. it gets passed straight through to X509_NAME_print_ex(3). here's the tea:

  • If nameflags is X509_FLAG_COMPAT, the indent argument of X509_NAME_print_ex(3) is set to 16 spaces and the traditional SSLeay format is used. retro slay.
  • Otherwise, if the only bit set in XN_FLAG_SEP_MASK is XN_FLAG_SEP_MULTILINE, indent is set to 12 spaces.
  • Otherwise, indent is set to zero. no indent, no problem.

the side quest: X509_CERT_AUX_print() πŸ“

X509_CERT_AUX_print() prints the info contained in aux to bio in human-readable form with a left margin of indent spaces. if aux is NULL, it prints nothing at all. silent. mysterious. 🫢

info comes out in this order:


the fp twins 🌈

X509_print_ex_fp() is basically X509_print_ex()'s twin, except it prints to fp. same vibes, different destination.

X509_print() and X509_print_fp() are wrapper functions that set nameflags to XN_FLAG_COMPAT and skipflags to X509_FLAG_COMPAT. the defaults. the classics. the "i don't want to think about flags today" option. πŸ’œ


πŸ‘‘ RETURN VALUES πŸ‘‘

X509_print_ex(), X509_print_ex_fp(), X509_print(), and X509_print_fp() return 1 if all requested information was successfully printed β€” even if failures happened while trying to decode or print the public key or the X.509 version 3 extensions. they return 0 if any other operation failed. so yes, 1 here is like "we're good, mostly" πŸ’€

X509_CERT_AUX_print() always returns 1 and silently ignores write errors. it literally cannot fail. unbothered. flourishing. πŸ™ˆ


⭐ SEE ALSO ⭐

BIO_new(3), X509_CERT_AUX_new(3), X509_CRL_print(3), X509_new(3), X509_REQ_print_ex(3)


🧚 HISTORY 🧚

X509_print() first appeared in SSLeay 0.5.1, and got changed to print to a BIO in SSLeay 0.6.0. X509_print_fp() first appeared in SSLeay 0.6.0. both have been available since OpenBSD 2.4. ancient. legendary. πŸ’…

X509_CERT_AUX_print() first appeared in OpenSSL 0.9.5 and has been available since OpenBSD 2.7.

X509_print_ex() and X509_print_ex_fp() first appeared in OpenSSL 0.9.7 and have been available since OpenBSD 3.2.


πŸ’€ BUGS πŸ’€

ok so hear me out β€” if arbitrary data was stored into x using X509_alias_set1(3), these functions may print binary data and even NUL bytes. yes, actual NUL bytes, in your nice little terminal output. proceed accordingly bestie 😭

that's the whole page 🫢 written by the Debian crew, dated July 1, 2025 β€” go print some certificates and stay hydrated βœ¨πŸŽ€πŸ’–

πŸ“¦ where this page comes from