use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64};
use bistun_core::error::LmsError;
use ed25519_dalek::{Signature, Verifier, VerifyingKey};
pub fn verify_snapshot(
payload: &str,
signature_b64: &str,
public_key_b64: &str,
) -> Result<(), LmsError> {
let pub_key_bytes = BASE64.decode(public_key_b64).map_err(|e| LmsError::SecurityFault {
pipeline_step: "Phase 0: Security Gate".to_string(),
context: "Key Parsing".to_string(),
reason: format!("Failed to decode Base64 public key: {e}"),
})?;
let verifying_key =
VerifyingKey::try_from(pub_key_bytes.as_slice()).map_err(|e| LmsError::SecurityFault {
pipeline_step: "Phase 0: Security Gate".to_string(),
context: "Key Parsing".to_string(),
reason: format!("Invalid Ed25519 public key format: {e}"),
})?;
let sig_bytes = BASE64.decode(signature_b64).map_err(|e| LmsError::SecurityFault {
pipeline_step: "Phase 0: Security Gate".to_string(),
context: "Signature Parsing".to_string(),
reason: format!("Failed to decode Base64 signature: {e}"),
})?;
let signature = Signature::from_slice(&sig_bytes).map_err(|e| LmsError::SecurityFault {
pipeline_step: "Phase 0: Security Gate".to_string(),
context: "Signature Parsing".to_string(),
reason: format!("Invalid Ed25519 signature format: {e}"),
})?;
verifying_key.verify(payload.as_bytes(), &signature).map_err(|_| LmsError::SecurityFault {
pipeline_step: "Phase 0: Security Gate".to_string(),
context: "Cryptographic Validation".to_string(),
reason: "CRITICAL: Snapshot signature does not match the authoritative Public Key!"
.to_string(),
})?;
Ok(())
}
#[cfg(all(test, feature = "simulation"))]
mod tests {
use super::*;
use ed25519_dalek::{Signer, SigningKey};
use rand::rngs::OsRng;
fn generate_test_credentials(payload: &str) -> (String, String) {
let mut csprng = OsRng;
let signing_key = SigningKey::generate(&mut csprng);
let public_key = BASE64.encode(signing_key.verifying_key().as_bytes());
let signature = BASE64.encode(signing_key.sign(payload.as_bytes()).to_bytes());
(signature, public_key)
}
#[test]
fn test_verify_passes_valid_signature() {
let payload = "{\"registry\": \"data\"}";
let (valid_sig, pub_key) = generate_test_credentials(payload);
assert!(verify_snapshot(payload, &valid_sig, &pub_key).is_ok());
}
#[test]
fn test_verify_catches_invalid_signature() {
let payload = "{\"registry\": \"data\"}";
let (_, pub_key) = generate_test_credentials(payload);
let forged_bytes = [0u8; 64];
let forged_sig = BASE64.encode(forged_bytes);
let err = verify_snapshot(payload, &forged_sig, &pub_key)
.expect_err("LMS-TEST: Forged signature must fail validation");
assert!(matches!(err, LmsError::SecurityFault { .. }));
}
#[test]
fn test_verify_catches_malformed_base64() {
let payload = "{\"registry\": \"data\"}";
let err = verify_snapshot(payload, "invalid_b64!@#", "invalid_b64!@#")
.expect_err("LMS-TEST: Malformed Base64 must fail during parsing");
assert!(matches!(err, LmsError::SecurityFault { .. }));
}
}