Skip to main content

basil_cose/
lib.rs

1// SPDX-FileCopyrightText: 2026 OpenBasil Contributors
2//
3// SPDX-License-Identifier: Apache-2.0
4
5//! # basil-cose
6//!
7//! A strict, deterministic COSE (RFC 9052/9053) profile for basil's sealed
8//! invocations: broker-free and publishable, shared by the basil broker,
9//! the basil client, and some basil clients.
10//!
11//! Three constructions:
12//!
13//! - **Signed**: a bare `COSE_Sign1` ([`build_signed`] / [`verify_signed`]).
14//! - **Sealed**: a `COSE_Sign1` over an embedded tagged `COSE_Encrypt`
15//!   ([`build_sealed`] / [`verify_sealed`], then [`VerifiedSealed::open`]).
16//! - **Seal-only**: a bare `COSE_Encrypt` ([`build_encrypted`] /
17//!   [`decode_encrypted`], then [`EncryptedMessage::open`]).
18//!
19//! Algorithms: `EdDSA` (-8) or `ES256` (-7, ECDSA P-256 + SHA-256) signatures,
20//! ECDH-ES + HKDF-256 (-25) key agreement with X25519, and A256GCM (3) or
21//! `ChaCha20`-`Poly1305` (24) content encryption. Key material stays behind
22//! the [`Signer`], [`Verifier`], and [`Recipient`] traits; nonces and
23//! ephemerals are always generated by the library. `ES256` signing is
24//! deterministic (RFC 6979), so both signature algorithms re-sign
25//! byte-identically.
26//!
27//! ## Strictness
28//!
29//! Every decode entry point enforces the profile: tagged top-level
30//! structures only, definite lengths, RFC 8949 §4.2 deterministic encodings
31//! (checked by re-encoding the parsed message and comparing bytes, on every
32//! decode, release builds included), closed algorithm/label allow-sets with
33//! no `Unknown` arms, `crit` coverage of every profile label, claims only in
34//! protected headers, and exactly one recipient.
35//!
36//! ## Claims
37//!
38//! Claims ride in the protected header as a CWT map (header 15) plus basil
39//! private labels (`-70001..=-70005`, see [`label`]). [`ValidationParams`]
40//! parameterizes skew/TTL/audience bounds; `now` is injected, never sampled.
41//!
42//! The crate is `no_std` + `alloc` and obtains production randomness through
43//! `getrandom`.
44
45#![no_std]
46#![cfg_attr(
47    test,
48    allow(clippy::unwrap_used, clippy::indexing_slicing, clippy::panic)
49)]
50// AFIT is a deliberate design decision (approved design §4.5/§7.1): traits
51// are consumed through generics, and local implementations are synchronous.
52// Send bounds, when a consumer needs them, are added at the consumer's
53// generic bound site, which is also why `future_not_send` is allowed: the
54// entry-point futures are generic over unbounded `Signer`/`Verifier`/
55// `Recipient` implementations, and imposing `Send` here would forbid
56// legitimate single-threaded (e.g. WASM) implementors.
57#![allow(async_fn_in_trait)]
58#![allow(clippy::future_not_send)]
59
60extern crate alloc;
61
62mod alg;
63mod claims;
64mod codec;
65mod encrypt;
66mod error;
67mod hash;
68mod kdf;
69mod keys;
70pub mod label;
71mod seal;
72mod sign;
73#[cfg(test)]
74mod tests;
75mod traits;
76mod types;
77
78pub use alg::{ContentAlgorithm, KeyAgreementAlgorithm, SignatureAlgorithm};
79pub use claims::{Claims, MessageRole, ProtectedHeaders, ValidationParams};
80pub use encrypt::{EncryptParams, EncryptedMessage, Opened, build_encrypted, decode_encrypted};
81#[cfg(feature = "fixtures")]
82pub use encrypt::{SealParts, build_encrypted_with_parts};
83pub use error::{
84    BuildError, ClaimsError, DecodeError, OpenError, ProfileError, SignError, VerifyError,
85};
86pub use hash::{RequestHash, request_hash};
87pub use kdf::{KdfParties, PartyIdentity};
88pub use keys::{
89    Ed25519Signer, Ed25519Verifier, Es256Signer, KeyError, KeyLengthError, P256Verifier,
90    X25519Recipient, X25519RecipientPublic,
91};
92#[cfg(feature = "fixtures")]
93pub use seal::build_sealed_with_parts;
94pub use seal::{SealParams, VerifiedSealed, VerifySealedParams, build_sealed, verify_sealed};
95pub use sign::{
96    SignParams, VerifiedSigned, VerifySignedParams, build_signed, build_signed_with_headers,
97    verify_signed,
98};
99pub use traits::{OpenRequest, Recipient, Signer, Verifier};
100pub use types::{
101    ContentType, CoseBytes, ExternalAad, KeyId, MessageId, ResponseSubject, SealedAad, Signature,
102    Subject, UnixTime,
103};
104
105// Re-exported so trait implementors and callers name the same zeroizing
106// wrapper this crate's APIs use.
107pub use zeroize::Zeroizing;