1use crate::{digest, hmac, rand};
6use hawk::crypto as hc;
7
8impl From<crate::Error> for hc::CryptoError {
9 fn from(e: crate::Error) -> Self {
11 hc::CryptoError::Other(e.into())
12 }
13}
14
15pub(crate) struct RcCryptoCryptographer;
16
17impl hc::HmacKey for crate::hmac::SigningKey {
18 fn sign(&self, data: &[u8]) -> Result<Vec<u8>, hc::CryptoError> {
19 let digest = hmac::sign(self, data)?;
20 Ok(digest.as_ref().into())
21 }
22}
23
24struct NssHasher {
28 buffer: Vec<u8>,
29 algorithm: &'static digest::Algorithm,
30}
31
32impl hc::Hasher for NssHasher {
33 fn update(&mut self, data: &[u8]) -> Result<(), hc::CryptoError> {
34 self.buffer.extend_from_slice(data);
35 Ok(())
36 }
37
38 fn finish(&mut self) -> Result<Vec<u8>, hc::CryptoError> {
39 let digest = digest::digest(self.algorithm, &self.buffer)?;
40 let bytes: &[u8] = digest.as_ref();
41 Ok(bytes.to_owned())
42 }
43}
44
45impl hc::Cryptographer for RcCryptoCryptographer {
46 fn rand_bytes(&self, output: &mut [u8]) -> Result<(), hc::CryptoError> {
47 rand::fill(output)?;
48 Ok(())
49 }
50
51 fn new_key(
52 &self,
53 algorithm: hawk::DigestAlgorithm,
54 key: &[u8],
55 ) -> Result<Box<dyn hc::HmacKey>, hc::CryptoError> {
56 let k = hmac::SigningKey::new(to_rc_crypto_algorithm(algorithm)?, key);
57 Ok(Box::new(k))
58 }
59
60 fn constant_time_compare(&self, a: &[u8], b: &[u8]) -> bool {
61 crate::constant_time::verify_slices_are_equal(a, b).is_ok()
62 }
63
64 fn new_hasher(
65 &self,
66 algorithm: hawk::DigestAlgorithm,
67 ) -> Result<Box<dyn hc::Hasher>, hc::CryptoError> {
68 Ok(Box::new(NssHasher {
69 algorithm: to_rc_crypto_algorithm(algorithm)?,
70 buffer: vec![],
71 }))
72 }
73}
74
75fn to_rc_crypto_algorithm(
76 algorithm: hawk::DigestAlgorithm,
77) -> Result<&'static digest::Algorithm, hc::CryptoError> {
78 match algorithm {
79 hawk::DigestAlgorithm::Sha256 => Ok(&digest::SHA256),
80 algo => Err(hc::CryptoError::UnsupportedDigest(algo)),
81 }
82}
83
84pub(crate) fn init() {
86 hawk::crypto::set_cryptographer(&crate::hawk_crypto::RcCryptoCryptographer)
87 .expect("Failed to initialize `hawk` cryptographer!")
88}
89
90#[cfg(test)]
91mod test {
92
93 #[test]
95 fn test_hawk_hashing() {
96 nss::ensure_initialized();
97 crate::ensure_initialized();
98
99 let mut hasher1 = hawk::PayloadHasher::new("text/plain", hawk::SHA256).unwrap();
100 hasher1.update("pày").unwrap();
101 hasher1.update("load").unwrap();
102 let hash1 = hasher1.finish().unwrap();
103
104 let mut hasher2 = hawk::PayloadHasher::new("text/plain", hawk::SHA256).unwrap();
105 hasher2.update("pàyload").unwrap();
106 let hash2 = hasher2.finish().unwrap();
107
108 let hash3 = hawk::PayloadHasher::hash("text/plain", hawk::SHA256, "pàyload").unwrap();
109
110 let hash4 = hawk::PayloadHasher::hash("text/plain", hawk::SHA256, [112, 195, 160, 121, 108, 111, 97, 100]).unwrap();
112
113 assert_eq!(
114 hash1,
115 &[
116 228, 238, 241, 224, 235, 114, 158, 112, 211, 254, 118, 89, 25, 236, 87, 176, 181,
117 54, 61, 135, 42, 223, 188, 103, 194, 59, 83, 36, 136, 31, 198, 50
118 ]
119 );
120 assert_eq!(hash2, hash1);
121 assert_eq!(hash3, hash1);
122 assert_eq!(hash4, hash1);
123 }
124
125 #[test]
127 fn test_hawk_signing() {
128 nss::ensure_initialized();
129 crate::ensure_initialized();
130
131 let key = hawk::Key::new(
132 [
133 11u8, 19, 228, 209, 79, 189, 200, 59, 166, 47, 86, 254, 235, 184, 120, 197, 75,
134 152, 201, 79, 115, 61, 111, 242, 219, 187, 173, 14, 227, 108, 60, 232,
135 ],
136 hawk::SHA256,
137 )
138 .unwrap();
139
140 let mac = hawk::mac::Mac::new(
141 hawk::mac::MacType::Header,
142 &key,
143 std::time::UNIX_EPOCH + std::time::Duration::new(1000, 100),
144 "nonny",
145 "POST",
146 "mysite.com",
147 443,
148 "/v1/api",
149 None,
150 None,
151 )
152 .unwrap();
153 assert_eq!(
154 mac.as_ref(),
155 &[
156 192, 227, 235, 121, 157, 185, 197, 79, 189, 214, 235, 139, 9, 232, 99, 55, 67, 30,
157 68, 0, 150, 187, 192, 238, 21, 200, 209, 107, 245, 159, 243, 178
158 ]
159 );
160 }
161}