use crate::QueryValue;
use crate::Result;
use anyhow::Context;
use http::HeaderMap;
use std::borrow::Cow;
mod acs3;
mod oss4;
pub use acs3::Acs3HmacSha256;
pub use oss4::Oss4HmacSha256;
#[derive(Clone, Debug)]
pub struct AccessKeySecret(Cow<'static, str>, Cow<'static, str>);
impl AccessKeySecret {
#[inline]
pub fn new(key: impl Into<Cow<'static, str>>, secret: impl Into<Cow<'static, str>>) -> Self {
Self(key.into(), secret.into())
}
#[inline]
pub fn access_key_id(&self) -> &str {
&self.0
}
#[inline]
pub fn access_key_secret(&self) -> &str {
&self.1
}
}
impl From<(&'static str, &'static str)> for AccessKeySecret {
fn from(value: (&'static str, &'static str)) -> Self {
Self(value.0.into(), value.1.into())
}
}
impl From<(Cow<'static, str>, Cow<'static, str>)> for AccessKeySecret {
fn from(value: (Cow<'static, str>, Cow<'static, str>)) -> Self {
Self(value.0, value.1)
}
}
pub trait AliyunAuth: Send + Sync {
fn sign(
&self,
headers: &mut HeaderMap,
path: &str,
query_string: &str,
method: &str,
body: &reqwest::Body,
resource_path: &str,
) -> Result<String>;
fn canonical_query_string(&self, values: Vec<(Cow<'static, str>, QueryValue)>) -> String;
fn create_headers(&self, action: &str, version: &str) -> Result<HeaderMap>;
}
fn hmac_sha256(key: &[u8], data: &[u8]) -> Result<Vec<u8>> {
use hmac::{Hmac, Mac};
use sha2::Sha256;
let mut mac = Hmac::<Sha256>::new_from_slice(key).context("Create hmac from key")?;
mac.update(data);
Ok(mac.finalize().into_bytes().to_vec())
}
fn hexed_hmac_sha256(key: &[u8], to_sign: &[u8]) -> Result<String> {
let result = hmac_sha256(key, to_sign)?;
Ok(hex::encode(result))
}
fn hexed_sha256(s: impl AsRef<[u8]>) -> String {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(s);
hex::encode(hasher.finalize())
}
fn percent_encode(s: &str) -> Cow<'_, str> {
urlencoding::encode(s)
}