qiniu_download/base/
credential.rs1use hmac::{Hmac, Mac};
2use sha1::Sha1;
3
4use super::base64;
5
6#[derive(Debug, Clone)]
8pub struct Credential {
9 access_key: String,
10 secret_key: String,
11}
12
13impl Credential {
14 #[inline]
15 pub fn new(ak: impl Into<String>, sk: impl Into<String>) -> Credential {
20 Credential {
21 access_key: ak.into(),
22 secret_key: sk.into(),
23 }
24 }
25
26 pub(crate) fn access_key(&self) -> &str {
27 &self.access_key
28 }
29
30 pub(crate) fn sign(&self, data: &[u8]) -> String {
31 self.access_key.to_owned() + ":" + &self.base64_hmac_digest(data)
32 }
33
34 pub(crate) fn sign_with_data(&self, data: &[u8]) -> String {
35 let encoded_data = base64::urlsafe(data);
36 self.sign(encoded_data.as_bytes()) + ":" + &encoded_data
37 }
38
39 fn base64_hmac_digest(&self, data: &[u8]) -> String {
40 let mut hmac = Hmac::<Sha1>::new_from_slice(self.secret_key.as_bytes()).unwrap();
41 hmac.update(data);
42 base64::urlsafe(&hmac.finalize().into_bytes())
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 use std::{boxed::Box, error::Error, result::Result, sync::Arc, thread};
50
51 #[test]
52 fn test_sign() -> Result<(), Box<dyn Error>> {
53 env_logger::try_init().ok();
54
55 let credential = Arc::new(Credential::new("abcdefghklmnopq", "1234567890"));
56 let mut threads = Vec::new();
57 {
58 threads.push(thread::spawn(move || {
59 assert_eq!(
60 credential.sign(b"hello"),
61 "abcdefghklmnopq:b84KVc-LroDiz0ebUANfdzSRxa0="
62 );
63 assert_eq!(
64 credential.sign(b"world"),
65 "abcdefghklmnopq:VjgXt0P_nCxHuaTfiFz-UjDJ1AQ="
66 );
67 }));
68 }
69 {
70 let credential = Arc::new(Credential::new("abcdefghklmnopq", "1234567890"));
71 threads.push(thread::spawn(move || {
72 assert_eq!(
73 credential.sign(b"-test"),
74 "abcdefghklmnopq:vYKRLUoXRlNHfpMEQeewG0zylaw="
75 );
76 assert_eq!(
77 credential.sign(b"ba#a-"),
78 "abcdefghklmnopq:2d_Yr6H1GdTKg3RvMtpHOhi047M="
79 );
80 }));
81 }
82 threads
83 .into_iter()
84 .for_each(|thread| thread.join().unwrap());
85 Ok(())
86 }
87}