use super::address::Adrs;
use super::hash::TweakableHash;
use super::params::Params;
use tessera::{Digest, Sha256, Sha512, hmac_multi, mgf1};
pub struct Sha2Family;
#[inline]
fn padded_sha2<D: Digest>(pk_seed: &[u8], adrs_c: &[u8; 22], parts: &[&[u8]], n: usize, out: &mut [u8]) {
let mut h = D::new();
h.update(pk_seed); let zeros = [0u8; 128];
h.update(&zeros[..D::BLOCK_LEN - n]); h.update(adrs_c); for p in parts {
h.update(p);
}
let mut digest = [0u8; 64];
h.finalize(&mut digest[..D::OUTPUT_LEN]);
out[..n].copy_from_slice(&digest[..n]); }
#[inline]
fn h_msg_sha2<D: Digest>(r: &[u8], pk_seed: &[u8], pk_root: &[u8], m: &[u8], out: &mut [u8]) {
let mut h = D::new();
h.update(r);
h.update(pk_seed);
h.update(pk_root);
h.update(m);
let mut inner = [0u8; 64];
h.finalize(&mut inner[..D::OUTPUT_LEN]);
let mut seed = [0u8; 128];
let mut pos = 0;
seed[pos..pos + r.len()].copy_from_slice(r);
pos += r.len();
seed[pos..pos + pk_seed.len()].copy_from_slice(pk_seed);
pos += pk_seed.len();
seed[pos..pos + D::OUTPUT_LEN].copy_from_slice(&inner[..D::OUTPUT_LEN]);
pos += D::OUTPUT_LEN;
mgf1::<D>(&seed[..pos], out);
}
#[inline]
fn prf_msg_sha2<D: Digest>(sk_prf: &[u8], opt_rand: &[u8], m: &[u8], n: usize, out: &mut [u8]) {
let mut tag = [0u8; 64];
hmac_multi::<D>(sk_prf, &[opt_rand, m], &mut tag[..D::OUTPUT_LEN]);
out[..n].copy_from_slice(&tag[..n]); }
impl TweakableHash for Sha2Family {
fn h_msg_into<P: Params>(r: &[u8], pk_seed: &[u8], pk_root: &[u8], m: &[u8], out: &mut [u8]) {
if P::N == 16 {
h_msg_sha2::<Sha256>(r, pk_seed, pk_root, m, out);
} else {
h_msg_sha2::<Sha512>(r, pk_seed, pk_root, m, out);
}
}
fn prf_into<P: Params>(pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs, out: &mut [u8]) {
padded_sha2::<Sha256>(pk_seed, &adrs.as_bytes_compressed(), &[sk_seed], P::N, out);
}
fn prf_msg_into<P: Params>(sk_prf: &[u8], opt_rand: &[u8], m: &[u8], out: &mut [u8]) {
if P::N == 16 {
prf_msg_sha2::<Sha256>(sk_prf, opt_rand, m, P::N, out);
} else {
prf_msg_sha2::<Sha512>(sk_prf, opt_rand, m, P::N, out);
}
}
fn t_l_into<P: Params>(pk_seed: &[u8], adrs: &Adrs, m: &[u8], out: &mut [u8]) {
let c = adrs.as_bytes_compressed();
if P::N == 16 {
padded_sha2::<Sha256>(pk_seed, &c, &[m], P::N, out);
} else {
padded_sha2::<Sha512>(pk_seed, &c, &[m], P::N, out);
}
}
fn hash_h_into<P: Params>(pk_seed: &[u8], adrs: &Adrs, m1: &[u8], m2: &[u8], out: &mut [u8]) {
let c = adrs.as_bytes_compressed();
if P::N == 16 {
padded_sha2::<Sha256>(pk_seed, &c, &[m1, m2], P::N, out);
} else {
padded_sha2::<Sha512>(pk_seed, &c, &[m1, m2], P::N, out);
}
}
fn f_hash_into<P: Params>(pk_seed: &[u8], adrs: &Adrs, m1: &[u8], out: &mut [u8]) {
padded_sha2::<Sha256>(pk_seed, &adrs.as_bytes_compressed(), &[m1], P::N, out);
}
}