Update documentation and error messages

This allows users to get an actionable error message about this
particular problem. We also add detection for this problem.

Signed-off-by: Joe Richey <joerichey@google.com>
This commit is contained in:
Joe Richey 2022-09-13 01:21:36 -07:00
parent d69e8e003b
commit 0579fe3014
3 changed files with 32 additions and 11 deletions

View File

@ -53,6 +53,9 @@ impl Error {
pub const NODE_CRYPTO: Error = internal_error(12);
/// Calling Node.js function `crypto.randomFillSync` failed.
pub const NODE_RANDOM_FILL_SYNC: Error = internal_error(13);
/// Called from an ES module on Node.js. This is unsupported, see:
/// https://docs.rs/getrandom#nodejs-es6-module-support.
pub const NODE_ES_MODULE: Error = internal_error(14);
/// Codes below this point represent OS Errors (i.e. positive i32 values).
/// Codes at or above this point, but below [`Error::CUSTOM_START`] are
@ -170,6 +173,7 @@ fn internal_desc(error: Error) -> Option<&'static str> {
Error::VXWORKS_RAND_SECURE => Some("randSecure: VxWorks RNG module is not initialized"),
Error::NODE_CRYPTO => Some("Node.js crypto CommonJS module is unavailable"),
Error::NODE_RANDOM_FILL_SYNC => Some("Calling Node.js API crypto.randomFillSync failed"),
Error::NODE_ES_MODULE => Some("Node.js ES modules are not directly supported, see https://docs.rs/getrandom#nodejs-es6-module-support"),
_ => None,
}
}

View File

@ -10,7 +10,7 @@ use crate::Error;
extern crate std;
use std::thread_local;
use js_sys::{global, Uint8Array};
use js_sys::{global, Function, Uint8Array};
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};
// Size of our temporary Uint8Array buffer used with WebCrypto methods
@ -68,10 +68,14 @@ fn getrandom_init() -> Result<RngSource, Error> {
c if c.is_object() => c,
// Node.js CommonJS Crypto module
_ if is_node(&global) => {
match MODULE.require("crypto") {
Ok(n) if n.is_object() => return Ok(RngSource::Node(n)),
_ => return Err(Error::NODE_CRYPTO),
};
// If require isn't a valid function, we are in an ES module.
match Module::require_fn().dyn_into::<Function>() {
Ok(require_fn) => match require_fn.call1(&global, &JsValue::from_str("crypto")) {
Ok(n) => return Ok(RngSource::Node(n.unchecked_into())),
Err(_) => return Err(Error::NODE_CRYPTO),
},
Err(_) => return Err(Error::NODE_ES_MODULE),
}
}
// IE 11 Workaround
_ => match global.ms_crypto() {
@ -122,10 +126,8 @@ extern "C" {
// js_name = "module.require", so that Webpack doesn't give a warning. See:
// https://github.com/rust-random/getrandom/issues/224
type Module;
#[wasm_bindgen(js_name = module)]
static MODULE: Module;
#[wasm_bindgen(method, catch)]
fn require(this: &Module, s: &str) -> Result<NodeCrypto, JsValue>;
#[wasm_bindgen(getter, static_method_of = Module, js_class = module, js_name = require)]
fn require_fn() -> JsValue;
// Node JS process Object (https://nodejs.org/api/process.html)
#[wasm_bindgen(method, getter)]

View File

@ -31,7 +31,7 @@
//! | Emscripten | `*emscripten` | `/dev/random` (identical to `/dev/urandom`)
//! | WASI | `wasm32wasi` | [`random_get`]
//! | Web Browser | `wasm32*unknown` | [`Crypto.getRandomValues`], see [WebAssembly support]
//! | Node.js | `wasm32*unknown` | [`crypto.randomBytes`], see [WebAssembly support]
//! | Node.js | `wasm32*unknown` | [`crypto.randomFillSync`], see [WebAssembly support]
//! | SOLID | `*-kmc-solid_*` | `SOLID_RNG_SampleRandomBytes`
//! | Nintendo 3DS | `armv6k-nintendo-3ds` | [`getrandom`][1]
//!
@ -91,6 +91,18 @@
//!
//! This feature has no effect on targets other than `wasm32-unknown-unknown`.
//!
//! #### Node.js ES module support
//!
//! Node.js supports both [CommonJS modules] and [ES modules]. Due to
//! limitations in wasm-bindgen's [`module`] support, we cannot directly
//! support ES Modules running on Node.js. However, on Node v15 and later, the
//! module author can add a simple shim to support the Web Cryptography API:
//! ```js
//! import { webcrypto } from 'node:crypto'
//! globalThis.crypto = webcrypto
//! ```
//! This crate will then use the provided `webcrypto` implementation.
//!
//! ### Custom implementations
//!
//! The [`register_custom_getrandom!`] macro allows a user to mark their own
@ -154,11 +166,14 @@
//! [`RDRAND`]: https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
//! [`SecRandomCopyBytes`]: https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc
//! [`cprng_draw`]: https://fuchsia.dev/fuchsia-src/zircon/syscalls/cprng_draw
//! [`crypto.randomBytes`]: https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback
//! [`crypto.randomFillSync`]: https://nodejs.org/api/crypto.html#cryptorandomfillsyncbuffer-offset-size
//! [`esp_fill_random`]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html#_CPPv415esp_fill_randomPv6size_t
//! [`random_get`]: https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#-random_getbuf-pointeru8-buf_len-size---errno
//! [WebAssembly support]: #webassembly-support
//! [`wasm-bindgen`]: https://github.com/rustwasm/wasm-bindgen
//! [`module`]: https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-js-imports/module.html
//! [CommonJS modules]: https://nodejs.org/api/modules.html
//! [ES modules]: https://nodejs.org/api/esm.html
#![doc(
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",