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
use commit::Commit;
use errors::*;
use crypto_mac::generic_array::GenericArray;
use crypto_mac::Mac;
use bincode;
use rand::{CryptoRng, Rng};
use serde::Serialize;
use typenum::Unsigned;
#[derive(Debug)]
pub struct Secret<T, M>
where
M: Mac,
{
value: T,
key: GenericArray<u8, M::KeySize>,
}
impl<T, M> Secret<T, M>
where
M: Mac,
{
pub fn new<R>(rng: &mut R, value: T) -> Self
where
R: Rng + CryptoRng,
{
let mut key = vec![0; M::KeySize::to_usize()];
rng.fill_bytes(&mut key);
Self {
value,
key: GenericArray::from_exact_iter(key).unwrap(),
}
}
}
impl<T, M> Secret<T, M>
where
M: Mac,
T: Serialize,
{
pub fn commit(&self) -> Result<Commit<T, M>> {
let bytes = bincode::serialize(&self.value)
.map_err(|e| Error::with_chain(e, ErrorKind::Serialize))?;
Ok(Commit::new(&self.key, &bytes))
}
pub(crate) fn validate(self, commit: Commit<T, M>) -> Result<T> {
let mine = self.commit()?.into_mac();
let other = commit.into_mac();
if mine == other {
Ok(self.value)
} else {
bail!("validation failed");
}
}
}
#[cfg(test)]
mod tests {
extern crate hmac;
extern crate sha2;
use self::hmac::Hmac;
use self::sha2::Sha512;
use super::*;
use rand::thread_rng;
#[test]
fn new() {
let mut rng = thread_rng();
let s: Secret<u32, Hmac<Sha512>> = Secret::new(&mut rng, 4);
assert_eq!(s.value, 4);
assert_eq!(s.key.len(), 128);
}
}