Repository navigation
feat(picky-crypto): add the RustCrypto backend - #559
Merged
Benoît Cortier (CBenoit) merged 30 commits intoOct 15, 2026
Merged
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Contract inconsistencies, ECDSA nonce handling, PBKDF2 error mapping, and the prohibited intent-file addition remain unresolved.
5 open findings
What changed in this PR
Adds a feature-gated RustCrypto implementation of the picky-crypto provider contract and integrates it with conformance testing and CI.
Changes:
- Implements 64 cryptographic provider entries across eight feature families.
- Clarifies contract error handling and malformed RSA-key behavior.
- Adds conformance, feature-powerset, documentation, and dependency-policy checks.
| File | Description |
|---|---|
.github/workflows/ci.yml |
Adds backend conformance and CI checks. |
Cargo.lock |
Locks backend dependencies. |
Cargo.toml |
Registers the backend workspace crate. |
picky/src/signature.rs |
Disambiguates signature encoding. |
picky-crypto/CONTRACT.md |
Revises error and RSA-key rules. |
picky-crypto-conformance/Cargo.toml |
Adds the optional backend feature. |
picky-crypto-conformance/tests/main.rs |
Registers the RustCrypto provider. |
picky-crypto-rustcrypto/AGENTS.md |
Adds backend maintenance guidance. |
picky-crypto-rustcrypto/Cargo.toml |
Defines features and dependencies. |
picky-crypto-rustcrypto/INTENT.md |
Adds backend intent and invariants. |
picky-crypto-rustcrypto/README.md |
Documents features and capabilities. |
picky-crypto-rustcrypto/deny.toml |
Bans weakened Ed25519 compatibility. |
picky-crypto-rustcrypto/src/aead.rs |
Implements AES-GCM. |
picky-crypto-rustcrypto/src/cbc.rs |
Implements CBC ciphers. |
picky-crypto-rustcrypto/src/curve25519.rs |
Implements Ed25519 and X25519. |
picky-crypto-rustcrypto/src/ec.rs |
Implements NIST EC operations. |
picky-crypto-rustcrypto/src/hash.rs |
Implements digest entries. |
picky-crypto-rustcrypto/src/key_wrap.rs |
Implements AES-KW. |
picky-crypto-rustcrypto/src/lib.rs |
Assembles feature-selected entries. |
picky-crypto-rustcrypto/src/mac.rs |
Implements HMAC. |
picky-crypto-rustcrypto/src/pbkdf2.rs |
Implements PBKDF2. |
picky-crypto-rustcrypto/src/random.rs |
Implements secure randomness. |
picky-crypto-rustcrypto/src/rc4.rs |
Implements RC4. |
picky-crypto-rustcrypto/src/rsa.rs |
Implements RSA operations and keys. |
picky-crypto-rustcrypto/src/util.rs |
Adds zeroizing buffer and length helpers. |
🧠 Review effort: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Benoît Cortier (CBenoit)
force-pushed
the
cbenoit-picky-crypto-rustcrypto
branch
7 times, most recently
from
October 13, 2026 08:19
6482c34 to
89e0b3f
Compare
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
ECDSA signing now mixes operating-system randomness into the RFC 6979 nonce, as the contract requires for ECDSA nonces. PBKDF2 reports an output allocation failure as unsupported only above the must-support output length. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The section 4 rule on library validation failures covers key validation only; non-key inputs keep the errors the section 4 table assigns. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Conformance outcome sets for RSA private keys with inconsistent or non-distinct components are exact per test input: a signature verifies under (n, e) or the call returns InvalidKey, and decrypting a ciphertext with valid padding returns the expected plaintext or InvalidKey, never VerificationFailed. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Benoît Cortier (CBenoit)
force-pushed
the
cbenoit-picky-crypto-rustcrypto
branch
from
October 13, 2026 08:49
89e0b3f to
7d72ffc
Compare
The conformance suite generates RSA keys only in extended runs, so an inline test now generates a small key through the backend's seeded generation path and loads it. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
An input beyond a backend's size limit may be refused with Unsupported before its structure is examined, whether or not it is also malformed. Rule 4, the section 4 conformance expectations, section 6.9 and the section 12 eligibility rules follow it; a size limit lies above the must-support set and never applies to a length the algorithm or operation fixes. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Public and private RSA key encodings longer than the largest encoding within the rsa crate's limits return Unsupported before any decoder runs, so no oversized input reaches code whose cost and stack use grow with its size. The caps are derived from the library's maximum modulus and exponent plus DER overhead. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Member
Author
|
Review notes, kept out of the squash commit:
Note LLM-assisted content (no human feedback). |
RFC 8032 §5.1.7 requires S < L. ed25519-dalek weakens its own check when any crate in a build enables its `legacy_compatibility` feature, and the cargo-deny ban protects only this workspace. A CI step runs the signature conformance area with that feature enabled, so the adapter check is exercised on the Wycheproof S + L signatures. The MSRV matrix now checks the backend with every feature. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Benoît Cortier (CBenoit)
force-pushed
the
cbenoit-picky-crypto-rustcrypto
branch
from
October 14, 2026 12:41
e634153 to
3edb3e8
Compare
`UNTESTED:` comments mark the properties no test checks: capacity-limit branches, PBKDF2's allocation-failure mapping, RSA blinding, ECDSA nonce hedging, RSA key-generation seed wiping and buffer zeroization. The RSA encoded-length caps state their invariant in `INVARIANT:` doc comments. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The thin-adapter and conformance invariants are already stated by the picky-crypto and conformance suite intents. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…istency Rule 4 states which outcome wins (a bounds error always, a capacity limit over a structure error) without prescribing an evaluation order. Section 4 allows skipping validation work that grows with an exceeded parameter. Sections 7 and 12 describe RSA private keys whose components are not a consistent key for (n, e), which also covers composite factors. The padding-oracle sentence keeps only the protocol countermeasure, since the decrypt row already states the error. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
DER decoding at the locked versions does not grow the stack with input size, and the loader's modulus check keeps oversized keys away from the library's key construction. The README separates error masking from the timing advisory, and AGENTS.md also forbids editing the contract to make the backend pass. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…gths The inconsistent-RSA areas check the base key's public-key export next to its positive-control load. The differential self-test's PBKDF2 mock differs at both compared control lengths, and each length is asserted separately. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The PKCS#8 decoder skips attributes of any length, so a whole-document cap refused valid maximum-size keys with attributes, which the contract allows only to load or to fail with InvalidKey. DER parsing does not grow with the input, and the modulus and exponent check after parsing already keeps oversized keys away from the library's key construction. The exact public-key cap stays. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Base keys published only with decryption vectors, and keys derived from them, now get signing checks on the vectors' published messages. With no published signature to pin the base key, a signature passes only if the provider's verifier, or else the conformance runner's reference verifier, accepts it, and the check fails if neither exists. Keys from signature vectors keep their checks. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The `random` feature provides the operating-system secure-random entry on its own, for code that needs only randomness. The families that draw randomness (`aead`, `rsa`, `nist-ec`, `curve25519`) enable it. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Implementing the picky-crypto contract needs at least one software backend. RustCrypto covers every contract algorithm except the key-based KDFs and FFDH, and it includes the legacy algorithms NTLM, Kerberos and legacy PKCS#12 need.
Add the picky-crypto-rustcrypto crate (
publish = false). It is a thin adapter: each entry maps the contract's arguments to RustCrypto calls, checks algorithm-fixed lengths and constant bytes, and maps library errors to the contract's error set. Library capabilities the adapter relies on are cited at their locked versions in code comments.fips()is always false. Library zeroize features are enabled, and adapter-held secret copies and returned buffers use zeroizing storage. No secret-holding type implementsDebug.Algorithm families are features, with nothing enabled by default. A build without features yields an empty provider, and each feature only adds entries:
random: the operating-system secure-random entrydigest: SHA-1, SHA-2 and SHA3-384/512 hashes, HMAC and PBKDF2aes: AES-CBCaead: AES-GCMkey-wrap: AES-KWrsa: PKCS#1 v1.5 signature verification (MD5, SHA-1, SHA-2, SHA3-384/512), PKCS#1 v1.5 and OAEP encryption, private-key loading, 2048/3072/4096-bit generationnist-ec: ECDSA and ECDH on P-256, P-384 and P-521, private-key loading and generationcurve25519: Ed25519 verification, loading and generation; X25519 ephemeral and static agreementlegacy: MD4, MD5, RC4, 3DES-EDE3-CBC and RC2-CBCall: every family (64 entries)aead,rsa,nist-ecandcurve25519enablerandom, because they draw randomness from its generator. Key-based KDFs and FFDH are not provided; other providers supply them.Where the library falls short of the contract, the adapter uses library functions only:
legacy_compatibilityfeature.Unsupported: public-key encodings longer than the largest key within those limits are refused before decoding, and private keys are checked after parsing, before key construction.Unsupportedbefore allocation, after the fixed-length and standard-range checks.RSA signing and decryption are blinded, and ECDSA signing mixes OS randomness into the RFC 6979 nonce.
picky-crypto-rustcrypto/deny.toml also bans ed25519-dalek's
legacy_compatibilityfeature over the workspace.CONTRACT.md clarifications motivated by this backend:
InvalidKey, except when the library only rejects a well-formed key for its size or parameters, which maps toUnsupported.Unsupported; a backend may skip validation work that grows with the exceeded parameter.InvalidKeyor behaves as specified under (n, e). Protocols exposed to padding oracles apply their own countermeasure.The conformance suite gains in-range controls next to the RC2, RC4 and PBKDF2 range boundaries and a control just above the PBKDF2 must-support output length, with differential comparison of their outputs. The suite's hand-written-input rule allows such controls, accepting success or
Unsupportedoutside the must-support set. The picky-crypto-conformance runner gains arustcryptofeature that registers this provider withall. CI runs it, together with a depth-2 cargo-hack clippy powerset over the backend's features, the cargo-deny feature ban, the signature area withlegacy_compatibilityenabled, and an MSRV check withall.rsais the prerelease 0.10.0-rc.18, which the workspace already locks.Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com