Skip to main content

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}