1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// This is free and unencumbered software released into the public domain.
//! Shared HTTP integrity for clients and servers.
//!
//! SHA-256 is the sole digest algorithm (RFC 9530). With `std`, this crate
//! implements RFC 9421 Ed25519 signatures using the protocol crate's keys,
//! HTTP message-component canonicalization, and frame-preserving body adapters.
//! Without `std`, SHA-256 hashing and digest-field encoding remain available.
//!
//! Signature processing operates on an explicit message context, independently
//! of HTTP versions and body types. Servers supply the externally visible target
//! URI, including trusted proxy routing context, rather than guessing a scheme
//! from an incoming origin-form URI. See `Message` and `SignatureInput`.
//!
//! Streaming bodies deliver provisional data and verify at EOF. Callers must
//! consume the entire stream and observe its terminal result before treating
//! the message as authenticated. Dropping a body early never verifies it.
//! Application authorization and atomic nonce-replay rejection follow successful
//! signature AND body verification; freshness checks alone do not prevent replay.
//!
//! # Buffered requests
//!
//! ```no_run
//! # #[cfg(feature = "std")] {
//! use asimov_http::{
//! SecretKey, SignatureInput, SignatureParams, Signer, VerificationPolicy,
//! REQUEST_SIGNATURE_TAG, body::sign_request, http::Request,
//! };
//!
//! let key = SecretKey::generate(); // Or load the protocol identity from keyring.
//! let input = SignatureInput::new(
//! VerificationPolicy::request().required_components,
//! SignatureParams::fresh(&key.public(), REQUEST_SIGNATURE_TAG)?,
//! )?;
//! let signer = Signer::new(key, "asimov", input)?;
//! let target = "https://example.com/fetch";
//! let mut request = Request::post(target)
//! .header("authorization", "Bearer token")
//! .header("accept", "application/jsonl")
//! .header("content-type", "application/json")
//! .body(br#"{"urls":["example:"]}"#.as_slice())?;
//! sign_request(&mut request, target, &signer)?;
//! # }
//! # Ok::<(), Box<dyn core::error::Error>>(())
//! ```
//!
//! # Streaming responses
//!
//! ```no_run
//! # #[cfg(feature = "std")] {
//! use asimov_http::{
//! Component, FieldSection, SecretKey, SignatureInput, SignatureParams,
//! Signer, body::SigningBody, http::Response,
//! };
//! use bytes::Bytes;
//! use http_body_util::Full;
//!
//! let key = SecretKey::generate();
//! let input = SignatureInput::new(vec![
//! Component::new("@status")?,
//! Component::new("content-type")?,
//! Component::trailer("content-digest")?,
//! ], SignatureParams::fresh(&key.public(), "example-response")?)?;
//! let signer = Signer::new(key, "response", input)?;
//! // Any http_body::Body<Data = Bytes> works, including an unbounded stream.
//! let response = Response::builder()
//! .header("content-type", "application/jsonl")
//! .body(Full::new(Bytes::from_static(b"{}\n")))?;
//! let response = SigningBody::response(
//! response, None, Some(signer), FieldSection::Headers,
//! )?;
//! // Send with Hyper. Content-Digest and Signature are produced at EOF.
//! # }
//! # Ok::<(), Box<dyn core::error::Error>>(())
//! ```
extern crate alloc;
extern crate std;
pub use ;
pub use Error;
pub use ;
pub use ;
pub use ;
pub use http;