dcrypt_api/traits/signature.rs
1//! Digital signature traits for dcrypt
2//!
3//! This module defines the traits that all signature algorithms must implement.
4//! The design prioritizes security by not requiring mutable access to secret keys.
5
6use crate::{Result, ZeroizingBytes};
7use dcrypt_internal::random::{CryptoRng, RngCore};
8use dcrypt_internal::zeroing::Zeroize;
9
10#[cfg(not(feature = "std"))]
11use alloc::vec::Vec;
12#[cfg(feature = "std")]
13use std::vec::Vec;
14
15/// Core trait for digital signature algorithms
16///
17/// This trait defines the minimal interface that all signature algorithms
18/// must implement. It intentionally does not require `AsRef` or `AsMut`
19/// implementations for secret keys to prevent accidental key corruption.
20///
21/// # Type Safety
22///
23/// Secret keys are opaque types that cannot be directly manipulated as bytes.
24/// This prevents common security vulnerabilities where keys are accidentally
25/// modified or exposed.
26///
27/// # Example Implementation
28///
29/// See the implementation modules for examples of how to implement this trait
30/// for specific algorithms like Ed25519, ECDSA, etc.
31pub trait Signature {
32 /// Public key type for this algorithm
33 type PublicKey: Clone;
34
35 /// Secret key type - must be zeroizable but not byte-accessible
36 ///
37 /// # Security Note
38 ///
39 /// This type should not implement `AsMut<[u8]>` to prevent corruption
40 /// of key material. Use explicit serialization methods if needed.
41 type SecretKey: Zeroize + Clone;
42
43 /// Signature data type
44 type SignatureData: Clone;
45
46 /// Key pair type (typically a tuple of public and secret keys)
47 type KeyPair;
48
49 /// Returns the name of this signature algorithm
50 fn name() -> &'static str;
51
52 /// Generate a new key pair using the provided RNG
53 ///
54 /// # Security Requirements
55 ///
56 /// Implementations must use the provided cryptographically secure RNG
57 /// for all random number generation.
58 fn keypair<R: CryptoRng + RngCore>(rng: &mut R) -> Result<Self::KeyPair>;
59
60 /// Extract the public key from a key pair
61 fn public_key(keypair: &Self::KeyPair) -> Self::PublicKey;
62
63 /// Extract the secret key from a key pair
64 fn secret_key(keypair: &Self::KeyPair) -> Self::SecretKey;
65
66 /// Sign a message with the given secret key
67 ///
68 /// # Security Requirements
69 ///
70 /// - Implementations should be deterministic when possible (e.g., Ed25519)
71 /// - Must not leak information about the secret key through timing
72 fn sign(message: &[u8], secret_key: &Self::SecretKey) -> Result<Self::SignatureData>;
73
74 /// Verify a signature against a message and public key
75 ///
76 /// # Security Requirements
77 ///
78 /// - Must be constant-time with respect to the signature value
79 /// - Should validate all inputs before processing
80 fn verify(
81 message: &[u8],
82 signature: &Self::SignatureData,
83 public_key: &Self::PublicKey,
84 ) -> Result<()>;
85}
86
87/// Optional trait for signature algorithms that support key serialization
88///
89/// This trait should only be implemented for algorithms where key
90/// import/export is safe and well-defined.
91pub trait SignatureSerialize: Signature {
92 /// Size of serialized public keys in bytes
93 const PUBLIC_KEY_SIZE: usize;
94
95 /// Size of serialized secret keys in bytes
96 const SECRET_KEY_SIZE: usize;
97
98 /// Size of serialized signatures in bytes
99 const SIGNATURE_SIZE: usize;
100
101 /// Export a public key to bytes
102 fn serialize_public_key(key: &Self::PublicKey) -> Vec<u8>;
103
104 /// Import a public key from bytes
105 ///
106 /// # Errors
107 ///
108 /// Returns an error if the bytes are malformed or invalid
109 fn deserialize_public_key(bytes: &[u8]) -> Result<Self::PublicKey>;
110
111 /// Export a secret key to bytes
112 ///
113 /// # Security Warning
114 ///
115 /// The returned bytes contain sensitive key material and must be
116 /// handled with appropriate care. The exact-size zeroizing wrapper ensures
117 /// every initialized byte is cleared from memory when dropped.
118 fn serialize_secret_key(key: &Self::SecretKey) -> ZeroizingBytes;
119
120 /// Import a secret key from bytes
121 ///
122 /// # Security Requirements
123 ///
124 /// - Input bytes should be zeroized after use
125 /// - Implementation must validate the key format
126 ///
127 /// # Errors
128 ///
129 /// Returns an error if the bytes are malformed or invalid
130 fn deserialize_secret_key(bytes: &[u8]) -> Result<Self::SecretKey>;
131
132 /// Export a signature to bytes
133 fn serialize_signature(sig: &Self::SignatureData) -> Vec<u8>;
134
135 /// Import a signature from bytes
136 ///
137 /// # Errors
138 ///
139 /// Returns an error if the bytes are malformed or invalid
140 fn deserialize_signature(bytes: &[u8]) -> Result<Self::SignatureData>;
141}
142
143/// Optional trait for signature algorithms that support key derivation
144///
145/// This trait is for algorithms that can derive keys from seed material
146/// in a deterministic way.
147pub trait SignatureDerive: Signature {
148 /// Minimum seed size in bytes
149 const MIN_SEED_SIZE: usize;
150
151 /// Derive a key pair from seed material
152 ///
153 /// # Security Requirements
154 ///
155 /// - The seed must have sufficient entropy
156 /// - Derivation must be deterministic
157 /// - Same seed must always produce same key pair
158 ///
159 /// # Errors
160 ///
161 /// Returns an error if the seed is too short or invalid
162 fn derive_keypair(seed: &[u8]) -> Result<Self::KeyPair>;
163
164 /// Derive the public key from a secret key
165 ///
166 /// This is useful when you have a secret key and need to
167 /// recover the corresponding public key.
168 ///
169 /// # Errors
170 ///
171 /// Returns an error if the secret key is invalid
172 fn derive_public_key(secret_key: &Self::SecretKey) -> Result<Self::PublicKey>;
173}
174
175/// Optional trait for signature algorithms with message size limits
176///
177/// Some algorithms may have restrictions on message sizes or require
178/// pre-hashing for large messages.
179pub trait SignatureMessageLimits: Signature {
180 /// Maximum message size that can be signed directly (in bytes)
181 ///
182 /// `None` indicates no limit
183 const MAX_MESSAGE_SIZE: Option<usize>;
184
185 /// Whether this algorithm requires pre-hashing of messages
186 const REQUIRES_PREHASH: bool;
187}
188
189/// Optional trait for batch signature verification
190///
191/// Some algorithms (like Ed25519) support efficient batch verification
192/// of multiple signatures.
193pub trait SignatureBatchVerify: Signature {
194 /// Verify multiple signatures in a batch
195 ///
196 /// # Parameters
197 ///
198 /// - `messages`: Slice of messages to verify
199 /// - `signatures`: Corresponding signatures
200 /// - `public_keys`: Corresponding public keys
201 ///
202 /// All three slices must have the same length.
203 ///
204 /// # Returns
205 ///
206 /// - `Ok(())` if all signatures are valid
207 /// - `Err(_)` if any signature is invalid or inputs are malformed
208 ///
209 /// # Performance
210 ///
211 /// This should be significantly faster than verifying each signature
212 /// individually when the batch size is large.
213 fn batch_verify(
214 messages: &[&[u8]],
215 signatures: &[Self::SignatureData],
216 public_keys: &[Self::PublicKey],
217 ) -> Result<()>;
218}
219
220/// Extension trait for convenient public key operations
221///
222/// This trait can be implemented for public key types that have
223/// a byte representation.
224pub trait PublicKeyBytes: Sized {
225 /// Create from byte representation
226 fn from_bytes(bytes: &[u8]) -> Result<Self>;
227
228 /// Convert to byte representation
229 fn to_bytes(&self) -> Vec<u8>;
230}
231
232/// Extension trait for convenient signature operations
233///
234/// This trait can be implemented for signature types that have
235/// a byte representation.
236pub trait SignatureBytes: Sized {
237 /// Create from byte representation
238 fn from_bytes(bytes: &[u8]) -> Result<Self>;
239
240 /// Convert to byte representation
241 fn to_bytes(&self) -> Vec<u8>;
242}