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
use crate::sha::const_tables::{SHA1_DIGEST_WSIZE, SHA1_BLOCK_SIZE, SHA1_INIT, SHA1_DIGEST_SIZE};
use crate::Digest;
#[derive(Clone)]
pub struct SHA1 {
pub(super) digest: [u32; SHA1_DIGEST_WSIZE],
pub(super) buf: [u8; SHA1_BLOCK_SIZE],
pub(super) idx: usize,
pub(super) len: usize,
pub(super) is_checked: bool,
}
impl SHA1 {
pub fn new() -> SHA1 {
SHA1 {
digest: SHA1_INIT,
buf: [0u8; SHA1_BLOCK_SIZE],
idx: 0,
len: 0,
is_checked: false,
}
}
}
impl Digest for SHA1 {
fn block_size(&self) -> Option<usize> {
Some(64)
}
fn bits_len(&self) -> usize {
SHA1_DIGEST_SIZE << 3
}
fn write(&mut self, data: &[u8]) {
let mut data = data;
self.len += data.len();
if self.idx > 0 {
let min = std::cmp::min(SHA1_BLOCK_SIZE - self.idx, data.len());
let dst = &mut self.buf[self.idx..(self.idx+min)];
let src = &data[0..min];
dst.copy_from_slice(src);
self.idx += min;
if self.idx == SHA1_BLOCK_SIZE {
self.update(None);
self.idx = 0;
}
data = &data[min..];
}
if data.len() > SHA1_BLOCK_SIZE {
let n = data.len() & (!(SHA1_BLOCK_SIZE - 1));
let data_block = &data[0..n];
self.update(Some(data_block));
data = &data[n..];
}
if data.len() > 0 {
let dst = &mut self.buf[..data.len()];
dst.copy_from_slice(data);
self.idx += data.len();
}
self.is_checked = false;
}
fn checksum(&mut self, digest: &mut Vec<u8>) {
if !self.is_checked {
let mut tmp = [0u8; SHA1_BLOCK_SIZE];
tmp[0] = 0x80;
let len = self.len;
if len % SHA1_BLOCK_SIZE < 56 {
self.write(&tmp[0..(56-(len%SHA1_BLOCK_SIZE))]);
} else {
self.write(&tmp[0..(64+56-(len%SHA1_BLOCK_SIZE))]);
}
let len = (len as u64) << 3;
let len_bytes = len.to_be_bytes();
self.write(&len_bytes[..]);
self.len = 0;
self.is_checked = true;
}
digest.clear();
self.digest.iter().for_each(|&e| {
digest.extend(e.to_be_bytes().iter());
});
}
fn reset(&mut self) {
*self = SHA1::new();
}
}