Clause
← All documentation

public_key

Clause's public_key application consists of generated ASN.1 modules, the header library/public_key/include/public_key.hrl and the public_key module. clau generates the ASN.1 modules from library/public_key/asn1/ to encode and decode PKIX and PKCS types. The public_key module exports the OTP 29 interface. Implemented functions cover DER and PEM encoding and decoding, keys and signatures, certificate, name, CRL and hostname operations, path validation, CRL validation, OCSP validation, test data and trust stores. See the function inventory.

Specifications

library/public_key/asn1/ contains the ASN.1 modules compiled by OTP's public_key application, with matching module names:

SourceModules
RFC 5912 (PKIX, 2009 ASN.1)AlgorithmInformation-2009, AttributeCertificateVersion1-2009, EnrollmentMessageSyntax-2009, PKCS-10, PKIX-CommonTypes-2009, PKIX-X400Address-2009, PKIX1-PSS-OAEP-Algorithms-2009, PKIX1Explicit-2009, PKIX1Implicit-2009, PKIXAlgs-2009, PKIXAttributeCertificate-2009, PKIXCRMF-2009
RFC 5911 (CMS and S/MIME)CryptographicMessageSyntax-2009, CryptographicMessageSyntaxAlgorithms-2009, CMSAesRsaesOaep-2009, SecureMimeMessageV3dot1-2009
RFC 5915, 5958, 8017, 8018, 8410, 9629, 9654, 9810, 9814, 9881, 9935ECPrivateKey, AsymmetricKeyPackageModuleV1, PKCS-1, PKCS5v2-0, Safecurves-pkix-18, KEMAlgorithmInformation-2023, OCSP-2024-08, PKIXCMP-2023, SLH-DSA-Module-2024, X509-ML-DSA-2025, X509-ML-KEM-2025
Clause implementationsOTP-PKIX and OTP-PKIX-Relaxed (OTPCertificate representations), DSS (DSAPrivateKey), PKCS-3 (DHParameter), RFC5639 (Brainpool curve identifiers), PKCS-FRAME.set.asn (AsymmetricKeyPackageModuleV1 with PKCS5v2-0)

Each RFC module contains the RFC's code component and the IETF Trust BSD notice. Module text is modified only to match OTP's specification differences. Modifications are documented at the start of the affected files: PKCS-1, PKCS5v2-0, ECPrivateKey, PKIX1Explicit-2009, PKIXAlgs-2009 and PKIXCMP-2023. Generated Erlang modules and headers match those produced from OTP's specifications.

Generated modules

The build invokes clau --generate-asn1 with OTP's ber, der and noobj options. Generated modules, including 'OTP-PKIX' and 'PKIX1Explicit-2009', are written to library-asn1/public_key/ in the build tree. This directory is under the second library root, searched after library/. A program referencing a generated module causes it to be compiled into the batch according to the library discovery rules.

As in OTP, AsymmetricKeyPackageModuleV1 and PKCS5v2-0 are merged into PKCS-FRAME and are not available as separate modules. Encodings, decoded values and record definitions match asn1ct; see ASN.1. OTP's asn1config exclusive decode functions, including decode_TBSCert_exclusive/1, are not generated.

-include_lib("public_key/include/public_key.hrl") resolves to Clause's header unless the project defines its own public_key application. The header defines OTP-compatible records and macros. Most records and values are generated from the specifications. Additional definitions include the pre-2009 'Certificate' representation, 'ECPoint', ML-DSA, ML-KEM and SLH-DSA key records, #cert{} and the object identifiers used by public_key.

The public_key_records golden test compares every record field, default value and macro value against OTP's header. The public_key_asn1 golden test decodes and encodes certificates, keys and parameters through the generated modules.

Functions

The application includes public_key.app and an asn1.app dependency resource. public_key delegates encoding and decoding functions to clause_public_key_codec, which includes public_key.hrl. Runtime builtins implement the record traversals and object identifier tables corresponding to OTP's pubkey_translation and pubkey_cert_records, PEM text and the password-based encryption tables; see public key builtins.

The public_key_codec golden test compares these functions against OTP, including the PEM text of encrypted entries.

Keys and signatures

clause_public_key_keys converts key records to OTP-compatible crypto key lists and delegates cryptographic operations to that module:

