Open aki-cat opened 6 months ago
@aki-cat, I support your request for improvement. I faced the same problem. Thanks for your knowledgeable description of the issue 👍
You need a random entropy source, and your VM may not be capable if it doesn't have native crypto
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);
}
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 onrandombytes
' implementation ofgetRandomValues
. 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 implementcrypto
), 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?