Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/getrandom/src/   (Firefox Browser Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 6 kB image not shown  

Quelle  js.rs

  Sprache: Rust
 

//! Implementation for WASM based on Web and Node.js
use crate::Error;

extern crate std;
use std::{mem::MaybeUninit, thread_local};

use js_sys::{global, Function, Uint8Array};
use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue};

// Size of our temporary Uint8Array buffer used with WebCrypto methods
// Maximum is 65536 bytes see https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
const WEB_CRYPTO_BUFFER_SIZE: usize = 256;
// Node.js's crypto.randomFillSync requires the size to be less than 2**31.
const NODE_MAX_BUFFER_SIZE: usize = (1 << 31) - 1;

enum RngSource {
    Node(NodeCrypto),
    Web(WebCrypto, Uint8Array),
}

// JsValues are always per-thread, so we initialize RngSource for each thread.
//   See: https://github.com/rustwasm/wasm-bindgen/pull/955
thread_local!(
    static RNG_SOURCE: Result<RngSource, Error> = getrandom_init();
);

pub(cratefn getrandom_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    RNG_SOURCE.with(|result| {
        let source = result.as_ref().map_err(|&e| e)?;

        match source {
            RngSource::Node(n) => {
                for chunk in dest.chunks_mut(NODE_MAX_BUFFER_SIZE) {
                    // SAFETY: chunk is never used directly, the memory is only
                    // modified via the Uint8Array view, which is passed
                    // directly to JavaScript. Also, crypto.randomFillSync does
                    // not resize the buffer. We know the length is less than
                    // u32::MAX because of the chunking above.
                    // Note that this uses the fact that JavaScript doesn't
                    // have a notion of "uninitialized memory", this is purely
                    // a Rust/C/C++ concept.
                    let res = n.random_fill_sync(unsafe {
                        Uint8Array::view_mut_raw(chunk.as_mut_ptr() as *mut u8, chunk.len())
                    });
                    if res.is_err() {
                        return Err(Error::NODE_RANDOM_FILL_SYNC);
                    }
                }
            }
            RngSource::Web(crypto, buf) => {
                // getRandomValues does not work with all types of WASM memory,
                // so we initially write to browser memory to avoid exceptions.
                for chunk in dest.chunks_mut(WEB_CRYPTO_BUFFER_SIZE) {
                    // The chunk can be smaller than buf's length, so we call to
                    // JS to create a smaller view of buf without allocation.
                    let sub_buf = buf.subarray(0, chunk.len() as u32);

                    if crypto.get_random_values(&sub_buf).is_err() {
                        return Err(Error::WEB_GET_RANDOM_VALUES);
                    }

                    // SAFETY: `sub_buf`'s length is the same length as `chunk`
                    unsafe { sub_buf.raw_copy_to_ptr(chunk.as_mut_ptr() as *mut u8) };
                }
            }
        };
        Ok(())
    })
}

fn getrandom_init() -> Result<RngSource, Error> {
    let global: Global = global().unchecked_into();

    // Get the Web Crypto interface if we are in a browser, Web Worker, Deno,
    // or another environment that supports the Web Cryptography API. This
    // also allows for user-provided polyfills in unsupported environments.
    let crypto = match global.crypto() {
        // Standard Web Crypto interface
        c if c.is_object() => c,
        // Node.js CommonJS Crypto module
        _ if is_node(&global) => {
            // If module.require isn't a valid function, we are in an ES module.
            match Module::require_fn().and_then(JsCast::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() {
            c if c.is_object() => c,
            _ => return Err(Error::WEB_CRYPTO),
        },
    };

    let buf = Uint8Array::new_with_length(WEB_CRYPTO_BUFFER_SIZE as u32);
    Ok(RngSource::Web(crypto, buf))
}

// Taken from https://www.npmjs.com/package/browser-or-node
fn is_node(global: &Global) -> bool {
    let process = global.process();
    if process.is_object() {
        let versions = process.versions();
        if versions.is_object() {
            return versions.node().is_string();
        }
    }
    false
}

#[wasm_bindgen]
extern "C" {
    // Return type of js_sys::global()
    type Global;

    // Web Crypto API: Crypto interface (https://www.w3.org/TR/WebCryptoAPI/)
    type WebCrypto;
    // Getters for the WebCrypto API
    #[wasm_bindgen(method, getter)]
    fn crypto(this: &Global) -> WebCrypto;
    #[wasm_bindgen(method, getter, js_name = msCrypto)]
    fn ms_crypto(this: &Global) -> WebCrypto;
    // Crypto.getRandomValues()
    #[wasm_bindgen(method, js_name = getRandomValues, catch)]
    fn get_random_values(this: &WebCrypto, buf: &Uint8Array) -> Result<(), JsValue>;

    // Node JS crypto module (https://nodejs.org/api/crypto.html)
    type NodeCrypto;
    // crypto.randomFillSync()
    #[wasm_bindgen(method, js_name = randomFillSync, catch)]
    fn random_fill_sync(this: &NodeCrypto, buf: Uint8Array) -> Result<(), JsValue>;

    // Ideally, we would just use `fn require(s: &str)` here. However, doing
    // this causes a Webpack warning. So we instead return the function itself
    // and manually invoke it using call1. This also lets us to check that the
    // function actually exists, allowing for better error messages. See:
    //   https://github.com/rust-random/getrandom/issues/224
    //   https://github.com/rust-random/getrandom/issues/256
    type Module;
    #[wasm_bindgen(getter, static_method_of = Module, js_class = module, js_name = require, catch)]
    fn require_fn() -> Result<JsValue, JsValue>;

    // Node JS process Object (https://nodejs.org/api/process.html)
    #[wasm_bindgen(method, getter)]
    fn process(this: &Global) -> Process;
    type Process;
    #[wasm_bindgen(method, getter)]
    fn versions(this: &Process) -> Versions;
    type Versions;
    #[wasm_bindgen(method, getter)]
    fn node(this: &Versions) -> JsValue;
}

Messung V0.5 in Prozent
C=85 H=89 G=86

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-06-19) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.