#[cfg(feature = "alloc")]
use alloc::{
boxed::Box,
string::String,
vec::Vec,
};
use super::BaseContext;
#[cfg(test)]
use crate::api::HashOperations;
use crate::api::{
Algorithm,
AlgorithmCategory,
CryptoProvider,
};
use crate::error::Result;
#[cfg(feature = "alloc")]
pub struct HashContext {
inner: BaseContext<Self>,
}
#[cfg(feature = "alloc")]
impl HashContext {
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 hash(&mut self, algorithm: Algorithm, data: &[u8]) -> Result<Vec<u8>> {
self.inner.ensure_initialized()?;
if algorithm.category() != AlgorithmCategory::Hash {
return Err(crate::error::Error::InvalidAlgorithm {
algorithm: "Algorithm is not a hash algorithm",
});
}
match self.inner.provider().and_then(|p| p.hash()) {
Some(hash_ops) => hash_ops.hash(algorithm, data),
None => Err(crate::error::Error::ProviderNotConfigured {
operation: String::from("hash"),
}),
}
}
pub fn is_initialized(&self) -> bool {
self.inner.is_initialized()
}
}
#[cfg(feature = "alloc")]
impl Default for HashContext {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::api::CryptoProvider;
struct MockHashProvider;
impl CryptoProvider for MockHashProvider {
fn kem(&self) -> Option<&dyn crate::api::KemOperations> {
None
}
fn signature(&self) -> Option<&dyn crate::api::SignatureOperations> {
None
}
fn hash(&self) -> Option<&dyn HashOperations> {
Some(self)
}
fn aead(&self) -> Option<&dyn crate::api::AeadOperations> {
None
}
}
impl HashOperations for MockHashProvider {
fn hash(&self, _algorithm: Algorithm, _data: &[u8]) -> Result<Vec<u8>> {
Err(crate::error::Error::NotImplemented {
feature: "Mock hash operations not implemented".to_string(),
})
}
}
#[test]
fn test_hash_context_creation() {
let context = HashContext::new();
assert!(!context.is_initialized());
assert!(context.provider().is_none());
}
#[test]
fn test_hash_context_with_provider() {
let provider = Box::new(MockHashProvider);
let context = HashContext::with_provider(provider);
assert!(!context.is_initialized());
assert!(context.provider().is_some());
}
#[test]
fn test_hash_context_provider_management() {
let mut context = HashContext::new();
assert!(context.provider().is_none());
let provider = Box::new(MockHashProvider);
context.set_provider(provider);
assert!(context.provider().is_some());
}
#[test]
fn test_hash_context_initialization() {
let mut context = HashContext::new();
assert!(!context.is_initialized());
let result = context.hash(Algorithm::Sha3_256, b"test data");
assert!(result.is_err()); assert!(context.is_initialized());
}
#[test]
fn test_hash_context_algorithm_validation() {
let mut context = HashContext::new();
let result = context.hash(Algorithm::MlKem512, b"test data");
assert!(result.is_err());
if let Err(crate::error::Error::InvalidAlgorithm { .. }) = result {
} else {
panic!("Expected InvalidAlgorithm error");
}
}
}