use super::proof_certificate::{ProofCertificate, Verified};
use sha2::{Digest, Sha256};
pub const SHA256_DETERMINISTIC_CERT: ProofCertificate = ProofCertificate::new(
100, 1, 2026_0205, 0, );
pub const SHA256_NON_DEGENERATE_CERT: ProofCertificate = ProofCertificate::new(
101, 1, 2026_0205, 1, );
pub const CHAIN_HASH_GENESIS_INTEGRITY_CERT: ProofCertificate = ProofCertificate::new(
102, 1, 2026_0205, 1, );
pub struct VerifiedSha256;
impl VerifiedSha256 {
pub fn hash(data: &[u8]) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(data);
let result: [u8; 32] = hasher.finalize().into();
assert_ne!(
result, [0u8; 32],
"SHA-256 produced all zeros (violation of non_degenerate theorem)"
);
result
}
pub fn chain_hash(prev_hash: Option<&[u8; 32]>, data: &[u8]) -> [u8; 32] {
match prev_hash {
None => {
Self::hash(data)
}
Some(prev) => {
let mut hasher = Sha256::new();
hasher.update(prev);
hasher.update(data);
let result: [u8; 32] = hasher.finalize().into();
assert_ne!(result, [0u8; 32]);
result
}
}
}
}
impl Verified for VerifiedSha256 {
fn proof_certificate() -> ProofCertificate {
SHA256_DETERMINISTIC_CERT
}
fn theorem_name() -> &'static str {
"sha256_deterministic"
}
fn theorem_description() -> &'static str {
"SHA-256 is deterministic: hashing the same input always produces the same output"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sha256_deterministic() {
let data = b"test data";
let hash1 = VerifiedSha256::hash(data);
let hash2 = VerifiedSha256::hash(data);
assert_eq!(hash1, hash2);
}
#[test]
fn test_sha256_non_degenerate() {
let data = b"any data";
let hash = VerifiedSha256::hash(data);
assert_ne!(hash, [0u8; 32]);
}
#[test]
fn test_sha256_different_inputs_different_outputs() {
let hash1 = VerifiedSha256::hash(b"data1");
let hash2 = VerifiedSha256::hash(b"data2");
assert_ne!(hash1, hash2);
}
#[test]
fn test_chain_hash_genesis() {
let genesis1 = VerifiedSha256::chain_hash(None, b"genesis data");
let genesis2 = VerifiedSha256::chain_hash(None, b"genesis data");
assert_eq!(genesis1, genesis2);
}
#[test]
fn test_chain_hash_different_genesis() {
let genesis1 = VerifiedSha256::chain_hash(None, b"data1");
let genesis2 = VerifiedSha256::chain_hash(None, b"data2");
assert_ne!(genesis1, genesis2);
}
#[test]
fn test_chain_hash_chaining() {
let genesis = VerifiedSha256::chain_hash(None, b"block 0");
let block1 = VerifiedSha256::chain_hash(Some(&genesis), b"block 1");
let block2 = VerifiedSha256::chain_hash(Some(&block1), b"block 2");
assert_ne!(genesis, block1);
assert_ne!(block1, block2);
let block2_again = VerifiedSha256::chain_hash(Some(&block1), b"block 2");
assert_eq!(block2, block2_again);
}
#[test]
fn test_proof_certificate() {
let cert = VerifiedSha256::proof_certificate();
assert_eq!(cert.theorem_id, 100);
assert_eq!(cert.proof_system_id, 1);
assert_eq!(cert.verified_at, 20_260_205);
assert_eq!(cert.assumption_count, 0);
assert!(cert.is_complete());
}
#[test]
fn test_verified_trait() {
assert_eq!(VerifiedSha256::theorem_name(), "sha256_deterministic");
assert!(VerifiedSha256::theorem_description().contains("deterministic"));
}
#[test]
fn test_matches_existing_implementation() {
use sha2::{Digest, Sha256};
let data = b"test compatibility";
let verified_hash = VerifiedSha256::hash(data);
let mut hasher = Sha256::new();
hasher.update(data);
let direct_hash: [u8; 32] = hasher.finalize().into();
assert_eq!(verified_hash, direct_hash);
}
}
#[cfg(test)]
mod proptests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn prop_sha256_deterministic(data in prop::collection::vec(any::<u8>(), 0..10000)) {
let hash1 = VerifiedSha256::hash(&data);
let hash2 = VerifiedSha256::hash(&data);
prop_assert_eq!(hash1, hash2);
}
#[test]
fn prop_different_inputs_different_hashes(
data1 in prop::collection::vec(any::<u8>(), 1..1000),
data2 in prop::collection::vec(any::<u8>(), 1..1000)
) {
prop_assume!(data1 != data2);
let hash1 = VerifiedSha256::hash(&data1);
let hash2 = VerifiedSha256::hash(&data2);
prop_assert_ne!(hash1, hash2);
}
#[test]
fn prop_sha256_non_degenerate(data in prop::collection::vec(any::<u8>(), 0..10000)) {
let hash = VerifiedSha256::hash(&data);
prop_assert_ne!(hash, [0u8; 32]);
}
#[test]
fn prop_chain_hash_genesis_unique(
data1 in prop::collection::vec(any::<u8>(), 1..1000),
data2 in prop::collection::vec(any::<u8>(), 1..1000)
) {
prop_assume!(data1 != data2);
let genesis1 = VerifiedSha256::chain_hash(None, &data1);
let genesis2 = VerifiedSha256::chain_hash(None, &data2);
prop_assert_ne!(genesis1, genesis2);
}
#[test]
fn prop_chain_hash_deterministic(
prev in prop::array::uniform32(any::<u8>()),
data in prop::collection::vec(any::<u8>(), 0..1000)
) {
let hash1 = VerifiedSha256::chain_hash(Some(&prev), &data);
let hash2 = VerifiedSha256::chain_hash(Some(&prev), &data);
prop_assert_eq!(hash1, hash2);
}
#[test]
fn prop_chain_hash_unique_per_step(
data1 in prop::collection::vec(any::<u8>(), 1..100),
data2 in prop::collection::vec(any::<u8>(), 1..100)
) {
prop_assume!(data1 != data2);
let genesis = VerifiedSha256::chain_hash(None, &data1);
let block1 = VerifiedSha256::chain_hash(Some(&genesis), &data2);
prop_assert_ne!(genesis, block1);
}
}
}