Repository navigation
feat(sdk): add AesGcmEncryptor to CryptoService (DSPX-4496) - #1063
Draft
dmihalcik-virtru wants to merge 1 commit into
Draft
dmihalcik-virtru wants to merge 1 commit into
dmihalcik-virtru wants to merge 1 commit into
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Oct 6, 2026
dmihalcik-virtru
force-pushed
the
DSPX-4496-aes-gcm-encryptor
branch
from
October 7, 2026 13:30
442bc14 to
1b7c6e9
Compare
dmihalcik-virtru
force-pushed
the
DSPX-4496-encrypted-segment-size
branch
from
October 7, 2026 13:30
32d08b0 to
5281f17
Compare
X-Test Failure Reportcoverage-web-app-browser |
dmihalcik-virtru
force-pushed
the
DSPX-4496-encrypted-segment-size
branch
from
October 7, 2026 17:04
5281f17 to
e6951e2
Compare
Add an optional `CryptoService.createAesGcmEncryptor(key)` that returns a per-key AES-GCM encryptor. The encryptor owns its IV construction, either NIST SP 800-38D 8.2.1 deterministic or 8.2.2 RBG, and reports it, together with its invocation limit, as read-only properties. No IV goes in; the IV only comes out. That lets a module-backed provider keep IV generation inside its own boundary, as FIPS 140-3 IG C.H requires. - `DefaultCryptoService` implements it with `GcmIvCounter`: a random 8-byte fixed field drawn per encryptor, then a 4-byte big-endian counter. - `createAesGcmEncryptorFor` falls back to the same deterministic construction over the caller-IV `encrypt` for providers without the method. - `guardAesGcmEncryptor` wraps every encryptor. It enforces `invocationLimit` with the new IvExhaustionError, counting failed attempts too, and checks the IV, ciphertext and tag lengths of every result. The writer does not use any of this yet; a follow-up change routes payload and metadata encryption through it. The design note is spec/DSPX-4496.md. Signed-off-by: Dave Mihalcik <dmihalcik@virtru.com> wip: review fixes for #1063
dmihalcik-virtru
force-pushed
the
DSPX-4496-aes-gcm-encryptor
branch
from
October 15, 2026 13:11
1b7c6e9 to
a05aa55
Compare
|
This branch has not been deployed
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.



What
Adds an optional, per-key AES-GCM encryptor to the
CryptoServiceinterface. The encryptor owns its IV construction: no IV goes in, and the IV only comes back as output.createAesGcmEncryptorFor(cryptoService, key)uses the provider's encryptor when the provider has one. Otherwise it builds §8.2.1 deterministic IVs throughGcmIvCounterover the provider's ownrandomBytesand caller-IVencrypt: a random 8-byte fixed field drawn per encryptor, then a 4-byte big-endian counter, with aninvocationLimitof 2^32.DefaultCryptoServicedeliberately does not implementcreateAesGcmEncryptor, and takes that fallback. If it did, a provider written as{ ...DefaultCryptoService, encrypt: hsmEncrypt }would inherit an encryptor bound to the WebCryptoencrypt, and the SDK would prefer it, silently bypassing the override.guardAesGcmEncryptorwraps every encryptor:ivConstructionandinvocationLimitonce, and rejects an unknown construction or a limit that is not an integer from 1 to 2^32;IvExhaustionErrorat the limit;Uint8Arrays;AesGcmEncryptor,AesGcmEncryptResultandAesGcmIvConstructionfromtdf3;IvExhaustionErrorfrom the package root.ciphers/aes-gcm-limits.ts, so sizing code later in the series can use them without an import cycle.spec/DSPX-4496.md.The writer doesn't use any of this yet. #1018 routes encryption through it, so this PR changes nothing at runtime.
Why
The DSPX-4492 ADR allows both §8.2.1 deterministic and §8.2.2 RBG IVs. FIPS 140-3 IG C.H ties approved AES-GCM encryption to IVs generated inside the module, and deterministic counter state is security-relevant state. If the SDK builds the IV and passes it in, the IV comes from outside the module.
Making the IV an output of a per-key encryptor lets any provider keep the whole construction inside its boundary. The SDK only looks at what the encryptor reports; it never needs to know which provider it has. SP 800-38D §8.3 caps RBG-based IVs at 2^32 invocations per key; per the ADR, providers using random IVs should report
invocationLimit ≤ 2^26. The limit is enforced per encryptor, not across encryptors that share a key.Open question for reviewers
ivConstruction: 'deterministic' | 'rbg'versus a boolean such asdeterministicCounterorneedsRbgIvs. See the spec.How to test
cd lib && npm test.tests/mocha/unit/aes-gcm-encryptor.spec.tsand theGcmIvCountertests intdf.spec.tscover:DefaultCryptoServicekeeping itsencryptandrandomBytesoverrides;encryptfails;NaN,Infinity, strings,undefined, out of range);Risk
This adds to the public crypto interface, so please review the API shape carefully. The runtime risk is nil until #1018.
DSPX-4496 series
mainmainmainmainAesGcmEncryptorSPImainDSPX-4496-aes-gcm-encryptorThe large-file work (#1019 through #1024) is stacked on #1018. #1022 uses the payload encryptor's
invocationLimitfor its up-front byte ceiling.