diff --git a/Cargo.toml b/Cargo.toml index 956f82b..b934c58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,9 +7,11 @@ edition = "2021" [dependencies] hex = "0.4.3" +hmac-sha1 = "0.1.3" hmac-sha256 = "1.1.7" hmac-sm3 = "0.1.0" rand = "0.8.5" +sha1 = "0.10.5" sha256 = "1.4.0" sm3 = "0.4.2" zeroize = "1.6.0" diff --git a/src/v4/common_util.rs b/src/common_util.rs similarity index 100% rename from src/v4/common_util.rs rename to src/common_util.rs diff --git a/src/main.rs b/src/main.rs index 9ab73bb..88a16a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod v4; -mod util; -// mod v4_algorithm; +mod map_util; +mod common_util; +mod sign_algorithm; fn main() { println!("Hello, world!"); diff --git a/src/util.rs b/src/map_util.rs similarity index 100% rename from src/util.rs rename to src/map_util.rs diff --git a/src/v4/sign_algorithm.rs b/src/sign_algorithm.rs similarity index 64% rename from src/v4/sign_algorithm.rs rename to src/sign_algorithm.rs index 2d57f06..3f496ef 100644 --- a/src/v4/sign_algorithm.rs +++ b/src/sign_algorithm.rs @@ -1,3 +1,4 @@ +use sha1::Sha1; use sm3::{Digest, Sm3}; const ACS4_HMAC_SHA256: &str = "ACS4-HMAC-SHA256"; @@ -6,7 +7,11 @@ const ACS4_HMAC_SM3: &str = "ACS4-HMAC-SM3"; #[derive(Clone, Copy)] pub enum SignAlgorithm { + /// SHA1 is used for Signatures before V4 + Sha1, + // V4 NIST Signature Algorithm Sha256, + // V4 SM Signature Algorithm Sm3, } @@ -20,14 +25,15 @@ impl SignAlgorithm { } #[inline] - pub fn as_aliyun_name(&self) -> &'static str { - inner_as_aliyun_name(self) + pub fn as_aliyun_name_v4(&self) -> &'static str { + inner_as_aliyun_name_v4(self) } } #[inline] -fn inner_as_aliyun_name(sign_algorithm: &SignAlgorithm) -> &'static str { +fn inner_as_aliyun_name_v4(sign_algorithm: &SignAlgorithm) -> &'static str { match sign_algorithm { + SignAlgorithm::Sha1 => "N/A", SignAlgorithm::Sha256 => ACS4_HMAC_SHA256, SignAlgorithm::Sm3 => ACS4_HMAC_SM3, } @@ -36,11 +42,16 @@ fn inner_as_aliyun_name(sign_algorithm: &SignAlgorithm) -> &'static str { #[inline] fn inner_digest(sign_algorithm: &SignAlgorithm, message: &[u8]) -> String { match sign_algorithm { + SignAlgorithm::Sha1 => { + let mut h = Sha1::new(); + h.update(message); + hex::encode(h.finalize().as_slice()) + } SignAlgorithm::Sha256 => sha256::digest(message), SignAlgorithm::Sm3 => { - let mut sm3 = Sm3::new(); - sm3.update(&message); - hex::encode(sm3.finalize().as_slice()) + let mut h = Sm3::new(); + h.update(&message); + hex::encode(h.finalize().as_slice()) } } } @@ -48,6 +59,7 @@ fn inner_digest(sign_algorithm: &SignAlgorithm, message: &[u8]) -> String { #[inline] fn inner_hmac_sign(sign_algorithm: &SignAlgorithm, message: &[u8], key: &[u8]) -> Vec { match sign_algorithm { + SignAlgorithm::Sha1 => hmacsha1::hmac_sha1(key, message).to_vec(), SignAlgorithm::Sha256 => { let mut hsha256 = hmac_sha256::HMAC::new(key); hsha256.update(message); @@ -59,6 +71,10 @@ fn inner_hmac_sign(sign_algorithm: &SignAlgorithm, message: &[u8], key: &[u8]) - #[test] fn test_digest() { + assert_eq!( + "0a4d55a8d778e5022fab701977c5d840bbc486d0", + SignAlgorithm::Sha1.digest(b"Hello World") + ); assert_eq!( "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e", SignAlgorithm::Sha256.digest(b"Hello World") diff --git a/src/v4/aliyun_util.rs b/src/v4/aliyun_util.rs index 63b56e9..9dc339c 100644 --- a/src/v4/aliyun_util.rs +++ b/src/v4/aliyun_util.rs @@ -4,11 +4,11 @@ use std::time::SystemTime; use rand::random; -use crate::util::BTreeMapAddKv; +use crate::common_util::{join_slices, percent_encode}; +use crate::map_util::BTreeMapAddKv; +use crate::sign_algorithm::SignAlgorithm; use crate::v4::access_key::{AccessKey, DerivedAccessKey}; -use crate::v4::common_util::{join_slices, percent_encode}; use crate::v4::constant::{ALIYUN_V4, ALIYUN_V4_REQUEST, CONTENT_TYPE_APPLICATION_JSON, HEADER_ACCEPT, HEADER_AUTHORIZATION, HEADER_CONTENT_TYPE, HEADER_HOST, HEADER_USER_AGENT, HEADER_X_ACS_PREFIX, HEADER_X_ASC_ACCESS_KEY_ID, HEADER_X_ASC_ACTION, HEADER_X_ASC_CONTENT_SHA256, HEADER_X_ASC_CONTENT_SM3, HEADER_X_ASC_DATE, HEADER_X_ASC_SECURITY_TOKEN, HEADER_X_ASC_SIGNATURE_NONCE, HEADER_X_ASC_VERSION, REGION_CENTER}; -use crate::v4::sign_algorithm::SignAlgorithm; const SEQ: AtomicU64 = AtomicU64::new(0); @@ -27,18 +27,21 @@ struct Request { } fn add_common_headers(header: &mut BTreeMap, request: &Request) { + let (ymd, date) = get_timestamp(); + header.insert_kv(HEADER_HOST, "endpoint"); // TODO header.insert_kv(HEADER_X_ASC_VERSION, &request.version); header.insert_kv(HEADER_X_ASC_ACTION, &request.action); header.insert_kv(HEADER_USER_AGENT, &request.user_agent); - header.insert_kv(HEADER_X_ASC_DATE, get_timestamp()); + header.insert_kv(HEADER_X_ASC_DATE, date); header.insert_kv(HEADER_X_ASC_SIGNATURE_NONCE, get_nonce()); header.insert_kv(HEADER_ACCEPT, CONTENT_TYPE_APPLICATION_JSON); // TODO BODY ... + // TODO signature ... match &request.sign_algorithm { - // TODO ... + SignAlgorithm::Sha1 => panic!("SHA1 in V4 is NOT supported!"), SignAlgorithm::Sha256 => { header.insert_kv(HEADER_X_ASC_CONTENT_SHA256, ""); } @@ -111,7 +114,7 @@ fn get_authorization(sign_algorithm: &SignAlgorithm, let signed_headers_str = get_signed_headers(headers).iter().map(|(k, _)| k.as_str()).collect::>().join(";"); let mut authorization = String::with_capacity(512); - authorization.push_str(sign_algorithm.as_aliyun_name()); + authorization.push_str(sign_algorithm.as_aliyun_name_v4()); authorization.push_str(" Credential="); authorization.push_str(&access_key.access_key_id); authorization.push('/'); @@ -153,7 +156,7 @@ fn get_signature(sign_algorithm: &SignAlgorithm, string_to_sign.push_str(payload); let string_to_sign_digest_hex = sign_algorithm.digest(string_to_sign.as_bytes()); - string_to_sign.push_str(sign_algorithm.as_aliyun_name()); + string_to_sign.push_str(sign_algorithm.as_aliyun_name_v4()); string_to_sign.push('\n'); string_to_sign.push_str(&string_to_sign_digest_hex); diff --git a/src/v4/mod.rs b/src/v4/mod.rs index 63ed817..6422cfa 100644 --- a/src/v4/mod.rs +++ b/src/v4/mod.rs @@ -1,5 +1,3 @@ mod constant; -mod sign_algorithm; mod access_key; -mod common_util; mod aliyun_util;