#![allow(missing_docs)]
use sha2::Digest as Sha2Digest;
use sha3::Digest as Sha3Digest;
use uor_foundation::enforcement::{Hasher, ShapeViolation};
use uor_foundation::pipeline::AxisExtension;
use uor_foundation_sdk::axis;
axis! {
pub trait HashAxis: AxisExtension {
const AXIS_ADDRESS: &'static str = "https://uor.foundation/axis/HashAxis";
const MAX_OUTPUT_BYTES: usize = 64;
fn hash(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation>;
}
}
fn out_too_small_violation() -> ShapeViolation {
ShapeViolation {
shape_iri: "https://uor.foundation/axis/HashAxis",
constraint_iri: "https://uor.foundation/axis/HashAxis/outputBuffer",
property_iri: "https://uor.foundation/axis/outputBufferBytes",
expected_range: "https://uor.foundation/axis/DigestBytesFit",
min_count: 0,
max_count: 0,
kind: uor_foundation::ViolationKind::ValueCheck,
}
}
const SHA256_BYTES: usize = 32;
#[derive(Debug, Clone)]
pub struct Sha256Hasher {
inner: sha2::Sha256,
}
impl Default for Sha256Hasher {
fn default() -> Self {
Self::initial()
}
}
impl HashAxis for Sha256Hasher {
const AXIS_ADDRESS: &'static str = "https://uor.foundation/axis/HashAxis/Sha256";
const MAX_OUTPUT_BYTES: usize = SHA256_BYTES;
fn hash(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation> {
if out.len() < SHA256_BYTES {
return Err(out_too_small_violation());
}
let digest = sha2::Sha256::digest(input);
out[..SHA256_BYTES].copy_from_slice(&digest);
Ok(SHA256_BYTES)
}
}
axis_extension_impl_for_hash_axis!(Sha256Hasher);
impl Hasher for Sha256Hasher {
const OUTPUT_BYTES: usize = SHA256_BYTES;
fn initial() -> Self {
Self {
inner: sha2::Sha256::new(),
}
}
fn fold_byte(mut self, b: u8) -> Self {
Sha2Digest::update(&mut self.inner, [b]);
self
}
fn fold_bytes(mut self, bytes: &[u8]) -> Self {
Sha2Digest::update(&mut self.inner, bytes);
self
}
fn finalize(self) -> [u8; 32] {
let result = Sha2Digest::finalize(self.inner);
let mut out = [0u8; 32];
out.copy_from_slice(&result);
out
}
}
const SHA512_BYTES: usize = 64;
#[derive(Debug, Clone)]
pub struct Sha512Hasher {
inner: sha2::Sha512,
}
impl Default for Sha512Hasher {
fn default() -> Self {
<Self as Hasher<64>>::initial()
}
}
impl HashAxis for Sha512Hasher {
const AXIS_ADDRESS: &'static str = "https://uor.foundation/axis/HashAxis/Sha512";
const MAX_OUTPUT_BYTES: usize = SHA512_BYTES;
fn hash(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation> {
if out.len() < SHA512_BYTES {
return Err(out_too_small_violation());
}
let digest = sha2::Sha512::digest(input);
out[..SHA512_BYTES].copy_from_slice(&digest);
Ok(SHA512_BYTES)
}
}
axis_extension_impl_for_hash_axis!(Sha512Hasher);
impl Hasher<64> for Sha512Hasher {
const OUTPUT_BYTES: usize = SHA512_BYTES;
fn initial() -> Self {
Self {
inner: sha2::Sha512::new(),
}
}
fn fold_byte(mut self, b: u8) -> Self {
Sha2Digest::update(&mut self.inner, [b]);
self
}
fn fold_bytes(mut self, bytes: &[u8]) -> Self {
Sha2Digest::update(&mut self.inner, bytes);
self
}
fn finalize(self) -> [u8; 64] {
let result = Sha2Digest::finalize(self.inner);
let mut out = [0u8; 64];
out.copy_from_slice(&result);
out
}
}
const SHA3_256_BYTES: usize = 32;
#[derive(Debug, Clone)]
pub struct Sha3_256Hasher {
inner: sha3::Sha3_256,
}
impl Default for Sha3_256Hasher {
fn default() -> Self {
Self::initial()
}
}
impl HashAxis for Sha3_256Hasher {
const AXIS_ADDRESS: &'static str = "https://uor.foundation/axis/HashAxis/Sha3_256";
const MAX_OUTPUT_BYTES: usize = SHA3_256_BYTES;
fn hash(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation> {
if out.len() < SHA3_256_BYTES {
return Err(out_too_small_violation());
}
let digest = sha3::Sha3_256::digest(input);
out[..SHA3_256_BYTES].copy_from_slice(&digest);
Ok(SHA3_256_BYTES)
}
}
axis_extension_impl_for_hash_axis!(Sha3_256Hasher);
impl Hasher for Sha3_256Hasher {
const OUTPUT_BYTES: usize = SHA3_256_BYTES;
fn initial() -> Self {
Self {
inner: sha3::Sha3_256::new(),
}
}
fn fold_byte(mut self, b: u8) -> Self {
Sha3Digest::update(&mut self.inner, [b]);
self
}
fn fold_bytes(mut self, bytes: &[u8]) -> Self {
Sha3Digest::update(&mut self.inner, bytes);
self
}
fn finalize(self) -> [u8; 32] {
let result = Sha3Digest::finalize(self.inner);
let mut out = [0u8; 32];
out.copy_from_slice(&result);
out
}
}
const KECCAK256_BYTES: usize = 32;
#[derive(Debug, Clone)]
pub struct Keccak256Hasher {
inner: sha3::Keccak256,
}
impl Default for Keccak256Hasher {
fn default() -> Self {
Self::initial()
}
}
impl HashAxis for Keccak256Hasher {
const AXIS_ADDRESS: &'static str = "https://uor.foundation/axis/HashAxis/Keccak256";
const MAX_OUTPUT_BYTES: usize = KECCAK256_BYTES;
fn hash(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation> {
if out.len() < KECCAK256_BYTES {
return Err(out_too_small_violation());
}
let digest = sha3::Keccak256::digest(input);
out[..KECCAK256_BYTES].copy_from_slice(&digest);
Ok(KECCAK256_BYTES)
}
}
axis_extension_impl_for_hash_axis!(Keccak256Hasher);
impl Hasher for Keccak256Hasher {
const OUTPUT_BYTES: usize = KECCAK256_BYTES;
fn initial() -> Self {
Self {
inner: sha3::Keccak256::new(),
}
}
fn fold_byte(mut self, b: u8) -> Self {
Sha3Digest::update(&mut self.inner, [b]);
self
}
fn fold_bytes(mut self, bytes: &[u8]) -> Self {
Sha3Digest::update(&mut self.inner, bytes);
self
}
fn finalize(self) -> [u8; 32] {
let result = Sha3Digest::finalize(self.inner);
let mut out = [0u8; 32];
out.copy_from_slice(&result);
out
}
}
const BLAKE3_BYTES: usize = 32;
#[derive(Debug, Clone, Default)]
pub struct Blake3Hasher {
inner: blake3::Hasher,
}
impl HashAxis for Blake3Hasher {
const AXIS_ADDRESS: &'static str = "https://uor.foundation/axis/HashAxis/Blake3";
const MAX_OUTPUT_BYTES: usize = BLAKE3_BYTES;
fn hash(input: &[u8], out: &mut [u8]) -> Result<usize, ShapeViolation> {
if out.len() < BLAKE3_BYTES {
return Err(out_too_small_violation());
}
let digest = blake3::hash(input);
out[..BLAKE3_BYTES].copy_from_slice(digest.as_bytes());
Ok(BLAKE3_BYTES)
}
}
axis_extension_impl_for_hash_axis!(Blake3Hasher);
impl Hasher for Blake3Hasher {
const OUTPUT_BYTES: usize = BLAKE3_BYTES;
fn initial() -> Self {
Self::default()
}
fn fold_byte(mut self, b: u8) -> Self {
self.inner.update(&[b]);
self
}
fn fold_bytes(mut self, bytes: &[u8]) -> Self {
self.inner.update(bytes);
self
}
fn finalize(self) -> [u8; 32] {
*self.inner.finalize().as_bytes()
}
}