Repository commit signature verification.
Every repository commit is a DAG-CBOR object carrying a sig field: the raw
ECDSA signature, in low-S form, over the SHA-256 of the unsigned commit
(the same object with the sig field removed) encoded as canonical DAG-CBOR.
This module re-encodes the unsigned commit and verifies the signature against
an account's signing key, tying together Exosphere.ATProto.CBOR,
Exosphere.ATProto.Crypto, and Exosphere.ATProto.Identity.
Examples
# With an explicit public key + curve
:ok = Exosphere.ATProto.Repo.Commit.verify(commit, public_key, :secp256k1)
# Or resolve the signing key straight from a DID Document
:ok = Exosphere.ATProto.Repo.Commit.verify_with_document(commit, did_document)
Summary
Functions
Verify a decoded commit object against a public key.
Verify a commit against a block store containing its MST, returning the repository's record set.
Verify that a commit's data field (the MST root) matches a set of records.
Verify a commit using the signing key advertised in a DID Document.
Types
Functions
@spec verify(commit(), binary(), Exosphere.ATProto.Crypto.curve()) :: :ok | {:error, :missing_sig | :invalid_signature | term()}
Verify a decoded commit object against a public key.
The commit is the map produced by decoding the commit block (e.g. via
Exosphere.ATProto.CBOR.decode/1 or extracted from a CAR file), with the
data field as an Exosphere.ATProto.CID and sig as raw bytes.
Returns :ok, or {:error, reason} if the signature is missing, malformed,
or invalid.
@spec verify_checkout(commit(), %{ required(Exosphere.ATProto.CID.t()) => binary() | map() }) :: {:ok, %{required(Exosphere.ATProto.MST.key()) => Exosphere.ATProto.CID.t()}} | {:error, term()}
Verify a commit against a block store containing its MST, returning the repository's record set.
blocks maps CIDs to encoded DAG-CBOR bytes or decoded nodes (e.g. the
blocks from CAR.decode_full/1). The tree is walked from the commit's
data root, and the resulting records are checked against the signed root
via verify_data/2, proving the blocks form exactly the tree the commit
attests to.
This is the structural half of repository verification. To also authenticate
the signer, follow up with verify/3 or verify_with_document/2 (or use
Exosphere.ATProto.Repo.verify_checkout/3, which does both).
Returns {:ok, records} (path => CID), or errors from MST.read/2 /
verify_data/2 (e.g. {:error, {:missing_block, cid}} when the block store
is incomplete).
@spec verify_data(commit(), Enumerable.t()) :: :ok | {:error, :data_mismatch | :missing_data | term()}
Verify that a commit's data field (the MST root) matches a set of records.
records is a path => CID map (or enumerable of {path, %CID{}}) of every
record in the repository. The records are assembled into an MST and the
resulting root CID is compared to the commit's data link, confirming the
commit actually attests to exactly those records.
Combine with verify/3 to fully authenticate a repository: verify/3 proves
the commit is signed by the account, and verify_data/2 proves the records
match the signed root.
Returns :ok, {:error, :data_mismatch}, {:error, :missing_data}, or any
error from MST construction.
@spec verify_with_document(commit(), Exosphere.ATProto.Identity.Document.t()) :: :ok | {:error, :missing_sig | :invalid_signature | :not_found | term()}
Verify a commit using the signing key advertised in a DID Document.