Skip to content
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

Implement browser getRandomValues without depending on crypto #37

Open
aki-cat opened this issue Mar 8, 2024 · 3 comments
Open

Implement browser getRandomValues without depending on crypto #37

aki-cat opened this issue Mar 8, 2024 · 3 comments
Labels

Comments

@aki-cat
Copy link

aki-cat commented Mar 8, 2024

This is based on this discussion

TL;DR: I propose having an implementation of getRandomValues that does not depend on a native implementation of crypto.

I am having an issue with bundling my code and running it in a non-browser environment, using modules that depend on crypto, which depends on randombytes' implementation of getRandomValues. If I bundle my code in "browser" mode, I get the error 'Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11'.

If I don't bundle it in browser mode but force browser fallback for crypto-browserify (which is necessary in my use-case, the javascript VM I'm using does not implement crypto), then I get a circular dependency and getRandomBytes is never implemented.

Is it possible to implement it in this package? If not is there any particular reason? And can I help in some way?

@SValentyn
Copy link

@aki-cat, I support your request for improvement. I faced the same problem.
Thanks for your knowledgeable description of the issue 👍

@dcousens
Copy link
Member

dcousens commented Apr 2, 2024

You need a random entropy source, and your VM may not be capable if it doesn't have native crypto

@SValentyn
Copy link

The code below solves my problem with polyfills (like crypto, stream, process) and errors using components from Node.js modules. I used the usual low-level Web Crypto API. Maybe it will be useful for someone.

/**
 * Information about Webpack 5 Breaking Changes...
 * Webpack 5 introduced breaking changes related to polyfills, especially for Node.js core modules like 'crypto'.
 * Previously, Webpack automatically provided polyfills for Node.js core modules, allowing developers to use them in browser environments seamlessly.
 * However, starting from Webpack 5, this behavior changed, and Webpack no longer includes polyfills for Node.js core modules by default.
 * This change requires developers to find alternative solutions for using Node.js core modules in web environments,
 * such as directly utilizing browser-native functionalities or third-party libraries.
 * In this utility file, the logic has been refactored to utilize the Web Crypto API directly instead of relying on the 'crypto' module.
 * The Web Crypto API provides cryptographic operations in web applications, allowing for secure cryptographic functionalities without the need for polyfills.
 *
 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto | Web Crypto API – SubtleCrypto}
 * @see {@link https://github.com/webpack/changelog-v5?tab=readme-ov-file#automatic-nodejs-polyfills-removed | Webpack 5 – Automatic Node.js Polyfills Removed}
 * @see {@link https://stackoverflow.com/questions/67065644/nodejs-crypto-module-not-working-in-browser-after-bundling-with-webpack | NodeJS crypto module not working in browser after bundling with webpack}
 */

import { Buffer } from "buffer";

/**
 * Generates cryptographically strong random bytes using the Web Crypto API.
 * @param {number} size – The number of random bytes to generate.
 * @returns {Promise<Buffer>} A promise that resolves to a buffer containing random bytes.
 */
export async function randomBytes(size: number): Promise<Buffer> {
    const array = new Uint8Array(size);
    window.crypto.getRandomValues(array);
    return Buffer.from(array.buffer);
}

/**
 * Creates a hash of the provided data using the Web Crypto API.
 * @param {string} data – The data to hash.
 * @param {string} algorithm – The hash algorithm to use, e.g., 'SHA-256'.
 * @returns {Promise<Buffer>} A promise that resolves to the hash of the data as a buffer.
 */
export async function createHash(data: string, algorithm: string): Promise<Buffer> {
    const encoder = new TextEncoder();
    const dataBuffer = encoder.encode(data);
    const hashBuffer = await window.crypto.subtle.digest(algorithm, dataBuffer);
    return Buffer.from(hashBuffer);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants