pub trait Hash {
const NAME: &'static str;
const HASH_LEN: usize;
fn hash(data: &[u8]) -> Vec<u8>;
fn hmac(key: &[u8], data: &[u8]) -> Vec<u8>;
fn hash_two(a: &[u8], b: &[u8]) -> Vec<u8>;
}
mod hmac_blake2 {
use cryptoxide::hashing::blake2b::{Blake2b as B2b, Context as CtxB};
use cryptoxide::hashing::blake2s::{Blake2s as B2s, Context as CtxS};
use cryptoxide::hmac::{Algorithm, Tag};
const IPAD: u8 = 0x36;
const OPAD: u8 = 0x5c;
pub(super) struct Blake2bHmac;
impl Algorithm for Blake2bHmac {
const BLOCK_SIZE: usize = B2b::<512>::BLOCK_BYTES;
const OUTPUT_SIZE: usize = B2b::<512>::OUTPUT_BITS / 8;
type Context = CtxB<512>;
type Output = [u8; Self::OUTPUT_SIZE];
type MacOutput = Tag<{ Self::OUTPUT_SIZE }>;
fn init(key: &[u8]) -> (Self::Context, Self::Context) {
let mut k = [0u8; Self::BLOCK_SIZE];
if key.len() <= Self::BLOCK_SIZE {
k[..key.len()].copy_from_slice(key);
} else {
let mut kh = B2b::<512>::new();
kh.update_mut(key);
let mut kd = kh.finalize();
k[..Self::OUTPUT_SIZE].copy_from_slice(&kd);
crate::zeroize::zeroize_array(&mut kd);
}
let mut inner = B2b::<512>::new();
let mut outer = B2b::<512>::new();
let mut mix = [0u8; Self::BLOCK_SIZE];
for (m, kb) in mix.iter_mut().zip(k.iter()) {
*m = kb ^ IPAD;
}
inner.update_mut(&mix);
for (m, kb) in mix.iter_mut().zip(k.iter()) {
*m = kb ^ OPAD;
}
outer.update_mut(&mix);
crate::zeroize::zeroize_array(&mut k);
crate::zeroize::zeroize_array(&mut mix);
(inner, outer)
}
fn update(context: &mut Self::Context, input: &[u8]) {
context.update_mut(input);
}
fn feed(context: &mut Self::Context, other: &mut Self::Context) {
let inner_digest = other.finalize_reset();
context.update_mut(&inner_digest);
}
fn finalize(context: &mut Self::Context) -> Self::MacOutput {
Tag(context.finalize_reset())
}
fn finalize_at(context: &mut Self::Context, out: &mut [u8]) {
context.finalize_reset_at(out);
}
}
pub(super) struct Blake2sHmac;
impl Algorithm for Blake2sHmac {
const BLOCK_SIZE: usize = B2s::<256>::BLOCK_BYTES;
const OUTPUT_SIZE: usize = B2s::<256>::OUTPUT_BITS / 8;
type Context = CtxS<256>;
type Output = [u8; Self::OUTPUT_SIZE];
type MacOutput = Tag<{ Self::OUTPUT_SIZE }>;
fn init(key: &[u8]) -> (Self::Context, Self::Context) {
let mut k = [0u8; Self::BLOCK_SIZE];
if key.len() <= Self::BLOCK_SIZE {
k[..key.len()].copy_from_slice(key);
} else {
let mut kh = B2s::<256>::new();
kh.update_mut(key);
let mut kd = kh.finalize();
k[..Self::OUTPUT_SIZE].copy_from_slice(&kd);
crate::zeroize::zeroize_array(&mut kd);
}
let mut inner = B2s::<256>::new();
let mut outer = B2s::<256>::new();
let mut mix = [0u8; Self::BLOCK_SIZE];
for (m, kb) in mix.iter_mut().zip(k.iter()) {
*m = kb ^ IPAD;
}
inner.update_mut(&mix);
for (m, kb) in mix.iter_mut().zip(k.iter()) {
*m = kb ^ OPAD;
}
outer.update_mut(&mix);
crate::zeroize::zeroize_array(&mut k);
crate::zeroize::zeroize_array(&mut mix);
(inner, outer)
}
fn update(context: &mut Self::Context, input: &[u8]) {
context.update_mut(input);
}
fn feed(context: &mut Self::Context, other: &mut Self::Context) {
let inner_digest = other.finalize_reset();
context.update_mut(&inner_digest);
}
fn finalize(context: &mut Self::Context) -> Self::MacOutput {
Tag(context.finalize_reset())
}
fn finalize_at(context: &mut Self::Context, out: &mut [u8]) {
context.finalize_reset_at(out);
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Blake2b;
impl Hash for Blake2b {
const NAME: &'static str = "BLAKE2b";
const HASH_LEN: usize = 64;
fn hash(data: &[u8]) -> Vec<u8> {
use cryptoxide::hashing::blake2b::Blake2b as B2b;
let mut ctx = B2b::<512>::new();
ctx.update_mut(data);
ctx.finalize().to_vec()
}
fn hmac(key: &[u8], data: &[u8]) -> Vec<u8> {
use cryptoxide::hmac;
let mut ctx = hmac::Context::<hmac_blake2::Blake2bHmac>::new(key);
ctx.update(data);
ctx.finalize().0.to_vec()
}
fn hash_two(a: &[u8], b: &[u8]) -> Vec<u8> {
use cryptoxide::hashing::blake2b::Blake2b as B2b;
let mut ctx = B2b::<512>::new();
ctx.update_mut(a);
ctx.update_mut(b);
ctx.finalize().to_vec()
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Blake2s;
impl Hash for Blake2s {
const NAME: &'static str = "BLAKE2s";
const HASH_LEN: usize = 32;
fn hash(data: &[u8]) -> Vec<u8> {
use cryptoxide::hashing::blake2s::Blake2s as B2s;
let mut ctx = B2s::<256>::new();
ctx.update_mut(data);
ctx.finalize().to_vec()
}
fn hmac(key: &[u8], data: &[u8]) -> Vec<u8> {
use cryptoxide::hmac;
let mut ctx = hmac::Context::<hmac_blake2::Blake2sHmac>::new(key);
ctx.update(data);
ctx.finalize().0.to_vec()
}
fn hash_two(a: &[u8], b: &[u8]) -> Vec<u8> {
use cryptoxide::hashing::blake2s::Blake2s as B2s;
let mut ctx = B2s::<256>::new();
ctx.update_mut(a);
ctx.update_mut(b);
ctx.finalize().to_vec()
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Sha256;
impl Hash for Sha256 {
const NAME: &'static str = "SHA256";
const HASH_LEN: usize = 32;
fn hash(data: &[u8]) -> Vec<u8> {
use cryptoxide::hashing::sha2::Sha256 as S256;
let mut ctx = S256::new();
ctx.update_mut(data);
ctx.finalize().to_vec()
}
fn hmac(key: &[u8], data: &[u8]) -> Vec<u8> {
use cryptoxide::hashing::sha2::Sha256 as S256;
use cryptoxide::hmac;
let mut ctx = hmac::Context::<S256>::new(key);
ctx.update(data);
ctx.finalize().0.to_vec()
}
fn hash_two(a: &[u8], b: &[u8]) -> Vec<u8> {
use cryptoxide::hashing::sha2::Sha256 as S256;
let mut ctx = S256::new();
ctx.update_mut(a);
ctx.update_mut(b);
ctx.finalize().to_vec()
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Sha512;
impl Hash for Sha512 {
const NAME: &'static str = "SHA512";
const HASH_LEN: usize = 64;
fn hash(data: &[u8]) -> Vec<u8> {
use cryptoxide::hashing::sha2::Sha512 as S512;
let mut ctx = S512::new();
ctx.update_mut(data);
ctx.finalize().to_vec()
}
fn hmac(key: &[u8], data: &[u8]) -> Vec<u8> {
use cryptoxide::hashing::sha2::Sha512 as S512;
use cryptoxide::hmac;
let mut ctx = hmac::Context::<S512>::new(key);
ctx.update(data);
ctx.finalize().0.to_vec()
}
fn hash_two(a: &[u8], b: &[u8]) -> Vec<u8> {
use cryptoxide::hashing::sha2::Sha512 as S512;
let mut ctx = S512::new();
ctx.update_mut(a);
ctx.update_mut(b);
ctx.finalize().to_vec()
}
}