MetamorphicLog.Policy (metamorphic_log v0.1.5)

Copy Markdown View Source

Signed namespace policy verification and declared-vs-observed enforcement.

A namespace policy is a signed, in-log, versioned record declaring the cryptographic posture a namespace operates under: checkpoint signature suite and security level, the CONIKS commitment hash, the VRF mode, and the directory route (CONIKS vs the experimental IETF KEYTRANS backend and its cipher suite). Because the policy is itself a log leaf, the posture is auditable and tamper-evident.

verify/1 checks the policy's self-signature and returns the declared posture. The enforce_* functions then assert that an observed artifact (a checkpoint signing key, a checkpoint signature, a VRF suite id, a commitment hash, or a directory backend id) matches what the verified policy declares — the "declared == observed" invariant that stops an operator from silently downgrading.

The signed policy envelope is base64-encoded.

Summary

Types

A directory backend identifier (§3.3 DirectoryBackendId, a u16).

t()

A verified namespace policy.

Functions

Enforce that a checkpoint signature_b64 matches the verified policy's declared checkpoint posture. Returns :ok or {:error, reason}.

Enforce that a checkpoint signing key (public_key_b64) matches the verified policy's declared checkpoint posture. Returns :ok or {:error, reason}.

Enforce that an observed commitment_hash (:sha3_256 | :sha3_512) matches the policy's declaration. Returns :ok or {:error, reason}.

Enforce that an observed directory backend matches the one the verified policy declares (from its :directory_mode / :keytrans_suite axis).

Enforce that an observed VRF suite_id matches the policy's declared VRF mode. Returns :ok or {:error, reason}.

Sign a namespace policy and return its base64-encoded signed envelope, the producer counterpart to verify/1.

Verify a signed policy envelope and return the declared posture as a %MetamorphicLog.Policy{} struct.

Types

directory_backend()

@type directory_backend() :: :coniks | :keytrans | 0..65535

A directory backend identifier (§3.3 DirectoryBackendId, a u16).

Pass either a well-known atom or the raw id:

  • :coniks — the shipped, frozen CONIKS prefix-tree backend (0x0001)
  • :keytrans — the experimental IETF KEYTRANS combined-tree backend (0xF004, KEYTRANS_EXP_V04; movable — the id tracks the draft)

t()

@type t() :: %MetamorphicLog.Policy{
  checkpoint_suite: :hybrid | :hybrid_matched | :pure_cnsa2,
  commitment_hash: :sha3_256 | :sha3_512,
  created_at: non_neg_integer(),
  directory_mode: :coniks | :keytrans,
  effective_from: non_neg_integer(),
  keytrans_suite:
    :metamorphic_hybrid_exp | :kt128_sha256_p256 | :kt128_sha256_ed25519,
  namespace: String.t(),
  policy_hash: String.t(),
  policy_schema_version: non_neg_integer(),
  rfc6962_leaf_hash: String.t(),
  security_level: :cat3 | :cat5,
  vrf_mode: :classical | :hybrid_output | :pure_pq_experimental
}

A verified namespace policy.

  • :security_level:cat3 | :cat5

  • :checkpoint_suite:hybrid | :hybrid_matched | :pure_cnsa2

  • :commitment_hash:sha3_256 | :sha3_512

  • :vrf_mode:classical | :hybrid_output | :pure_pq_experimental

  • :directory_mode:coniks | :keytrans (the Layer-3 directory route)

  • :keytrans_suite:metamorphic_hybrid_exp | :kt128_sha256_p256 | :kt128_sha256_ed25519 (only meaningful when :directory_mode is :keytrans; the default suite otherwise)

  • :policy_hash, :rfc6962_leaf_hash — base64-encoded

Functions

enforce_checkpoint_signature(signed_b64, signature_b64)

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

Enforce that a checkpoint signature_b64 matches the verified policy's declared checkpoint posture. Returns :ok or {:error, reason}.

enforce_checkpoint_signing_key(signed_b64, public_key_b64)

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

