Security hardening, GCP provider, native CLI binaries + differential coverage#34
Merged
Merged
Conversation
…ryption.Gcp) Completes the AWS KMS / Azure Key Vault / Google Cloud KMS trio over the IContentKeyProvider seam. GcpKmsContentKeyProvider generates the per-file content key locally (Cloud KMS has no server-side data-key generation), wraps it with Cloud KMS Encrypt bound to library-specific AAD, and unwraps against only the configured CryptoKey — a tampered, foreign-key, or AAD-mismatched blob fails closed with PqDecryptionException while operational failures propagate as the SDK's own exceptions. The CRC32C integrity fields are populated on every request and verified on every response (the .NET SDK does not do this itself), pinned by the RFC 3720 check value. Ships entirely around the frozen .pqfe v2 format via the existing provider seam. Wired into the solution, test project, and release pipeline (pack, SBOM, NuGet push). Unit-tested against an in-process fake reproducing the service's binding and INVALID_ARGUMENT semantics. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…n (security review) An adversarial multi-zone review of the engine surfaced eight bugs that weakened the fail-closed contract; all are fixed here with regression tests and no change to the frozen .pqfe v2 / PQKF v1 / .sig v1 formats. - PQKF ExportEncrypted validates options before writing, so an out-of-range option can no longer silently produce a key file the correct passphrase could never open; ImportEncrypted validates caller-supplied limits so a below-minimum limit is a configuration error, not a hostile-file rejection. - A corrupt ML-KEM-768 recipient key (public half on encrypt, private half on decrypt) now fails closed as a library exception instead of leaking a raw platform/BouncyCastle exception, matching the mirror paths. - Detached-signature verification validates the sidecar before hashing the content (per SIGNATURE-FORMAT.md ordering), and evaluates both signature components in independent guarded steps so one half throwing cannot skip the other. - Cancellation is honored immediately before the password KDF, so a cancelled token no longer pays the full (up to gibibyte-scale) derivation cost first. - LocalKekContentKeyProvider reports a malformed wrap as PqFormatException, keeping PqDecryptionException reserved for one generic auth-failure message. - pqfe encrypt/decrypt refuse to overwrite an existing output without --force. - DecryptAtomicAsync and the DI limits-overload document their boundaries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tions Surface the library's differentiators (open, frozen-format, verifiable) and close the transparency gaps the security review found. - README: a threat-model-in-one-table section, a "verify it yourself" section (provenance, KAT reproduction, cross-implementation), a composable package table, and a zero-friction (no license key) install pitch. - test-vectors/: the known-answer vectors committed as ready-to-use binaries with pinned SHA-256 sums and a 30-second verification walkthrough, guarded by VectorArtifactTests so a frozen artifact cannot drift. - docs/CRYPTO-AGILITY.md: how the format versions, how existing ciphertext stays decryptable across a migration, and the harvest-now-decrypt-later reasoning, stated in one place. - KNOWN-GAPS: correct the frozen-format reader-leniency entry (the KeySource-4 body tolerates trailing bytes / extra blocks and aborts on unknown KemId), and record the directory-fsync durability boundary and DecryptAtomicAsync in-memory ceiling — all format-v3 candidates or documented limitations. - SECURITY.md supported-versions refresh; KEY-MANAGEMENT / COOKBOOK / AUDIT-SCOPE / Hybrid README updated for the Gcp provider and the 55-recipient cap rationale. - CHANGELOG [Unreleased] records the Gcp provider and the security fixes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two developer-experience additions for people building on post-quantum crypto. - Native single-file `pqfe` binaries (linux-x64, win-x64, osx-arm64) are built natively per target in the release pipeline and attached to each release with a SHA-256 sum and a build-provenance attestation — usable with no .NET runtime. - A Rust round-trip property test sweeps the framing matrix (chunk sizes × lengths straddling one/two/three chunks, plus per-byte tamper and truncation at every length), catching encode/decode asymmetry the fixed KATs cannot. The cross-implementation CI harness now randomizes payload sizes each run, so the .NET <-> Rust agreement is exercised at fresh points continuously. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent row Add a fair "versus general-purpose crypto toolkits" section to COMPARISON.md — the broad BouncyCastle-wrapper libraries that expose ML-KEM/ML-DSA as primitives. Framed as a scope/altitude difference (primitives vs a finished fail-closed construction; no-footguns-by-omission; hybrid vs bare Kyber; a verifiable format vs a library), not open-vs-closed, since several are also MIT. Describes the category rather than naming specific packages, so it ages well. Also corrects the at-a-glance table, which still called the recipient path "experimental" — it is the shipped hybrid X25519 + ML-KEM-768 Hybrid package. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bump all nine lockstep packages to 1.6.0, promote the Gcp package's public API from Unshipped to Shipped, and set PackageValidationBaselineVersion to the previous release (1.5.0). Sweep every user-facing version reference: the root README Status line, all `dotnet add package --version` snippets (root + package READMEs), the supply-chain verify/download examples, and the ROADMAP-2.0 "NuGet package version" cell. Finalize the CHANGELOG [1.6.0] section and compare-link footer. Historical references (audit-scope tag/commit, coverage measured at v1.5.0) are left as the facts they are. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The new CLI overwrite guard (refuses to replace an existing output without --force) broke the cross-implementation harness, which re-encrypts to the same temp paths every loop iteration. Add --force to the two reused .NET CLI calls; the other CI encrypt/decrypt calls write once to a fresh temp dir and are unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.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.
Four logical commits from a hardening + developer-experience session on the encryption engine. No change to the frozen
.pqfev2 /PQKFv1 /.sigv1 formats. 537 .NET tests + 13 Rust tests green; zero warnings.1.
feat: Google Cloud KMS envelope-key providerPostQuantum.FileEncryption.Gcpcompletes the AWS / Azure / GCP trio overIContentKeyProvider. CEK generated locally, wrapped with bound AAD, unwrapped only against the configuredCryptoKey, fail-closed on tamper/foreign-key/AAD-mismatch. CRC32C verified both ways (RFC 3720 check value). Wired into solution, tests, and release pipeline.2.
fix: security review (8 bugs, all adversarially verified)PQKF option/limit validation at the boundary (no more silently-unopenable key files); corrupt ML-KEM-768 keys fail closed as library exceptions instead of raw platform/BouncyCastle throws; signature verification validates structure before hashing and evaluates both halves independently; cancellation honored before the KDF; LocalKek taxonomy;
pqferefuses to overwrite output without--force.3.
docs: positioning + trust artifactsThreat-model-in-one-table + "verify it yourself" README sections;
test-vectors/committed as verifiable binaries with pinned hashes (drift-guarded);docs/CRYPTO-AGILITY.md; corrected KNOWN-GAPS reader-leniency ledger + durability/DecryptAtomicAsyncentries.4.
feat: native CLI binaries + differential coverageStandalone single-file
pqfebinaries (linux-x64/win-x64/osx-arm64) attached to each release with SHA-256 + provenance, no .NET runtime needed. A Rust round-trip property test sweeps the framing matrix (chunk × length boundaries, per-byte tamper, truncation) and the cross-implementation CI harness now randomizes payload sizes each run.🤖 Generated with Claude Code