Ed25519 sign/verify primitives + canonical-term encoding for plugin signing.
The signing scheme (see MOB_PLUGIN_SECURITY.md, Phase 2):
- Plugin authors generate a per-plugin Ed25519 keypair; the public key
ships in
priv/mob_plugin.puband the manifest+sources are signed with the private key intopriv/mob_plugin.sig. - Hosts verify the signature against the public key at activation time and refuse to build untrusted/unsigned plugins.
This module is the single place the Ed25519 + canonical-encoding
decisions are encoded. Keep it crypto-only — workflow (sign/verify
orchestration, fingerprint storage) lives in Sign, Verify, and
TrustStore.
Summary
Types
Host-visible trust identifier; base64-encoded SHA-256 of the public key.
Raw 32-byte Ed25519 private key.
Raw 32-byte Ed25519 public key.
Raw 64-byte Ed25519 signature.
Functions
Canonical encoding of an arbitrary Erlang term to a binary.
Computes the host-visible trust identifier for a public key.
Generates a fresh Ed25519 keypair.
Signs payload_term with priv_bin.
Verifies signature_bin against payload_term and pub_bin.
Types
@type fingerprint() :: String.t()
Host-visible trust identifier; base64-encoded SHA-256 of the public key.
@type priv_key() :: <<_::256>>
Raw 32-byte Ed25519 private key.
@type pub_key() :: <<_::256>>
Raw 32-byte Ed25519 public key.
@type signature() :: <<_::512>>
Raw 64-byte Ed25519 signature.
Functions
Canonical encoding of an arbitrary Erlang term to a binary.
Uses :erlang.term_to_binary/2 with :deterministic so the same logical
value produces the same bytes regardless of map iteration order.
Centralised here so the determinism flag is in one place: sign/2,
verify/3, and any future hash-of-payload helper all agree.
@spec fingerprint(pub_key()) :: fingerprint()
Computes the host-visible trust identifier for a public key.
Format: "ed25519:<base64>" where <base64> is the standard base64
encoding (with = padding) of the SHA-256 digest of the raw 32-byte
public key. Suitable for storing in mob.exs under
:trusted_plugins and for comparing two keys for equality without
printing the key itself.
Generates a fresh Ed25519 keypair.
Returns {priv_bin, pub_bin} as raw 32-byte binaries. The format
matches what :crypto.sign/4 and :crypto.verify/5 accept directly
with the :eddsa/:ed25519 options.
Signs payload_term with priv_bin.
The term is canonically encoded via canonical_encode/1 before signing,
so the signature is over the deterministic binary form — the same map
with the same contents produces the same signature regardless of map
insertion order.
Verifies signature_bin against payload_term and pub_bin.
Returns :ok on valid signature, {:error, :invalid_signature}
otherwise. Mirrors sign/2 — the same canonical encoding is applied
before verifying.