1 // Copyright 2021 Ian Jackson and contributors to Hippotat
2 // SPDX-License-Identifier: GPL-3.0-or-later
3 // There is NO WARRANTY.
8 impl<T> T where T: Debug {
9 fn to_debug(&self) -> String { format!("{:?}", self) }
13 impl<T,E> Result<T,E> where AE: From<E> {
14 fn dcontext<D:Debug>(self, d: D) -> anyhow::Result<T> {
15 self.map_err(|e| AE::from(e)).with_context(|| d.to_debug())
19 #[derive(Error,Debug)]
20 pub enum ReadLimitedError {
21 #[error("maximum size {limit} exceeded")]
22 Truncated { sofar: Box<[u8]>, limit: usize },
24 #[error("HTTP error {0}")]
25 Hyper(#[from] hyper::Error),
28 impl ReadLimitedError {
29 pub fn discard_data(&mut self) { match self {
30 ReadLimitedError::Truncated { sofar,.. } => { mem::take(sofar); },
35 impl<T> Result<T,ReadLimitedError> {
36 fn discard_data(self) -> Self {
37 self.map_err(|mut e| { e.discard_data(); e })
41 #[throws(ReadLimitedError)]
42 pub async fn read_limited_bytes<S>(limit: usize, initial: Box<[u8]>,
43 stream: &mut S) -> Box<[u8]>
44 where S: futures::Stream<Item=Result<hyper::body::Bytes,hyper::Error>>
46 // we also require that the Stream is cancellation-safe
48 let mut accum = initial.into_vec();
49 while let Some(item) = stream.next().await {
52 if accum.len() > limit {
53 throw!(ReadLimitedError::Truncated { limit, sofar: accum.into() })
59 pub fn time_t_now() -> u64 {
61 .duration_since(UNIX_EPOCH)
62 .unwrap_or_else(|_| Duration::default()) // clock is being weird
66 use sha2::Digest as _;
68 pub type HmacH = sha2::Sha256;
69 pub const HMAC_B: usize = 64;
70 pub const HMAC_L: usize = 32;
72 pub fn token_hmac(key: &[u8], message: &[u8]) -> [u8; HMAC_L] {
74 let mut padded = [0; HMAC_B];
75 if key.len() > padded.len() {
76 let digest: [u8; HMAC_L] = HmacH::digest(key).into();
77 padded[0..HMAC_L].copy_from_slice(&digest);
79 padded[0.. key.len()].copy_from_slice(key);
83 let mut ikey = key; for k in &mut ikey { *k ^= 0x36; }
84 let mut okey = key; for k in &mut okey { *k ^= 0x5C; }
86 //dbg!(DumpHex(&key), DumpHex(message), DumpHex(&ikey), DumpHex(&okey));
100 fn hmac_test_vectors(){
103 Key = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
105 Data = 4869205468657265 ("Hi There")
107 HMAC-SHA-256 = b0344c61d8db38535ca8afceaf0bf12b
108 881dc200c9833da726e9376c2e32cff7
111 Key = 4a656665 ("Jefe")
112 Data = 7768617420646f2079612077616e7420 ("what do ya want ")
113 666f72206e6f7468696e673f ("for nothing?")
115 HMAC-SHA-256 = 5bdcc146bf60754e6a042426089575c7
116 5a003f089d2739839dec58b964ec3843
119 Key = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
121 Data = dddddddddddddddddddddddddddddddd
122 dddddddddddddddddddddddddddddddd
123 dddddddddddddddddddddddddddddddd
126 HMAC-SHA-256 = 773ea91e36800e46854db8ebd09181a7
127 2959098b3ef8c122d9635514ced565fe
130 Key = 0102030405060708090a0b0c0d0e0f10
131 111213141516171819 (25 bytes)
132 Data = cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd
133 cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd
134 cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd
137 HMAC-SHA-256 = 82558a389a443c0ea4cc819899f2083a
138 85f0faa3e578f8077a2e3ff46729665b
142 Key = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
143 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
144 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
145 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
146 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
147 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
148 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
149 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
151 Data = 54657374205573696e67204c61726765 ("Test Using Large")
152 72205468616e20426c6f636b2d53697a ("r Than Block-Siz")
153 65204b6579202d2048617368204b6579 ("e Key - Hash Key")
154 204669727374 (" First")
156 HMAC-SHA-256 = 60e431591ee0b67f0d8a26aacbf5b77f
157 8e0bc6213728c5140546040f0ee37f54
159 Key = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
160 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
161 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
162 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
163 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
164 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
165 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
166 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
168 Data = 54686973206973206120746573742075 ("This is a test u")
169 73696e672061206c6172676572207468 ("sing a larger th")
170 616e20626c6f636b2d73697a65206b65 ("an block-size ke")
171 7920616e642061206c61726765722074 ("y and a larger t")
172 68616e20626c6f636b2d73697a652064 ("han block-size d")
173 6174612e20546865206b6579206e6565 ("ata. The key nee")
174 647320746f2062652068617368656420 ("ds to be hashed ")
175 6265666f7265206265696e6720757365 ("before being use")
176 642062792074686520484d414320616c ("d by the HMAC al")
177 676f726974686d2e ("gorithm.")
179 HMAC-SHA-256 = 9b09ffa71b942fcb27635fbcd5b0e944
180 bfdc63644f0713938a7f51535c3a35e2
182 let vectors = regex_replace_all!{
187 let vectors = regex_replace_all!{
192 let vectors = regex_replace_all!{
197 let mut lines = vectors.split('\n');
198 assert_eq!( lines.next().unwrap(), "" );
199 let mut get = |prefix| {
200 let l = lines.next()?;
202 let b = l.strip_prefix(prefix).unwrap().as_bytes().chunks(2)
203 .map(|s| str::from_utf8(s).unwrap())
204 .map(|s| { assert_eq!(s.len(), 2); u8::from_str_radix(s,16).unwrap() })
205 .collect::<Vec<u8>>();
208 while let Some(key) = get(" Key = ") {
209 let data = get(" Data = ").unwrap();
210 let exp = get(" HMAC-SHA-256 = ").unwrap();
211 let got = token_hmac(&key, &data);
212 assert_eq!(&got[..], &exp);