use core::ops::{Deref, DerefMut};
use super::digest::{Algorithm, Digest, SHA1, SHA256, SHA384, SHA512, SHA512_256};
use crate::mid::{sha1, sha2};
#[derive(Copy, Clone)]
pub(crate) struct HashBlock {
buf: [u8; 128],
len: usize,
}
impl HashBlock {
fn new(len: usize) -> Self {
Self {
buf: [0u8; 128],
len,
}
}
}
impl Deref for HashBlock {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.buf[..self.len]
}
}
impl DerefMut for HashBlock {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.buf[..self.len]
}
}
pub(crate) trait Hash {
type Context: HashContext;
const ALGORITHM: &'static Algorithm;
fn new() -> Self::Context;
fn hash(bytes: &[u8]) -> Digest {
let mut ctx = Self::new();
ctx.update(bytes);
ctx.finish()
}
fn zeroed_block() -> HashBlock;
fn zeroed_output() -> Digest {
Digest::zeroed(Self::ALGORITHM)
}
}
pub(crate) trait SignatureHash: Hash {}
pub(crate) trait HashContext: Clone {
fn update(&mut self, bytes: &[u8]);
fn finish(self) -> Digest;
fn finish_block(&self, tail: &[u8]) -> Digest;
}
#[derive(Clone)]
pub(crate) struct LegacySha1;
impl Hash for LegacySha1 {
type Context = sha1::Sha1Context;
const ALGORITHM: &'static Algorithm = &SHA1;
fn new() -> Self::Context {
sha1::Sha1Context::new()
}
fn zeroed_block() -> HashBlock {
HashBlock::new(sha1::Sha1Context::BLOCK_SZ)
}
}
impl HashContext for sha1::Sha1Context {
fn update(&mut self, bytes: &[u8]) {
Self::update(self, bytes)
}
fn finish(self) -> Digest {
Digest::new(LegacySha1::ALGORITHM, &Self::finish(self))
}
fn finish_block(&self, tail: &[u8]) -> Digest {
Digest::new(LegacySha1::ALGORITHM, &Self::finish_block(self, tail))
}
}
#[derive(Clone)]
pub(crate) struct Sha256;
impl Hash for Sha256 {
type Context = sha2::Sha256Context;
const ALGORITHM: &'static Algorithm = &SHA256;
fn new() -> Self::Context {
sha2::Sha256Context::new()
}
fn zeroed_block() -> HashBlock {
HashBlock::new(sha2::Sha256Context::BLOCK_SZ)
}
}
impl SignatureHash for Sha256 {}
impl HashContext for sha2::Sha256Context {
fn update(&mut self, bytes: &[u8]) {
Self::update(self, bytes)
}
fn finish(self) -> Digest {
Digest::new(Sha256::ALGORITHM, &Self::finish(self))
}
fn finish_block(&self, tail: &[u8]) -> Digest {
Digest::new(Sha256::ALGORITHM, &Self::finish_block(self, tail))
}
}
#[derive(Clone)]
pub(crate) struct Sha384;
impl Hash for Sha384 {
type Context = sha2::Sha384Context;
const ALGORITHM: &'static Algorithm = &SHA384;
fn new() -> Self::Context {
sha2::Sha384Context::new()
}
fn zeroed_block() -> HashBlock {
HashBlock::new(sha2::Sha512Context::BLOCK_SZ)
}
}
impl SignatureHash for Sha384 {}
impl HashContext for sha2::Sha384Context {
fn update(&mut self, bytes: &[u8]) {
Self::update(self, bytes)
}
fn finish(self) -> Digest {
Digest::new(Sha384::ALGORITHM, &Self::finish(self))
}
fn finish_block(&self, tail: &[u8]) -> Digest {
Digest::new(Sha384::ALGORITHM, &Self::finish_block(self, tail))
}
}
#[derive(Clone)]
pub(crate) struct Sha512;
impl Hash for Sha512 {
type Context = sha2::Sha512Context;
const ALGORITHM: &'static Algorithm = &SHA512;
fn new() -> Self::Context {
sha2::Sha512Context::new()
}
fn zeroed_block() -> HashBlock {
HashBlock::new(sha2::Sha512Context::BLOCK_SZ)
}
}
impl SignatureHash for Sha512 {}
impl HashContext for sha2::Sha512Context {
fn update(&mut self, bytes: &[u8]) {
Self::update(self, bytes)
}
fn finish(self) -> Digest {
Digest::new(Sha512::ALGORITHM, &Self::finish(self))
}
fn finish_block(&self, tail: &[u8]) -> Digest {
Digest::new(Sha512::ALGORITHM, &Self::finish_block(self, tail))
}
}
impl HashContext for sha2::Sha512_256Context {
fn update(&mut self, bytes: &[u8]) {
Self::update(self, bytes)
}
fn finish(self) -> Digest {
Digest::new(&SHA512_256, &Self::finish(self))
}
fn finish_block(&self, tail: &[u8]) -> Digest {
Digest::new(&SHA512_256, &Self::finish_block(self, tail))
}
}