use core::ops::{Deref, DerefMut};
use super::digest::{Algorithm, Digest, SHA1, SHA256, SHA384, SHA512};
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;
type State: HashState<Context = Self::Context>;
const ALGORITHM: &'static Algorithm;
fn initial() -> Self::State;
fn new() -> Self::Context;
fn hash(bytes: &[u8]) -> Digest {
Self::initial().finish_with(bytes)
}
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;
}
pub(crate) trait HashState: Clone {
type Context;
fn update_blocks(&mut self, blocks: &[u8]);
fn finish_with(&self, message: &[u8]) -> Digest;
fn resume(&self) -> Self::Context;
}
#[derive(Clone)]
pub(crate) struct LegacySha1;
impl Hash for LegacySha1 {
type Context = Sha1Context;
type State = Sha1State;
const ALGORITHM: &'static Algorithm = &SHA1;
fn new() -> Self::Context {
Sha1Context(sha1::Sha1Context::new())
}
fn initial() -> Self::State {
Sha1State(sha1::Sha1State::new())
}
fn zeroed_block() -> HashBlock {
HashBlock::new(sha1::Sha1Context::BLOCK_SZ)
}
}
#[derive(Clone)]
pub(crate) struct Sha1Context(sha1::Sha1Context);
impl HashContext for Sha1Context {
fn update(&mut self, bytes: &[u8]) {
self.0.update(bytes)
}
fn finish(&self) -> Digest {
Digest::new(LegacySha1::ALGORITHM, &self.0.finish())
}
}
#[derive(Clone)]
pub(crate) struct Sha1State(sha1::Sha1State);
impl HashState for Sha1State {
type Context = Sha1Context;
fn update_blocks(&mut self, blocks: &[u8]) {
self.0.update_blocks(blocks)
}
fn finish_with(&self, message: &[u8]) -> Digest {
Digest::new(LegacySha1::ALGORITHM, &self.0.finish_with(message))
}
fn resume(&self) -> Self::Context {
Sha1Context(sha1::Sha1Context::resume(self.0.clone()))
}
}
#[derive(Clone)]
pub(crate) struct Sha256;
impl Hash for Sha256 {
type Context = Sha256Context;
type State = Sha256State;
const ALGORITHM: &'static Algorithm = &SHA256;
fn new() -> Self::Context {
Sha256Context(sha2::Sha256Context::new())
}
fn initial() -> Self::State {
Sha256State(sha2::Sha256State::new())
}
fn zeroed_block() -> HashBlock {
HashBlock::new(sha2::Sha256Context::BLOCK_SZ)
}
}
impl SignatureHash for Sha256 {}
#[derive(Clone)]
pub(crate) struct Sha256Context(sha2::Sha256Context);
impl HashContext for Sha256Context {
fn update(&mut self, bytes: &[u8]) {
self.0.update(bytes)
}
fn finish(&self) -> Digest {
Digest::new(Sha256::ALGORITHM, &self.0.finish())
}
}
#[derive(Clone)]
pub(crate) struct Sha256State(sha2::Sha256State);
impl HashState for Sha256State {
type Context = Sha256Context;
fn update_blocks(&mut self, blocks: &[u8]) {
self.0.update_blocks(blocks)
}
fn finish_with(&self, message: &[u8]) -> Digest {
Digest::new(Sha256::ALGORITHM, &self.0.finish_with(message))
}
fn resume(&self) -> Self::Context {
Sha256Context(sha2::Sha256Context::resume(self.0.clone()))
}
}
#[derive(Clone)]
pub(crate) struct Sha384;
impl Hash for Sha384 {
type Context = Sha384Context;
type State = Sha384State;
const ALGORITHM: &'static Algorithm = &SHA384;
fn new() -> Self::Context {
Sha384Context(sha2::Sha384Context::new())
}
fn initial() -> Self::State {
Sha384State(sha2::Sha384Context::INITIAL)
}
fn zeroed_block() -> HashBlock {
HashBlock::new(sha2::Sha512Context::BLOCK_SZ)
}
}
impl SignatureHash for Sha384 {}
#[derive(Clone)]
pub(crate) struct Sha384Context(sha2::Sha384Context);
impl HashContext for Sha384Context {
fn update(&mut self, bytes: &[u8]) {
self.0.update(bytes)
}
fn finish(&self) -> Digest {
Digest::new(Sha384::ALGORITHM, &self.0.finish())
}
}
#[derive(Clone)]
pub(crate) struct Sha384State(sha2::Sha512State);
impl HashState for Sha384State {
type Context = Sha384Context;
fn update_blocks(&mut self, blocks: &[u8]) {
self.0.update_blocks(blocks)
}
fn finish_with(&self, message: &[u8]) -> Digest {
Digest::new(
Sha384::ALGORITHM,
&sha2::Sha384Context::truncate(&self.0.finish_with(message)),
)
}
fn resume(&self) -> Self::Context {
Sha384Context(sha2::Sha384Context::resume(self.0.clone()))
}
}
#[derive(Clone)]
pub(crate) struct Sha512;
impl Hash for Sha512 {
type Context = Sha512Context;
type State = Sha512State;
const ALGORITHM: &'static Algorithm = &SHA512;
fn new() -> Self::Context {
Sha512Context(sha2::Sha512Context::new())
}
fn initial() -> Self::State {
Sha512State(sha2::Sha512State::new())
}
fn zeroed_block() -> HashBlock {
HashBlock::new(sha2::Sha512Context::BLOCK_SZ)
}
}
impl SignatureHash for Sha512 {}
#[derive(Clone)]
pub(crate) struct Sha512Context(sha2::Sha512Context);
impl HashContext for Sha512Context {
fn update(&mut self, bytes: &[u8]) {
self.0.update(bytes)
}
fn finish(&self) -> Digest {
Digest::new(Sha512::ALGORITHM, &self.0.finish())
}
}
#[derive(Clone)]
pub(crate) struct Sha512State(sha2::Sha512State);
impl HashState for Sha512State {
type Context = Sha512Context;
fn update_blocks(&mut self, blocks: &[u8]) {
self.0.update_blocks(blocks)
}
fn finish_with(&self, message: &[u8]) -> Digest {
Digest::new(Sha512::ALGORITHM, &self.0.finish_with(message))
}
fn resume(&self) -> Self::Context {
Sha512Context(sha2::Sha512Context::resume(self.0.clone()))
}
}