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
use digest::FixedOutput;
use digest::Input;
#[derive(Debug, Clone)]
pub enum Digestable {
Sha1(::sha1::Sha1),
Sha256(::sha2::Sha256),
Sha512(::sha2::Sha512),
}
impl Digestable {
pub fn sha1() -> Digestable {
Digestable::Sha1(::sha1::Sha1::default())
}
pub fn sha256() -> Digestable {
Digestable::Sha256(::sha2::Sha256::default())
}
pub fn sha512() -> Digestable {
Digestable::Sha512(::sha2::Sha512::default())
}
pub fn process(&mut self, data: &[u8]) {
match *self {
Digestable::Sha1(ref mut x) => x.input(data),
Digestable::Sha256(ref mut x) => x.input(data),
Digestable::Sha512(ref mut x) => x.input(data),
}
}
pub fn hash(self) -> Vec<u8> {
match self {
Digestable::Sha1(x) => x.fixed_result().to_vec(),
Digestable::Sha256(x) => x.fixed_result().to_vec(),
Digestable::Sha512(x) => x.fixed_result().to_vec(),
}
}
pub fn emsa_pkcs1_v1_5(&self, hash: &[u8], output_len: usize) -> Option<Vec<u8>> {
let mut digest_info = self.asn1_prefix().to_vec();
digest_info.extend(hash);
if output_len <= digest_info.len() + 11 {
return None;
}
let mut ret = Vec::with_capacity(output_len);
ret.push(0x00);
ret.push(0x01);
for _ in 0..(output_len - digest_info.len() - 3) {
ret.push(0xff);
}
ret.push(0x00);
ret.extend(digest_info);
assert_eq!(ret.len(), output_len);
Some(ret)
}
pub fn asn1_prefix(&self) -> &'static [u8] {
use self::Digestable::*;
#[cfg_attr(rustfmt, rustfmt_skip)]
match *self {
Sha1(_) => &[
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E,
0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14],
Sha256(_) => &[
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
0x00, 0x04, 0x20],
Sha512(_) => &[
0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
0x00, 0x04, 0x40],
}
}
}