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
use std::vec;
use proto::message::AuthType;
use crypto::{hmac, sha1};
use crypto::digest::Digest;
use crypto::mac::Mac;
#[derive(Clone)]
pub enum Credentials {
Hmac { identity: i64, key: vec::Vec<u8>, },
Pin { pin: vec::Vec<u8> }
}
impl Credentials {
#[inline]
fn calculate_hmac(key: &vec::Vec<u8>, data: &[u8]) -> vec::Vec<u8> {
let mut hmac = hmac::Hmac::new(sha1::Sha1::new(), key.as_ref());
let buffer: [u8;4] = unsafe { ::std::mem::transmute((data.len() as u32).to_be()) };
hmac.input(&buffer);
hmac.input(data);
hmac.result().code().to_vec()
}
pub fn authenticate_proto(&self, command_bytes: &vec::Vec<u8>) -> ::proto::Message {
let mut msg = ::proto::Message::new();
match *self {
Credentials::Hmac { identity, ref key } => {
msg.set_authType(AuthType::HMACAUTH);
let mut auth = ::proto::message::HmacAuth::new();
auth.set_identity(identity);
auth.set_hmac(Credentials::calculate_hmac(key, command_bytes.as_ref()));
msg.set_hmacAuth(auth);
},
Credentials::Pin { ref pin } => {
msg.set_authType(AuthType::PINAUTH);
let mut pin_auth = ::proto::message::PinAuth::new();
pin_auth.set_pin(pin.clone());
msg.set_pinAuth(pin_auth);
}
}
msg
}
pub fn verify_proto(&self, msg: &::proto::Message) -> bool {
match *self {
Credentials::Hmac { identity, ref key } => {
if msg.get_authType() != AuthType::HMACAUTH { return false; }
if msg.get_hmacAuth().get_identity() != identity { return false; }
let received_hmac = msg.get_hmacAuth().get_hmac();
let calculated_hmac_vec = Credentials::calculate_hmac(key, msg.get_commandBytes());
let calculated_hmac: &[u8] = calculated_hmac_vec.as_ref();
(received_hmac == calculated_hmac)
},
Credentials::Pin { .. } => msg.get_authType() == AuthType::PINAUTH
}
}
}
impl ::std::default::Default for Credentials {
fn default() -> Credentials {
Credentials::Hmac { identity: 1,
key: "asdfasdf".as_bytes().to_vec(), }
}
}