Enforce that a checkpoint signing key (public_key_b64) matches the verified policy's declared checkpoint posture. Returns :ok or {:error, reason}.

enforce_commitment_hash(signed_b64, commitment_hash)

@spec enforce_commitment_hash(String.t(), :sha3_256 | :sha3_512) ::
  :ok | {:error, String.t()}

Enforce that an observed commitment_hash (:sha3_256 | :sha3_512) matches the policy's declaration. Returns :ok or {:error, reason}.

enforce_directory_backend(signed_b64, observed)

@spec enforce_directory_backend(String.t(), directory_backend()) ::
  :ok | {:error, String.t()}

Enforce that an observed directory backend matches the one the verified policy declares (from its :directory_mode / :keytrans_suite axis).

A CONIKS-route policy must be served by the CONIKS backend; a KEYTRANS-route policy by the KEYTRANS combined-tree backend. Any disagreement — including a route that declares a reserved/not-built suite — is a hard rejection.

observed is a directory_backend/0: :coniks, :keytrans, or a raw u16. Returns :ok or {:error, reason}.

Example

:ok = MetamorphicLog.Policy.enforce_directory_backend(signed_b64, :coniks)

enforce_vrf_suite_id(signed_b64, suite_id)

@spec enforce_vrf_suite_id(String.t(), 0..255) :: :ok | {:error, String.t()}

Enforce that an observed VRF suite_id matches the policy's declared VRF mode. Returns :ok or {:error, reason}.

sign(params, secret_key_b64)

@spec sign(
  params :: Enumerable.t(),
  secret_key_b64 :: String.t()
) :: {:ok, String.t()} | {:error, String.t()}

Sign a namespace policy and return its base64-encoded signed envelope, the producer counterpart to verify/1.

params is a keyword list or map declaring the posture to attest. The enum fields take the same atoms verify/1 returns, so a verified policy can be re-signed by feeding its struct fields straight back in:

  • :namespace (required) — the namespace identity string
  • :policy_schema_version (required) — non-negative integer
  • :security_level (required) — :cat3 | :cat5

  • :checkpoint_suite (required) — :hybrid | :hybrid_matched | :pure_cnsa2

  • :commitment_hash (required) — :sha3_256 | :sha3_512

  • :vrf_mode (required) — :classical | :hybrid_output | :pure_pq_experimental

  • :directory_mode (required) — :coniks | :keytrans

  • :keytrans_suite (required only when :directory_mode is :keytrans) — :metamorphic_hybrid_exp | :kt128_sha256_p256 | :kt128_sha256_ed25519; ignored for the CONIKS route (defaults to :metamorphic_hybrid_exp)
  • :effective_from (required) — non-negative integer timestamp
  • :created_at (required) — non-negative integer timestamp
  • :prev_policy_hash (optional) — base64 of the previous policy's 64-byte hash to chain revisions, or nil for the first policy

secret_key_b64 is the base64 metamorphic-crypto composite secret key. ML-DSA signing is hedged, so the envelope bytes are not reproducible, but the result verifies deterministically via verify/1.

Returns {:ok, signed_b64} or {:error, reason} (unknown enum value, malformed namespace, a prev_policy_hash that is not 64 bytes, or a signing failure).

Example

{:ok, signed} =
  MetamorphicLog.Policy.sign(
    [
      namespace: "metamorphic.app/log",
      policy_schema_version: 1,
      security_level: :cat3,
      checkpoint_suite: :hybrid,
      commitment_hash: :sha3_256,
      vrf_mode: :classical,
      directory_mode: :coniks,
      effective_from: 0,
      created_at: 0
    ],
    secret_key_b64
  )

verify(signed_b64)

@spec verify(signed_b64 :: String.t()) :: {:ok, t()} | {:error, String.t()}

Verify a signed policy envelope and return the declared posture as a %MetamorphicLog.Policy{} struct.

Returns {:ok, %Policy{}} or {:error, reason}.

Example

{:ok, %MetamorphicLog.Policy{checkpoint_suite: :hybrid}} =
  MetamorphicLog.Policy.verify(signed_b64)