What's the vulnerability?

pyca/cryptography SECT curve public key parsing lacks subgroup validation, enabling small-subgroup attacks that leak ECDH private key bits and allow ECDSA signature forgery.

Root Cause Analysis

# Root Cause Analysis Report

## Summary
pyca/cryptography accepts SECT curve public keys without verifying subgroup membership. For curves with cofactor > 1 (e.g., SECT163K1), a malicious point of small order can be loaded and used in ECDH, causing the shared secret to depend only on the victim’s private key modulo the small subgroup order. This enables leakage of private key bits and breaks protocol security.

## Impact
- **Package/component affected:** pyca/cryptography EC public key parsing and construction paths (EllipticCurvePublicNumbers.public_key, load_der_public_key, load_pem_public_key). 
- **Affected versions:** <= 46.0.4 (per ticket).
- **Risk level and consequences:** High. Small-subgroup points allow ECDH key leakage (private key mod small subgroup order) and can lead to ECDSA forgery in small subgroups.

## Root Cause
The EC public key parsing/building logic relies on OpenSSL EC point construction without enforcing subgroup membership checks for binary SECT curves with nontrivial cofactor. In the Rust key parsing path (`cryptography/src/rust/cryptography-key-parsing/src/spki.rs`), points are accepted via `EcPoint::from_bytes` and `EcKey::from_public_key` without an explicit subgroup validation step. Similarly, `EllipticCurvePublicNumbers.public_key()` constructs a public key without verifying that the point is in the prime-order subgroup. This allows small-order points (e.g., order-2 point (0,1) on SECT163K1) to be accepted as valid public keys.

## Reproduction Steps
1. Run `repro/reproduction_steps.sh`.
2. The script installs `cryptography==46.0.4`, constructs a small-subgroup SECT163K1 public key at point (0,1), and performs ECDH with private keys 1–4.
3. Expected evidence: the point is accepted; odd private keys succeed with a constant shared secret, while even private keys fail, revealing private key parity (mod 2).

## Evidence
- Log file: `logs/repro_output.txt`
- Key excerpts:
  - "accepted small-subgroup point (0,1) on SECT163K1"
  - `d=1 status=ok ...` and `d=2 status=err ...` demonstrating parity leakage.
- Environment: Python 3 with `cryptography==46.0.4` installed by the script.

## Recommendations / Next Steps
- Add explicit subgroup membership checks for SECT curves with cofactor > 1 when constructing or loading public keys.
- Reject points not in the prime-order subgroup or perform cofactor multiplication validation.
- Upgrade to a fixed cryptography release once available and add regression tests for small-subgroup points.

## Additional Notes
- Idempotent: running `repro/reproduction_steps.sh` repeatedly yields the same acceptance/leakage pattern.
- Limitation: demonstration focuses on SECT163K1 order-2 subgroup; other SECT curves with higher cofactors are also affected.
One Command

Verify with pruva-verify

Run the Pruva CLI to automatically fetch and execute the reproduction script.

pruva-verify REPRO-2026-00089
or pruva-verify GHSA-R6PH-V2QM-Q3C2
or pruva-verify CVE-2026-26007
Install: curl -fsSL https://pruva.dev/install.sh | sh

Or Run Manually

1

Download the script

curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00089/artifacts/reproduction_steps.sh
2

Make executable

chmod +x reproduction_steps.sh
3

Run the script

./reproduction_steps.sh
Run in a VM, container, or disposable environment. This exploits a real vulnerability.

How Pruva Reproduced This

Watch the AI agent's step-by-step process.

Loading session...

Artifacts

No artifacts available