-
Notifications
You must be signed in to change notification settings - Fork 43
refactor: Offload message signing to Web Worker #3376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mondoreale
wants to merge
15
commits into
NET-1663-validation
Choose a base branch
from
worker-based-signing
base: NET-1663-validation
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
6f99146
Workerize signing
mondoreale 80e521f
Consolidate worker rollup
mondoreale 54068e5
Make eslint happy
mondoreale 70c5fff
Stick to mjs
mondoreale afb7cab
Simplify signing worker types
mondoreale 5f158ab
Make Identity#getPrivateKey() synchronous
mondoreale 384b718
Reuse MessageSigner instance in test to avoid worker startup overhead
mondoreale 4145e1e
Inline browser worker dependencies to avoid chunk copying issues
mondoreale 90f46f3
Extract SigningService from MessageSigner for clearer separation of c…
mondoreale 902eb49
Add unit tests for SigningService with actual worker
mondoreale 618b89e
Eslint
mondoreale ae85fd7
Export DestroySignal and SigningService from SDK for external usage
mondoreale 718b098
Register SigningService in FakeEnvironment dependency container
mondoreale 3e84fc6
Increase test timeout for CLI tools
mondoreale 3209476
Use transferable objects for signing worker communication
mondoreale File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| /** | ||
| * Browser-specific signing worker factory. | ||
| */ | ||
| import Worker from 'web-worker' | ||
|
|
||
| export function createSigningWorker(): InstanceType<typeof Worker> { | ||
| return new Worker( | ||
| new URL('./workers/SigningWorker.browser.mjs', import.meta.url), | ||
| { type: 'module' } | ||
| ) | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| /** | ||
| * Jest-specific signing worker factory. | ||
| * Points to the built worker in dist/ for testing. | ||
| */ | ||
| import Worker from 'web-worker' | ||
|
|
||
| export function createSigningWorker(): InstanceType<typeof Worker> { | ||
| return new Worker( | ||
| new URL('../../dist/workers/SigningWorker.node.mjs', import.meta.url), | ||
| { type: 'module' } | ||
| ) | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| /** | ||
| * Karma-specific signing worker factory. | ||
| * Points to the built worker in dist/ for browser testing. | ||
| */ | ||
| import Worker from 'web-worker' | ||
|
|
||
| export function createSigningWorker(): InstanceType<typeof Worker> { | ||
| return new Worker( | ||
| new URL('../../dist/workers/SigningWorker.browser.mjs', import.meta.url), | ||
| { type: 'module' } | ||
| ) | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| /** | ||
| * Node.js-specific signing worker factory. | ||
| */ | ||
| import Worker from 'web-worker' | ||
|
|
||
| export function createSigningWorker(): InstanceType<typeof Worker> { | ||
| return new Worker( | ||
| new URL('./workers/SigningWorker.node.mjs', import.meta.url), | ||
| { type: 'module' } | ||
| ) | ||
| } |
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /** | ||
| * Singleton signing service using Web Worker. | ||
| * This offloads CPU-intensive cryptographic operations to a separate thread. | ||
| * Works in both browser and Node.js environments via platform-specific config. | ||
| * | ||
| * The worker is lazily initialized on first use and shared across all MessageSigner instances. | ||
| */ | ||
| import { wrap, releaseProxy, type Remote } from 'comlink' | ||
| import { Lifecycle, scoped } from 'tsyringe' | ||
| import { createSigningWorker } from '@/createSigningWorker' | ||
| import { SigningResult, SigningRequest } from './signingUtils' | ||
| import type { SigningWorkerApi } from './SigningWorker' | ||
| import { DestroySignal } from '../DestroySignal' | ||
|
|
||
| @scoped(Lifecycle.ContainerScoped) | ||
| export class SigningService { | ||
| private worker: ReturnType<typeof createSigningWorker> | undefined | ||
| private workerApi: Remote<SigningWorkerApi> | undefined | ||
|
|
||
| constructor(destroySignal: DestroySignal) { | ||
| destroySignal.onDestroy.listen(() => this.destroy()) | ||
| } | ||
|
|
||
| private getWorkerApi(): Remote<SigningWorkerApi> { | ||
| if (this.workerApi === undefined) { | ||
| this.worker = createSigningWorker() | ||
| this.workerApi = wrap<SigningWorkerApi>(this.worker) | ||
| } | ||
| return this.workerApi | ||
| } | ||
|
|
||
| async sign(request: SigningRequest): Promise<SigningResult> { | ||
| return this.getWorkerApi().createSignature(request) | ||
| } | ||
|
|
||
| destroy(): void { | ||
| if (this.workerApi !== undefined) { | ||
| this.workerApi[releaseProxy]() | ||
| this.workerApi = undefined | ||
| } | ||
| if (this.worker !== undefined) { | ||
| this.worker.terminate() | ||
| this.worker = undefined | ||
| } | ||
| } | ||
| } | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { expose, transfer } from 'comlink' | ||
| import { | ||
| createSignatureFromData, | ||
| SigningResult, | ||
| SigningRequest, | ||
| } from './signingUtils' | ||
|
|
||
| const workerApi = { | ||
| createSignature: async ( | ||
| request: SigningRequest | ||
| ): Promise<SigningResult> => { | ||
| const result = await createSignatureFromData(request) | ||
| if (result.type === 'success') { | ||
| return transfer(result, [result.signature.buffer]) | ||
| } | ||
| return result | ||
| }, | ||
| } | ||
|
|
||
| export type SigningWorkerApi = typeof workerApi | ||
|
|
||
| expose(workerApi) |
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if it would make more sense to just create the worker in the constructor