jh/
lib.rs

1//! Implementation of the [JH] cryptographic hash function.
2//!
3//! There are 4 standard versions of the JH hash function:
4//!
5//! * [JH-224][Jh224]
6//! * [JH-256][Jh256]
7//! * [JH-384][Jh384]
8//! * [JH-512][Jh512]
9//!
10//! # Examples
11//!
12//! Hash functionality is usually accessed via the [`Digest`] trait:
13//!
14//! ```
15//! use hex_literal::hex;
16//! use jh::{Digest, Jh256};
17//!
18//! // create a JH-256 object
19//! let mut hasher = Jh256::new();
20//!
21//! // write input message
22//! hasher.update(b"hello");
23//!
24//! // read hash digest
25//! let result = hasher.finalize();
26//!
27//! let expected = hex!("94fd3f4c564957c6754265676bf8b244c707d3ffb294e18af1f2e4f9b8306089");
28//! assert_eq!(result[..], expected[..]);
29//! ```
30//! Also see [RustCrypto/hashes] readme.
31//!
32//! [JH]: https://en.wikipedia.org/wiki/JH_(hash_function)
33//! [RustCrypto/hashes]: https://github.com/RustCrypto/hashes
34#![no_std]
35#![doc(
36    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
37    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
38)]
39#![warn(missing_docs, rust_2018_idioms)]
40
41mod compressor;
42mod consts;
43
44// This function is exported only for benchmarks
45pub use compressor::f8_impl;
46
47pub use digest::{self, Digest};
48
49use crate::compressor::Compressor;
50use core::fmt;
51use digest::{
52    block_buffer::Eager,
53    core_api::{
54        AlgorithmName, Block, Buffer, BufferKindUser, CoreWrapper, CtVariableCoreWrapper,
55        TruncSide, UpdateCore, VariableOutputCore,
56    },
57    crypto_common::{BlockSizeUser, OutputSizeUser},
58    generic_array::typenum::{Unsigned, U28, U32, U48, U64},
59    HashMarker, InvalidOutputSize, Output,
60};
61
62/// Core JH hasher state
63#[derive(Clone)]
64pub struct JhCore {
65    state: Compressor,
66    block_len: u64,
67}
68
69impl HashMarker for JhCore {}
70
71impl BlockSizeUser for JhCore {
72    type BlockSize = U64;
73}
74
75impl BufferKindUser for JhCore {
76    type BufferKind = Eager;
77}
78
79impl OutputSizeUser for JhCore {
80    type OutputSize = U64;
81}
82
83impl UpdateCore for JhCore {
84    #[inline]
85    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
86        self.block_len = self.block_len.wrapping_add(blocks.len() as u64);
87        for b in blocks {
88            self.state.update(b);
89        }
90    }
91}
92
93impl VariableOutputCore for JhCore {
94    const TRUNC_SIDE: TruncSide = TruncSide::Right;
95
96    #[inline]
97    fn new(output_size: usize) -> Result<Self, InvalidOutputSize> {
98        let h0 = match output_size {
99            28 => consts::JH224_H0,
100            32 => consts::JH256_H0,
101            48 => consts::JH384_H0,
102            64 => consts::JH512_H0,
103            _ => return Err(InvalidOutputSize),
104        };
105        Ok(Self {
106            state: Compressor::new(h0),
107            block_len: 0,
108        })
109    }
110
111    #[inline]
112    fn finalize_variable_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
113        let Self { state, block_len } = self;
114        let bit_len = block_len
115            .wrapping_mul(Self::BlockSize::U64)
116            .wrapping_add(buffer.get_pos() as u64)
117            .wrapping_mul(8);
118        if buffer.get_pos() == 0 {
119            buffer.len64_padding_be(bit_len, |b| state.update(b));
120        } else {
121            buffer.digest_pad(0x80, &[], |b| state.update(b));
122            buffer.digest_pad(0, &bit_len.to_be_bytes(), |b| state.update(b));
123        }
124        out.copy_from_slice(&self.state.finalize()[64..]);
125    }
126}
127
128impl AlgorithmName for JhCore {
129    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        f.write_str("Jh")
131    }
132}
133
134impl fmt::Debug for JhCore {
135    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136        f.write_str("JhCore { ... }")
137    }
138}
139
140/// Jh-224 hasher state
141pub type Jh224 = CoreWrapper<CtVariableCoreWrapper<JhCore, U28>>;
142/// Jh-256 hasher state
143pub type Jh256 = CoreWrapper<CtVariableCoreWrapper<JhCore, U32>>;
144/// Jh-384 hasher state
145pub type Jh384 = CoreWrapper<CtVariableCoreWrapper<JhCore, U48>>;
146/// Jh-512 hasher state
147pub type Jh512 = CoreWrapper<CtVariableCoreWrapper<JhCore, U64>>;