Skip to main content

lib_q_core/contexts/
signature.rs

1//! Signature context implementation for lib-Q Core
2//!
3//! This module provides the signature context that handles digital signature
4//! operations with proper security validation.
5
6#[cfg(feature = "alloc")]
7use alloc::{
8    boxed::Box,
9    string::String,
10    vec::Vec,
11};
12
13use super::BaseContext;
14#[cfg(test)]
15use crate::api::SignatureOperations;
16use crate::api::{
17    Algorithm,
18    AlgorithmCategory,
19    CryptoProvider,
20};
21use crate::error::Result;
22use crate::traits::{
23    SigKeypair,
24    SigPublicKey,
25    SigSecretKey,
26};
27
28/// Signature context for digital signature operations
29#[cfg(feature = "alloc")]
30pub struct SignatureContext {
31    inner: BaseContext<Self>,
32}
33
34#[cfg(feature = "alloc")]
35impl SignatureContext {
36    /// Create a new signature context with no provider
37    pub fn new() -> Self {
38        Self {
39            inner: BaseContext::new(),
40        }
41    }
42
43    /// Create a new signature context with a provider
44    pub fn with_provider(provider: Box<dyn CryptoProvider>) -> Self {
45        Self {
46            inner: BaseContext::with_provider(provider),
47        }
48    }
49
50    /// Create a new signature context with the default provider
51    #[cfg(feature = "alloc")]
52    pub fn with_default_provider() -> Self {
53        Self {
54            inner: match crate::providers::LibQCryptoProvider::new() {
55                Ok(provider) => BaseContext::with_provider(Box::new(provider)),
56                Err(_) => BaseContext::new(),
57            },
58        }
59    }
60
61    /// Set the cryptographic provider
62    pub fn set_provider(&mut self, provider: Box<dyn CryptoProvider>) {
63        self.inner.set_provider(provider);
64    }
65
66    /// Get the current provider
67    pub fn provider(&self) -> Option<&dyn CryptoProvider> {
68        self.inner.provider()
69    }
70
71    /// Generate a keypair for the specified algorithm
72    pub fn generate_keypair(
73        &mut self,
74        algorithm: Algorithm,
75        randomness: Option<&[u8]>,
76    ) -> Result<SigKeypair> {
77        self.inner.ensure_initialized()?;
78
79        // Validate algorithm category
80        if algorithm.category() != AlgorithmCategory::Signature {
81            return Err(crate::error::Error::InvalidAlgorithm {
82                algorithm: "Algorithm is not a signature algorithm",
83            });
84        }
85
86        // Use provider if available
87        match self.inner.provider().and_then(|p| p.signature()) {
88            Some(sig_ops) => sig_ops.generate_keypair(algorithm, randomness),
89            None => Err(crate::error::Error::ProviderNotConfigured {
90                operation: String::from("signature"),
91            }),
92        }
93    }
94
95    /// Sign a message using the given secret key
96    pub fn sign(
97        &self,
98        algorithm: Algorithm,
99        secret_key: &SigSecretKey,
100        message: &[u8],
101        randomness: Option<&[u8]>,
102    ) -> Result<Vec<u8>> {
103        if !self.inner.is_initialized() {
104            return Err(crate::error::Error::InvalidState {
105                operation: String::from("sign"),
106                reason: String::from("Context not initialized"),
107            });
108        }
109
110        // Validate algorithm category
111        if algorithm.category() != AlgorithmCategory::Signature {
112            return Err(crate::error::Error::InvalidAlgorithm {
113                algorithm: "Algorithm is not a signature algorithm",
114            });
115        }
116
117        // Use provider if available
118        match self.inner.provider().and_then(|p| p.signature()) {
119            Some(sig_ops) => sig_ops.sign(algorithm, secret_key, message, randomness),
120            None => Err(crate::error::Error::ProviderNotConfigured {
121                operation: String::from("signature"),
122            }),
123        }
124    }
125
126    /// Verify a signature for the given message and public key
127    pub fn verify(
128        &self,
129        algorithm: Algorithm,
130        public_key: &SigPublicKey,
131        message: &[u8],
132        signature: &[u8],
133    ) -> Result<bool> {
134        if !self.inner.is_initialized() {
135            return Err(crate::error::Error::InvalidState {
136                operation: String::from("verify"),
137                reason: String::from("Context not initialized"),
138            });
139        }
140
141        // Validate algorithm category
142        if algorithm.category() != AlgorithmCategory::Signature {
143            return Err(crate::error::Error::InvalidAlgorithm {
144                algorithm: "Algorithm is not a signature algorithm",
145            });
146        }
147
148        // Use provider if available
149        match self.inner.provider().and_then(|p| p.signature()) {
150            Some(sig_ops) => sig_ops.verify(algorithm, public_key, message, signature),
151            None => Err(crate::error::Error::ProviderNotConfigured {
152                operation: String::from("signature"),
153            }),
154        }
155    }
156
157    /// Check if the context is initialized
158    pub fn is_initialized(&self) -> bool {
159        self.inner.is_initialized()
160    }
161}
162
163#[cfg(feature = "alloc")]
164impl Default for SignatureContext {
165    fn default() -> Self {
166        Self::new()
167    }
168}
169
170#[cfg(test)]
171mod tests {
172    use super::*;
173    use crate::api::CryptoProvider;
174
175    // Mock provider for testing
176    struct MockSignatureProvider;
177
178    impl CryptoProvider for MockSignatureProvider {
179        fn kem(&self) -> Option<&dyn crate::api::KemOperations> {
180            None
181        }
182        fn signature(&self) -> Option<&dyn SignatureOperations> {
183            Some(self)
184        }
185        fn hash(&self) -> Option<&dyn crate::api::HashOperations> {
186            None
187        }
188        fn aead(&self) -> Option<&dyn crate::api::AeadOperations> {
189            None
190        }
191    }
192
193    impl SignatureOperations for MockSignatureProvider {
194        fn generate_keypair(
195            &self,
196            _algorithm: Algorithm,
197            _randomness: Option<&[u8]>,
198        ) -> Result<SigKeypair> {
199            Err(crate::error::Error::NotImplemented {
200                feature: "Mock signature operations not implemented".to_string(),
201            })
202        }
203
204        fn sign(
205            &self,
206            _algorithm: Algorithm,
207            _secret_key: &SigSecretKey,
208            _message: &[u8],
209            _randomness: Option<&[u8]>,
210        ) -> Result<Vec<u8>> {
211            Err(crate::error::Error::NotImplemented {
212                feature: "Mock signature operations not implemented".to_string(),
213            })
214        }
215
216        fn verify(
217            &self,
218            _algorithm: Algorithm,
219            _public_key: &SigPublicKey,
220            _message: &[u8],
221            _signature: &[u8],
222        ) -> Result<bool> {
223            Err(crate::error::Error::NotImplemented {
224                feature: "Mock signature operations not implemented".to_string(),
225            })
226        }
227    }
228
229    #[test]
230    fn test_signature_context_creation() {
231        let context = SignatureContext::new();
232        assert!(!context.is_initialized());
233        assert!(context.provider().is_none());
234    }
235
236    #[test]
237    fn test_signature_context_with_provider() {
238        let provider = Box::new(MockSignatureProvider);
239        let context = SignatureContext::with_provider(provider);
240        assert!(!context.is_initialized());
241        assert!(context.provider().is_some());
242    }
243
244    #[test]
245    fn test_signature_context_provider_management() {
246        let mut context = SignatureContext::new();
247        assert!(context.provider().is_none());
248
249        let provider = Box::new(MockSignatureProvider);
250        context.set_provider(provider);
251        assert!(context.provider().is_some());
252    }
253
254    #[test]
255    fn test_signature_context_initialization() {
256        let mut context = SignatureContext::new();
257        assert!(!context.is_initialized());
258
259        // Should initialize automatically on first operation
260        let result = context.generate_keypair(Algorithm::MlDsa44, None);
261        assert!(result.is_err()); // Will fail due to no provider, but context should be initialized
262        assert!(context.is_initialized());
263    }
264
265    #[test]
266    fn test_signature_context_algorithm_validation() {
267        let mut context = SignatureContext::new();
268
269        // Try to use a non-signature algorithm
270        let result = context.generate_keypair(Algorithm::Sha3_256, None);
271        assert!(result.is_err());
272        if let Err(crate::error::Error::InvalidAlgorithm { .. }) = result {
273            // Expected error
274        } else {
275            panic!("Expected InvalidAlgorithm error");
276        }
277    }
278}