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
//! Transport-agnostic pairing protocol for the auths identity system.
//!
//! This crate implements the cryptographic pairing protocol that allows
//! cross-device identity linking. It is intentionally free of transport
//! dependencies (no axum, tower-http, mdns-sd, reqwest) so that mobile
//! apps can use it with their own transport layer.
//!
//! ## Curve choice
//!
//! The device's long-term **signing** curve (Ed25519 or P-256, carried via
//! the `curve` wire field on [`PairingResponse`]) is independent of the
//! **ephemeral ECDH** curve used for key agreement.
//!
//! We use **P-256 ECDH unconditionally**, regardless of signing curve.
//! Ephemeral keys are generated fresh per session (`p256::ecdh::EphemeralSecret::random`),
//! never reused, and have zero cryptographic relationship to the device's
//! long-term signing seed. There is no "signing-curve-to-ECDH-curve mapper"
//! and no need for one.
//!
//! **Why P-256 for ECDH:**
//! - P-256 is the workspace default curve, already a dependency for signing.
//! - iOS Secure Enclave is P-256 exclusively; Android StrongBox supports
//! P-256 only for EC.
//! - Removes the X25519 dependency and the 32-byte pubkey ambiguity
//! (X25519 and Ed25519 both produce 32-byte keys).
//! - Constant-time P-256 ECDH via the `p256` crate (RustCrypto, audited).
//!
//! See `docs/architecture/cryptography.md` → Wire-format Curve Tagging for
//! the workspace-wide curve-agnosticism rule.
// fn-129.T1: statically forbid `unsafe` in this crate. The pairing protocol
// has no `unsafe` today; this attribute freezes that invariant so future
// code cannot accidentally introduce a soundness hole around the ephemeral
// ECDH secret or the transport key.
pub use ;
pub use ProtocolError;
pub use ;
pub use ;
// The `SubkeyChain` wire type is always compiled in so every builder
// that constructs a `SubmitResponseRequest` can spell the field — a
// feature-gated field would require `#[cfg]` at every call site. The
// verifier logic (`verify_subkey_chain`, `build_binding_message_v1`,
// and the domain separator) is gated behind `subkey-chain-v1`. A
// daemon compiled without the feature that receives a request with
// `subkey_chain.is_some()` must reject with an explicit unsupported
// error — silent ignore is a security regression.
pub use ;
pub use SubkeyChain;
pub use ;
pub use ;
pub use *;