diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4aafe85..afd500c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,8 +58,11 @@ jobs: uses: actions/checkout@v6 - name: Install Rust 1.85 uses: dtolnay/rust-toolchain@1.85 + # there's no lockfile, so pick the newest dependency versions that support the rust-version - name: Check run: cargo check -p sfio-rustls-config --features ${{ matrix.provider }} + env: + CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS: fallback # Fail on any advisory against the dependencies audit: runs-on: ubuntu-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 34049a1..7c81fc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.4.2 +* :shield: Update `pkcs8` to 0.11, so `block-buffer` 0.10, which scanners flag for [GHSA-qwgh-2vcv-g2f7](https://github.com/advisories/GHSA-qwgh-2vcv-g2f7), is replaced by 0.12.1. Earlier versions aren't affected: the advisory's inline cursor doesn't exist in 0.10, and the crate uses it only to decrypt a password-protected private key file. +* :wrench: Rust 1.85 is still the minimum, but the newest versions of some dependencies need a later compiler. Cargo's MSRV-aware resolver (`resolver.incompatible-rust-versions = "fallback"`) picks versions that support 1.85. + # 0.4.1 * :bug: Remove a debug `println!` that wrote the client certificate verification result to stdout on every handshake of a server using authority-based client verification. * :wrench: Set `rust-version` to 1.85, the minimum the current dependencies require. diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 7533d4e..c4ca66e 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sfio-rustls-config" -version = "0.4.1" +version = "0.4.2" license = "MIT OR Apache-2.0" edition = "2021" description = "Configuration routines for Rustls used in libraries from Step Function I/O" @@ -11,7 +11,7 @@ rust-version = "1.85" [dependencies] pem = { version = "^3.0" } -pkcs8 = { version = "0.10.2", features = ["encryption", "pkcs5", "pem", "std"] } +pkcs8 = { version = "0.11", features = ["encryption", "pkcs5", "pem", "std"] } rx509 = "^0.2" rustls = { version = "0.23", default-features = false, features = ["std", "logging", "tls12"] } rustls-pki-types = { version = "1.11.0" } diff --git a/lib/src/pem.rs b/lib/src/pem.rs index 5c457b7..fcf4645 100644 --- a/lib/src/pem.rs +++ b/lib/src/pem.rs @@ -189,7 +189,7 @@ impl PrivateKey { Some(x) => x, }; - let parsed = pkcs8::EncryptedPrivateKeyInfo::try_from(encrypted.as_slice())?; + let parsed = pkcs8::EncryptedPrivateKeyInfoRef::try_from(encrypted.as_slice())?; let document = parsed.decrypt(password.as_ref())?; let key = PrivateKeyDer::Pkcs8(document.to_bytes().to_vec().into()); Ok(Self(key)) @@ -223,6 +223,7 @@ mod test { use super::PrivateKey; use rustls::pki_types::PrivateKeyDer; + // PBES2 with scrypt and AES-256-CBC const TEST_KEY: &str = r#" -----BEGIN ENCRYPTED PRIVATE KEY----- MIIFJTBPBgkqhkiG9w0BBQ0wQjAhBgkrBgEEAdpHBAswFAQIu0Ufk06Ty+ICAkAA @@ -314,6 +315,24 @@ zMeBzj4b4shWrRaiOKoQop5QXWazx4Ma14PehEK8WXgqlHvaD6FMZF432DlpiApC cr+jfC1zzDLXwxa69QcwOcFGkxtsl9QPToviY4+5PcjU5+ioaA7Hw14= -----END RSA PRIVATE KEY-----"#; + // PBES2 with PBKDF2 (HMAC-SHA256) and AES-256-CBC + const PBKDF2_TEST_KEY: &str = r#" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIH0MF8GCSqGSIb3DQEFDTBSMDEGCSqGSIb3DQEFDDAkBBC6Frp0xHoSHhk6wvGi +F/9xAgIIADAMBggqhkiG9w0CCQUAMB0GCWCGSAFlAwQBKgQQLmBknR96e7s53ayA +BiIklQSBkAvRTDcNRTnLI5SSB6n74W7f2PS/0WNxmn5YDUpkvl0PzPC+UNCL1HNM +GThI4tPZiD5YPvGNVbwIQ/wKFMu10NA7ZybJfw5co7z3hHrLa23P4KQZXI5jymdH +8aBtQh2fv5Opob7exI5ZtEu439wJVYFMe15tDSwX/Uoq43OidZdF3qrTjkFWZzv7 +RAzz5MFDjw== +-----END ENCRYPTED PRIVATE KEY-----"#; + + const PBKDF2_DECRYPTED_KEY: &str = r#" +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQge/LHy5tkqlvtdgMy +mFBSvV27TC8xyA7biqUfhH7XPKehRANCAAQEKrgmUMmdMTw756XW4zefh7LZS9Of +VXh8HuSqV9S2vRuB76VWBR7b6wh2uYSbMKKoYpPb5uhwROTbX81XUy64 +-----END PRIVATE KEY-----"#; + #[test] fn can_decrypt_pkcs8_key() { let key = PrivateKey::decrypt_from_pem(TEST_KEY, "foobar").unwrap(); @@ -322,6 +341,14 @@ cr+jfC1zzDLXwxa69QcwOcFGkxtsl9QPToviY4+5PcjU5+ioaA7Hw14= assert_eq!(key.into_inner().secret_der(), decrypted.contents()); } + #[test] + fn can_decrypt_pbkdf2_pkcs8_key() { + let key = PrivateKey::decrypt_from_pem(PBKDF2_TEST_KEY, "foobar").unwrap(); + + let decrypted = pem::parse(PBKDF2_DECRYPTED_KEY).unwrap(); + assert_eq!(key.into_inner().secret_der(), decrypted.contents()); + } + #[test] fn can_read_pkcs1_key() { let key = PrivateKey::read_from_pem(RSA_PRIVATE_KEY).unwrap();