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
#![no_std]
extern crate byte_tools;
extern crate digest;
extern crate digest_buffer;
extern crate generic_array;
pub use digest::Digest;
use byte_tools::copy_memory;
use digest_buffer::DigestBuffer;
use generic_array::GenericArray;
use generic_array::typenum::{U16, U48};
mod consts;
type BlockSize = U16;
type Block = GenericArray<u8, U16>;
#[derive(Copy, Clone, Default)]
struct Md2State {
x: GenericArray<u8, U48>,
checksum: GenericArray<u8, U16>,
}
#[derive(Copy, Clone, Default)]
pub struct Md2 {
buffer: DigestBuffer<BlockSize>,
state: Md2State,
}
impl Md2State {
fn process_block(&mut self, input: &Block) {
for j in 0..16 {
self.x[16 + j] = input[j];
self.x[32 + j] = self.x[16 + j] ^ self.x[j];
}
let mut t = 0u8;
for j in 0..18u8 {
for k in 0..48 {
self.x[k] ^= consts::S[t as usize];
t = self.x[k];
}
t = t.wrapping_add(j);
}
let mut l = self.checksum[15];
for j in 0..16 {
self.checksum[j] ^= consts::S[(input[j] ^ l) as usize];
l = self.checksum[j];
}
}
}
impl Md2 {
pub fn new() -> Md2 {
Default::default()
}
fn finalize(&mut self) {
let self_state = &mut self.state;
{
let rem = self.buffer.remaining();
let mut buffer_end = self.buffer.next(rem);
for idx in 0..rem {
buffer_end[idx] = rem as u8;
}
}
self_state.process_block(self.buffer.full_buffer());
let checksum = self_state.checksum;
self_state.process_block(&checksum);
}
}
impl digest::Input for Md2 {
type BlockSize = BlockSize;
fn digest(&mut self, input: &[u8]) {
let self_state = &mut self.state;
self.buffer.input(input, |d: &Block| {
self_state.process_block(d);
});
}
}
impl digest::FixedOutput for Md2 {
type OutputSize = U16;
fn fixed_result(mut self) -> GenericArray<u8, Self::OutputSize> {
self.finalize();
let mut out = GenericArray::default();
copy_memory(&self.state.x[0..16], &mut out);
out
}
}