lib_q_core/contexts/
signature.rs1#[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#[cfg(feature = "alloc")]
30pub struct SignatureContext {
31 inner: BaseContext<Self>,
32}
33
34#[cfg(feature = "alloc")]
35impl SignatureContext {
36 pub fn new() -> Self {
38 Self {
39 inner: BaseContext::new(),
40 }
41 }
42
43 pub fn with_provider(provider: Box<dyn CryptoProvider>) -> Self {
45 Self {
46 inner: BaseContext::with_provider(provider),
47 }
48 }
49
50 #[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 pub fn set_provider(&mut self, provider: Box<dyn CryptoProvider>) {
63 self.inner.set_provider(provider);
64 }
65
66 pub fn provider(&self) -> Option<&dyn CryptoProvider> {
68 self.inner.provider()
69 }
70
71 pub fn generate_keypair(
73 &mut self,
74 algorithm: Algorithm,
75 randomness: Option<&[u8]>,
76 ) -> Result<SigKeypair> {
77 self.inner.ensure_initialized()?;
78
79 if algorithm.category() != AlgorithmCategory::Signature {
81 return Err(crate::error::Error::InvalidAlgorithm {
82 algorithm: "Algorithm is not a signature algorithm",
83 });
84 }
85
86 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 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 if algorithm.category() != AlgorithmCategory::Signature {
112 return Err(crate::error::Error::InvalidAlgorithm {
113 algorithm: "Algorithm is not a signature algorithm",
114 });
115 }
116
117 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 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 if algorithm.category() != AlgorithmCategory::Signature {
143 return Err(crate::error::Error::InvalidAlgorithm {
144 algorithm: "Algorithm is not a signature algorithm",
145 });
146 }
147
148 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 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 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 let result = context.generate_keypair(Algorithm::MlDsa44, None);
261 assert!(result.is_err()); assert!(context.is_initialized());
263 }
264
265 #[test]
266 fn test_signature_context_algorithm_validation() {
267 let mut context = SignatureContext::new();
268
269 let result = context.generate_keypair(Algorithm::Sha3_256, None);
271 assert!(result.is_err());
272 if let Err(crate::error::Error::InvalidAlgorithm { .. }) = result {
273 } else {
275 panic!("Expected InvalidAlgorithm error");
276 }
277 }
278}