fix(protocols): return errors instead of panics for sync signatures (#2120)

Co-authored-by: houseme <housemecn@gmail.com>
Co-authored-by: heihutu <30542132+heihutu@users.noreply.github.com>
This commit is contained in:
安正超
2026-03-11 11:22:20 +08:00
committed by GitHub
parent 4b480727d6
commit 9908a44c38
2 changed files with 14 additions and 11 deletions
+12 -9
View File
@@ -276,24 +276,27 @@ pub fn extract_target_container(sync_to: &str) -> SwiftResult<String> {
/// Generate sync signature for authentication /// Generate sync signature for authentication
/// ///
/// Uses HMAC-SHA1 of the request path with shared secret /// Uses HMAC-SHA1 of the request path with shared secret
pub fn generate_sync_signature(path: &str, key: &str) -> String { pub fn generate_sync_signature(path: &str, key: &str) -> SwiftResult<String> {
use hmac::{Hmac, KeyInit, Mac}; use hmac::{Hmac, KeyInit, Mac};
use sha1::Sha1; use sha1::Sha1;
type HmacSha1 = Hmac<Sha1>; type HmacSha1 = Hmac<Sha1>;
let mut mac = HmacSha1::new_from_slice(key.as_bytes()).unwrap_or_else(|_| panic!("HMAC key error")); let mut mac = HmacSha1::new_from_slice(key.as_bytes())
.map_err(|_| SwiftError::BadRequest("Invalid X-Container-Sync-Key".to_string()))?;
mac.update(path.as_bytes()); mac.update(path.as_bytes());
let result = mac.finalize(); let result = mac.finalize();
hex::encode(result.into_bytes()) Ok(hex::encode(result.into_bytes()))
} }
/// Verify sync signature /// Verify sync signature
pub fn verify_sync_signature(path: &str, key: &str, signature: &str) -> bool { pub fn verify_sync_signature(path: &str, key: &str, signature: &str) -> bool {
let expected = generate_sync_signature(path, key); match generate_sync_signature(path, key) {
expected == signature Ok(expected) => expected == signature,
Err(_) => false,
}
} }
#[cfg(test)] #[cfg(test)]
@@ -454,15 +457,15 @@ mod tests {
let path = "/v1/AUTH_test/container/object.txt"; let path = "/v1/AUTH_test/container/object.txt";
let key = "mysecretkey"; let key = "mysecretkey";
let sig1 = generate_sync_signature(path, key); let sig1 = generate_sync_signature(path, key).expect("failed to generate sync signature");
let sig2 = generate_sync_signature(path, key); let sig2 = generate_sync_signature(path, key).expect("failed to generate sync signature");
// Signature should be deterministic // Signature should be deterministic
assert_eq!(sig1, sig2); assert_eq!(sig1, sig2);
assert_eq!(sig1.len(), 40); // SHA1 = 20 bytes = 40 hex chars assert_eq!(sig1.len(), 40); // SHA1 = 20 bytes = 40 hex chars
// Different key produces different signature // Different key produces different signature
let sig3 = generate_sync_signature(path, "differentkey"); let sig3 = generate_sync_signature(path, "differentkey").expect("failed to generate sync signature");
assert_ne!(sig1, sig3); assert_ne!(sig1, sig3);
} }
@@ -471,7 +474,7 @@ mod tests {
let path = "/v1/AUTH_test/container/object.txt"; let path = "/v1/AUTH_test/container/object.txt";
let key = "mysecretkey"; let key = "mysecretkey";
let signature = generate_sync_signature(path, key); let signature = generate_sync_signature(path, key).expect("failed to generate sync signature");
assert!(verify_sync_signature(path, key, &signature)); assert!(verify_sync_signature(path, key, &signature));
// Wrong signature // Wrong signature
@@ -53,8 +53,8 @@ fn test_sync_signatures() {
let path = "/v1/AUTH_test/container/object.txt"; let path = "/v1/AUTH_test/container/object.txt";
let key = "sharedsecret"; let key = "sharedsecret";
let sig1 = sync::generate_sync_signature(path, key); let sig1 = sync::generate_sync_signature(path, key).expect("failed to generate sync signature");
let sig2 = sync::generate_sync_signature(path, key); let sig2 = sync::generate_sync_signature(path, key).expect("failed to generate sync signature");
assert_eq!(sig1, sig2); assert_eq!(sig1, sig2);
assert_eq!(sig1.len(), 40); // HMAC-SHA1 = 40 hex chars assert_eq!(sig1.len(), 40); // HMAC-SHA1 = 40 hex chars