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
// SPDX-License-Identifier: Apache-2.0
//! Signing primitives — classical, post-quantum, and hybrid.
//!
//! Signet defaults to **hybrid** signing for new applications. A hybrid
//! signature is unforgeable as long as **either** primitive holds; a
//! vulnerability in one (e.g. a future quantum attack on Ed25519, or a
//! bug in Falcon) does not break the scheme.
//!
//! # Quick reference
//!
//! | Need | Use |
//! |------|-----|
//! | Recommended for new code | [`signing::hybrid::HybridSigningKeyBundle`] |
//! | Pure Ed25519 (no PQ) | [`signing::classical::Ed25519Signer`] |
//! | Pure Falcon-1024 (PQ only) | [`signing::postquantum::Falcon1024Signer`] |
//! | Pure SLH-DSA (hash-based) | \[`pqc::slhdsa`\] |
//! | secp256k1 Schnorr | [`ec_schnorr`] |
//!
//! # Submodule organization
//!
//! - [`signing::classical`] — Ed25519 (32-byte keys, 64-byte signatures)
//! - [`signing::postquantum`] — Falcon-512/1024, SLH-DSA, ML-DSA
//! - [`signing::hybrid`] — Ed25519 + PQ constructions (canonical signing API)
//!
//! # Design: static methods, not traits
//!
//! Unlike many crypto crates, this module does **not** expose a `Signer` /
//! `Verifier` trait. Instead, every signing algorithm is implemented as
//! a unit struct with static `sign` / `verify` methods:
//!
//! ```no_run
//! use origin_crypto_sdk::signing::classical::Ed25519Signer;
//!
//! let signer = Ed25519Signer::from_seed(&[1u8; 32]);
//! let sig = signer.sign(b"message");
//! assert!(signer.verify(b"message", &sig));
//! ```
//!
//! This has two benefits:
//!
//! 1. **No "blanket impl" attacks** — a downstream crate cannot
//! implement `Signer` for a custom type and silently intercept
//! signatures. The compiler refuses anything not defined here.
//! 2. **No `dyn` dispatch overhead** — all paths are monomorphized.
//!
//! The cost is that generic code (e.g. accepting "any signer") needs to
//! be a function on the algorithm enum (`HybridSigningKeyBundle`) or
//! an explicit match. For 99% of use cases this is the right tradeoff.
/// Legacy compatibility shim for code that used `origin_crypto_sdk::hybrid::*`.
/// **Deprecated.** Use `signing::hybrid` directly instead.
// ──────────────────────────────────────────────────────────────────────
// Legacy re-exports
//
// These types used to live at `origin_crypto_sdk::signing::*` (a flat
// module). The new structure puts them in `signing::{classical,hybrid}`.
// We re-export them at this level for backward compat with callers that
// did `use origin_crypto_sdk::signing::{HybridSigningKey, ...};`.
// ──────────────────────────────────────────────────────────────────────
// `HybridSigningKey` (the OOP wrapper around HybridSigningKeyBundle) was
// the main public type from the old `signing.rs`. It's now in the
// `signing_legacy` top-level module.
pub use crate;