Keycrypto algorithm or dispatch
#'RSAPrivateKey'{} (all CRT components, or only [E, N, D]), {RSAKey, PssParams}; #'RSAPublicKey'{}rsa
#'DSAPrivateKey'{}; {Y, #'Dss-Parms'{}}dss
#'ECPrivateKey'{} with named or explicit parameters; {#'ECPoint'{}, Params}ecdsa
Ed25519/Ed448 #'ECPrivateKey'{}, {ed_pri, Curve, Pub, Priv}; {#'ECPoint'{}, {namedCurve, Oid}}, {ed_pub, Curve, Key}eddsa
#'ML-DSAPrivateKey'{} (seed, otherwise expanded key), #'SLH-DSAPrivateKey'{}; corresponding public keysSelected parameter set
Map containing sign_fun or encrypt_funInvocation of the supplied function

The implementation preserves the following OTP behavior: generate_key/1 produces an ML-DSA key with an empty seed, which crypto rejects for signing; DSA private keys are rejected for verification; and decoding explicit prime-field curves fails when decoding the prime. The public_key_keys golden test compares deterministic signatures (RSA PKCS #1, EdDSA and certificates), encryption, key agreement, types, hashes and group selection against OTP.

Certificates and names

clause_public_key_cert implements certificate operations corresponding to OTP's pubkey_cert, pubkey_crl and public_key:

As in OTP, decoding an X9.42 DH certificate into the otp representation fails with {badarg, {unknown_type, 'DHPublicKey'}}. Consequently, pkix_is_fixed_dh_cert/1 operates only on decoded records. The public_key_certs golden test compares these functions against OTP using certificates and a CRL generated with OpenSSL.

Path validation

pkix_path_validation/3, implemented by clause_public_key_path, validates a certificate chain from a trusted certificate in DER, otp or plain representation. It follows OTP's implementation of RFC 5280 section 6.1 and checks:

Supported OTP options are verify_fun, max_path_length, explicit_policy, inhibit_any_policy, inhibit_policy_mapping and policy_set. verify_fun accepts arity 3 or 4 and receives {bad_cert, Reason}, {extension, Ext}, valid and valid_peer events. A path error atom supplied as the first argument is passed to the verification function before further processing.

The result is {ok, {{Algorithm, PublicKey, Params}, PolicyNodes}}, including the valid policies' qualifiers, or {error, {bad_cert, Reason}}. The public_key_path golden test compares valid chains, failure cases, policies, mappings, options and verification callback events against OTP using chains generated with OpenSSL.

CRL validation

pkix_crls_validate/3, implemented by clause_public_key_crl, checks a certificate against CRLs according to OTP's implementation of RFC 5280 section 6.3:

The result is valid, {bad_cert, {revoked, Reason}} or {bad_cert, revocation_status_undetermined}. When undetermined_details is enabled, the result includes rejected CRLs and their rejection reasons. The public_key_crls golden test compares revoked and unrevoked certificates, delta CRLs, stale CRLs, unknown critical extensions, invalid signatures, missing issuer chains and a separate CRL signer against OTP using CRLs generated with OpenSSL.

OCSP validation

pkix_ocsp_validate/5, implemented by clause_public_key_ocsp, validates a DER-encoded OCSP response according to OTP's implementation of RFC 6960:

The result is {ok, Details}, {error, {bad_cert, {revoked, RevokedInfo}}} or {error, {bad_cert, {revocation_status_undetermined, Reason}}}. ocsp_extensions/1 constructs the request nonce extension. The public_key_ocsp golden test compares good, revoked and unknown statuses, designated, unauthorized and expired responders, nonce handling, modified and re-signed responses, and stale times against OTP using responses generated with OpenSSL.

Test data

pkix_test_data/1 and pkix_test_root_cert/2, implemented by clause_public_key_test_data, generate test certificates with OTP-compatible structure and defaults. A self-signed root can be supplied as #{cert, key} or generated from options. Generated intermediate CAs and peers form either one chain, returned as [{cert, _}, {key, _}, {cacerts, _}], or server and client chains, returned as #{server_config, client_config} with each chain trusting the other's root.

The public_key_test_data golden test compares the non-random components of generated certificates and their path validation results against OTP.

Trust stores

cacerts_load/0,1, cacerts_get/0 and cacerts_clear/0, implemented by clause_public_key_cacerts, load trusted CA certificates as OTP does and cache them as #cert{} records in a persistent term:

cacerts_get/0 loads on first use, from the public_key application's cacerts_path setting if present, and fails with {failed_load_cacerts, Reason} when nothing loads. cacerts_clear/0 returns whether certificates were loaded. The public_key_cacerts golden test compares bundles, directories, cacerts_path, errors and whether the system store has certificates against OTP.