diff options
author | Antoine du Hamel <duhamelantoine1995@gmail.com> | 2022-02-14 19:14:49 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-14 19:14:49 +0300 |
commit | 849991c6c47a0e05365feb4c9b1fb841924a5192 (patch) | |
tree | 056d4fc7618a0834f15afffa91aa013c37f13c0e | |
parent | b53f927a521e6bae7e12583634b4a21aef348f13 (diff) |
crypto: expose Web Crypto API on the global scope
PR-URL: https://github.com/nodejs/node/pull/41938
Refs: https://developer.mozilla.org/en-US/docs/Web/API/crypto_property
Refs: https://github.com/nodejs/node/pull/41782
Refs: https://w3c.github.io/webcrypto
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michaƫl Zasso <targos@protonmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
-rw-r--r-- | .eslintrc.js | 4 | ||||
-rw-r--r-- | doc/api/cli.md | 10 | ||||
-rw-r--r-- | doc/api/crypto.md | 2 | ||||
-rw-r--r-- | doc/api/globals.md | 52 | ||||
-rw-r--r-- | doc/node.1 | 3 | ||||
-rw-r--r-- | lib/.eslintrc.yaml | 8 | ||||
-rw-r--r-- | lib/internal/bootstrap/pre_execution.js | 26 | ||||
-rw-r--r-- | lib/internal/crypto/webcrypto.js | 1 | ||||
-rw-r--r-- | lib/internal/main/worker_thread.js | 2 | ||||
-rw-r--r-- | src/node_options.cc | 4 | ||||
-rw-r--r-- | src/node_options.h | 1 | ||||
-rw-r--r-- | test/common/index.js | 6 | ||||
-rw-r--r-- | test/parallel/test-global-webcrypto-classes.js | 13 | ||||
-rw-r--r-- | test/parallel/test-global-webcrypto.js | 13 |
14 files changed, 145 insertions, 0 deletions
diff --git a/.eslintrc.js b/.eslintrc.js index da17fd47acd..c7c7cc56051 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -340,5 +340,9 @@ module.exports = { Headers: 'readable', Request: 'readable', Response: 'readable', + crypto: 'readable', + Crypto: 'readable', + CryptoKey: 'readable', + SubtleCrypto: 'readable', }, }; diff --git a/doc/api/cli.md b/doc/api/cli.md index 10500f130a6..a551a3fff9c 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -288,6 +288,14 @@ added: v17.5.0 Enable experimental support for the [Fetch API][]. +### `--experimental-global-webcrypto` + +<!-- YAML +added: REPLACEME +--> + +Expose the [Web Crypto API][] on the global scope. + ### `--experimental-import-meta-resolve` <!-- YAML @@ -1580,6 +1588,7 @@ Node.js options that are allowed are: * `--enable-source-maps` * `--experimental-abortcontroller` * `--experimental-fetch` +* `--experimental-global-webcrypto` * `--experimental-import-meta-resolve` * `--experimental-json-modules` * `--experimental-loader` @@ -1982,6 +1991,7 @@ $ node --max-old-space-size=1536 index.js [Source Map]: https://sourcemaps.info/spec.html [Subresource Integrity]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity [V8 JavaScript code coverage]: https://v8project.blogspot.com/2017/12/javascript-code-coverage.html +[Web Crypto API]: webcrypto.md [`"type"`]: packages.md#type [`--cpu-prof-dir`]: #--cpu-prof-dir [`--diagnostic-dir`]: #--diagnostic-dirdirectory diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 0e56f12a6fd..e5b83eb4ff5 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -41,6 +41,8 @@ calling `require('crypto')` will result in an error being thrown. When using CommonJS, the error thrown can be caught using try/catch: +<!-- eslint-skip --> + ```cjs let crypto; try { diff --git a/doc/api/globals.md b/doc/api/globals.md index 1fa6801dda6..f4ea4fb4747 100644 --- a/doc/api/globals.md +++ b/doc/api/globals.md @@ -307,6 +307,43 @@ added: v0.1.100 Used to print to stdout and stderr. See the [`console`][] section. +## `Crypto` + +<!-- YAML +added: REPLACEME +--> + +> Stability: 1 - Experimental. Enable this API with the +> [`--experimental-global-webcrypto`][] CLI flag. + +A browser-compatible implementation of {Crypto}. This global is available +only if the Node.js binary was compiled with including support for the +`crypto` module. + +## `crypto` + +<!-- YAML +added: REPLACEME +--> + +> Stability: 1 - Experimental. Enable this API with the +> [`--experimental-global-webcrypto`][] CLI flag. + +A browser-compatible implementation of the [Web Crypto API][]. + +## `CryptoKey` + +<!-- YAML +added: REPLACEME +--> + +> Stability: 1 - Experimental. Enable this API with the +> [`--experimental-global-webcrypto`][] CLI flag. + +A browser-compatible implementation of {CryptoKey}. This global is available +only if the Node.js binary was compiled with including support for the +`crypto` module. + ## `Event` <!-- YAML @@ -534,6 +571,19 @@ added: v17.0.0 The WHATWG [`structuredClone`][] method. +## `SubtleCrypto` + +<!-- YAML +added: REPLACEME +--> + +> Stability: 1 - Experimental. Enable this API with the +> [`--experimental-global-webcrypto`][] CLI flag. + +A browser-compatible implementation of {SubtleCrypto}. This global is available +only if the Node.js binary was compiled with including support for the +`crypto` module. + ## `DOMException` <!-- YAML @@ -598,7 +648,9 @@ The object that acts as the namespace for all W3C [WebAssembly][webassembly-org] related functionality. See the [Mozilla Developer Network][webassembly-mdn] for usage and compatibility. +[Web Crypto API]: webcrypto.md [`--experimental-fetch`]: cli.md#--experimental-fetch +[`--experimental-global-webcrypto`]: cli.md#--experimental-global-webcrypto [`AbortController`]: https://developer.mozilla.org/en-US/docs/Web/API/AbortController [`DOMException`]: https://developer.mozilla.org/en-US/docs/Web/API/DOMException [`EventTarget` and `Event` API]: events.md#eventtarget-and-event-api diff --git a/doc/node.1 b/doc/node.1 index 86a5bd865ae..972487be121 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -142,6 +142,9 @@ Enable Source Map V3 support for stack traces. .It Fl -experimental-fetch Enable experimental support for the Fetch API. . +.It Fl -experimental-global-webcrypto +Expose the Web Crypto API on the global scope. +. .It Fl -experimental-import-meta-resolve Enable experimental ES modules support for import.meta.resolve(). . diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index c5e1058a306..709c5f4c93e 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -79,6 +79,12 @@ rules: message: "Use `const { atob } = require('buffer');` instead of the global." - name: btoa message: "Use `const { btoa } = require('buffer');` instead of the global." + - name: crypto + message: "Use `const { crypto } = require('internal/crypto/webcrypto');` instead of the global." + - name: Crypto + message: "Use `const { Crypto } = require('internal/crypto/webcrypto');` instead of the global." + - name: CryptoKey + message: "Use `const { CryptoKey } = require('internal/crypto/webcrypto');` instead of the global." - name: global message: "Use `const { globalThis } = primordials;` instead of `global`." - name: globalThis @@ -89,6 +95,8 @@ rules: message: "Use `const { queueMicrotask } = require('internal/process/task_queues');` instead of the global." - name: structuredClone message: "Use `const { structuredClone } = require('internal/structured_clone');` instead of the global." + - name: SubtleCrypto + message: "Use `const { SubtleCrypto } = require('internal/crypto/webcrypto');` instead of the global." # Custom rules in tools/eslint-rules node-core/lowercase-name-for-primitive: error node-core/non-ascii-character: error diff --git a/lib/internal/bootstrap/pre_execution.js b/lib/internal/bootstrap/pre_execution.js index 1fe56478e0a..ca7063ac90d 100644 --- a/lib/internal/bootstrap/pre_execution.js +++ b/lib/internal/bootstrap/pre_execution.js @@ -3,6 +3,7 @@ const { NumberParseInt, ObjectDefineProperty, + ObjectGetOwnPropertyDescriptor, SafeMap, SafeWeakMap, StringPrototypeStartsWith, @@ -36,6 +37,7 @@ function prepareMainThreadExecution(expandArgv1 = false) { setupInspectorHooks(); setupWarningHandler(); setupFetch(); + setupWebCrypto(); // Resolve the coverage directory to an absolute path, and // overwrite process.env so that the original path gets passed @@ -162,6 +164,29 @@ function setupFetch() { exposeInterface(globalThis, 'Response', undici.Response); } +// TODO(aduh95): move this to internal/bootstrap/browser when the CLI flag is +// removed. +function setupWebCrypto() { + if (!getOptionValue('--experimental-global-webcrypto')) { + return; + } + + let webcrypto; + ObjectDefineProperty(globalThis, 'crypto', + ObjectGetOwnPropertyDescriptor({ + get crypto() { + webcrypto ??= require('internal/crypto/webcrypto'); + return webcrypto.crypto; + } + }, 'crypto')); + if (internalBinding('config').hasOpenSSL) { + webcrypto ??= require('internal/crypto/webcrypto'); + exposeInterface(globalThis, 'Crypto', webcrypto.Crypto); + exposeInterface(globalThis, 'CryptoKey', webcrypto.CryptoKey); + exposeInterface(globalThis, 'SubtleCrypto', webcrypto.SubtleCrypto); + } +} + // Setup User-facing NODE_V8_COVERAGE environment variable that writes // ScriptCoverage to a specified file. function setupCoverageHooks(dir) { @@ -503,6 +528,7 @@ module.exports = { setupCoverageHooks, setupWarningHandler, setupFetch, + setupWebCrypto, setupDebugEnv, setupPerfHooks, prepareMainThreadExecution, diff --git a/lib/internal/crypto/webcrypto.js b/lib/internal/crypto/webcrypto.js index c022bb44223..8e3822494be 100644 --- a/lib/internal/crypto/webcrypto.js +++ b/lib/internal/crypto/webcrypto.js @@ -808,6 +808,7 @@ ObjectDefineProperties( module.exports = { Crypto, + CryptoKey, SubtleCrypto, crypto, }; diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js index 5e24b84e14c..a5816f1f1cf 100644 --- a/lib/internal/main/worker_thread.js +++ b/lib/internal/main/worker_thread.js @@ -18,6 +18,7 @@ const { setupInspectorHooks, setupWarningHandler, setupFetch, + setupWebCrypto, setupDebugEnv, setupPerfHooks, initializeDeprecations, @@ -69,6 +70,7 @@ setupDebugEnv(); setupWarningHandler(); setupFetch(); +setupWebCrypto(); initializeSourceMapsHandlers(); // Since worker threads cannot switch cwd, we do not need to diff --git a/src/node_options.cc b/src/node_options.cc index bac3de2404b..ab3b736e07d 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -319,6 +319,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "experimental Fetch API", &EnvironmentOptions::experimental_fetch, kAllowedInEnvironment); + AddOption("--experimental-global-webcrypto", + "expose experimental Web Crypto API on the global scope", + &EnvironmentOptions::experimental_global_web_crypto, + kAllowedInEnvironment); AddOption("--experimental-json-modules", "", NoOp{}, kAllowedInEnvironment); AddOption("--experimental-loader", "use the specified module as a custom loader", diff --git a/src/node_options.h b/src/node_options.h index 6042f5e7f5e..0ded5d89bee 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -108,6 +108,7 @@ class EnvironmentOptions : public Options { std::string dns_result_order; bool enable_source_maps = false; bool experimental_fetch = false; + bool experimental_global_web_crypto = false; bool experimental_https_modules = false; std::string experimental_specifier_resolution; bool experimental_wasm_modules = false; diff --git a/test/common/index.js b/test/common/index.js index fdffecb9af1..46a59b54d52 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -308,6 +308,12 @@ if (global.fetch) { global.Headers, ); } +if (hasCrypto && global.crypto) { + knownGlobals.push(global.crypto); + knownGlobals.push(global.Crypto); + knownGlobals.push(global.CryptoKey); + knownGlobals.push(global.SubtleCrypto); +} function allowGlobals(...allowlist) { knownGlobals = knownGlobals.concat(allowlist); diff --git a/test/parallel/test-global-webcrypto-classes.js b/test/parallel/test-global-webcrypto-classes.js new file mode 100644 index 00000000000..083592bd922 --- /dev/null +++ b/test/parallel/test-global-webcrypto-classes.js @@ -0,0 +1,13 @@ +// Flags: --experimental-global-webcrypto --expose-internals +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const webcrypto = require('internal/crypto/webcrypto'); + +assert.strictEqual(Crypto, webcrypto.Crypto); +assert.strictEqual(CryptoKey, webcrypto.CryptoKey); +assert.strictEqual(SubtleCrypto, webcrypto.SubtleCrypto); diff --git a/test/parallel/test-global-webcrypto.js b/test/parallel/test-global-webcrypto.js new file mode 100644 index 00000000000..70f84a1b3a0 --- /dev/null +++ b/test/parallel/test-global-webcrypto.js @@ -0,0 +1,13 @@ +// Flags: --experimental-global-webcrypto +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const assert = require('assert'); +const crypto = require('crypto'); + +assert.strictEqual(globalThis.crypto, crypto.webcrypto); +assert.strictEqual(Crypto, crypto.webcrypto.constructor); +assert.strictEqual(SubtleCrypto, crypto.webcrypto.subtle.constructor); |