Host-side signature verification for activated mob plugins.
Given a plugin directory + its loaded manifest, this module:
- Loads
priv/mob_plugin.sig(the signed envelope). - Loads
priv/mob_plugin.pub(the plugin author's public key). - Recomputes the file-hash list via
Sign.compute_file_hashes/2. - Reconstructs the canonical payload and runs
Crypto.verify/3.
Failure modes are distinguished:
:missing_signature— nopriv/mob_plugin.sig.:missing_pubkey— nopriv/mob_plugin.pub.:invalid_signature— sig file present but the signature doesn't verify against the canonical payload reconstructed from disk. This is the failure mode for both manifest tampering and source-file tampering: the recomputedfile_hashesno longer match what was signed, so the payload differs and the signature check fails.
Trust (mapping a verified public key to "the host operator approved
it") lives in TrustStore and is layered on top of this module.
Summary
Types
Errors load_pubkey/1 can return.
Errors load_signature/1 can return.
Errors verify_plugin/2 can return.
Functions
Loads the raw 32-byte public key from priv/mob_plugin.pub.
Loads the raw 64-byte signature from priv/mob_plugin.sig.
Verifies that the plugin in plugin_dir has a valid signature for the
given manifest + the current file contents on disk.
Types
@type pubkey_error() :: :missing | :malformed
Errors load_pubkey/1 can return.
@type sig_error() :: :missing | :corrupt
Errors load_signature/1 can return.
@type verify_error() :: :missing_signature | :missing_pubkey | :invalid_signature
Errors verify_plugin/2 can return.
Functions
@spec load_pubkey(Path.t()) :: {:ok, MobDev.Plugin.Crypto.pub_key()} | {:error, pubkey_error()}
Loads the raw 32-byte public key from priv/mob_plugin.pub.
Format: a single line of base64 (with = padding) of the raw 32-byte
Ed25519 public key, optionally followed by a trailing newline. Plain
text so plugin authors can cat it or paste it into a release note.
@spec load_signature(Path.t()) :: {:ok, MobDev.Plugin.Crypto.signature()} | {:error, sig_error()}
Loads the raw 64-byte signature from priv/mob_plugin.sig.
The file is the Crypto.canonical_encode/1 of an envelope map
(%{signature: <64-byte sig>, envelope_version: 1}); this function
decodes the envelope and returns the inner signature binary.
@spec verify_plugin(Path.t(), map() | nil) :: :ok | {:error, verify_error()}
Verifies that the plugin in plugin_dir has a valid signature for the
given manifest + the current file contents on disk.
Returns :ok on success or one of the distinguished error reasons
(see verify_error/0). The caller is responsible for any trust
decision; this function only proves that the bytes on disk match
what the plugin author signed.