Skip to content

feat: Add X25519 key derivation functions - #10503

Merged
FrederikBolding merged 10 commits into
mainfrom
fb/x25519
Sep 29, 2026
Merged

FrederikBolding merged 10 commits into
mainfrom
fb/x25519

Conversation

@FrederikBolding

@FrederikBolding FrederikBolding commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Explanation

Add functions for deriving X25519 public keys and shared secrets.

React Native benchmark:

Finished x25519 public key benchmark: WebCrypto = 3 ms JS = 78 ms
Finished x25519 shared secret benchmark: WebCrypto = 3 ms JS = 90 ms

References

https://consensyssoftware.atlassian.net/browse/WPC-1336

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Introduces new cryptographic key-agreement APIs where misuse could affect secret derivation, though behavior is delegated to WebCrypto with strict length checks and RFC test vectors.

Overview
Adds X25519 key agreement to @metamask/cryptography as a dedicated subpath export (@metamask/cryptography/x25519), exposing getPublicKey and getSharedSecret for 32-byte keys.

Both operations share a WebCrypto deriveBits path: raw private keys are wrapped in a fixed PKCS#8 header before import, public keys use raw import, and scalar multiplication covers public-key derivation from the RFC 7748 base point and ECDH-style shared secrets. A small toUint8Array helper normalizes BufferSource inputs (including ArrayBuffer and DataView).

The changelog documents the new API, and tests cover custom vectors plus RFC 7748 Section 6.1 Alice/Bob cases, input-type variants, and explicit errors for wrong key lengths.

Reviewed by Cursor Bugbot for commit 935bff1. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread packages/cryptography/src/x25519.ts
Comment thread packages/cryptography/src/x25519.ts Outdated
@FrederikBolding
FrederikBolding marked this pull request as ready for review September 29, 2026 08:57
@FrederikBolding
FrederikBolding requested a review from a team as a code owner September 29, 2026 08:57
Comment thread packages/cryptography/src/x25519.ts Outdated
export async function getPublicKey(
privateKey: BufferSource,
): Promise<Uint8Array> {
return getSharedSecret(privateKey, X25519_BASE_POINT);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the underlying functionality is correct here, using getSharedSecret to get a public key is a bit confusing. Maybe we should extract the functionality into a new function (scalarMultiply or something), and call that from getPublicKey and getSharedSecret.

async function scalarMultiply(privateKey: BufferSource, publicKey: BufferSource): Promise<Uint8Array> {
  // Current implementation of `getSharedSecret`.
}

export async function getPublicKey(privateKey: BufferSource): Promise<Uint8Array> {
  return await scalarMultiply(privateKey, X25519_BASE_POINT);
}

export async function getSharedSecret(privateKey: BufferSource, publicKey: BufferSource): Promise<Uint8Array> {
  return await scalarMultiply(privateKey, publicKey);
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's a good idea. It's a bit of a hack, so good to make it clearer.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FrederikBolding
FrederikBolding added this pull request to the merge queue Sep 29, 2026
Merged via the queue into main with commit 82eeba7 Sep 29, 2026
44 checks passed
@FrederikBolding
FrederikBolding deleted the fb/x25519 branch September 29, 2026 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants