#![no_std]
#![warn(missing_docs, rust_2018_idioms)]
use core::fmt;
#[cfg(feature = "std")]
extern crate std;
mod sha1;
use crate::sha1 as sys;
mod ubc_check;
pub use generic_array;
use generic_array::{GenericArray, typenum::consts::U20};
pub type Output = GenericArray<u8, U20>;
#[derive(Default)]
pub struct Builder(sys::SHA1_CTX);
impl Builder {
pub fn safe_hash(mut self, v: bool) -> Self {
self.0.set_safe_hash(v);
self
}
pub fn use_ubc(mut self, v: bool) -> Self {
self.0.set_use_UBC(v);
self
}
pub fn detect_collisions(mut self, v: bool) -> Self {
self.0.set_use_detect_coll(v);
self
}
pub fn build(self) -> Sha1CD {
Sha1CD(self.0)
}
}
#[derive(Clone)]
pub struct Sha1CD(sys::SHA1_CTX);
impl fmt::Debug for Sha1CD {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Sha1CD { ... }")
}
}
impl Default for Sha1CD {
fn default() -> Self {
Builder::default().build()
}
}
#[cfg(feature = "digest-trait")]
pub use digest::{self, Digest};
#[cfg(feature = "digest-trait")]
use digest::{FixedOutput, HashMarker, OutputSizeUser, Reset, Update};
#[cfg(feature = "digest-trait")]
type DigestOutput = digest::generic_array::GenericArray<
u8, digest::generic_array::typenum::consts::U20>;
#[cfg(feature = "digest-trait")]
impl HashMarker for Sha1CD {}
#[cfg(feature = "digest-trait")]
impl Update for Sha1CD {
fn update(&mut self, input: &[u8]) {
Sha1CD::update(self, input);
}
}
#[cfg(feature = "digest-trait")]
impl Reset for Sha1CD {
fn reset(&mut self) {
Sha1CD::reset(self);
}
}
#[cfg(feature = "digest-trait")]
impl OutputSizeUser for Sha1CD {
type OutputSize = digest::generic_array::typenum::consts::U20;
}
#[cfg(feature = "digest-trait")]
impl FixedOutput for Sha1CD {
fn finalize_into(mut self, out: &mut DigestOutput) {
let mut digest = Output::default();
let _ = self.finalize_into_dirty_cd(&mut digest);
out.copy_from_slice(&digest);
}
}
#[cfg(feature = "oid")]
use const_oid::{AssociatedOid, ObjectIdentifier};
#[cfg(feature = "oid")]
impl AssociatedOid for Sha1CD {
const OID: ObjectIdentifier =
ObjectIdentifier::new_unwrap("1.3.14.3.2.26");
}
impl Sha1CD {
pub fn configure() -> Builder {
Builder::default()
}
pub fn update(&mut self, input: impl AsRef<[u8]>) {
self.0.update(input.as_ref());
}
pub fn reset(&mut self) {
let safe_hash = self.0.safe_hash;
let ubc_check = self.0.ubc_check;
let detect_coll = self.0.detect_coll;
let reduced_round_coll = self.0.reduced_round_coll;
let callback = self.0.callback;
self.0.reset();
self.0.safe_hash = safe_hash;
self.0.ubc_check = ubc_check;
self.0.detect_coll = detect_coll;
self.0.reduced_round_coll = reduced_round_coll;
self.0.callback = callback;
}
pub fn finalize_cd(mut self)
-> Result<Output, Collision> {
let mut digest = Output::default();
self.finalize_into_dirty_cd(&mut digest)?;
Ok(digest)
}
pub fn finalize_reset_cd(&mut self)
-> Result<Output, Collision> {
let mut digest = Output::default();
self.finalize_into_dirty_cd(&mut digest)?;
Sha1CD::reset(self);
Ok(digest)
}
pub fn finalize_into_dirty_cd(&mut self, out: &mut Output)
-> Result<(), Collision> {
if ! self.0.finalize(out.as_mut()) {
Ok(())
} else {
Err(Collision::new())
}
}
}
#[cfg(feature = "std")]
impl std::io::Write for Sha1CD {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
Sha1CD::update(self, buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Collision {
}
impl fmt::Display for Collision {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("SHA-1 Collision detected")
}
}
impl Collision {
fn new() -> Self {
Collision {
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Collision {}