Skip to main content

Module note

Module note 

Source
Expand description

Signing and verifying C2SP signed notes, mirroring the Go sumdb/note reference implementation line-for-line.

§Invariants

  • The signature line prefix is the U+2014 em dash followed by one ASCII space — bytes E2 80 94 20, never -- or a lookalike.
  • The Ed25519 signature covers the body including its trailing '\n', excluding the blank line and signature lines.
  • Key ID = first 4 bytes of SHA-256(keyname ‖ 0x0A ‖ 0x01 ‖ pubkey).
  • sign_note enforces preconditions (valid name; body non-empty, '\n'-terminated, no "\n\n", no ASCII control character below 0x20 other than '\n'; emitted note within MAX_NOTE_BYTES) that guarantee the emitted note always re-verifies under verify_note AND under Go note.Open.
  • verify_note splits at the LAST "\n\n" (Go bytes.LastIndex), rejects any malformed signature line, caps at 100 signature lines (Go’s exact cap) and 1 MiB total (a lys defensive cap that sign_note also enforces), and mirrors Go note.Open candidate semantics exactly: the FIRST signature line matching the verifier’s (name, key ID) decides the whole note — strict Ed25519 success accepts, failure rejects (later lines are never consulted, matching Go’s duplicate-signer skip and hard InvalidSignatureError reject; the C2SP signed-note spec likewise says a failed known-key signature rejects the whole note).
  • Every verification failure collapses to the single non-oracle TrustError::NoteVerification value.

Functions§

key_id
Computes the signed-note key ID: SHA-256(name ‖ 0x0A ‖ 0x01 ‖ pubkey)[..4].
sign_note
Signs body under name and emits the complete note text: body ‖ blank line ‖ one signature line.
verify_checkpoint
verify_note followed by CheckpointBody::parse and the origin-binding check body.origin() == verifier.name().
verify_note
Parses and verifies an untrusted note; returns the verified body text (including its trailing newline).