Skip to content

Commit 1a9aa42

Browse files
committed
refactor: update several internal processes
1 parent c5e161d commit 1a9aa42

6 files changed

Lines changed: 64 additions & 51 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ This crates provides a basic library [httpsig](./httpsig) and [its extension](./
1616
- [x] HMAC using SHA-256
1717
- [x] Ed25519
1818
- [x] ECDSA-P256 using SHA-256
19-
- [ ] ECDSA-P384 using SHA-384
19+
- [x] ECDSA-P384 using SHA-384
2020
- [x] RSASSA-PSS using SHA-512
2121
- [x] RSASSA-PKCS1-v1_5 using SHA-256
2222

23-
At this point, **RSA signature is non-default** due to [the problem related to the non-constant time operation](https://github.com/RustCrypto/RSA/issues/19), i.e., [Mervin Attack](https://people.redhat.com/~hkario/marvin/). If you want to use RSA signature, please enable the `rsa-signature` feature flag in your `Cargo.toml`.
23+
At this point, **RSA signature is non-default** due to [the problem related to the non-constant time operation](https://github.com/RustCrypto/RSA/issues/19), i.e., [Marvin Attack](https://people.redhat.com/~hkario/marvin/). If you want to use RSA signature, please enable the `rsa-signature` feature flag in your `Cargo.toml`.
2424

2525
## Usage of Extension for `hyper` (`httpsig-hyper`)
2626

@@ -127,7 +127,7 @@ async fn verifier<B>(res: &Response<B>, sent_req: &Request<B>) -> HttpSigResult<
127127
// specify algorithm name since we cannot always infer it from key info
128128
let alg = AlgorithmName::Ed25519; // directly use Ed25519 algorithm
129129
// or else infer it from the response. Find your public key from IndexMap with alg and key_id pairs
130-
// let alg_key_id_map = res.get_alg_key_ids().unwrap()
130+
// let alg_key_id_map = res.get_alg_key_ids().unwrap();
131131
let public_key = PublicKey::from_pem(&alg, PUBLIC_KEY_STRING).unwrap();
132132
let key_id = public_key.key_id();
133133

httpsig-hyper/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ rust-version.workspace = true
1313
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1414

1515
[features]
16-
default = ["blocking"]
16+
default = ["blocking", "rsa-signature"]
1717
blocking = ["futures/executor"]
18-
rsasig = ["httpsig/rsasig"]
18+
rsa-signature = ["httpsig/rsa-signature"]
1919

2020

2121
[dependencies]

httpsig-hyper/src/hyper_http.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,7 @@ MCowBQYDK2VwAyEA1ixMQcxO46PLlgQfYS46ivFd+n0CcDHSKUnuhm3i1O0=
12071207
assert_eq!(key_ids[0].1.as_ref().unwrap(), "gjrE7ACMxgzYfFHgabgf4kLTg1eKIdsJ94AiFTFj1is=");
12081208
}
12091209

1210-
const P256_SECERT_KEY: &str = r##"-----BEGIN PRIVATE KEY-----
1210+
const P256_SECRET_KEY: &str = r##"-----BEGIN PRIVATE KEY-----
12111211
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgv7zxW56ojrWwmSo1
12121212
4uOdbVhUfj9Jd+5aZIB9u8gtWnihRANCAARGYsMe0CT6pIypwRvoJlLNs4+cTh2K
12131213
L7fUNb5i6WbKxkpAoO+6T3pMBG5Yw7+8NuGTvvtrZAXduA2giPxQ8zCf
@@ -1226,7 +1226,7 @@ ii+31DW+YulmysZKQKDvuk96TARuWMO/vDbhk777a2QF3bgNoIj8UPMwnw==
12261226
let mut signature_params_eddsa = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
12271227
signature_params_eddsa.set_key_info(&secret_key_eddsa);
12281228

1229-
let secret_key_p256 = SecretKey::from_pem(&AlgorithmName::EcdsaP256Sha256, P256_SECERT_KEY).unwrap();
1229+
let secret_key_p256 = SecretKey::from_pem(&AlgorithmName::EcdsaP256Sha256, P256_SECRET_KEY).unwrap();
12301230
let mut signature_params_hmac = HttpSignatureParams::try_new(&build_covered_components_req()).unwrap();
12311231
signature_params_hmac.set_key_info(&secret_key_p256);
12321232

httpsig/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ rust-version.workspace = true
1414

1515
[features]
1616
default = []
17-
rsasig = ["rsa"]
17+
rsa-signature = ["rsa"]
1818

1919
[dependencies]
2020
thiserror = { version = "2.0.18" }

httpsig/src/crypto/asymmetric.rs

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use pkcs8::{der::Decode, Document, PrivateKeyInfo};
1414
use sha2::{Digest, Sha256, Sha384};
1515
use spki::SubjectPublicKeyInfoRef;
1616

17-
#[cfg(feature = "rsasig")]
17+
#[cfg(feature = "rsa-signature")]
1818
use rsa::{
1919
pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey, EncodeRsaPublicKey},
2020
pkcs1v15, pss,
@@ -29,7 +29,7 @@ mod algorithm_oids {
2929
pub const EC: &str = "1.2.840.10045.2.1";
3030
/// OID for `id-Ed25519`, if you're curious
3131
pub const Ed25519: &str = "1.3.101.112";
32-
#[cfg(feature = "rsasig")]
32+
#[cfg(feature = "rsa-signature")]
3333
/// OID for `id-rsaEncryption`, if you're curious
3434
pub const rsaEncryption: &str = "1.2.840.113549.1.1.1";
3535
}
@@ -53,10 +53,10 @@ pub enum SecretKey {
5353
EcdsaP256Sha256(EcSecretKey<NistP256>),
5454
/// ed25519
5555
Ed25519(Ed25519SecretKey),
56-
#[cfg(feature = "rsasig")]
56+
#[cfg(feature = "rsa-signature")]
5757
/// rsa-v1_5-sha256
5858
RsaV1_5Sha256(pkcs1v15::SigningKey<rsa::sha2::Sha256>),
59-
#[cfg(feature = "rsasig")]
59+
#[cfg(feature = "rsa-signature")]
6060
RsaPssSha512(pss::SigningKey<rsa::sha2::Sha512>),
6161
}
6262

@@ -81,14 +81,14 @@ impl SecretKey {
8181
let sk = ed25519_compact::KeyPair::from_seed(ed25519_compact::Seed::new(seed)).sk;
8282
Ok(Self::Ed25519(sk))
8383
}
84-
#[cfg(feature = "rsasig")]
84+
#[cfg(feature = "rsa-signature")]
8585
AlgorithmName::RsaV1_5Sha256 => {
8686
debug!("Read RSA private key");
8787
// read PrivateKeyInfo.private_key as RsaPrivateKey (RFC 3447), which is DER encoded RSAPrivateKey in PKCS#1
8888
let sk = RsaPrivateKey::from_pkcs1_der(bytes).map_err(|e| HttpSigError::ParsePrivateKeyError(e.to_string()))?;
8989
Ok(Self::RsaV1_5Sha256(pkcs1v15::SigningKey::<rsa::sha2::Sha256>::new(sk)))
9090
}
91-
#[cfg(feature = "rsasig")]
91+
#[cfg(feature = "rsa-signature")]
9292
AlgorithmName::RsaPssSha512 => {
9393
debug!("Read RSA-PSS private key");
9494
// read PrivateKeyInfo.private_key as RsaPrivateKey (RFC 3447), which is DER encoded RSAPrivateKey in PKCS#1
@@ -133,8 +133,15 @@ impl SecretKey {
133133
&pki.private_key[2..]
134134
}
135135
// rsa
136-
#[cfg(feature = "rsasig")]
137-
algorithm_oids::rsaEncryption => pki.private_key,
136+
#[cfg(feature = "rsa-signature")]
137+
algorithm_oids::rsaEncryption => {
138+
// assert algorithm
139+
match alg {
140+
AlgorithmName::RsaV1_5Sha256 | AlgorithmName::RsaPssSha512 => {}
141+
_ => return Err(HttpSigError::ParsePrivateKeyError("Algorithm mismatch".to_string())),
142+
}
143+
pki.private_key
144+
}
138145
_ => return Err(HttpSigError::ParsePrivateKeyError("Unsupported algorithm".to_string())),
139146
};
140147
let sk = Self::from_bytes(alg, sk_bytes)?;
@@ -156,9 +163,9 @@ impl SecretKey {
156163
Self::EcdsaP256Sha256(key) => PublicKey::EcdsaP256Sha256(key.public_key()),
157164
Self::EcdsaP384Sha384(key) => PublicKey::EcdsaP384Sha384(key.public_key()),
158165
Self::Ed25519(key) => PublicKey::Ed25519(key.public_key()),
159-
#[cfg(feature = "rsasig")]
166+
#[cfg(feature = "rsa-signature")]
160167
Self::RsaV1_5Sha256(key) => PublicKey::RsaV1_5Sha256(key.verifying_key()),
161-
#[cfg(feature = "rsasig")]
168+
#[cfg(feature = "rsa-signature")]
162169
Self::RsaPssSha512(key) => PublicKey::RsaPssSha512(key.verifying_key()),
163170
}
164171
}
@@ -189,13 +196,13 @@ impl super::SigningKey for SecretKey {
189196
let sig = sk.sign(data, Some(ed25519_compact::Noise::default()));
190197
Ok(sig.as_ref().to_vec())
191198
}
192-
#[cfg(feature = "rsasig")]
199+
#[cfg(feature = "rsa-signature")]
193200
Self::RsaV1_5Sha256(sk) => {
194201
debug!("Sign RsaV1_5Sha256");
195202
let sig = sk.sign_with_rng(&mut rand::rng(), data);
196203
Ok(sig.to_vec())
197204
}
198-
#[cfg(feature = "rsasig")]
205+
#[cfg(feature = "rsa-signature")]
199206
Self::RsaPssSha512(sk) => {
200207
debug!("Sign RsaPssSha512");
201208
let sig = sk.sign_with_rng(&mut rand::rng(), data);
@@ -240,10 +247,10 @@ pub enum PublicKey {
240247
EcdsaP384Sha384(EcPublicKey<NistP384>),
241248
/// ed25519
242249
Ed25519(Ed25519PublicKey),
243-
#[cfg(feature = "rsasig")]
250+
#[cfg(feature = "rsa-signature")]
244251
/// rsa-v1_5-sha256
245252
RsaV1_5Sha256(pkcs1v15::VerifyingKey<rsa::sha2::Sha256>),
246-
#[cfg(feature = "rsasig")]
253+
#[cfg(feature = "rsa-signature")]
247254
/// rsa-pss-sha512
248255
RsaPssSha512(pss::VerifyingKey<rsa::sha2::Sha512>),
249256
}
@@ -267,17 +274,17 @@ impl PublicKey {
267274
let pk = ed25519_compact::PublicKey::from_slice(bytes).map_err(|e| HttpSigError::ParsePublicKeyError(e.to_string()))?;
268275
Ok(Self::Ed25519(pk))
269276
}
270-
#[cfg(feature = "rsasig")]
277+
#[cfg(feature = "rsa-signature")]
271278
AlgorithmName::RsaV1_5Sha256 => {
272279
debug!("Read RSA public key");
273-
// read RsaPublicKey in SubjectPublicKeyInfo format in PKCS#8, which is DER encoded RSAPublicKey in PKCS#1
280+
// read RsaPublicKey in PKCS#1 DER format
274281
let pk = RsaPublicKey::from_pkcs1_der(bytes).map_err(|e| HttpSigError::ParsePublicKeyError(e.to_string()))?;
275282
Ok(Self::RsaV1_5Sha256(pkcs1v15::VerifyingKey::new(pk)))
276283
}
277-
#[cfg(feature = "rsasig")]
284+
#[cfg(feature = "rsa-signature")]
278285
AlgorithmName::RsaPssSha512 => {
279286
debug!("Read RSA-PSS public key");
280-
// read RsaPublicKey in SubjectPublicKeyInfo format in PKCS#8, which is DER encoded RSAPublicKey in PKCS#1
287+
// read RsaPublicKey in PKCS#1 DER format
281288
let pk = RsaPublicKey::from_pkcs1_der(bytes).map_err(|e| HttpSigError::ParsePublicKeyError(e.to_string()))?;
282289
Ok(Self::RsaPssSha512(pss::VerifyingKey::new(pk)))
283290
}
@@ -329,11 +336,17 @@ impl PublicKey {
329336
.ok_or(HttpSigError::ParsePublicKeyError("Invalid public key".to_string()))?
330337
}
331338
// rsa
332-
#[cfg(feature = "rsasig")]
333-
algorithm_oids::rsaEncryption => spki_ref
334-
.subject_public_key
335-
.as_bytes()
336-
.ok_or(HttpSigError::ParsePublicKeyError("Invalid public key".to_string()))?,
339+
#[cfg(feature = "rsa-signature")]
340+
algorithm_oids::rsaEncryption => {
341+
match alg {
342+
AlgorithmName::RsaV1_5Sha256 | AlgorithmName::RsaPssSha512 => {}
343+
_ => return Err(HttpSigError::ParsePublicKeyError("Algorithm mismatch".to_string())),
344+
}
345+
spki_ref
346+
.subject_public_key
347+
.as_bytes()
348+
.ok_or(HttpSigError::ParsePublicKeyError("Invalid public key".to_string()))?
349+
}
337350
_ => return Err(HttpSigError::ParsePublicKeyError("Unsupported algorithm".to_string())),
338351
};
339352
Self::from_bytes(alg, pk_bytes)
@@ -371,14 +384,14 @@ impl super::VerifyingKey for PublicKey {
371384
pk.verify(data, &sig)
372385
.map_err(|e| HttpSigError::InvalidSignature(e.to_string()))
373386
}
374-
#[cfg(feature = "rsasig")]
387+
#[cfg(feature = "rsa-signature")]
375388
Self::RsaV1_5Sha256(pk) => {
376389
debug!("Verify RsaV1_5Sha256");
377390
let sig = pkcs1v15::Signature::try_from(signature).map_err(|e| HttpSigError::ParseSignatureError(e.to_string()))?;
378391
pk.verify(data, &sig)
379392
.map_err(|e| HttpSigError::InvalidSignature(e.to_string()))
380393
}
381-
#[cfg(feature = "rsasig")]
394+
#[cfg(feature = "rsa-signature")]
382395
Self::RsaPssSha512(pk) => {
383396
debug!("Verify RsaPssSha512");
384397
let sig = pss::Signature::try_from(signature).map_err(|e| HttpSigError::ParseSignatureError(e.to_string()))?;
@@ -391,26 +404,26 @@ impl super::VerifyingKey for PublicKey {
391404
/// Create key id, created by SHA-256 hash of the public key bytes, then encoded in base64
392405
/// - For ECDSA keys, use the uncompressed SEC1 encoding of the public key point as the byte representation.
393406
/// - For Ed25519 keys, use the raw 32-byte public key.
394-
/// - For RSA keys, use the DER encoding of the RSAPublicKey structure (SubjectPublicKeyInfo) as defined in PKCS#1.
407+
/// - For RSA keys, use the DER encoding of the RSAPublicKey structure in PKCS#1 format.
395408
fn key_id(&self) -> String {
396409
use base64::{engine::general_purpose, Engine as _};
397410

398411
let bytes = match self {
399412
Self::EcdsaP256Sha256(vk) => vk.to_encoded_point(true).as_bytes().to_vec(),
400413
Self::EcdsaP384Sha384(vk) => vk.to_encoded_point(true).as_bytes().to_vec(),
401414
Self::Ed25519(vk) => vk.as_ref().to_vec(),
402-
#[cfg(feature = "rsasig")]
415+
#[cfg(feature = "rsa-signature")]
403416
Self::RsaV1_5Sha256(vk) => vk
404417
.as_ref()
405418
.to_pkcs1_der()
406419
.map(|der| der.as_bytes().to_vec())
407-
.unwrap_or_default(),
408-
#[cfg(feature = "rsasig")]
420+
.unwrap_or(b"rsa-der-serialization-failed".to_vec()),
421+
#[cfg(feature = "rsa-signature")]
409422
Self::RsaPssSha512(vk) => vk
410423
.as_ref()
411424
.to_pkcs1_der()
412425
.map(|der| der.as_bytes().to_vec())
413-
.unwrap_or_default(),
426+
.unwrap_or(b"rsa-der-serialization-failed".to_vec()),
414427
};
415428
let mut hasher = <Sha256 as Digest>::new();
416429
hasher.update(&bytes);
@@ -424,9 +437,9 @@ impl super::VerifyingKey for PublicKey {
424437
Self::EcdsaP256Sha256(_) => AlgorithmName::EcdsaP256Sha256,
425438
Self::EcdsaP384Sha384(_) => AlgorithmName::EcdsaP384Sha384,
426439
Self::Ed25519(_) => AlgorithmName::Ed25519,
427-
#[cfg(feature = "rsasig")]
440+
#[cfg(feature = "rsa-signature")]
428441
Self::RsaV1_5Sha256(_) => AlgorithmName::RsaV1_5Sha256,
429-
#[cfg(feature = "rsasig")]
442+
#[cfg(feature = "rsa-signature")]
430443
Self::RsaPssSha512(_) => AlgorithmName::RsaPssSha512,
431444
}
432445
}
@@ -473,7 +486,7 @@ MCowBQYDK2VwAyEA1ixMQcxO46PLlgQfYS46ivFd+n0CcDHSKUnuhm3i1O0=
473486
-----END PUBLIC KEY-----
474487
"##;
475488

476-
#[cfg(feature = "rsasig")]
489+
#[cfg(feature = "rsa-signature")]
477490
const RSA2048_SECRET_KEY: &str = r##"-----BEGIN PRIVATE KEY-----
478491
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCrjtdIxemmmL9V
479492
wfp7qqwytfRDZqQM6XNWcAi3x+j5dHFFIKKWQktJ7eCTRYQrBwjQs5sb0ieNUYwQ
@@ -503,7 +516,7 @@ KDYy4jUp2TeTPBpqwS24KzFaFx0y2U99TWrzt6sQJr7Y9NlR7S0znc/L7wwFobjr
503516
XVdlU40OaPP7xs0er/tWVAPY
504517
-----END PRIVATE KEY-----"##;
505518

506-
#[cfg(feature = "rsasig")]
519+
#[cfg(feature = "rsa-signature")]
507520
const RSA2048_PUBLIC_KEY: &str = r##"-----BEGIN PUBLIC KEY-----
508521
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq47XSMXpppi/VcH6e6qs
509522
MrX0Q2akDOlzVnAIt8fo+XRxRSCilkJLSe3gk0WEKwcI0LObG9InjVGMEL0yB+d8
@@ -552,7 +565,7 @@ tQIDAQAB
552565
assert!(matches!(pk, PublicKey::Ed25519(_)));
553566
}
554567

555-
#[cfg(feature = "rsasig")]
568+
#[cfg(feature = "rsa-signature")]
556569
#[test]
557570
fn test_from_pem_rsa() {
558571
let sk = SecretKey::from_pem(&AlgorithmName::RsaV1_5Sha256, RSA2048_SECRET_KEY).unwrap();
@@ -591,7 +604,7 @@ tQIDAQAB
591604
assert!(pk.verify(b"hello", &signature).is_err());
592605
}
593606

594-
#[cfg(feature = "rsasig")]
607+
#[cfg(feature = "rsa-signature")]
595608
#[test]
596609
fn test_sign_verify_rsa() {
597610
use super::super::{SigningKey, VerifyingKey};
@@ -630,7 +643,7 @@ tQIDAQAB
630643
Ok(())
631644
}
632645

633-
#[cfg(feature = "rsasig")]
646+
#[cfg(feature = "rsa-signature")]
634647
#[test]
635648
fn test_kid_rsa() -> HttpSigResult<()> {
636649
use super::super::VerifyingKey;

httpsig/src/crypto/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ pub enum AlgorithmName {
1313
EcdsaP256Sha256,
1414
EcdsaP384Sha384,
1515
Ed25519,
16-
#[cfg(feature = "rsasig")]
16+
#[cfg(feature = "rsa-signature")]
1717
RsaV1_5Sha256,
18-
#[cfg(feature = "rsasig")]
18+
#[cfg(feature = "rsa-signature")]
1919
RsaPssSha512,
2020
}
2121

@@ -26,9 +26,9 @@ impl AlgorithmName {
2626
AlgorithmName::EcdsaP256Sha256 => "ecdsa-p256-sha256",
2727
AlgorithmName::EcdsaP384Sha384 => "ecdsa-p384-sha384",
2828
AlgorithmName::Ed25519 => "ed25519",
29-
#[cfg(feature = "rsasig")]
29+
#[cfg(feature = "rsa-signature")]
3030
AlgorithmName::RsaV1_5Sha256 => "rsa-v1_5-sha256",
31-
#[cfg(feature = "rsasig")]
31+
#[cfg(feature = "rsa-signature")]
3232
AlgorithmName::RsaPssSha512 => "rsa-pss-sha512",
3333
}
3434
}
@@ -49,9 +49,9 @@ impl core::str::FromStr for AlgorithmName {
4949
"ecdsa-p256-sha256" => Ok(Self::EcdsaP256Sha256),
5050
"ecdsa-p384-sha384" => Ok(Self::EcdsaP384Sha384),
5151
"ed25519" => Ok(Self::Ed25519),
52-
#[cfg(feature = "rsasig")]
52+
#[cfg(feature = "rsa-signature")]
5353
"rsa-v1_5-sha256" => Ok(Self::RsaV1_5Sha256),
54-
#[cfg(feature = "rsasig")]
54+
#[cfg(feature = "rsa-signature")]
5555
"rsa-pss-sha512" => Ok(Self::RsaPssSha512),
5656
_ => Err(HttpSigError::InvalidAlgorithmName(s.to_string())),
5757
}

0 commit comments

Comments
 (0)