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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! `aethel-sdk`: a Rust surface over aethel-core's post-quantum identity primitives.
//!
//! ```
//! use aethel_sdk::{verify, Identity};
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // The signing key is derived inside the embedded component from OS entropy
//! // and never enters this process.
//! let mut identity = Identity::generate()?;
//!
//! let message = b"the message that was actually signed";
//! let signature = identity.sign(message)?;
//!
//! // Ok(false) is "this signature does not verify". An Err means the input
//! // could not be processed at all. They are different answers: treating an
//! // error as "invalid" is what makes malformed input look like a failed check.
//! assert!(verify(identity.public_key(), message, &signature)?);
//! assert!(!verify(identity.public_key(), b"something else", &signature)?);
//!
//! // The interoperable form of the public key, for a DID document.
//! println!("{}", identity.public_key_multibase());
//! # Ok(())
//! # }
//! ```
//!
//! Fuller worked examples are in `examples/` in the published package:
//! `quickstart.rs` (generate, sign, verify, persist, disclose), `projection.rs`,
//! and `bench_verify.rs`. Run them with `cargo run --example quickstart` from a
//! checkout of the repository.
//!
//! # Before you add this crate
//!
//! This crate embeds a WebAssembly runtime. `cargo add aethel-sdk` pulls
//! wasmtime and Cranelift, roughly 120 crates, and a cold debug build takes
//! **several minutes** and produces a target directory over a gigabyte. That is
//! a one-time cost and it is not a hung build. Separately, the first
//! verification in a process pays a ~230 ms component compile; [`Verifier`]
//! exists so you can pay that at startup rather than on a caller's request.
//!
//! Host platforms only. wasmtime needs mmap and cannot itself be compiled to
//! `wasm32-unknown-unknown`, so this crate is scoped away from that target: it
//! will not build for a browser. The identity operations still all happen inside
//! WebAssembly; it is the runtime executing them that has to be native.
//!
//! [`SECURITY-MODEL.md`](https://github.com/0x307/aethel-sdk/blob/main/SECURITY-MODEL.md)
//! states what this crate claims, how each claim is checked, what you are
//! responsible for, and what is out of scope. It ships in this package. Read it
//! before depending on this for anything that matters.
//!
//! # What runs today
//!
//! The compiled `aethel:core` component is embedded in this crate, its integrity
//! is checked against a hash the package declares ([`artifact`]), and it loads
//! and executes in an embedded runtime ([`component`]).
//!
//! It is the L1 boundary from the initiative charter: one WebAssembly artifact,
//! embedded by every language, carrying every cryptographic operation. Nothing
//! in this crate implements crypto, and nothing in this crate is allowed to.
//!
//! On top of that, the following work end to end, and every one of them is
//! exercised by the test suite and by `examples/quickstart.rs`, which runs in
//! CI:
//!
//! - [`Identity::generate`] and [`Identity::from_entropy`], keys derived inside
//! the component and never present in this process
//! - [`Identity::sign`], and the free function [`identity::verify`] (there is
//! no `Identity::verify`: verification needs only public material). ML-DSA-65
//! - [`Identity::export_sealed`] and [`Identity::open_sealed`], so an identity
//! survives the process
//! - [`Identity::split_for_recovery`] and [`Identity::recover_from_shares`],
//! authenticated 3-of-5 recovery over the canonical sealed identity
//! - [`Identity::public_key_multibase`], the public key as a W3C Multikey
//! - [`Identity::project_at`], fresh, context-bound PLP projections
//! - [`Identity::issue_credential`], BDLOP issuance over named attributes
//! - [`Identity::present`] and [`verify_presentation`], SAAP selective
//! disclosure: the verifier learns the disclosed attributes and nothing about
//! the hidden ones
//!
//! # What is not on this surface
//!
//! Callable through the component but not wrapped here: standalone PLP proof
//! (`prove`, `plp-verify`).
//! `ROADMAP.md` has the sequence.
//!
//! # What is not built anywhere
//!
//! - **Issuer key management. Verifying a presentation currently requires the
//! issuer's secret seed.** [`verify_presentation`] takes the same
//! `issuer_seed` that [`Identity::issue_credential`] takes, so any party that
//! can verify can also issue. There are no public issuer parameters to verify
//! against yet: `aethel-core` does not expose them. Until it does, an issuer
//! and a verifier cannot be separate parties, and a verifier cannot be a
//! public endpoint. This is a limitation of the current world, not of the
//! underlying construction.
//! - **Predicate proofs over hidden values.** "Age over 21 without revealing
//! age" does not work. Selective disclosure reveals the exact value of a
//! disclosed attribute; it cannot prove a bound on an undisclosed one. This is
//! RFC 5.6 relation 3, deliberately deferred, with three `identity-error`
//! variants reserved upstream for it.
//! - **Revocation and key rotation.** There is no revocation list, no expiry, no
//! epoch on a credential or presentation, and no way to bind an identity to a
//! successor.
//! - **Issuance orchestration.** `issue_credential` is one local call and needs
//! the issuer seed in this process. There is no two-party issuer/holder
//! protocol.
//!
//! # A correction
//!
//! Earlier versions of this comment said the ergonomic surface was "designed and
//! none of them is callable from this crate yet", and that "SAAP selective
//! disclosure does not work in the embedded component" because `saap-verify`
//! denied unconditionally. Both were true once and neither is true now. The
//! quickstart in this repository exercises exactly those paths and passes.
pub use ;
pub use ;
pub use Verifier;