Skip to content

Commit eadff53

Browse files
committed
perf: don't duplicate signature name, available in header map key
1 parent 8a15bf3 commit eadff53

5 files changed

Lines changed: 41 additions & 52 deletions

File tree

httpsig-hyper/src/hyper_http.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ where
254254
}
255255
}
256256

257+
/// Default signature name used to indicate signature in http header (`signature` and `signature-input`)
258+
const DEFAULT_SIGNATURE_NAME: &str = "sig";
259+
257260
impl<D> MessageSignatureReq for Request<D>
258261
where
259262
D: Send + Body + Sync,
@@ -289,21 +292,21 @@ where
289292
build_signature_base(&req_or_res, params, None as Option<&Request<()>>).map(|base| (base, key, name))
290293
})
291294
.collect::<Result<Vec<_>, _>>()?;
292-
let vec_signature_headers = futures::future::join_all(
293-
vec_signature_bases
294-
.into_iter()
295-
.map(|(base, key, name)| async move { base.build_signature_headers(key, name) }),
296-
)
295+
let vec_signature_headers = futures::future::join_all(vec_signature_bases.into_iter().map(|(base, key, name)| async move {
296+
base
297+
.build_signature_headers(key)
298+
.map(|headers| (name.unwrap_or(DEFAULT_SIGNATURE_NAME), headers))
299+
}))
297300
.await
298301
.into_iter()
299302
.collect::<Result<Vec<_>, _>>()?;
300-
vec_signature_headers.iter().try_for_each(|headers| {
303+
vec_signature_headers.iter().try_for_each(|(name, headers)| {
301304
self
302305
.headers_mut()
303-
.append("signature-input", headers.signature_input_header_value().parse()?);
306+
.append("signature-input", headers.signature_input_header_value(name).parse()?);
304307
self
305308
.headers_mut()
306-
.append("signature", headers.signature_header_value().parse()?);
309+
.append("signature", headers.signature_header_value(name).parse()?);
307310
Ok(()) as Result<(), HyperSigError>
308311
})
309312
}
@@ -413,22 +416,22 @@ where
413416
.into_iter()
414417
.map(|(params, key, name)| build_signature_base(&req_or_res, params, req_for_param).map(|base| (base, key, name)))
415418
.collect::<Result<Vec<_>, _>>()?;
416-
let vec_signature_headers = futures::future::join_all(
417-
vec_signature_bases
418-
.into_iter()
419-
.map(|(base, key, name)| async move { base.build_signature_headers(key, name) }),
420-
)
419+
let vec_signature_headers = futures::future::join_all(vec_signature_bases.into_iter().map(|(base, key, name)| async move {
420+
base
421+
.build_signature_headers(key)
422+
.map(|headers| (name.unwrap_or(DEFAULT_SIGNATURE_NAME), headers))
423+
}))
421424
.await
422425
.into_iter()
423426
.collect::<Result<Vec<_>, _>>()?;
424427

425-
vec_signature_headers.iter().try_for_each(|headers| {
428+
vec_signature_headers.iter().try_for_each(|(name, headers)| {
426429
self
427430
.headers_mut()
428-
.append("signature-input", headers.signature_input_header_value().parse()?);
431+
.append("signature-input", headers.signature_input_header_value(name).parse()?);
429432
self
430433
.headers_mut()
431-
.append("signature", headers.signature_header_value().parse()?);
434+
.append("signature", headers.signature_header_value(name).parse()?);
432435
Ok(()) as Result<(), HyperSigError>
433436
})
434437
}

httpsig-hyper/src/hyper_http_tests.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,10 @@ async fn test_extract_tuples_from_request() {
159159
let req_or_res = RequestOrResponse::Request(&req);
160160
let tuples = extract_signature_headers_with_name(&req_or_res).unwrap();
161161
assert_eq!(tuples.len(), 1);
162-
assert_eq!(tuples.get("sig11").unwrap().signature_name(), "sig11");
162+
let (signature_name, headers) = tuples.into_iter().next().expect("not empty");
163+
assert_eq!(signature_name, "sig11");
163164
assert_eq!(
164-
tuples.get("sig11").unwrap().signature_params().to_string(),
165+
headers.signature_params().to_string(),
165166
r##"("@method" "@authority");created=1704972031"##
166167
);
167168
}
@@ -238,7 +239,8 @@ async fn test_set_verify_with_signature_name() {
238239
let req_or_res = RequestOrResponse::Request(&req);
239240
let signature_headers_map = extract_signature_headers_with_name(&req_or_res).unwrap();
240241
assert_eq!(signature_headers_map.len(), 1);
241-
assert_eq!(signature_headers_map[0].signature_name(), "custom_sig_name");
242+
let sig_name = signature_headers_map.keys().next().expect("not empty");
243+
assert_eq!(sig_name, "custom_sig_name");
242244

243245
let public_key = PublicKey::from_pem(&AlgorithmName::Ed25519, EDDSA_PUBLIC_KEY).unwrap();
244246
let verification_res = req.verify_message_signature(&public_key, None).await;

httpsig/benches/noncrypto.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ fn setup_signature_input() -> (String, String, &'static [&'static str]) {
5454
let signature_params = HttpSignatureParams::try_from(SIGNATURE_PARAMS).unwrap();
5555
let signature_base = HttpSignatureBase::try_new(component_lines, signature_params).unwrap();
5656
let sk = SecretKey::from_pem(&AlgorithmName::Ed25519, EDDSA_SECRET_KEY).unwrap();
57-
let signature_headers = signature_base.build_signature_headers(&sk, Some("sig-b26")).unwrap();
57+
let signature_headers = signature_base.build_signature_headers(&sk).unwrap();
5858
(
59-
signature_headers.signature_input_header_value(),
60-
signature_headers.signature_header_value(),
59+
signature_headers.signature_input_header_value("sig-b26"),
60+
signature_headers.signature_header_value("sig-b26"),
6161
COMPONENT_LINES,
6262
)
6363
}

httpsig/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ Signature: sig-b26=:wqcAqbmYJ2ji2glfAMaRy4gruYYnx2nEFN2HN6jrnDnQCK1u02Gb04v9EDgw
142142
let signature_params = HttpSignatureParams::try_from(SIGNATURE_PARAMS).unwrap();
143143
let signature_base = HttpSignatureBase::try_new(component_lines.clone(), signature_params).unwrap();
144144
let sk = SecretKey::from_pem(&AlgorithmName::Ed25519, EDDSA_SECRET_KEY).unwrap();
145-
let signature_headers = signature_base.build_signature_headers(&sk, Some("sig-b26")).unwrap();
146-
let signature_params_header_string = signature_headers.signature_input_header_value();
147-
let signature_header_string = signature_headers.signature_header_value();
145+
let signature_headers = signature_base.build_signature_headers(&sk).unwrap();
146+
let signature_params_header_string = signature_headers.signature_input_header_value("sig-b26");
147+
let signature_header_string = signature_headers.signature_header_value("sig-b26");
148148

149149
assert_eq!(signature_params_header_string, format!("sig-b26={}", SIGNATURE_PARAMS));
150150
assert!(signature_header_string.starts_with("sig-b26=:") && signature_header_string.ends_with(':'));

httpsig/src/signature_base.rs

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,9 @@ use sfv::{BareItem, Item, ListEntry, Parser};
1313
/// IndexMap of signature name and HttpSignatureHeaders
1414
pub type HttpSignatureHeadersMap = IndexMap<String, HttpSignatureHeaders, FxBuildHasher>;
1515

16-
/// Default signature name used to indicate signature in http header (`signature` and `signature-input`)
17-
const DEFAULT_SIGNATURE_NAME: &str = "sig";
18-
1916
#[derive(Debug, Clone)]
2017
/// Signature Headers derived from HttpSignatureBase
2118
pub struct HttpSignatureHeaders {
22-
/// signature name coupling signature with signature input
23-
signature_name: String,
2419
/// Signature value of "Signature" http header in the form of "<signature_name>=:<base64_signature>:"
2520
signature: HttpSignature,
2621
/// signature-params value of "Signature-Input" http header in the form of "<signature_name>=:<signature_params>:"
@@ -87,9 +82,8 @@ impl HttpSignatureHeaders {
8782
let signature = HttpSignature(signature_bytes);
8883

8984
Ok((
90-
signature_name.clone(),
85+
signature_name,
9186
Self {
92-
signature_name,
9387
signature,
9488
signature_params,
9589
},
@@ -99,11 +93,6 @@ impl HttpSignatureHeaders {
9993
Ok(res)
10094
}
10195

102-
/// Returns the signature name
103-
pub fn signature_name(&self) -> &str {
104-
&self.signature_name
105-
}
106-
10796
/// Returns the signature value without name
10897
pub fn signature(&self) -> &HttpSignature {
10998
&self.signature
@@ -120,12 +109,12 @@ impl HttpSignatureHeaders {
120109
}
121110

122111
/// Returns the signature value of "Signature" http header in the form of "<signature_name>=:<base64_signature>:"
123-
pub fn signature_header_value(&self) -> String {
124-
format!("{}=:{}:", self.signature_name, self.signature)
112+
pub fn signature_header_value(&self, signature_name: &str) -> String {
113+
format!("{}=:{}:", signature_name, self.signature)
125114
}
126115
/// Returns the signature input value of "Signature-Input" http header in the form of "<signature_name>=<signature_params>"
127-
pub fn signature_input_header_value(&self) -> String {
128-
format!("{}={}", self.signature_name, self.signature_params)
116+
pub fn signature_input_header_value(&self, signature_name: &str) -> String {
117+
format!("{}={}", signature_name, self.signature_params)
129118
}
130119
}
131120

@@ -190,16 +179,11 @@ impl HttpSignatureBase {
190179
}
191180

192181
/// Build the signature and signature-input headers structs
193-
pub fn build_signature_headers(
194-
&self,
195-
signing_key: &impl SigningKey,
196-
signature_name: Option<&str>,
197-
) -> HttpSigResult<HttpSignatureHeaders> {
182+
pub fn build_signature_headers(self, signing_key: &impl SigningKey) -> HttpSigResult<HttpSignatureHeaders> {
198183
let signature = self.build_raw_signature(signing_key)?;
199184
Ok(HttpSignatureHeaders {
200-
signature_name: signature_name.unwrap_or(DEFAULT_SIGNATURE_NAME).to_string(),
201185
signature: HttpSignature(signature),
202-
signature_params: self.signature_params.clone(),
186+
signature_params: self.signature_params,
203187
})
204188
}
205189

@@ -288,15 +272,15 @@ mod test {
288272
const SIGNATURE_INPUT: &str = r##"sig-b26=("date" "@method" "@path" "@authority" "content-type" "content-length");created=1618884473;keyid="test-key-ed25519", sig-b27=("date" "@method" "@path" "@authority" "content-type" "content-length");created=1618884473;keyid="test-key-ed25519-alt""##;
289273
const SIGNATURE: &str = r##"sig-b26=:wqcAqbmYJ2ji2glfAMaRy4gruYYnx2nEFN2HN6jrnDnQCK1u02Gb04v9EDgwUPiu4A0w6vuQv5lIp5WPpBKRCw==:, sig-b27=:wqcAqbmYJ2ji2glfAMaRy4gruYYnx2nEFN2HN6jrnDnQCK1u02Gb04v9EDgwUPiu4A0w6vuQv5lIp5WPpBKRCw==:"##;
290274

291-
let header_map = HttpSignatureHeaders::try_parse(SIGNATURE, SIGNATURE_INPUT).unwrap();
275+
let mut header_map = HttpSignatureHeaders::try_parse(SIGNATURE, SIGNATURE_INPUT).unwrap();
292276
assert!(header_map.len() == 2);
293-
let http_signature_headers = header_map.get("sig-b26").unwrap();
277+
let http_signature_headers = header_map.swap_remove("sig-b26").unwrap();
294278
assert_eq!(
295-
http_signature_headers.signature_header_value(),
279+
http_signature_headers.signature_header_value("sig-b26"),
296280
SIGNATURE.split(',').next().unwrap()
297281
);
298282
assert_eq!(
299-
http_signature_headers.signature_input_header_value(),
283+
http_signature_headers.signature_input_header_value("sig-b26"),
300284
SIGNATURE_INPUT.split(',').next().unwrap()
301285
);
302286
}

0 commit comments

Comments
 (0)