signed_note/
lib.rs

1// Ported from "mod" (https://pkg.go.dev/golang.org/x/mod)
2// Copyright 2009 The Go Authors
3// Licensed under the BSD-3-Clause license found in the LICENSE file or at https://opensource.org/licenses/BSD-3-Clause
4//
5// This ports code from the original Go project "mod" and adapts it to Rust idioms.
6//
7// Modifications and Rust implementation Copyright (c) 2025 Cloudflare, Inc.
8// Licensed under the BSD-3-Clause license found in the LICENSE file or at https://opensource.org/licenses/BSD-3-Clause
9
10//! This crate defines notes as specified by the [C2SP signed-note](https://c2sp.org/signed-note) specification.
11//!
12//! This file contains code ported from the original project [note](https://pkg.go.dev/golang.org/x/mod/sumdb/note).
13//!
14//! References:
15//! - [note](https://cs.opensource.google/go/x/mod/+/refs/tags/v0.21.0:sumdb/note/)
16//!
17//! # Signed Note
18//!
19//! A note is text signed by one or more server keys ([spec](https://c2sp.org/signed-note#note)).
20//! The text should be ignored unless the note is signed by a trusted server key and the signature
21//! has been verified using the server's public key.
22//!
23//! A server's public key is identified by a name, typically the "host[/path]" giving the base URL
24//! of the server's transparency log.  The syntactic restrictions on a name are that it be
25//! non-empty, well-formed UTF-8 containing neither Unicode spaces nor plus (U+002B).
26//!
27//! A server signs texts using public key cryptography.  A given server may have multiple public
28//! keys, each identified by a 32-bit ID of the public key.  The [`key_id`] function computes the
29//! key ID as RECOMMENDED by the [spec](https://c2sp.org/signed-note#signatures).
30//! ```text
31//! key ID = SHA-256(key name || 0x0A || signature type || public key)[:4]
32//! ```
33//!
34//! A [`Note`] represents a text with one or more signatures.  An implementation can reject a note
35//! with too many signatures (for example, more than 100 signatures).
36//!
37//! The [`Note::from_bytes`] function parses a message and validates that the text and signatures are
38//! syntactically valid, and returns a Note.
39//!
40//! The [`Note::new`] function accepts a text and an existing list of signatures and returns a Note.
41//!
42//! A [Signature] represents a signature on a note, verified or not
43//! ([spec](https://c2sp.org/signed-note.md#signatures)).
44//!
45//! The [`Signature::from_bytes`] function parses a note signature line and ensures that it is
46//! syntactically valid, returning a Signature.
47//!
48//! The [`Signature::to_bytes`] function encodes a signature for inclusion in a note.
49//!
50//! ## Verifying Notes
51//!
52//! A [`Verifier`] allows verification of signatures by one server public key.  It can report the
53//! name of the server and the uint32 ID of the key, and it can verify a purported signature by
54//! that key.
55//!
56//! The standard implementation of a Verifier is constructed by [`StandardVerifier::new`] starting
57//! from a verifier key, which is a plain text string of the form `<name>+<id>+<keydata>`.
58//!
59//! A [`Verifiers`] allows looking up a Verifier by the combination of server name and key ID.
60//!
61//! The standard implementation of a Verifiers is constructed by [`VerifierList`] from a list of
62//! known verifiers.
63//!
64//! The [`Note::verify`] function attempts to verify the signatures on a note using the provided
65//! Verifiers, and returns the verified and unverified signatures.
66//!
67//! ## Signing Notes
68//!
69//! A [`Signer`] allows signing a text with a given key. It can report the name of the server and the
70//! ID of the key and can sign a raw text using that key.
71//!
72//! The standard implementation of a Signer is constructed by [`StandardSigner::new`] starting from
73//! an encoded signer key, which is a plain text string of the form
74//! `PRIVATE+KEY+<name>+<id>+<keydata>`.  Anyone with an encoded signer key can sign messages using
75//! that key, so it must be kept secret. The encoding begins with the literal text `PRIVATE+KEY` to
76//! avoid confusion with the public server key. This format is not required by the C2SP spec.
77//!
78//! The [`Note::add_sigs`] function adds new signatures to the note from the provided list of
79//! Signers.
80//!
81//! ## Signed Note Format
82//!
83//! A signed note consists of a text ending in newline (U+000A), followed by a blank line (only a
84//! newline), followed by one or more signature lines of this form: em dash (U+2014), space
85//! (U+0020), server name, space, base64-encoded signature, newline
86//! ([spec](https://c2sp.org/signed-note#format)).
87//!
88//! Signed notes must be valid UTF-8 and must not contain any ASCII control characters (those below
89//! U+0020) other than newline.
90//!
91//! A signature is a base64 encoding of 4+n bytes.
92//!
93//! The first four bytes in the signature are the uint32 key ID stored in big-endian order.
94//!
95//! The remaining n bytes are the result of using the specified key to sign the note text
96//! (including the final newline but not the separating blank line).
97//!
98//! The [`Note::to_bytes`] function encodes a note into signed note format.
99//!
100//! ## Generating Keys
101//!
102//! There is only one key type, Ed25519 with algorithm identifier 1.  New key types may be
103//! introduced in the future as needed, although doing so will require deploying the new algorithms
104//! to all clients before starting to depend on them for signatures.
105//!
106//! The [`generate_key`] function generates and returns a new signer and corresponding verifier.
107//!
108//! ## Example
109//!
110//! Here is a well-formed signed note:
111//! ```text
112//! If you think cryptography is the answer to your problem,
113//! then you don't know what your problem is
114//! — PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=
115//! ```
116//!
117//! It can be constructed and displayed using:
118//!
119//! ```
120//! use signed_note::{Note, StandardSigner};
121//!
122//! let skey = "PRIVATE+KEY+PeterNeumann+c74f20a3+AYEKFALVFGyNhPJEMzD1QIDr+Y7hfZx09iUvxdXHKDFz";
123//! let text = "If you think cryptography is the answer to your problem,\n\
124//!             then you don't know what your problem is.\n";
125//!
126//! let signer = StandardSigner::new(skey).unwrap();
127//! let mut n = Note::new(text.as_bytes(), &[]).unwrap();
128//! n.add_sigs(&[&signer]).unwrap();
129//!
130//! let want = "If you think cryptography is the answer to your problem,\n\
131//!             then you don't know what your problem is.\n\
132//!             \n\
133//!             — PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n";
134//!
135//! assert_eq!(&n.to_bytes(), want.as_bytes());
136//! ```
137//!
138//! The note's text is two lines, including the final newline, and the text is purportedly signed
139//! by a server named "`PeterNeumann`". (Although server names are canonically base URLs, the only
140//! syntactic requirement is that they not contain spaces or newlines).
141//!
142//! If [`Note::verify`] is given access to a [`Verifiers`] including the [`Verifier`] for this key, then
143//! it will succeed at verifying the encoded message and returning the parsed [`Note`]:
144//!
145//! ```
146//! use signed_note::{Note, StandardVerifier, VerifierList};
147//!
148//! let vkey = "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW";
149//! let msg = "If you think cryptography is the answer to your problem,\n\
150//!            then you don't know what your problem is.\n\
151//!            \n\
152//!            — PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n";
153//!
154//! let verifier = StandardVerifier::new(vkey).unwrap();
155//! let n = Note::from_bytes(msg.as_bytes()).unwrap();
156//! let (verified_sigs, _) = n.verify(&VerifierList::new(vec![Box::new(verifier.clone())])).unwrap();
157//!
158//! let got = format!("{} ({:08x}):\n{}", verified_sigs[0].name(), verified_sigs[0].id(), std::str::from_utf8(n.text()).unwrap());
159//! let want = "PeterNeumann (c74f20a3):\n\
160//!             If you think cryptography is the answer to your problem,\n\
161//!             then you don't know what your problem is.\n";
162//! assert_eq!(want, got);
163//! ```
164//!
165//! You can add your own signature to this message by re-signing the note, which will produce a
166//! doubly-signed message.
167//!
168//! ### Sign and add signatures
169//! ```
170//! use signed_note::{Note, StandardSigner, StandardVerifier, VerifierList};
171//!
172//! let vkey = "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW";
173//! let msg = "If you think cryptography is the answer to your problem,\n\
174//!            then you don't know what your problem is.\n\
175//!            \n\
176//!            — PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n";
177//! let text = "If you think cryptography is the answer to your problem,\n\
178//!             then you don't know what your problem is.\n";
179//!
180//! let mut n = Note::from_bytes(msg.as_bytes()).unwrap();
181//!
182//! let verifier = StandardVerifier::new(vkey).unwrap();
183//! let (verified_sigs, unverified_sigs) = n.verify(&VerifierList::new(vec![Box::new(verifier.clone())])).unwrap();
184//! assert_eq!(verified_sigs.len(), 1);
185//! assert!(unverified_sigs.is_empty());
186//!
187//! struct ZeroRng;
188//!
189//! impl rand_core::RngCore for ZeroRng {
190//!     fn next_u32(&mut self) -> u32 {
191//!         0
192//!     }
193//!
194//!     fn next_u64(&mut self) -> u64 {
195//!         0
196//!     }
197//!
198//!     fn fill_bytes(&mut self, dest: &mut [u8]) {
199//!         for byte in dest.iter_mut() {
200//!             *byte = 0;
201//!         }
202//!     }
203//!
204//!     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
205//!         self.fill_bytes(dest);
206//!         Ok(())
207//!     }
208//! }
209//!
210//! impl rand_core::CryptoRng for ZeroRng {}
211//!
212//! let (skey, _) = signed_note::generate_key(&mut ZeroRng{}, "EnochRoot");
213//! let signer = StandardSigner::new(&skey).unwrap();
214//! n.add_sigs(&[&signer]).unwrap();
215//!
216//! let got = n.to_bytes();
217//!
218//! let want = "If you think cryptography is the answer to your problem,\n\
219//!            then you don't know what your problem is.\n\
220//!            \n\
221//!            — PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n\
222//!            — EnochRoot rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ=\n";
223//!
224//! assert_eq!(got, want.as_bytes());
225//! ```
226
227use base64::prelude::*;
228use ed25519_dalek::{
229    Signer as Ed25519Signer, SigningKey as Ed25519SigningKey, Verifier as Ed25519Verifier,
230    VerifyingKey as Ed25519VerifyingKey,
231};
232use rand_core::CryptoRngCore;
233use sha2::{Digest, Sha256};
234use std::collections::{BTreeSet, HashMap};
235use thiserror::Error;
236
237const MAX_NOTE_SIZE: usize = 1_000_000;
238const MAX_NOTE_SIGNATURES: usize = 100;
239
240/// A Verifier verifies messages signed with a specific key.
241pub trait Verifier {
242    /// Returns the server name associated with the key.
243    /// The name must be non-empty and not have any Unicode spaces or pluses.
244    fn name(&self) -> &str;
245
246    /// Returns the key ID.
247    fn key_id(&self) -> u32;
248
249    /// Reports whether sig is a valid signature of msg.
250    fn verify(&self, msg: &[u8], sig: &[u8]) -> bool;
251}
252
253/// A Signer signs messages using a specific key.
254pub trait Signer {
255    /// Returns the server name associated with the key.
256    /// The name must be non-empty and not have any Unicode spaces or pluses.
257    fn name(&self) -> &str;
258
259    /// Returns the key ID.
260    fn key_id(&self) -> u32;
261
262    /// Returns a signature for the given message.
263    ///
264    /// # Errors
265    ///
266    /// Returns a [`signature::Error`] if signing fails.
267    fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, signature::Error>;
268}
269
270/// Computes the key ID for the given server name and encoded public key
271/// as RECOMMENDED at <https://c2sp.org/signed-note#signatures>.
272///
273/// # Panics
274///
275/// Panics if slice conversion fails, which should never happen.
276pub fn key_id(name: &str, key: &[u8]) -> u32 {
277    let mut hasher = Sha256::new();
278    hasher.update(name.as_bytes());
279    hasher.update(b"\n");
280    hasher.update(key);
281    let result = hasher.finalize();
282
283    u32::from_be_bytes(result[0..4].try_into().unwrap())
284}
285
286/// An error returned from the [`StandardVerifier::new`] function when
287/// constructing a [`StandardVerifier`] from an encoded verifier key.
288#[derive(Error, Debug)]
289pub enum VerifierError {
290    #[error("malformed verifier key")]
291    Format,
292    #[error("unknown verifier algorithm")]
293    Alg,
294    #[error("invalid verifier ID")]
295    Id,
296}
297
298const ALG_ED25519: u8 = 1;
299
300// Reports whether name is valid according to <https://c2sp.org/signed-note#format>.
301// It must be non-empty and not have any Unicode spaces or pluses.
302pub fn is_key_name_valid(name: &str) -> bool {
303    !(name.is_empty() || name.chars().any(char::is_whitespace) || name.contains('+'))
304}
305
306/// [`StandardVerifier`] is a trivial Verifier implementation.
307#[derive(Clone)]
308pub struct StandardVerifier {
309    name: String,
310    id: u32,
311    verifying_key: Ed25519VerifyingKey,
312}
313
314impl Verifier for StandardVerifier {
315    fn name(&self) -> &str {
316        &self.name
317    }
318    fn key_id(&self) -> u32 {
319        self.id
320    }
321    fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
322        let sig_bytes: [u8; ed25519_dalek::SIGNATURE_LENGTH] = match sig.try_into() {
323            Ok(ok) => ok,
324            Err(_) => return false,
325        };
326        self.verifying_key
327            .verify(msg, &ed25519_dalek::Signature::from_bytes(&sig_bytes))
328            .is_ok()
329    }
330}
331
332impl StandardVerifier {
333    /// Construct a new [Verifier] from an encoded verifier key.
334    ///
335    /// # Errors
336    ///
337    /// Returns a [`VerifierError`] if `vkey` is malformed or otherwise invalid.
338    pub fn new(vkey: &str) -> Result<Self, VerifierError> {
339        let (name, vkey) = vkey.split_once('+').ok_or(VerifierError::Format)?;
340        let (id16, key64) = vkey.split_once('+').ok_or(VerifierError::Format)?;
341
342        let id = u32::from_str_radix(id16, 16).map_err(|_| VerifierError::Format)?;
343        let key = BASE64_STANDARD
344            .decode(key64)
345            .map_err(|_| VerifierError::Format)?;
346
347        if id16.len() != 8 || !is_key_name_valid(name) || key.is_empty() {
348            return Err(VerifierError::Format);
349        }
350
351        if id != key_id(name, &key) {
352            return Err(VerifierError::Id);
353        }
354
355        let alg = key[0];
356        let key = &key[1..];
357        match alg {
358            ALG_ED25519 => {
359                let key_bytes: &[u8; ed25519_dalek::PUBLIC_KEY_LENGTH] =
360                    &key.try_into().map_err(|_| VerifierError::Format)?;
361                let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(key_bytes)
362                    .map_err(|_| VerifierError::Format)?;
363                Ok(Self {
364                    name: name.to_owned(),
365                    id,
366                    verifying_key,
367                })
368            }
369            _ => Err(VerifierError::Alg),
370        }
371    }
372}
373
374/// An error returned from the [`StandardSigner::new`] function when
375/// constructing a [`StandardSigner`] from an encoded signer key.
376#[derive(Error, Debug)]
377pub enum SignerError {
378    #[error("malformed verifier key")]
379    Format,
380    #[error("unknown verifier algorithm")]
381    Alg,
382    #[error("invalid verifier ID")]
383    Id,
384}
385
386/// [`StandardSigner`] is a trivial Signer implementation.
387#[derive(Clone)]
388pub struct StandardSigner {
389    name: String,
390    id: u32,
391    signing_key: Ed25519SigningKey,
392}
393
394impl Signer for StandardSigner {
395    fn name(&self) -> &str {
396        &self.name
397    }
398    fn key_id(&self) -> u32 {
399        self.id
400    }
401    fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, signature::Error> {
402        let sig = self.signing_key.try_sign(msg)?;
403        Ok(sig.to_vec())
404    }
405}
406
407impl StandardSigner {
408    /// Construct a new [Signer] from an encoded signer key.
409    ///
410    /// # Errors
411    ///
412    /// Returns a [`SignerError`] if `skey` is malformed or otherwise invalid.
413    pub fn new(skey: &str) -> Result<Self, SignerError> {
414        let (priv1, skey) = skey.split_once('+').ok_or(SignerError::Format)?;
415        let (priv2, skey) = skey.split_once('+').ok_or(SignerError::Format)?;
416        let (name, skey) = skey.split_once('+').ok_or(SignerError::Format)?;
417        let (id16, key64) = skey.split_once('+').ok_or(SignerError::Format)?;
418
419        let id = u32::from_str_radix(id16, 16).map_err(|_| SignerError::Format)?;
420        let key = BASE64_STANDARD
421            .decode(key64)
422            .map_err(|_| SignerError::Format)?;
423
424        if priv1 != "PRIVATE"
425            || priv2 != "KEY"
426            || id16.len() != 8
427            || !is_key_name_valid(name)
428            || key.is_empty()
429        {
430            return Err(SignerError::Format);
431        }
432
433        // Note: id is the hash of the public key and we have the private key.
434        // Must verify id after deriving public key.
435
436        let signer: StandardSigner;
437        let pubkey: Vec<u8>;
438
439        let alg = key[0];
440        let key = &key[1..];
441        match alg {
442            ALG_ED25519 => {
443                let signing_key =
444                    ed25519_dalek::SigningKey::try_from(key).map_err(|_| SignerError::Format)?;
445
446                pubkey = [
447                    &[ALG_ED25519],
448                    ed25519_dalek::VerifyingKey::from(&signing_key)
449                        .to_bytes()
450                        .as_slice(),
451                ]
452                .concat();
453
454                signer = Self {
455                    name: name.to_owned(),
456                    id,
457                    signing_key,
458                };
459            }
460            _ => {
461                return Err(SignerError::Alg);
462            }
463        }
464
465        if id != key_id(name, &pubkey) {
466            return Err(SignerError::Id);
467        }
468
469        Ok(signer)
470    }
471}
472
473/// Generates a signer and verifier key pair for a named server.
474/// The signer key skey is private and must be kept secret.
475pub fn generate_key<R: CryptoRngCore + ?Sized>(csprng: &mut R, name: &str) -> (String, String) {
476    let signing_key = ed25519_dalek::SigningKey::generate(csprng);
477
478    let pubkey = [
479        &[ALG_ED25519],
480        signing_key.verifying_key().to_bytes().as_slice(),
481    ]
482    .concat();
483    let privkey = [&[ALG_ED25519], signing_key.to_bytes().as_slice()].concat();
484    let skey = format!(
485        "PRIVATE+KEY+{}+{:08x}+{}",
486        name,
487        key_id(name, &pubkey),
488        BASE64_STANDARD.encode(privkey)
489    );
490    let vkey = new_ed25519_verifier_key(name, &signing_key.verifying_key());
491
492    (skey, vkey)
493}
494
495/// Returns an encoded verifier key using the given name and Ed25519 public key.
496pub fn new_ed25519_verifier_key(name: &str, key: &ed25519_dalek::VerifyingKey) -> String {
497    let pubkey = [&[ALG_ED25519], key.to_bytes().as_slice()].concat();
498    format!(
499        "{}+{:08x}+{}",
500        name,
501        key_id(name, &pubkey),
502        BASE64_STANDARD.encode(&pubkey)
503    )
504}
505
506/// [`Verifiers`] is a collection of known verifier keys.
507pub trait Verifiers {
508    /// Returns the [`Verifier`] associated with the key identified by the name and
509    /// id.
510    ///
511    /// # Errors
512    ///
513    /// If the (name, id) pair is unknown, return a [`VerificationError::UnknownKey`].
514    fn verifier(&self, name: &str, id: u32) -> Result<&dyn Verifier, VerificationError>;
515}
516
517type VerifierMap = HashMap<(String, u32), Vec<Box<dyn Verifier>>>;
518
519/// [`VerifierList`] is a [Verifiers] implementation that uses the given list of verifiers.
520pub struct VerifierList {
521    map: VerifierMap,
522}
523
524/// An error returned from a Verifier when verifying a signature.
525#[derive(Error, Debug)]
526pub enum VerificationError {
527    #[error("unknown key {name}+{id:08x}")]
528    UnknownKey { name: String, id: u32 },
529    #[error("ambiguous key {name}+{id:08x}")]
530    AmbiguousKey { name: String, id: u32 },
531}
532
533impl Verifiers for VerifierList {
534    fn verifier(&self, name: &str, id: u32) -> Result<&dyn Verifier, VerificationError> {
535        match self.map.get(&(name.to_owned(), id)) {
536            Some(verifiers) => {
537                if verifiers.len() > 1 {
538                    return Err(VerificationError::AmbiguousKey {
539                        name: name.to_owned(),
540                        id,
541                    });
542                }
543                Ok(&*verifiers[0])
544            }
545            None => Err(VerificationError::UnknownKey {
546                name: name.to_owned(),
547                id,
548            }),
549        }
550    }
551}
552
553impl VerifierList {
554    /// Returns a [Verifiers] implementation that uses the given list of verifiers.
555    pub fn new(list: Vec<Box<dyn Verifier>>) -> Self {
556        let mut map: VerifierMap = HashMap::new();
557        for verifier in list {
558            map.entry((verifier.name().to_owned(), verifier.key_id()))
559                .or_default()
560                .push(verifier);
561        }
562        VerifierList { map }
563    }
564}
565
566/// A Note is a text and signatures.
567#[derive(Debug, PartialEq)]
568pub struct Note {
569    /// Text of note. Guaranteed to be well-formed.
570    text: Vec<u8>,
571    /// Signatures on note. Guaranteed to be well-formed.
572    sigs: Vec<Signature>,
573}
574
575/// A Signature is a single signature found in a note.
576#[derive(Debug, PartialEq, Clone)]
577pub struct Signature {
578    /// Name for the key that generated the signature.
579    name: String,
580    /// Key ID for the key that generated the signature.
581    id: u32,
582    /// The signature bytes.
583    sig: Vec<u8>,
584}
585
586impl Signature {
587    /// Returns a new signature from the given name and base64-encoded signature string.
588    ///
589    /// # Errors
590    ///
591    /// Returns [`NoteError::MalformedNote`] if the name is invalid according to [`is_key_name_valid`].
592    ///
593    pub fn new(name: String, id: u32, sig: Vec<u8>) -> Result<Self, NoteError> {
594        if !is_key_name_valid(&name) {
595            return Err(NoteError::MalformedNote);
596        }
597        Ok(Self { name, id, sig })
598    }
599
600    /// Parse a signature line into a [Signature].
601    ///
602    /// # Errors
603    ///
604    /// Returns a [`NoteError`] if the note is malformed.
605    ///
606    /// # Panics
607    ///
608    /// Panics if slice conversion fails, which should never happen.
609    pub fn from_bytes(line: &[u8]) -> Result<Self, NoteError> {
610        let line = std::str::from_utf8(line).map_err(|_| NoteError::MalformedNote)?;
611        let line = line.strip_prefix("— ").ok_or(NoteError::MalformedNote)?;
612        let (name, b64) = line.split_once(' ').ok_or(NoteError::MalformedNote)?;
613        let sig = BASE64_STANDARD
614            .decode(b64)
615            .map_err(|_| NoteError::MalformedNote)?;
616        if b64.is_empty() || sig.len() < 5 {
617            return Err(NoteError::MalformedNote);
618        }
619        let id = u32::from_be_bytes(sig[..4].try_into().unwrap());
620        let sig = &sig[4..];
621        Signature::new(name.to_owned(), id, sig.to_owned())
622    }
623
624    /// Return a signature's name.
625    pub fn name(&self) -> &str {
626        &self.name
627    }
628
629    /// Return a signature's key ID.
630    pub fn id(&self) -> u32 {
631        self.id
632    }
633
634    /// Return the signature bytes.
635    pub fn signature(&self) -> &[u8] {
636        &self.sig
637    }
638
639    /// Encode a signature for inclusion in a note.
640    pub fn to_bytes(&self) -> Vec<u8> {
641        let hbuf = self.id.to_be_bytes();
642        let base64 = BASE64_STANDARD.encode([&hbuf, self.sig.as_slice()].concat());
643        format!("— {} {}\n", self.name, base64).into()
644    }
645}
646
647/// An error returned for issues parsing, verifying, or adding signatures to notes.
648#[derive(Error, Debug)]
649pub enum NoteError {
650    #[error("malformed note")]
651    MalformedNote,
652    #[error("invalid signer")]
653    InvalidSigner,
654    #[error("invalid signature for key {name}+{id:08x}")]
655    InvalidSignature { name: String, id: u32 },
656    #[error("verifier name or id doesn't match signature")]
657    MismatchedVerifier,
658    #[error("note has no verifiable signatures")]
659    UnverifiedNote,
660    #[error(transparent)]
661    VerificationError(#[from] VerificationError),
662    #[error(transparent)]
663    SignatureError(#[from] signature::Error),
664}
665
666impl Note {
667    /// Returns a new note, ensuring that the text is well-formed, and
668    /// appending the provided signatures.
669    ///
670    /// # Errors
671    ///
672    /// Returns a [`NoteError::MalformedNote`] if the text is larger than
673    /// we're willing to parse, cannot be decoded as UTF-8, or contains
674    /// any non-newline ASCII control characters.
675    pub fn new(text: &[u8], existing_sigs: &[Signature]) -> Result<Self, NoteError> {
676        // Set some upper limit on what we're willing to process.
677        if text.len() > MAX_NOTE_SIZE {
678            return Err(NoteError::MalformedNote);
679        }
680        // Must have valid UTF-8 with no non-newline ASCII control characters.
681        let text_str = std::str::from_utf8(text).map_err(|_| NoteError::MalformedNote)?;
682        for ch in text_str.chars() {
683            // Validation checks
684            if ch < '\u{0020}' && ch != '\n' {
685                return Err(NoteError::MalformedNote);
686            }
687        }
688        if !text_str.ends_with('\n') {
689            return Err(NoteError::MalformedNote);
690        }
691
692        Ok(Self {
693            text: text.to_owned(),
694            sigs: existing_sigs.into(),
695        })
696    }
697
698    /// Parses the message msg into a note, returning a [`NoteError`] if any of the text or signatures are malformed.
699    ///
700    /// # Errors
701    ///
702    /// Returns a [`NoteError::MalformedNote`] if the message is larger than
703    /// we're willing to parse, cannot be decoded as UTF-8, contains
704    /// any non-newline ASCII control characters, or is otherwise invalid.
705    pub fn from_bytes(msg: &[u8]) -> Result<Self, NoteError> {
706        // Set some upper limit on what we're willing to process.
707        if msg.len() > MAX_NOTE_SIZE {
708            return Err(NoteError::MalformedNote);
709        }
710        // Must have valid UTF-8 (implied by &str type) with no non-newline ASCII control characters.
711        let msg_str = std::str::from_utf8(msg).map_err(|_| NoteError::MalformedNote)?;
712        for ch in msg_str.chars() {
713            // Validation checks
714            if ch < '\u{0020}' && ch != '\n' {
715                return Err(NoteError::MalformedNote);
716            }
717        }
718
719        // Must end with signature block preceded by blank line.
720        let (text, sigs) = msg_str
721            .rsplit_once("\n\n")
722            .ok_or(NoteError::MalformedNote)?;
723
724        // Add back the newline at the end of the text block.
725        let text = format!("{text}\n");
726
727        let sigs = sigs.strip_suffix("\n").ok_or(NoteError::MalformedNote)?;
728
729        let mut parsed_sigs: Vec<Signature> = Vec::new();
730        let mut num_sig = 0;
731
732        for line in sigs.split('\n') {
733            let sig = Signature::from_bytes(line.as_bytes())?;
734            num_sig += 1;
735            if num_sig > MAX_NOTE_SIGNATURES {
736                return Err(NoteError::MalformedNote);
737            }
738            parsed_sigs.push(sig);
739        }
740
741        Self::new(text.as_bytes(), &parsed_sigs)
742    }
743
744    /// Checks signatures on the note for those from known verifiers.
745    ///
746    /// For each signature in the message, [`Note::verify`] calls known.verifier to find a verifier.
747    /// If known.verifier returns a verifier and the verifier accepts the signature,
748    /// [`Note::verify`] includes the signature in the returned list of verified signatures.
749    /// If known.verifier returns a [`VerificationError::UnknownKey`],
750    /// [`Note::verify`] includes the signature in the returned list of unverified signatures.
751    ///
752    /// # Errors
753    ///
754    /// If known.verifier returns a verifier but the verifier rejects the signature,
755    /// [`Note::verify`] returns a [`NoteError::InvalidSignature`].
756    /// If known.verifier returns any other error, [`Note::verify`] returns that error.
757    ///
758    /// If no known verifier has signed an otherwise valid note,
759    /// [`Note::verify`] returns an [`NoteError::UnverifiedNote`].
760    pub fn verify(
761        &self,
762        known: &impl Verifiers,
763    ) -> Result<(Vec<Signature>, Vec<Signature>), NoteError> {
764        let mut verified_sigs = Vec::new();
765        let mut unverified_sigs = Vec::new();
766        let mut seen = BTreeSet::new();
767        let mut seen_unverified = BTreeSet::new();
768        for sig in &self.sigs {
769            match known.verifier(&sig.name, sig.id) {
770                Ok(verifier) => {
771                    if verifier.name() != sig.name || verifier.key_id() != sig.id {
772                        return Err(NoteError::MismatchedVerifier);
773                    }
774                    if seen.contains(&(&sig.name, sig.id)) {
775                        continue;
776                    }
777                    seen.insert((&sig.name, sig.id));
778                    if !verifier.verify(&self.text, &sig.sig) {
779                        return Err(NoteError::InvalidSignature {
780                            name: sig.name.clone(),
781                            id: sig.id,
782                        });
783                    }
784                    verified_sigs.push(sig.clone());
785                }
786                Err(VerificationError::UnknownKey { name: _, id: _ }) => {
787                    // Drop repeated identical unverified signatures.
788                    if seen_unverified.contains(&sig.to_bytes()) {
789                        continue;
790                    }
791                    seen_unverified.insert(sig.to_bytes());
792                    unverified_sigs.push(sig.clone());
793                }
794                Err(e) => return Err(e.into()),
795            }
796        }
797        if verified_sigs.is_empty() {
798            return Err(NoteError::UnverifiedNote);
799        }
800        Ok((verified_sigs, unverified_sigs))
801    }
802
803    /// Signs the note with the given signers. The new signatures from
804    /// signers are listed in the encoded message after the existing
805    /// signatures already present in n.sigs. If any signer uses the same key
806    /// as an existing signature, the existing signature is removed.
807    ///
808    /// # Errors
809    ///
810    /// Returns an error if any signers have invalid names.
811    /// Names must be non-empty and not have any Unicode spaces or pluses.
812    pub fn add_sigs(&mut self, signers: &[&dyn Signer]) -> Result<(), NoteError> {
813        // Prepare signatures and populate 'have' set.
814        let mut new_sigs = Vec::new();
815        let mut have = BTreeSet::new();
816        for s in signers {
817            let name = s.name();
818            let id = s.key_id();
819            have.insert((name, id));
820            if !is_key_name_valid(name) {
821                return Err(NoteError::InvalidSigner);
822            }
823            let sig = s.sign(&self.text)?;
824            new_sigs.push(Signature::new(name.to_owned(), id, sig)?);
825        }
826
827        // Remove existing signatures that have been replaced by new ones.
828        self.sigs.retain(|sig| !have.contains(&(&sig.name, sig.id)));
829
830        // Add new signatures at the end.
831        self.sigs.extend(new_sigs);
832
833        Ok(())
834    }
835
836    /// Returns a well-formed signed note.
837    pub fn to_bytes(&self) -> Vec<u8> {
838        let mut buf = self.text.clone();
839        buf.push(b'\n');
840        for sig in &self.sigs {
841            buf.extend(&sig.to_bytes());
842        }
843        buf
844    }
845
846    /// Returns the note's text.
847    pub fn text(&self) -> &[u8] {
848        &self.text
849    }
850}
851
852#[cfg(test)]
853mod tests {
854
855    use super::*;
856    use rand::rngs::OsRng;
857    static NAME: &str = "EnochRoot";
858
859    fn test_signer_and_verifier(name: &str, signer: &dyn Signer, verifier: &dyn Verifier) {
860        assert_eq!(&name, &signer.name());
861        assert_eq!(&name, &verifier.name());
862        assert_eq!(signer.key_id(), verifier.key_id());
863
864        let msg: &[u8] = b"hi";
865        let sig = signer.sign(msg).unwrap();
866        assert!(verifier.verify(msg, &sig));
867    }
868
869    #[test]
870    fn test_generate_key() {
871        let (skey, vkey) = generate_key(&mut OsRng, NAME);
872
873        let signer = StandardSigner::new(&skey).unwrap();
874        let verifier = StandardVerifier::new(&vkey).unwrap();
875
876        test_signer_and_verifier(NAME, &signer, &verifier);
877    }
878
879    #[test]
880    fn test_from_ed25519() {
881        let signing_key = ed25519_dalek::SigningKey::generate(&mut OsRng);
882
883        let pubkey = [
884            &[ALG_ED25519],
885            signing_key.verifying_key().to_bytes().as_slice(),
886        ]
887        .concat();
888        let id = key_id(NAME, &pubkey);
889
890        let vkey = new_ed25519_verifier_key(NAME, &signing_key.verifying_key());
891        let verifier = StandardVerifier::new(&vkey).unwrap();
892
893        let signer = StandardSigner {
894            name: NAME.to_owned(),
895            id,
896            signing_key,
897        };
898
899        test_signer_and_verifier(NAME, &signer, &verifier);
900    }
901
902    struct BadSigner {
903        s: Box<dyn Signer>,
904    }
905
906    impl Signer for BadSigner {
907        fn name(&self) -> &'static str {
908            "bad name"
909        }
910        fn key_id(&self) -> u32 {
911            self.s.key_id()
912        }
913        fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, signature::Error> {
914            self.s.sign(msg)
915        }
916    }
917
918    struct ErrSigner {
919        s: Box<dyn Signer>,
920    }
921
922    impl Signer for ErrSigner {
923        fn name(&self) -> &str {
924            self.s.name()
925        }
926        fn key_id(&self) -> u32 {
927            self.s.key_id()
928        }
929        fn sign(&self, _msg: &[u8]) -> Result<Vec<u8>, signature::Error> {
930            Err(signature::Error::new())
931        }
932    }
933
934    #[test]
935    fn test_sign() {
936        let skey = "PRIVATE+KEY+PeterNeumann+c74f20a3+AYEKFALVFGyNhPJEMzD1QIDr+Y7hfZx09iUvxdXHKDFz";
937        let text = b"If you think cryptography is the answer to your problem,\n\
938                    then you don't know what your problem is.\n";
939
940        let signer = StandardSigner::new(skey).unwrap();
941
942        let mut n = Note::new(text, &[]).unwrap();
943        n.add_sigs(&[&signer]).unwrap();
944        let want = "If you think cryptography is the answer to your problem,\n\
945                    then you don't know what your problem is.\n\
946                    \n\
947                    — PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n";
948
949        assert_eq!(n.to_bytes(), want.as_bytes());
950
951        // Check that existing signature is replaced by new one.
952        let mut n = Note::new(
953            text,
954            &[Signature::new("PeterNeumann".into(), 0xc74f_20a3, vec![]).unwrap()],
955        )
956        .unwrap();
957        n.add_sigs(&[&signer]).unwrap();
958        assert_eq!(n.to_bytes(), want.as_bytes());
959
960        // Check various bad inputs.
961
962        // Attempt to create note without terminating newline.
963        let err = Note::new(b"abc", &[]).unwrap_err();
964        assert!(matches!(err, NoteError::MalformedNote));
965
966        // Attempt to create signature with bad name.
967        let err = Signature::new("a+b".into(), 0, vec![]).unwrap_err();
968        assert!(matches!(err, NoteError::MalformedNote));
969
970        // Attempt to sign with bad signer.
971        let err = Note::new(text, &[])
972            .unwrap()
973            .add_sigs(&[&BadSigner {
974                s: Box::new(signer.clone()),
975            }])
976            .unwrap_err();
977        assert!(matches!(err, NoteError::InvalidSigner));
978
979        let err = Note::new(text, &[])
980            .unwrap()
981            .add_sigs(&[&ErrSigner {
982                s: Box::new(signer.clone()),
983            }])
984            .unwrap_err();
985        assert!(matches!(err, NoteError::SignatureError(_)));
986    }
987
988    struct FixedVerifier {
989        v: Box<dyn Verifier>,
990    }
991
992    impl Verifiers for FixedVerifier {
993        fn verifier(&self, _name: &str, _id: u32) -> Result<&dyn Verifier, VerificationError> {
994            Ok(&*self.v)
995        }
996    }
997
998    #[test]
999    fn test_open() {
1000        let peter_key = "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW";
1001        let peter_verifier = StandardVerifier::new(peter_key).unwrap();
1002
1003        let enoch_key = "EnochRoot+af0cfe78+ATtqJ7zOtqQtYqOo0CpvDXNlMhV3HeJDpjrASKGLWdop";
1004        let enoch_verifier = StandardVerifier::new(enoch_key).unwrap();
1005
1006        let text = "If you think cryptography is the answer to your problem,\n\
1007                    then you don't know what your problem is.\n";
1008        let peter_sig = "— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n";
1009        let enoch_sig = "— EnochRoot rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ=\n";
1010
1011        let peter = Signature::from_bytes(peter_sig.trim_end().as_bytes()).unwrap();
1012        let enoch = Signature::from_bytes(enoch_sig.trim_end().as_bytes()).unwrap();
1013
1014        // Check one signature verified, one not.
1015        let n = Note::from_bytes(format!("{text}\n{peter_sig}{enoch_sig}").as_bytes()).unwrap();
1016        let (verified_sigs, unverified_sigs) = n
1017            .verify(&VerifierList::new(vec![Box::new(peter_verifier.clone())]))
1018            .unwrap();
1019        assert_eq!(n.text(), text.as_bytes());
1020        assert_eq!(verified_sigs, vec![peter.clone()]);
1021        assert_eq!(unverified_sigs, vec![enoch.clone()]);
1022
1023        // Check both verified.
1024        let (verified_sigs, unverified_sigs) = n
1025            .verify(&VerifierList::new(vec![
1026                Box::new(peter_verifier.clone()),
1027                Box::new(enoch_verifier.clone()),
1028            ]))
1029            .unwrap();
1030        assert_eq!(verified_sigs, vec![peter.clone(), enoch.clone()]);
1031        assert!(unverified_sigs.is_empty());
1032
1033        // Check both unverified.
1034        let err = n.verify(&VerifierList::new(vec![])).unwrap_err();
1035        assert!(matches!(err, NoteError::UnverifiedNote));
1036
1037        // Check duplicated verifier.
1038        let err = Note::from_bytes(format!("{text}\n{enoch_sig}").as_bytes())
1039            .unwrap()
1040            .verify(&VerifierList::new(vec![
1041                Box::new(enoch_verifier.clone()),
1042                Box::new(peter_verifier.clone()),
1043                Box::new(enoch_verifier.clone()),
1044            ]))
1045            .unwrap_err();
1046        assert_eq!(err.to_string(), "ambiguous key EnochRoot+af0cfe78");
1047
1048        // Check unused duplicated verifier.
1049        let _ = Note::from_bytes(format!("{text}\n{peter_sig}").as_bytes())
1050            .unwrap()
1051            .verify(&VerifierList::new(vec![
1052                Box::new(enoch_verifier.clone()),
1053                Box::new(peter_verifier.clone()),
1054                Box::new(enoch_verifier.clone()),
1055            ]))
1056            .unwrap();
1057
1058        // Check too many signatures.
1059        let err = Note::from_bytes(format!("{}\n{}", text, peter_sig.repeat(101)).as_bytes())
1060            .unwrap_err();
1061        assert!(matches!(err, NoteError::MalformedNote));
1062
1063        // Invalid signature.
1064        let invalid_sig = format!("{}ABCD{}", &peter_sig[..60], &peter_sig[60..]);
1065        let err = Note::from_bytes(format!("{text}\n{invalid_sig}").as_bytes())
1066            .unwrap()
1067            .verify(&VerifierList::new(vec![Box::new(peter_verifier.clone())]))
1068            .unwrap_err();
1069        assert_eq!(
1070            err.to_string(),
1071            "invalid signature for key PeterNeumann+c74f20a3"
1072        );
1073
1074        // Duplicated verified and unverified signatures.
1075        let enoch_abcd = Signature::from_bytes("— EnochRoot rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5nABCD2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ="
1076            .as_bytes(),
1077        )
1078        .unwrap();
1079        let sigs = format!(
1080            "{peter_sig}{peter_sig}{peter_sig}{enoch_sig}{}ABCD{}",
1081            &enoch_sig[..60],
1082            &enoch_sig[60..]
1083        );
1084        let n = Note::from_bytes(format!("{text}\n{sigs}").as_bytes()).unwrap();
1085        let (verified_sigs, unverified_sigs) = n
1086            .verify(&VerifierList::new(vec![Box::new(peter_verifier.clone())]))
1087            .unwrap();
1088        assert_eq!(verified_sigs, vec![peter.clone()]);
1089        assert_eq!(unverified_sigs, vec![enoch.clone(), enoch_abcd.clone()]);
1090
1091        // Invalid encoded message syntax.
1092        let bad_msgs: Vec<Vec<u8>> = vec![
1093            text.as_bytes().to_vec(),
1094            format!("\n{text}").as_bytes().to_vec(),
1095            format!("{text}\n{}", &peter_sig[..peter_sig.len() - 1]).as_bytes().to_vec(),
1096            format!("\x01{text}\n{peter_sig}").as_bytes().to_vec(),
1097            [&[0xff], format!("{text}\n{peter_sig}").as_bytes()].concat(),
1098            format!("{text}\n— Bad Name x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=").as_bytes().to_vec(),
1099        ];
1100
1101        for msg in bad_msgs {
1102            let err = Note::from_bytes(&msg).unwrap_err();
1103            assert!(matches!(err, NoteError::MalformedNote));
1104        }
1105
1106        // Verifiers returns a Verifier for the wrong name or ID.
1107        let misnamed_sig = peter_sig.replace("PeterNeumann", "CarmenSandiego");
1108        let err = Note::from_bytes(format!("{text}\n{misnamed_sig}").as_bytes())
1109            .unwrap()
1110            .verify(&FixedVerifier {
1111                v: Box::new(peter_verifier.clone()),
1112            })
1113            .unwrap_err();
1114        assert!(matches!(err, NoteError::MismatchedVerifier));
1115
1116        let wrong_id = peter_sig.replace("x08g", "xxxx");
1117        let err = Note::from_bytes(format!("{text}\n{wrong_id}").as_bytes())
1118            .unwrap()
1119            .verify(&FixedVerifier {
1120                v: Box::new(peter_verifier.clone()),
1121            })
1122            .unwrap_err();
1123        assert!(matches!(err, NoteError::MismatchedVerifier));
1124    }
1125}