Conversation
Because: * Passkey PRF-derived keys need an HPKE envelope to wrap account keys client-side. This commit: * Adds packages/fxa-settings/src/lib/passkey-crypto with HPKE seal/open and key-wrap helpers, the shared ciphersuite in suite.ts, RFC 9180 A.6 test vectors, and unit tests. * Stores skR as the raw scalar (Nsk 66) rather than a pkcs8 export, so every stored length is a ciphersuite constant. pkcs8's 241 bytes rest on Web Crypto emitting an OPTIONAL public-key field, and a conforming implementation that omitted it would be zero-padded into the fixed-width column and never open again. Serialising is left to the library, which pads short scalars: ~1 P-521 key in 512 has a leading zero byte, so a stripping implementation would corrupt those wraps undetectably. Covered by a regression test. * Keeps openKb taking pkR alongside the private key, so the library never derives it via crypto.subtle.getPublicKey, whose fallback needs an extractable key and fails only in browsers lacking the method. * Adds the hpke dependency and allows it through Jest's transformIgnorePatterns.
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.
Because
client-side, which is the foundation the passkey sync sign-in flow builds on.
there is no version field, so the primitives and their sizes need to be
settled and test-pinned before anything composes them.
This pull request
packages/fxa-settings/src/lib/passkey-crypto/, a client-only module intwo layers:
hpke.tsseals and openskBagainst a per-wrap P-521 recipientkey, and
key-wrap.tsgenerates that keypair and wraps its private scalarunder the WebAuthn PRF output with AES-256-GCM.
CipherSuiteinsuite.tsso the AES-GCM layer can useSerializePrivateKeywithout depending on the HPKE layer above it, andfreezes the wire sizes in
constants.ts.skRas the RFC 9180 raw scalar rather than a PKCS#8 export, makingprfWrappedSkR82 bytes instead of 257.Nsk= 66 is a ciphersuite constant,whereas PKCS#8's 241 bytes depend on Web Crypto emitting an OPTIONAL
public-key field no spec requires — an implementation that omitted it would be
zero-padded into the fixed-width column and never open again.
pkRalongside the private key inopenKb, so the library neverderives the public key via
crypto.subtle.getPublicKey, whose fallback needsan extractable key and fails only in browsers lacking that method.
hpke@1.1.3as an exact pin and allows it through Jest'stransformIgnorePatterns.including the RFC 9180 Appendix A.6 vectors.
Issue that this pull request solves
Closes: FXA-13144
Checklist
Put an
xin the boxes that applyHow to review (Optional)
constants.ts(the frozen sizes), and theskR-as-raw-scalar reasoning inV1_SIZES.skRRaw.README.md→constants.ts→suite.ts→key-wrap.ts→hpke.ts→ tests.production. The two constraints most easily undone are the fresh-per-wrap
keyWrapIvandopenKbtakingpkR; both have dedicated regression tests.Screenshots (Optional)
Please attach the screenshots of the changes made in case of change in user interface.
Other information (Optional)
Depends on #20958 (FXA-13138), which must merge first.
V1_SIZES.prfWrappedSkR = 82here and
prfWrappedSkR BINARY(82)inpatch-194-195.sqlthere are the same decision intwo places and have to land together — merging this first would leave constants on
maindescribing a column that does not exist yet.
Nothing imports this module yet. FXA-13147 composes these primitives into the create and
unwrap flows, so this PR adds no behaviour on its own.