1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! Implementation of the [JH] cryptographic hash function.
//!
//! There are 4 standard versions of the JH hash function:
//!
//! * [JH-224][Jh224]
//! * [JH-256][Jh256]
//! * [JH-384][Jh384]
//! * [JH-512][Jh512]
//!
//! # Examples
//!
//! Hash functionality is usually accessed via the [`Digest`] trait:
//!
//! ```
//! use hex_literal::hex;
//! use jh::{Digest, Jh256};
//!
//! // create a JH-256 object
//! let mut hasher = Jh256::new();
//!
//! // write input message
//! hasher.update(b"hello");
//!
//! // read hash digest
//! let result = hasher.finalize();
//!
//! let expected = hex!("94fd3f4c564957c6754265676bf8b244c707d3ffb294e18af1f2e4f9b8306089");
//! assert_eq!(result[..], expected[..]);
//! ```
//! Also see [RustCrypto/hashes] readme.
//!
//! [JH]: https://en.wikipedia.org/wiki/JH_(hash_function)
//! [RustCrypto/hashes]: https://github.com/RustCrypto/hashes
#![no_std]
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
)]
#![warn(missing_docs, rust_2018_idioms)]

mod compressor;
mod consts;

// This function is exported only for benchmarks
pub use compressor::f8_impl;

pub use digest::{self, Digest};

use crate::compressor::Compressor;
use core::fmt;
use digest::{
    block_buffer::Eager,
    core_api::{
        AlgorithmName, Block, Buffer, BufferKindUser, CoreWrapper, CtVariableCoreWrapper,
        TruncSide, UpdateCore, VariableOutputCore,
    },
    crypto_common::{BlockSizeUser, OutputSizeUser},
    generic_array::typenum::{Unsigned, U28, U32, U48, U64},
    HashMarker, InvalidOutputSize, Output,
};

/// Core JH hasher state
#[derive(Clone)]
pub struct JhCore {
    state: Compressor,
    block_len: u64,
}

impl HashMarker for JhCore {}

impl BlockSizeUser for JhCore {
    type BlockSize = U64;
}

impl BufferKindUser for JhCore {
    type BufferKind = Eager;
}

impl OutputSizeUser for JhCore {
    type OutputSize = U64;
}

impl UpdateCore for JhCore {
    #[inline]
    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
        self.block_len = self.block_len.wrapping_add(blocks.len() as u64);
        for b in blocks {
            self.state.update(b);
        }
    }
}

impl VariableOutputCore for JhCore {
    const TRUNC_SIDE: TruncSide = TruncSide::Right;

    #[inline]
    fn new(output_size: usize) -> Result<Self, InvalidOutputSize> {
        let h0 = match output_size {
            28 => consts::JH224_H0,
            32 => consts::JH256_H0,
            48 => consts::JH384_H0,
            64 => consts::JH512_H0,
            _ => return Err(InvalidOutputSize),
        };
        Ok(Self {
            state: Compressor::new(h0),
            block_len: 0,
        })
    }

    #[inline]
    fn finalize_variable_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
        let Self { state, block_len } = self;
        let bit_len = block_len
            .wrapping_mul(Self::BlockSize::U64)
            .wrapping_add(buffer.get_pos() as u64)
            .wrapping_mul(8);
        if buffer.get_pos() == 0 {
            buffer.len64_padding_be(bit_len, |b| state.update(b));
        } else {
            buffer.digest_pad(0x80, &[], |b| state.update(b));
            buffer.digest_pad(0, &bit_len.to_be_bytes(), |b| state.update(b));
        }
        out.copy_from_slice(&self.state.finalize()[64..]);
    }
}

impl AlgorithmName for JhCore {
    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("Jh")
    }
}

impl fmt::Debug for JhCore {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("JhCore { ... }")
    }
}

/// Jh-224 hasher state
pub type Jh224 = CoreWrapper<CtVariableCoreWrapper<JhCore, U28>>;
/// Jh-256 hasher state
pub type Jh256 = CoreWrapper<CtVariableCoreWrapper<JhCore, U32>>;
/// Jh-384 hasher state
pub type Jh384 = CoreWrapper<CtVariableCoreWrapper<JhCore, U48>>;
/// Jh-512 hasher state
pub type Jh512 = CoreWrapper<CtVariableCoreWrapper<JhCore, U64>>;