Hashing and encryption
crypto.subtle
Baseline widely available
Chrome37
Edge12
Firefox34
Safari11
Features it needs
- Web CryptographyWidely available
crypto-js ships its own implementations of SHA-256, AES and HMAC as JavaScript, which is both a large download and slower than the same primitives compiled into the browser. crypto.subtle exposes those primitives natively, with key material held as CryptoKey objects the page cannot read out unless you mark them extractable. The API is asynchronous and takes bytes rather than strings, so a call site grows a TextEncoder and an await.
When this applies
Hashing, signing, or encrypting with SHA-2, HMAC, AES or RSA.
The native approach
async function sha256(text) {
const bytes = new TextEncoder().encode(text);
const digest = await crypto.subtle.digest("SHA-256", bytes);
return [...new Uint8Array(digest)]
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
}When the dependency is still right
An answer that always says "the platform covers it" is worse than no answer. These are the cases where this one does not hold.
- You need MD5, SHA-1 signing, or another legacy algorithm. crypto.subtle leaves those out deliberately, so a format that requires one keeps its library.
- The call has to be synchronous. Everything on crypto.subtle returns a promise, which changes any function that hashes inside a render pass or a sort comparator.
- The code runs on plain http somewhere other than localhost. crypto.subtle is undefined outside a secure context.
- You interoperate with crypto-js output that uses its own defaults, such as its OpenSSL-style key derivation for AES, where matching the format by hand is the harder job.
- You need password hashing. Neither the library nor crypto.subtle gives you bcrypt, scrypt or Argon2, and PBKDF2 is the only stretching primitive here.