Skip to content

Commit a592442

Browse files
aduh95danielleadams
authored andcommittedApr 24, 2022
crypto: expose Web Crypto API on the global scope
PR-URL: #41938 Refs: https://developer.mozilla.org/en-US/docs/Web/API/crypto_property Refs: #41782 Refs: https://w3c.github.io/webcrypto Reviewed-By: James M Snell <[email protected]> Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Filip Skokan <[email protected]>
1 parent 81e56c9 commit a592442

14 files changed

+161
-0
lines changed
 

‎.eslintrc.js

+4
Original file line numberDiff line numberDiff line change
@@ -339,5 +339,9 @@ module.exports = {
339339
Headers: 'readable',
340340
Request: 'readable',
341341
Response: 'readable',
342+
crypto: 'readable',
343+
Crypto: 'readable',
344+
CryptoKey: 'readable',
345+
SubtleCrypto: 'readable',
342346
},
343347
};

‎doc/api/cli.md

+10
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,14 @@ added: REPLACEME
280280

281281
Enable experimental support for the [Fetch API][].
282282

283+
### `--experimental-global-webcrypto`
284+
285+
<!-- YAML
286+
added: REPLACEME
287+
-->
288+
289+
Expose the [Web Crypto API][] on the global scope.
290+
283291
### `--experimental-import-meta-resolve`
284292

285293
<!-- YAML
@@ -1549,6 +1557,7 @@ Node.js options that are allowed are:
15491557
* `--enable-source-maps`
15501558
* `--experimental-abortcontroller`
15511559
* `--experimental-fetch`
1560+
* `--experimental-global-webcrypto`
15521561
* `--experimental-import-meta-resolve`
15531562
* `--experimental-json-modules`
15541563
* `--experimental-loader`
@@ -1948,6 +1957,7 @@ $ node --max-old-space-size=1536 index.js
19481957
[Source Map]: https://sourcemaps.info/spec.html
19491958
[Subresource Integrity]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
19501959
[V8 JavaScript code coverage]: https://v8project.blogspot.com/2017/12/javascript-code-coverage.html
1960+
[Web Crypto API]: webcrypto.md
19511961
[`"type"`]: packages.md#type
19521962
[`--cpu-prof-dir`]: #--cpu-prof-dir
19531963
[`--diagnostic-dir`]: #--diagnostic-dirdirectory

‎doc/api/crypto.md

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ calling `require('crypto')` will result in an error being thrown.
4141

4242
When using CommonJS, the error thrown can be caught using try/catch:
4343

