DEV Community

Faizan Shakeel
Faizan Shakeel

Posted on

The browser has a crypto library built in — you probably don't need a package

Reach for "generate a secure password" or "hash this string" in JavaScript and the instinct is to npm install something. Most of the time you don't have to. Every modern browser ships the Web Crypto API on window.crypto — a fast, audited, native cryptography toolkit. Here are three things it does with zero dependencies.

1. Cryptographically secure random values

Math.random() is not safe for anything security-sensitive — it's predictable. For passwords, tokens, or salts you want crypto.getRandomValues(), which pulls from the OS entropy source:

function securePassword(length = 20) {
  const charset =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*";
  const values = crypto.getRandomValues(new Uint32Array(length));
  return Array.from(values, (v) => charset[v % charset.length]).join("");
}

securePassword(); // e.g. "kR7$mQ2xL9!pW4nZ8vT#"
Enter fullscreen mode Exit fullscreen mode

No library, no server round-trip — the randomness comes straight from the platform.

2. UUIDs in one line

Need a unique ID? There's now a native call for that:

crypto.randomUUID(); // "36b8f84d-df4e-4d49-b662-bbfa2d9f4c15"
Enter fullscreen mode Exit fullscreen mode

That's a spec-compliant v4 UUID, no uuid package required.

3. Hashing with SubtleCrypto

crypto.subtle handles real hashing. Here's SHA-256 of a string:

async function sha256(text) {
  const data = new TextEncoder().encode(text);
  const buffer = await crypto.subtle.digest("SHA-256", data);
  return Array.from(new Uint8Array(buffer))
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
}

await sha256("hello world");
// "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
Enter fullscreen mode Exit fullscreen mode

subtle.digest supports SHA-1, SHA-256, SHA-384 and SHA-512. (MD5 isn't included — it's cryptographically broken — so for legacy MD5 checksums you do still need a small library.)

Why this matters beyond saving a dependency

Because it's native, the data never leaves the page. There's no request to a server, nothing logged, nothing to trust but the browser you already trust. That's the right model for anything sensitive.

It's also the model I built ToolNimbus on — a set of free tools that run entirely client-side. If you'd rather not paste the snippets, the same primitives are wired up here:

Open the network tab while you use them — you'll see nothing gets sent. That's the whole point of the native API.


What else have you built on Web Crypto instead of reaching for a package? I'd love to hear about it in the comments.

Top comments (0)