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
use crypto_mac::Mac; use hmac::Hmac; use sha1::Sha1; use super::base64; pub struct Credential { access_key: String, secret_key: String, } impl Credential { pub fn new(ak: impl Into<String>, sk: impl Into<String>) -> Credential { Credential { access_key: ak.into(), secret_key: sk.into(), } } pub(crate) fn sign(&self, data: &[u8]) -> String { self.access_key.to_owned() + ":" + &self.base64_hmac_digest(data) } fn base64_hmac_digest(&self, data: &[u8]) -> String { let mut hmac = Hmac::<Sha1>::new_varkey(self.secret_key.as_bytes()).unwrap(); hmac.input(data); base64::urlsafe(&hmac.result().code()) } } #[cfg(test)] mod tests { use super::*; use std::{boxed::Box, error::Error, result::Result, sync::Arc, thread}; #[test] fn test_sign() -> Result<(), Box<dyn Error>> { let credential = Arc::new(Credential::new("abcdefghklmnopq", "1234567890")); let mut threads = Vec::new(); { threads.push(thread::spawn(move || { assert_eq!( credential.sign(b"hello"), "abcdefghklmnopq:b84KVc-LroDiz0ebUANfdzSRxa0=" ); assert_eq!( credential.sign(b"world"), "abcdefghklmnopq:VjgXt0P_nCxHuaTfiFz-UjDJ1AQ=" ); })); } { let credential = Arc::new(Credential::new("abcdefghklmnopq", "1234567890")); threads.push(thread::spawn(move || { assert_eq!( credential.sign(b"-test"), "abcdefghklmnopq:vYKRLUoXRlNHfpMEQeewG0zylaw=" ); assert_eq!( credential.sign(b"ba#a-"), "abcdefghklmnopq:2d_Yr6H1GdTKg3RvMtpHOhi047M=" ); })); } threads .into_iter() .for_each(|thread| thread.join().unwrap()); Ok(()) } }