Skip to main content

ojak_sig/
lib.rs

1//! Signatures and proofs: HTTP Signatures (draft-cavage, and RFC 9421 with
2//! RSA or Ed25519) and the policy an inbox holds them to, FEP-8b32 Object
3//! Integrity Proofs (`eddsa-jcs-2022`, and the post-quantum
4//! `mldsa44-jcs-2024`), Linked Data Signatures (`RsaSignature2017`), and
5//! `did:key`.
6//!
7//! They do no I/O: callers supply byte slices, header pairs, keys, the time
8//! and, to make a key, randomness. Ojak fetches keys and sends requests with
9//! them, and re-exports this crate as `ojak::sig`.
10
11extern crate alloc;
12
13use alloc::string::String;
14use alloc::sync::Arc;
15use core::fmt;
16
17pub mod did;
18pub mod digest;
19pub mod integrity;
20pub mod linked_data;
21pub mod rfc9421;
22pub mod signature;
23pub mod verification;
24
25/// An RSA private key, parsed once; what a [`SenderKey`] signs with.
26pub use signature::PrivateKey;
27
28/// The randomness keys are made with, which the caller supplies: the
29/// system's (`rand::rngs::SysRng` behind `rand_core::UnwrapErr`, or
30/// `rand::rng()`), or a device's own.
31pub use rand_core::CryptoRng;
32
33/// An HTTP signature scheme.
34#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
35pub enum Scheme {
36    /// draft-cavage-http-signatures-12, which most of the network verifies.
37    DraftCavage,
38    /// RFC 9421 HTTP Message Signatures.
39    Rfc9421,
40}
41
42impl Scheme {
43    /// The scheme a refused request is retried in.
44    #[must_use]
45    pub fn other(self) -> Self {
46        match self {
47            Self::DraftCavage => Self::Rfc9421,
48            Self::Rfc9421 => Self::DraftCavage,
49        }
50    }
51}
52
53/// The key an actor signs deliveries with.
54#[derive(Clone, Debug)]
55pub struct SenderKey {
56    /// The key's IRI, as its actor document publishes it.
57    pub key_id: String,
58    pub private_key: Arc<PrivateKey>,
59}
60
61/// Why something could not be signed or verified.
62#[derive(Clone, Debug, Eq, PartialEq)]
63#[non_exhaustive]
64pub enum Error {
65    /// A key that cannot be read or made: a PEM, a Multikey, or a DID URL.
66    Key(String),
67    /// A signature, proof, header or URL that cannot be read.
68    Malformed(String),
69    /// Something a signature covers that the request does not carry.
70    Missing(String),
71    /// An algorithm, cryptosuite or component this crate does not know.
72    Unsupported(String),
73    /// A key of one kind, offered for a signature or proof of another.
74    WrongKey(String),
75    /// The body is not the one its digest describes.
76    DigestMismatch,
77    /// The signature or proof does not verify.
78    Invalid,
79}
80
81impl fmt::Display for Error {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        match self {
84            Self::Key(why) => write!(f, "unusable key: {why}"),
85            Self::Malformed(why) => write!(f, "malformed: {why}"),
86            Self::Missing(what) => write!(f, "{what} is covered but was not sent"),
87            Self::Unsupported(what) => write!(f, "unsupported {what}"),
88            Self::WrongKey(why) => write!(f, "wrong key: {why}"),
89            Self::DigestMismatch => f.write_str("the body does not match its digest"),
90            Self::Invalid => f.write_str("the signature does not verify"),
91        }
92    }
93}
94
95impl core::error::Error for Error {}