diff --git a/aws/rust-runtime/aws-sigv4/Cargo.toml b/aws/rust-runtime/aws-sigv4/Cargo.toml index ce91ae5209..1e628da528 100644 --- a/aws/rust-runtime/aws-sigv4/Cargo.toml +++ b/aws/rust-runtime/aws-sigv4/Cargo.toml @@ -13,7 +13,7 @@ default = ["sign-http"] http0-compat = ["dep:http"] sign-http = ["dep:http", "dep:percent-encoding", "dep:form_urlencoded"] sign-eventstream = ["dep:aws-smithy-eventstream"] -sigv4a = ["dep:p256", "dep:num-bigint", "dep:zeroize", "dep:ring"] +sigv4a = ["dep:p256", "dep:crypto-bigint", "dep:subtle", "dep:zeroize", "dep:ring"] [dependencies] aws-credential-types = { path = "../aws-credential-types" } @@ -33,6 +33,8 @@ percent-encoding = { version = "2.1", optional = true } regex = "1.5" ring = { version = "0.17.5", optional = true } sha2 = "0.10" +crypto-bigint = { version = "0.5.4", optional = true } +subtle = { version = "2.5.0", optional = true } time = "0.3.5" tracing = "0.1" zeroize = { version = "^1", optional = true } diff --git a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs index 9c2b8cb980..a8cb3f9538 100644 --- a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs +++ b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs @@ -5,7 +5,7 @@ use aws_smithy_runtime_api::client::identity::Identity; use bytes::{BufMut, BytesMut}; -use num_bigint::BigInt; +use crypto_bigint::{CheckedAdd, CheckedSub, Encoding, U256}; use once_cell::sync::Lazy; use p256::ecdsa::signature::Signer; use p256::ecdsa::{Signature, SigningKey}; @@ -14,16 +14,13 @@ use std::time::SystemTime; use zeroize::Zeroizing; const ALGORITHM: &[u8] = b"AWS4-ECDSA-P256-SHA256"; -static BIG_N_MINUS_2: Lazy = Lazy::new(|| { +static BIG_N_MINUS_2: Lazy = Lazy::new(|| { // The N value from section 3.2.1.3 of https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf // Used as the N value for the algorithm described in section A.2.2 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf // *(Basically a prime number blessed by the NSA for use in p256)* - const ORDER: &[u32] = &[ - 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xBCE6FAAD, 0xA7179E84, 0xF3B9CAC2, - 0xFC632551, - ]; - let big_n = BigInt::from_slice(num_bigint::Sign::Plus, ORDER); - big_n - BigInt::from(2i32) + const ORDER: U256 = + U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"); + ORDER.checked_sub(&U256::from(2u32)).unwrap() }); /// Calculates a Sigv4a signature @@ -64,14 +61,16 @@ pub fn generate_signing_key(access_key: &str, secret_access_key: &str) -> impl A let tag = ring::hmac::sign(&key, &buf); let tag = &tag.as_ref()[0..32]; - let k0 = BigInt::from_bytes_be(num_bigint::Sign::Plus, tag); + let k0 = U256::from_be_bytes(tag.try_into().expect("convert to [u8; 32]")); // It would be more secure for this to be a constant time comparison, but because this // is for client usage, that's not as big a deal. if k0 <= *BIG_N_MINUS_2 { - let pk = k0 + BigInt::from(1i32); - let d = Zeroizing::new(pk.to_bytes_be().1); - break SigningKey::from_bytes(&d).unwrap(); + let pk = k0 + .checked_add(&U256::ONE) + .expect("k0 is always less than U256::MAX"); + let d = Zeroizing::new(pk.to_be_bytes()); + break SigningKey::from_bytes(d.as_ref()).unwrap(); } *counter = counter