macula_cert (macula v0.20.5)
View SourceMacula Self-Sovereign Certificate System
Provides Ed25519 DID-anchored certificate generation and verification. Unlike traditional PKI, these certificates do not require external CAs.
Certificate hierarchy: - Realm certificates are self-signed (root of trust for a namespace) - Instance certificates are signed by the realm certificate
Example usage:
Generate realm keypair and certificate: {PubKey, PrivKey} = macula_cert:generate_keypair(), {ok, RealmCert} = macula_cert:generate_realm_cert(DID, PubKey, PrivKey).
Generate instance certificate signed by realm: {InstPub, InstPriv} = macula_cert:generate_keypair(), {ok, InstCert} = macula_cert:generate_instance_cert(InstanceDID, InstPub, RealmCert, PrivKey).
Verify certificate chain: ok = macula_cert:verify_cert(InstCert, RealmCert).
Summary
Functions
Generate canonical form for signing/verification The canonical form excludes the signature field and is deterministic.
Convert common name to DID format Example: "app.io.example" becomes "did:macula:io.example.app"
Decode certificate from binary format
Convert DID to common name format Example: "did:macula:io.example.app" becomes "app.io.example"
Encode certificate to binary format Uses term_to_binary for now; can switch to CBOR/JSON for interop.
Extract realm DID from an instance DID Example: "did:macula:io.example.app.node01" becomes "did:macula:io.example"
Convert map to certificate record
Generate an instance certificate signed by a realm certificate The instance DID must be under the realm's namespace.
Generate an instance certificate with custom validity
Generate a new Ed25519 keypair Returns {PublicKey, PrivateKey} as raw binaries.
Generate a self-signed realm certificate Realm certificates are the root of trust for a namespace.
Generate a self-signed realm certificate with custom validity
Generate a random certificate serial number
Check if a certificate is expired
Check if a certificate is currently valid (within validity period)
Sign a certificate request Used when processing CSRs from remote instances.
Convert certificate record to map
Verify an instance certificate against its issuer (realm) certificate
Verify a self-signed (realm) certificate
Types
-type macula_cert() :: #macula_cert{subject_did :: binary(), subject_cn :: binary(), issuer_did :: binary(), issuer_cn :: binary(), not_before :: non_neg_integer(), not_after :: non_neg_integer(), public_key :: binary(), signature :: binary(), serial :: binary(), version :: pos_integer(), extensions :: map()}.
-type macula_cert_request() :: #macula_cert_request{subject_did :: binary(), subject_cn :: binary(), public_key :: binary(), validity_days :: pos_integer()}.
Functions
-spec canonical_form(Cert :: macula_cert()) -> binary().
Generate canonical form for signing/verification The canonical form excludes the signature field and is deterministic.
Convert common name to DID format Example: "app.io.example" becomes "did:macula:io.example.app"
-spec decode(Binary :: binary()) -> {ok, macula_cert()} | {error, term()}.
Decode certificate from binary format
Convert DID to common name format Example: "did:macula:io.example.app" becomes "app.io.example"
-spec encode(Cert :: macula_cert()) -> binary().
Encode certificate to binary format Uses term_to_binary for now; can switch to CBOR/JSON for interop.
Extract realm DID from an instance DID Example: "did:macula:io.example.app.node01" becomes "did:macula:io.example"
-spec from_map(Map :: map()) -> {ok, macula_cert()} | {error, term()}.
Convert map to certificate record
-spec generate_instance_cert(InstanceDID :: binary(), InstancePubKey :: binary(), RealmCert :: macula_cert(), RealmPrivKey :: binary()) -> {ok, macula_cert()} | {error, term()}.
Generate an instance certificate signed by a realm certificate The instance DID must be under the realm's namespace.
-spec generate_instance_cert(InstanceDID :: binary(), InstancePubKey :: binary(), RealmCert :: macula_cert(), RealmPrivKey :: binary(), ValidityDays :: pos_integer()) -> {ok, macula_cert()} | {error, term()}.
Generate an instance certificate with custom validity
Generate a new Ed25519 keypair Returns {PublicKey, PrivateKey} as raw binaries.
-spec generate_realm_cert(RealmDID :: binary(), PublicKey :: binary(), PrivateKey :: binary()) -> {ok, macula_cert()} | {error, term()}.
Generate a self-signed realm certificate Realm certificates are the root of trust for a namespace.
-spec generate_realm_cert(RealmDID :: binary(), PublicKey :: binary(), PrivateKey :: binary(), ValidityDays :: pos_integer()) -> {ok, macula_cert()} | {error, term()}.
Generate a self-signed realm certificate with custom validity
-spec generate_serial() -> binary().
Generate a random certificate serial number
-spec is_expired(Cert :: macula_cert()) -> boolean().
Check if a certificate is expired
-spec is_valid_now(Cert :: macula_cert()) -> boolean().
Check if a certificate is currently valid (within validity period)
-spec sign_cert_request(Request :: macula_cert_request(), RealmCert :: macula_cert(), RealmPrivKey :: binary()) -> {ok, macula_cert()} | {error, term()}.
Sign a certificate request Used when processing CSRs from remote instances.
-spec to_map(Cert :: macula_cert()) -> map().
Convert certificate record to map
-spec verify_cert(InstanceCert :: macula_cert(), IssuerCert :: macula_cert()) -> ok | {error, term()}.
Verify an instance certificate against its issuer (realm) certificate
-spec verify_self_signed(Cert :: macula_cert()) -> ok | {error, term()}.
Verify a self-signed (realm) certificate