chains_sdk/traits.rs
1//! Unified trait interfaces for all signing algorithms.
2//!
3//! Every chain module implements these traits, providing a consistent API
4//! regardless of the underlying cryptographic algorithm.
5
6use zeroize::Zeroizing;
7
8/// A type that can produce cryptographic signatures.
9pub trait Signer {
10 /// The signature type produced by this signer.
11 type Signature;
12 /// The error type returned on failure.
13 type Error;
14
15 /// Sign a raw message. The implementation applies chain-specific hashing internally
16 /// (e.g., Keccak-256 for Ethereum, double-SHA-256 for Bitcoin).
17 fn sign(&self, message: &[u8]) -> Result<Self::Signature, Self::Error>;
18
19 /// Sign a pre-hashed digest directly. The caller is responsible for applying
20 /// the correct hash function. Returns `InvalidHashLength` if the digest
21 /// length doesn't match the expected hash output size.
22 fn sign_prehashed(&self, digest: &[u8]) -> Result<Self::Signature, Self::Error>;
23
24 /// Return the public key as bytes (compressed format where applicable).
25 /// - ECDSA (secp256k1, P-256): 33 bytes (SEC1 compressed)
26 /// - Ed25519: 32 bytes
27 /// - BIP-340 Schnorr: 32 bytes (x-only)
28 /// - BLS12-381: 48 bytes (compressed G1)
29 fn public_key_bytes(&self) -> Vec<u8>;
30
31 /// Return the public key in uncompressed format.
32 /// - ECDSA (secp256k1, P-256): 65 bytes (`04 || x || y`)
33 /// - Ed25519 / Schnorr / BLS: same as `public_key_bytes()` (no uncompressed form)
34 fn public_key_bytes_uncompressed(&self) -> Vec<u8>;
35}
36
37/// A type that can verify cryptographic signatures.
38pub trait Verifier {
39 /// The signature type this verifier accepts.
40 type Signature;
41 /// The error type returned on failure.
42 type Error;
43
44 /// Verify a signature against a raw message. The implementation applies
45 /// chain-specific hashing internally.
46 fn verify(&self, message: &[u8], signature: &Self::Signature) -> Result<bool, Self::Error>;
47
48 /// Verify a signature against a pre-hashed digest.
49 fn verify_prehashed(
50 &self,
51 digest: &[u8],
52 signature: &Self::Signature,
53 ) -> Result<bool, Self::Error>;
54}
55
56/// A type that represents a cryptographic key pair capable of signing.
57pub trait KeyPair: Signer {
58 /// Generate a new random key pair using OS entropy (CSPRNG).
59 fn generate() -> Result<Self, <Self as Signer>::Error>
60 where
61 Self: Sized;
62
63 /// Reconstruct a key pair from raw private key bytes (32 bytes).
64 fn from_bytes(private_key: &[u8]) -> Result<Self, <Self as Signer>::Error>
65 where
66 Self: Sized;
67
68 /// Export the private key as auto-zeroizing bytes.
69 /// The returned `Zeroizing<Vec<u8>>` will scrub the memory on drop.
70 fn private_key_bytes(&self) -> Zeroizing<Vec<u8>>;
71
72 /// Reconstruct a key pair from a 64-byte expanded keypair (seed ∥ pubkey).
73 /// Default impl uses only the first 32 bytes (seed).
74 fn from_keypair_bytes(keypair: &[u8]) -> Result<Self, <Self as Signer>::Error>
75 where
76 Self: Sized,
77 {
78 if keypair.len() < 32 {
79 return Self::from_bytes(keypair); // will error with proper message
80 }
81 Self::from_bytes(&keypair[..32])
82 }
83
84 /// Export the full keypair as `private_key ∥ public_key`.
85 /// Default: 32B seed + compressed pubkey.
86 fn keypair_bytes(&self) -> Zeroizing<Vec<u8>> {
87 let priv_key = self.private_key_bytes();
88 let pub_key = self.public_key_bytes();
89 let mut kp = Vec::with_capacity(priv_key.len() + pub_key.len());
90 kp.extend_from_slice(&priv_key);
91 kp.extend_from_slice(&pub_key);
92 Zeroizing::new(kp)
93 }
94}