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 {}