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
#![no_std]
extern crate generic_array;
extern crate byte_tools;
extern crate digest;
extern crate digest_buffer;
pub use digest::Digest;
use byte_tools::{write_u32_be, write_u32v_be, add_bytes_to_bits};
use digest_buffer::DigestBuffer;
use generic_array::GenericArray;
use generic_array::typenum::{U20, U64};
use core::mem;
const STATE_LEN: usize = 5;
pub const H: [u32; STATE_LEN] = [
0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
];
type BlockSize = U64;
type Block = GenericArray<u8, BlockSize>;
#[link(name="sha1", kind="static")]
extern "C" {
fn sha1_compress(state: &mut [u32; 5], block: &[u8; 64]);
}
#[inline(always)]
fn process_block(state: &mut [u32; 5], block: &Block) {
unsafe {
sha1_compress(state, mem::transmute(block));
}
}
#[derive(Clone)]
pub struct Sha1 {
h: [u32; STATE_LEN],
length_bits: u64,
buffer: DigestBuffer<BlockSize>,
}
impl Sha1 {
fn finalize(&mut self) {
let st_h = &mut self.h;
self.buffer
.standard_padding(8, |d| process_block(&mut *st_h, d));
write_u32_be(self.buffer.next(4), (self.length_bits >> 32) as u32);
write_u32_be(self.buffer.next(4), self.length_bits as u32);
process_block(st_h, self.buffer.full_buffer());
}
}
impl Default for Sha1 {
fn default() -> Self {
Sha1{ h: H, length_bits: 0u64, buffer: Default::default() }
}
}
impl digest::Input for Sha1 {
type BlockSize = BlockSize;
#[inline]
fn digest(&mut self, msg: &[u8]) {
self.length_bits = add_bytes_to_bits(self.length_bits, msg.len() as u64);
let st_h = &mut self.h;
self.buffer.input(msg, |d| {
process_block(st_h, d);
});
}
}
impl digest::FixedOutput for Sha1 {
type OutputSize = U20;
#[inline]
fn fixed_result(mut self) -> GenericArray<u8, Self::OutputSize> {
self.finalize();
let mut out = GenericArray::default();
write_u32v_be(&mut out[..], &self.h);
out
}
}