44+
<!-- eslint-skip -->
45+
4446
```cjs
4547
let crypto;
4648
try {

‎doc/api/globals.md

+52
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,43 @@ added: v0.1.100
261261

262262
Used to print to stdout and stderr. See the [`console`][] section.
263263

264+
## `Crypto`
265+
266+
<!-- YAML
267+
added: REPLACEME
268+
-->
269+
270+
> Stability: 1 - Experimental. Enable this API with the
271+
> [`--experimental-global-webcrypto`][] CLI flag.
272+
273+
A browser-compatible implementation of {Crypto}. This global is available
274+
only if the Node.js binary was compiled with including support for the
275+
`crypto` module.
276+
277+
## `crypto`
278+
279+
<!-- YAML
280+
added: REPLACEME
281+
-->
282+
283+
> Stability: 1 - Experimental. Enable this API with the
284+
> [`--experimental-global-webcrypto`][] CLI flag.
285+
286+
A browser-compatible implementation of the [Web Crypto API][].
287+
288+
## `CryptoKey`
289+
290+
<!-- YAML
291+
added: REPLACEME
292+
-->
293+
294+
> Stability: 1 - Experimental. Enable this API with the
295+
> [`--experimental-global-webcrypto`][] CLI flag.
296+
297+
A browser-compatible implementation of {CryptoKey}. This global is available
298+
only if the Node.js binary was compiled with including support for the
299+
`crypto` module.
300+
264301
## `Event`
265302

266303
<!-- YAML
@@ -489,6 +526,19 @@ added: v0.0.1
489526

490527
[`setTimeout`][] is described in the [timers][] section.
491528

529+
## `SubtleCrypto`
530+
531+
<!-- YAML
532+
added: REPLACEME
533+
-->
534+
535+
> Stability: 1 - Experimental. Enable this API with the
536+
> [`--experimental-global-webcrypto`][] CLI flag.
537+
538+
A browser-compatible implementation of {SubtleCrypto}. This global is available
539+
only if the Node.js binary was compiled with including support for the
540+
`crypto` module.
541+
492542
## `TextDecoder`
493543

494544
<!-- YAML
@@ -543,7 +593,9 @@ The object that acts as the namespace for all W3C
543593
[WebAssembly][webassembly-org] related functionality. See the
544594
[Mozilla Developer Network][webassembly-mdn] for usage and compatibility.
545595

596+
[Web Crypto API]: webcrypto.md
546597
[`--experimental-fetch`]: cli.md#--experimental-fetch
598+
[`--experimental-global-webcrypto`]: cli.md#--experimental-global-webcrypto
547599
[`AbortController`]: https://developer.mozilla.org/en-US/docs/Web/API/AbortController
548600
[`EventTarget` and `Event` API]: events.md#eventtarget-and-event-api
549601
[`MessageChannel`]: worker_threads.md#class-messagechannel

‎doc/node.1

+3
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ Enable Source Map V3 support for stack traces.
142142
.It Fl -experimental-fetch
143143
Enable experimental support for the Fetch API.
144144
.
145+
.It Fl -experimental-global-webcrypto
146+
Expose the Web Crypto API on the global scope.
147+
.
145148
.It Fl -experimental-import-meta-resolve
146149
Enable experimental ES modules support for import.meta.resolve().
147150
.

‎lib/.eslintrc.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ rules:
7777
message: "Use `const { atob } = require('buffer');` instead of the global."
7878
- name: btoa
7979
message: "Use `const { btoa } = require('buffer');` instead of the global."
80+
- name: crypto
81+
message: "Use `const { crypto } = require('internal/crypto/webcrypto');` instead of the global."
82+
- name: Crypto
83+
message: "Use `const { Crypto } = require('internal/crypto/webcrypto');` instead of the global."
84+
- name: CryptoKey
85+
message: "Use `const { CryptoKey } = require('internal/crypto/webcrypto');` instead of the global."
8086
- name: global
8187
message: "Use `const { globalThis } = primordials;` instead of `global`."
8288
- name: globalThis
@@ -85,6 +91,8 @@ rules:
8591
message: "Use `const { performance } = require('perf_hooks');` instead of the global."
8692
- name: queueMicrotask
8793
message: "Use `const { queueMicrotask } = require('internal/process/task_queues');` instead of the global."
94+
- name: SubtleCrypto
95+
message: "Use `const { SubtleCrypto } = require('internal/crypto/webcrypto');` instead of the global."
8896
# Custom rules in tools/eslint-rules
8997
node-core/lowercase-name-for-primitive: error
9098
node-core/non-ascii-character: error

‎lib/internal/bootstrap/pre_execution.js

+41
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const {
44
NumberParseInt,
55
ObjectDefineProperty,
6+
ObjectGetOwnPropertyDescriptor,
67
SafeMap,
78
SafeWeakMap,
89
StringPrototypeStartsWith,
@@ -36,6 +37,7 @@ function prepareMainThreadExecution(expandArgv1 = false) {
3637
setupInspectorHooks();
3738
setupWarningHandler();
3839
setupFetch();
40+
setupWebCrypto();
3941

4042
// Resolve the coverage directory to an absolute path, and
4143
// overwrite process.env so that the original path gets passed
@@ -163,6 +165,44 @@ function setupFetch() {
163165
exposeInterface(globalThis, 'Response', undici.Response);
164166
}
165167

168+
// TODO(aduh95): move this to internal/bootstrap/browser when the CLI flag is
169+
// removed.
170+
function setupWebCrypto() {
171+
if (!getOptionValue('--experimental-global-webcrypto')) {
172+
return;
173+
}
174+
175+
let webcrypto;
176+
ObjectDefineProperty(globalThis, 'crypto',
177+
ObjectGetOwnPropertyDescriptor({
178+
get crypto() {
179+
webcrypto ??= require('internal/crypto/webcrypto');
180+
return webcrypto.crypto;
181+
}
182+
}, 'crypto'));
183+
if (internalBinding('config').hasOpenSSL) {
184+
webcrypto ??= require('internal/crypto/webcrypto');
185+
ObjectDefineProperty(globalThis, 'Crypto', {
186+
writable: true,
187+
enumerable: false,
188+
configurable: true,
189+
value: webcrypto.Crypto
190+
});
191+
ObjectDefineProperty(globalThis, 'CryptoKey', {
192+
writable: true,
193+
enumerable: false,
194+
configurable: true,
195+
value: webcrypto.CryptoKey
196+
});
197+
ObjectDefineProperty(globalThis, 'SubtleCrypto', {
198+
writable: true,
199+
enumerable: false,
200+
configurable: true,
201+
value: webcrypto.SubtleCrypto
202+
});
203+
}
204+
}
205+
166206
// Setup User-facing NODE_V8_COVERAGE environment variable that writes
167207
// ScriptCoverage to a specified file.
168208
function setupCoverageHooks(dir) {
@@ -504,6 +544,7 @@ module.exports = {
504544
setupCoverageHooks,
505545
setupWarningHandler,
506546
setupFetch,
547+
setupWebCrypto,
507548
setupDebugEnv,
508549
setupPerfHooks,
509550
prepareMainThreadExecution,

‎lib/internal/crypto/webcrypto.js

+1
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,7 @@ ObjectDefineProperties(
808808

809809
module.exports = {
810810
Crypto,
811+
CryptoKey,
811812
SubtleCrypto,
812813
crypto,
813814
};

‎lib/internal/main/worker_thread.js

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const {
1818
setupInspectorHooks,
1919
setupWarningHandler,
2020
setupFetch,
21+
setupWebCrypto,
2122
setupDebugEnv,
2223
setupPerfHooks,
2324
initializeDeprecations,
@@ -69,6 +70,7 @@ setupDebugEnv();
6970

7071
setupWarningHandler();
7172
setupFetch();
73+
setupWebCrypto();
7274
initializeSourceMapsHandlers();
7375

7476
// Since worker threads cannot switch cwd, we do not need to

‎src/node_options.cc

+4
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
317317
&EnvironmentOptions::experimental_fetch,
318318
kAllowedInEnvironment);
319319
AddOption("--experimental-json-modules", "", NoOp{}, kAllowedInEnvironment);
320+
AddOption("--experimental-global-webcrypto",
321+
"expose experimental Web Crypto API on the global scope",
322+
&EnvironmentOptions::experimental_global_web_crypto,
323+
kAllowedInEnvironment);
320324
AddOption("--experimental-loader",
321325
"use the specified module as a custom loader",
322326
&EnvironmentOptions::userland_loader,

‎src/node_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class EnvironmentOptions : public Options {
105105
bool enable_source_maps = false;
106106
bool experimental_https_modules = false;
107107
bool experimental_fetch = false;
108+
bool experimental_global_web_crypto = false;
108109
std::string experimental_specifier_resolution;
109110
bool experimental_wasm_modules = false;
110111
bool experimental_import_meta_resolve = false;

‎test/common/index.js

+7
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,13 @@ if (global.fetch) {
303303
);
304304
}
305305

306+
if (hasCrypto && global.crypto) {
307+
knownGlobals.push(global.crypto);
308+
knownGlobals.push(global.Crypto);
309+
knownGlobals.push(global.CryptoKey);
310+
knownGlobals.push(global.SubtleCrypto);
311+
}
312+
306313
function allowGlobals(...allowlist) {
307314
knownGlobals = knownGlobals.concat(allowlist);
308315
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Flags: --experimental-global-webcrypto --expose-internals
2+
'use strict';
3+
4+
const common = require('../common');
5+
if (!common.hasCrypto)
6+
common.skip('missing crypto');
7+
8+
const assert = require('assert');
9+
const webcrypto = require('internal/crypto/webcrypto');
10+
11+
assert.strictEqual(Crypto, webcrypto.Crypto);
12+
assert.strictEqual(CryptoKey, webcrypto.CryptoKey);
13+
assert.strictEqual(SubtleCrypto, webcrypto.SubtleCrypto);
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Flags: --experimental-global-webcrypto
2+
'use strict';
3+
4+
const common = require('../common');
5+
if (!common.hasCrypto)
6+
common.skip('missing crypto');
7+
8+
const assert = require('assert');
9+
const crypto = require('crypto');
10+
11+
assert.strictEqual(globalThis.crypto, crypto.webcrypto);
12+
assert.strictEqual(Crypto, crypto.webcrypto.constructor);
13+
assert.strictEqual(SubtleCrypto, crypto.webcrypto.subtle.constructor);

0 commit comments

Comments
 (0)
Please sign in to comment.