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

Crypto import for non-node envs #1307

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions packages/crypto/src/pbkdf2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ import { sha512 as nobleSha512 } from "@noble/hashes/sha512";
* `undefined` in that case.
*/
export async function getCryptoModule(): Promise<any | undefined> {
const g: any = globalThis;
if (g.crypto) {
return g.crypto;
}
try {
const crypto = await import("crypto");
const crypto = await require("crypto");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you try this instead?

    // HACK: Use a variable to get webpack to ignore this and cause a
    // runtime error instead of build system error or fallback implementation.
    const nodeCryptoPackageName = "crypto";
    const crypto = await import(nodeCryptoPackageName);

We use this in a different place already. This should avoid build systems trying to bundle a crypto implementation when it is not available natively.

Copy link
Contributor Author

@mvid mvid Nov 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@webmaster128 I introduced this, however the problem is the same. It attempts to resolve crypto when bundling. In my current project, using Expo/React-Native/Metro, it seems to parse/resolve any import call, hence why I switched it to a require. I believe this is specific to the Metro bundler.

Any ideas on how to solve this?

// We get `Object{default: Object{}}` as a fallback when using
// `crypto: false` in Webpack 5, which we interprete as unavailable.
// `crypto: false` in Webpack 5, which we interpret as unavailable.
if (typeof crypto === "object" && Object.keys(crypto).length <= 1) {
return undefined;
}
Expand All @@ -24,15 +28,12 @@ export async function getCryptoModule(): Promise<any | undefined> {
}

export async function getSubtle(): Promise<any | undefined> {
const g: any = globalThis;
let subtle = g.crypto && g.crypto.subtle;
if (!subtle) {
const crypto = await getCryptoModule();
if (crypto && crypto.webcrypto && crypto.webcrypto.subtle) {
subtle = crypto.webcrypto.subtle;
}
const crypto = await getCryptoModule();
if (crypto && crypto.subtle) {
return crypto.subtle;
} else if (crypto.webcrypto && crypto.webcrypto.subtle) {
return crypto.webcrypto.subtle;
}
return subtle;
}

export async function pbkdf2Sha512Subtle(
Expand Down Expand Up @@ -108,12 +109,11 @@ export async function pbkdf2Sha512(
const subtle = await getSubtle();
if (subtle) {
return pbkdf2Sha512Subtle(subtle, secret, salt, iterations, keylen);
}
const crypto = await getCryptoModule();
if (crypto) {
return pbkdf2Sha512Crypto(crypto, secret, salt, iterations, keylen);
} else {
const crypto = await getCryptoModule();
if (crypto) {
return pbkdf2Sha512Crypto(crypto, secret, salt, iterations, keylen);
} else {
return pbkdf2Sha512Noble(secret, salt, iterations, keylen);
}
return pbkdf2Sha512Noble(secret, salt, iterations, keylen);
}
}