#[cfg(feature = "alloc")]
use alloc::{
boxed::Box,
string::String,
vec::Vec,
};
use super::BaseContext;
#[cfg(test)]
use crate::api::SignatureOperations;
use crate::api::{
Algorithm,
AlgorithmCategory,
CryptoProvider,
};
use crate::error::Result;
use crate::traits::{
SigKeypair,
SigPublicKey,
SigSecretKey,
};
#[cfg(feature = "alloc")]
pub struct SignatureContext {
inner: BaseContext<Self>,
}
#[cfg(feature = "alloc")]
impl SignatureContext {
pub fn new() -> Self {
Self {
inner: BaseContext::new(),
}
}
pub fn with_provider(provider: Box<dyn CryptoProvider>) -> Self {
Self {
inner: BaseContext::with_provider(provider),
}
}
#[cfg(feature = "alloc")]
pub fn with_default_provider() -> Self {
Self {
inner: match crate::providers::LibQCryptoProvider::new() {
Ok(provider) => BaseContext::with_provider(Box::new(provider)),
Err(_) => BaseContext::new(),
},
}
}
pub fn set_provider(&mut self, provider: Box<dyn CryptoProvider>) {
self.inner.set_provider(provider);
}
pub fn provider(&self) -> Option<&dyn CryptoProvider> {
self.inner.provider()
}
pub fn generate_keypair(
&mut self,
algorithm: Algorithm,
randomness: Option<&[u8]>,
) -> Result<SigKeypair> {
self.inner.ensure_initialized()?;
if algorithm.category() != AlgorithmCategory::Signature {
return Err(crate::error::Error::InvalidAlgorithm {
algorithm: "Algorithm is not a signature algorithm",
});
}
match self.inner.provider().and_then(|p| p.signature()) {
Some(sig_ops) => sig_ops.generate_keypair(algorithm, randomness),
None => Err(crate::error::Error::ProviderNotConfigured {
operation: String::from("signature"),
}),
}
}
pub fn sign(
&self,
algorithm: Algorithm,
secret_key: &SigSecretKey,
message: &[u8],
randomness: Option<&[u8]>,
) -> Result<Vec<u8>> {
if !self.inner.is_initialized() {
return Err(crate::error::Error::InvalidState {
operation: String::from("sign"),
reason: String::from("Context not initialized"),
});
}
if algorithm.category() != AlgorithmCategory::Signature {
return Err(crate::error::Error::InvalidAlgorithm {
algorithm: "Algorithm is not a signature algorithm",
});
}
match self.inner.provider().and_then(|p| p.signature()) {
Some(sig_ops) => sig_ops.sign(algorithm, secret_key, message, randomness),
None => Err(crate::error::Error::ProviderNotConfigured {
operation: String::from("signature"),
}),
}
}
pub fn verify(
&self,
algorithm: Algorithm,
public_key: &SigPublicKey,
message: &[u8],
signature: &[u8],
) -> Result<bool> {
if !self.inner.is_initialized() {
return Err(crate::error::Error::InvalidState {
operation: String::from("verify"),
reason: String::from("Context not initialized"),
});
}
if algorithm.category() != AlgorithmCategory::Signature {
return Err(crate::error::Error::InvalidAlgorithm {
algorithm: "Algorithm is not a signature algorithm",
});
}
match self.inner.provider().and_then(|p| p.signature()) {
Some(sig_ops) => sig_ops.verify(algorithm, public_key, message, signature),
None => Err(crate::error::Error::ProviderNotConfigured {
operation: String::from("signature"),
}),
}
}
pub fn is_initialized(&self) -> bool {
self.inner.is_initialized()
}
}
#[cfg(feature = "alloc")]
impl Default for SignatureContext {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::api::CryptoProvider;
struct MockSignatureProvider;
impl CryptoProvider for MockSignatureProvider {
fn kem(&self) -> Option<&dyn crate::api::KemOperations> {
None
}
fn signature(&self) -> Option<&dyn SignatureOperations> {
Some(self)
}
fn hash(&self) -> Option<&dyn crate::api::HashOperations> {
None
}
fn aead(&self) -> Option<&dyn crate::api::AeadOperations> {
None
}
}
impl SignatureOperations for MockSignatureProvider {
fn generate_keypair(
&self,
_algorithm: Algorithm,
_randomness: Option<&[u8]>,
) -> Result<SigKeypair> {
Err(crate::error::Error::NotImplemented {
feature: "Mock signature operations not implemented".to_string(),
})
}
fn sign(
&self,
_algorithm: Algorithm,
_secret_key: &SigSecretKey,
_message: &[u8],
_randomness: Option<&[u8]>,
) -> Result<Vec<u8>> {
Err(crate::error::Error::NotImplemented {
feature: "Mock signature operations not implemented".to_string(),
})
}
fn verify(
&self,
_algorithm: Algorithm,
_public_key: &SigPublicKey,
_message: &[u8],
_signature: &[u8],
) -> Result<bool> {
Err(crate::error::Error::NotImplemented {
feature: "Mock signature operations not implemented".to_string(),
})
}
}
#[test]
fn test_signature_context_creation() {
let context = SignatureContext::new();
assert!(!context.is_initialized());
assert!(context.provider().is_none());
}
#[test]
fn test_signature_context_with_provider() {
let provider = Box::new(MockSignatureProvider);
let context = SignatureContext::with_provider(provider);
assert!(!context.is_initialized());
assert!(context.provider().is_some());
}
#[test]
fn test_signature_context_provider_management() {
let mut context = SignatureContext::new();
assert!(context.provider().is_none());
let provider = Box::new(MockSignatureProvider);
context.set_provider(provider);
assert!(context.provider().is_some());
}
#[test]
fn test_signature_context_initialization() {
let mut context = SignatureContext::new();
assert!(!context.is_initialized());
let result = context.generate_keypair(Algorithm::MlDsa44, None);
assert!(result.is_err()); assert!(context.is_initialized());
}
#[test]
fn test_signature_context_algorithm_validation() {
let mut context = SignatureContext::new();
let result = context.generate_keypair(Algorithm::Sha3_256, None);
assert!(result.is_err());
if let Err(crate::error::Error::InvalidAlgorithm { .. }) = result {
} else {
panic!("Expected InvalidAlgorithm error");
}
}
}