use crate::ports::crypto::{CryptoError, EqualityChecker, HashVerifier, SignatureVerifier};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VerificationResult {
Success,
Failure(String),
}
impl VerificationResult {
#[must_use]
pub const fn is_success(&self) -> bool {
matches!(self, Self::Success)
}
#[must_use]
pub const fn is_failure(&self) -> bool {
!self.is_success()
}
}
pub fn verify_equality<C: EqualityChecker>(
checker: &C,
expected: &[u8],
actual: &[u8],
) -> VerificationResult {
if checker.are_equal(expected, actual) {
VerificationResult::Success
} else {
VerificationResult::Failure("values don't match".to_string())
}
}
pub fn verify_preimage<H: HashVerifier>(
verifier: &H,
hash: &[u8],
preimage: &[u8],
) -> VerificationResult {
match verifier.verify_preimage(hash, preimage) {
Ok(()) => VerificationResult::Success,
Err(CryptoError::HashMismatch) => {
VerificationResult::Failure("preimage doesn't match".to_string())
}
Err(CryptoError::InvalidHashAlgorithm(msg)) => {
VerificationResult::Failure(format!("invalid hash algorithm: {msg}"))
}
Err(e) => VerificationResult::Failure(e.to_string()),
}
}
pub fn verify_signature<S: SignatureVerifier>(
verifier: &S,
public_key: &[u8],
signature: &[u8],
message: &[u8],
) -> VerificationResult {
match verifier.verify_signature(public_key, signature, message) {
Ok(()) => VerificationResult::Success,
Err(e) => VerificationResult::Failure(e.to_string()),
}
}
#[cfg(test)]
mod tests {
use super::*;
struct AlwaysEqualChecker;
impl EqualityChecker for AlwaysEqualChecker {
fn are_equal(&self, _a: &[u8], _b: &[u8]) -> bool {
true
}
}
struct NeverEqualChecker;
impl EqualityChecker for NeverEqualChecker {
fn are_equal(&self, _a: &[u8], _b: &[u8]) -> bool {
false
}
}
#[test]
fn test_verify_equality_success() {
let result = verify_equality(&AlwaysEqualChecker, b"foo", b"bar");
assert!(result.is_success());
}
#[test]
fn test_verify_equality_failure() {
let result = verify_equality(&NeverEqualChecker, b"foo", b"foo");
assert!(result.is_failure());
}
}