Skip to content

Bump p12-keystore to 0.3 (unblocks the pbkdf2 0.12 → 0.13 migration downstream) #14

Description

@Akanoa

Hi!

tcp-stream is currently the only thing holding the pbkdf2 0.12 generation in place for the whole lapin dependency tree.

The chain

tcp-stream 0.34.14   →  p12-keystore ^0.2
p12-keystore 0.2.1   →  pkcs5 ^0.7
pkcs5 0.7.1          →  pbkdf2 ^0.12

The newer generation already exists upstream:

p12-keystore 0.3.1   →  pkcs5 ^0.8
pkcs5 0.8.1          →  pbkdf2 ^0.13

lapin, amq-protocol and amq-protocol-tcp are all already at their latest releases, so tcp-stream is the only place in the chain where this can move.

Why it matters downstream

Any tree combining lapin with a crate that has moved to pbkdf2 0.13 ends up with two pbkdf2 majors. In our case it's the mongodb driver: 3.8.0 requires pbkdf2 ^0.13, lapin transitively requires ^0.12, and with cargo deny's [bans] multiple-versions = "deny" there's no version of either we can pick that resolves it. The same will apply to anyone else on the RustCrypto formats train.

Proposed patch

p12-keystore is used in exactly one place (the private rustls_identity() in src/rustls_impl.rs) and 0.3 has three mechanical breaking changes:

  • KeyStore::from_pkcs12 takes a new Pkcs12ImportPolicy
  • PrivateKeyChain::chain()certs()
  • PrivateKeyChain::key() returns &PrivateKey instead of &[u8]

Cargo.toml:

 [dependencies.p12-keystore]
-version = "^0.2"
+version = "^0.3"
 optional = true

src/rustls_impl.rs:

         Identity::PKCS12 { der, password } => {
-            let pfx =
-                p12_keystore::KeyStore::from_pkcs12(der, password).map_err(io::Error::other)?;
+            let pfx = p12_keystore::KeyStore::from_pkcs12(
+                der,
+                password,
+                p12_keystore::Pkcs12ImportPolicy::Strict,
+            )
+            .map_err(io::Error::other)?;
             let Some((_, keychain)) = pfx.private_key_chain() else {
                 return Err(io::Error::other("No private key in pkcs12 DER"));
             };
             let certs = keychain
-                .chain()
+                .certs()
                 .iter()
                 .map(|cert| CertificateDer::from(cert.as_der().to_vec()))
                 .collect();
             (
                 certs,
-                PrivateKeyDer::from(PrivatePkcs8KeyDer::from(keychain.key().to_vec())),
+                PrivateKeyDer::from(PrivatePkcs8KeyDer::from(keychain.key().as_der().to_vec())),
             )
         }

Pkcs12ImportPolicy::Strict is the #[default], and it reproduces 0.2's behaviour exactly. The policy is read in three places in from_pkcs12, and under Strict all three collapse to what 0.2 did unconditionally: keys are linked to certificates by local_key_id, keys with no match are dropped (0.2 had no else branch there), and standalone certificates are imported only when local_key_id.is_none() && trusted. The issuer-chain walk is unchanged apart from chain being renamed to certs. So this should be a no-op for existing users of the rustls feature.

Verified

Applied to a local copy of 0.34.14 (src/rustls_impl.rs on main is identical to the published crate, so it applies as-is):

  • cargo check — clean
  • cargo test — passes (the doctest; no unit tests in the crate)
  • resolved graph becomes p12-keystore 0.3.1, pkcs5 0.8.1, pbkdf2 0.13.0
  • MSRV is fine: p12-keystore 0.3.1 declares rust-version = "1.85", tcp-stream already declares 1.88.0

Caveats

p12-keystore 0.3.1 pulls pre-release RustCrypto crates:

cms     0.3.0-pre.1
pkcs12  0.2.0-pre.0

Completely understandable if you don't want a stable tcp-stream release depending on pre-release dependencies. I'm mostly filing this so the change is written down and ready to go the day cms 0.3 and pkcs12 0.2 stabilise.

Happy to open a PR with the above whenever you'd find it useful, just say the word.

Thanks for maintaining all of this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions