Skip to content
This repository was archived by the owner on May 14, 2026. It is now read-only.
This repository was archived by the owner on May 14, 2026. It is now read-only.

feat(network): support PKCS#1 client keys (currently PKCS#8 only) #499

@zkochan

Description

@zkochan

Background

#490 wired client cert + key PEM through reqwest::Identity::from_pkcs8_pem, which is the only PKCS path reqwest exposes on its native-tls backend. PKCS#8 PEM (-----BEGIN PRIVATE KEY-----) works; legacy PKCS#1 (-----BEGIN RSA PRIVATE KEY-----) is rejected and surfaces as TlsError::InvalidClientIdentity.

Pnpm hands the cert / key to undici as separate PEM strings and lets Node's tls.createSecureContext accept any PEM format Node accepts — PKCS#1, PKCS#8, and EC keys are all valid. PKCS#12 (.p12 / .pfx) bundles are NOT supported by pnpm — pnpm's .npmrc allow-list at npmConfigTypes.ts declares only cert: [null, String] and key: [null, String]; there's no pfx option.

So the parity gap is PKCS#1 PEM keys, not PKCS#12.

A doc comment on apply_tls in crates/network/src/lib.rs (SHA 55083a4) documents the current PKCS#8-only limitation and the openssl pkcs8 -topk8 -nocrypt conversion workaround.

Options

  1. Switch reqwest's TLS backend to rustls. Identity::from_pem exists under the rustls-tls feature and accepts PKCS#1 + PKCS#8 + EC keys. Trade-offs:
    • Removes native-tls-vendored.
    • Changes platform-specific certificate-store behavior (rustls uses webpki-roots; native-tls uses the platform store). Adds rustls-native-certs to read the system trust roots, otherwise self-signed corporate CAs that work today (because they're in the OS store) silently break.
    • Probably surfaces in cargo deny since the dep tree changes substantially.
    • Existing hickory-dns resolver is rustls-backend-agnostic; should keep working.
  2. Add a preprocessing step. Detect -----BEGIN RSA PRIVATE KEY----- headers and convert PKCS#1 → PKCS#8 in pacquet before handing to Identity::from_pkcs8_pem. Possible via rsa or pkcs1 crates; adds a small new dep but no TLS-backend change.
  3. Document the limitation and stay on PKCS#8. Status quo. Users with PKCS#1 keys convert with openssl pkcs8 -topk8 -nocrypt.

Per AGENTS.md ("match pnpm bug-for-bug"), option 1 is the closest to upstream behavior since pnpm/Node accept any PEM. Option 2 is the smallest diff that still closes the parity gap. Option 3 (status quo) ships with a documented limitation.

What to do

  1. Decide between option 1 (rustls switch) and option 2 (preprocessing).
  2. If option 1: also evaluate impact on:
    • Platform certificate store lookup (rustls needs rustls-native-certs to read system trust roots).
    • DNS resolver — pacquet uses hickory-dns via reqwest; verify it's compatible with the rustls backend.
    • cargo deny posture — the dep tree change is substantial.
    • Existing tests that depend on native-tls error shapes.
  3. If option 2: add a convert_pkcs1_to_pkcs8 helper that detects the header and runs the conversion. Add tests for both PEM formats.

Out of scope

  • PKCS#12 (.pfx) support. Pnpm doesn't expose it, so pacquet shouldn't invent it.
  • EC keys. Native-tls's from_pkcs8_pem already accepts them when they're PKCS#8-encoded; legacy -----BEGIN EC PRIVATE KEY----- would have the same problem as PKCS#1 and would benefit from the same fix.

References


Written by an agent (Claude Code, claude-opus-4-7).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions