crate::ix!();
pub unsafe fn sha256_initialize_tagged(
hash: *mut Sha256,
tag: *const u8,
taglen: usize
) {
let mut buf: [u8; 32] = [0; 32];
sha256_initialize((*hash).s_mut().as_mut_ptr());
sha256_write(hash, tag, taglen);
sha256_finalize(hash, buf.as_mut_ptr());
(*hash).reset();
sha256_write(hash, buf.as_ptr(), 32);
sha256_write(hash, buf.as_ptr(), 32);
}
#[cfg(test)]
mod sha256_initialize_tagged_contract_validation {
use super::*;
use std::{io::Write, ptr::null};
use hex_literal::hex;
fn sha256_once(tag: &[u8]) -> [u8; 32] {
let mut out = [0u8; 32];
let mut ctx = Sha256::new();
ctx.write_all(tag).unwrap();
ctx.finalize(&mut out);
out
}
#[traced_test]
fn tagged_initialisation_matches_explicit_prefix_path() {
const TAG: &[u8] = b"example-tag";
const MSG: &[u8] = b"hello-tagged-world";
let tag_hash = sha256_once(TAG);
let mut ref_ctx = Sha256::new();
ref_ctx.write_all(&tag_hash).unwrap();
ref_ctx.write_all(&tag_hash).unwrap();
ref_ctx.write_all(MSG).unwrap();
let mut digest_ref = [0u8; 32];
ref_ctx.finalize(&mut digest_ref);
let mut ctx_tagged = Sha256::new();
unsafe {
sha256_initialize_tagged(
&mut ctx_tagged,
TAG.as_ptr(),
TAG.len(),
);
}
ctx_tagged.write_all(MSG).unwrap();
let mut digest_tagged = [0u8; 32];
ctx_tagged.finalize(&mut digest_tagged);
assert_eq!(
digest_tagged, digest_ref,
"tagged initialisation produced wrong digest"
);
}
#[traced_test]
fn empty_tag_behaviour_is_consistent() {
const MSG: &[u8] = b"data-with-empty-tag";
let tag_hash = sha256_once(b"");
let mut ref_ctx = Sha256::new();
ref_ctx.write_all(&tag_hash).unwrap();
ref_ctx.write_all(&tag_hash).unwrap();
ref_ctx.write_all(MSG).unwrap();
let mut digest_ref = [0u8; 32];
ref_ctx.finalize(&mut digest_ref);
let mut ctx = Sha256::new();
unsafe { sha256_initialize_tagged(&mut ctx, null(), 0) };
ctx.write_all(MSG).unwrap();
let mut digest_sut = [0u8; 32];
ctx.finalize(&mut digest_sut);
assert_eq!(digest_sut, digest_ref, "empty-tag initialisation mismatch");
}
}