crypto-js, js-sha256, sha.js, and sha256 are JavaScript libraries that provide SHA-256 cryptographic hashing functionality for use in browser environments. These packages enable developers to generate secure hashes from strings, typed arrays, or other data sources without relying on native Web Crypto APIs, which may not be available or suitable in all contexts. While all four support the SHA-256 algorithm, they differ significantly in scope, API design, implementation approach, and maintenance status.
When you need to compute SHA-256 hashes in the browser — for password pre-hashing, integrity checks, or blockchain-related tasks — you’ll likely consider one of these four libraries. They all promise SHA-256, but their design philosophies, APIs, and suitability vary widely. Let’s break them down.
sha256First, the bad news: sha256 is deprecated. Its npm page explicitly states: "This package is no longer maintained." It hasn’t been updated since 2016 and only accepts strings as input. For any new project, skip this entirely.
// sha256 (deprecated — do not use)
import sha256 from 'sha256';
const hash = sha256('hello'); // works only with strings
Now, let’s compare the three viable options.
js-sha256: Simple Function CallsThis library gives you a direct, stateless function. Pass in data, get a hex string back. No instantiation, no chaining.
// js-sha256
import { sha256 } from 'js-sha256';
const hash1 = sha256('hello');
const hash2 = sha256(new Uint8Array([104, 101, 108, 108, 111])); // also supports typed arrays
It also offers a .create() method if you need incremental updates:
const hasher = sha256.create();
hasher.update('he');
hasher.update('llo');
const final = hasher.hex();
crypto-js: Word Arrays and Method Chainingcrypto-js uses its own WordArray type internally. You typically pass strings or typed arrays, but the output is a WordArray object that you must convert to a string.
// crypto-js
import CryptoJS from 'crypto-js';
const hash = CryptoJS.SHA256('hello').toString(); // toString() gives hex
// Or with explicit encoding
const hash2 = CryptoJS.SHA256(CryptoJS.enc.Utf8.parse('hello')).toString();
It’s more verbose but integrates with other crypto-js features like HMAC:
const hmac = CryptoJS.HmacSHA256('message', 'key').toString();
sha.js: Stream-Like Interface (Node.js Style)sha.js mimics Node’s crypto.createHash('sha256') API. You create a hasher instance, feed it data, then call .digest().
// sha.js
import { sha256 } from 'sha.js';
const hasher = sha256();
hasher.update('hello');
const hash = hasher.digest('hex'); // specify output format
It also supports piping and works seamlessly in Node.js:
// Same code runs in Node.js and browser
const hash = require('sha.js').sha256().update('hello').digest('hex');
All three active libraries accept strings, but their support for binary data differs.
js-sha256: Accepts string, Array<number>, Uint8Array, and ArrayBuffer. Very flexible for modern web apps dealing with files or crypto keys.sha256(new Uint8Array([72, 101, 108, 108, 111]));
crypto-js: Accepts strings and WordArray. To use Uint8Array, you must first convert it:const wordArray = CryptoJS.lib.WordArray.create(uint8Array);
const hash = CryptoJS.SHA256(wordArray).toString();
sha.js: Accepts string and Buffer (in Node) or Uint8Array (in browser via polyfill). In practice, you’ll often pass strings or convert binary data to buffers.hasher.update(new Uint8Array([72, 101, 108, 108, 111]));
Need to hash large files in chunks? All three support it, but with different ergonomics.
js-sha256:const hasher = sha256.create();
hasher.update(chunk1);
hasher.update(chunk2);
const result = hasher.hex();
crypto-js does not support incremental updates for SHA-256. Each call to SHA256() is stateless. You’d need to concatenate all data first.
sha.js:
const hasher = sha256();
hasher.update(chunk1);
hasher.update(chunk2);
const result = hasher.digest('hex');
So if you’re processing file uploads or streams, avoid crypto-js for this use case.
js-sha256: Pure ES modules, works everywhere modern JS runs. No dependencies.crypto-js: Built for browsers, but can run in Node.js with bundlers. Uses its own encoding system.sha.js: Designed to mirror Node’s crypto API, so it’s ideal for isomorphic apps. Works in browsers via bundlers or direct inclusion.All three use well-reviewed, constant-time(ish) implementations suitable for non-cryptographic secret handling (e.g., client-side proof-of-work). However, never use client-side hashing as a substitute for server-side security — secrets can always be extracted from the browser.
None of these libraries use the native Web Crypto API (window.crypto.subtle.digest), which is faster and more secure but requires async/await and doesn’t support incremental updates. If you only need one-off hashes and can use async, consider Web Crypto instead:
// Native Web Crypto (async, no external deps)
const buffer = new TextEncoder().encode('hello');
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
But if you need sync hashing, incremental updates, or IE11 support, stick with one of these libraries.
| Feature | crypto-js | js-sha256 | sha.js | sha256 |
|---|---|---|---|---|
| Maintenance | ✅ Active | ✅ Active | ✅ Active | ❌ Deprecated |
| SHA-256 Only? | ❌ (Many algos) | ✅ (SHA family) | ❌ (Multiple algos) | ✅ |
| Input Types | String, WordArray | String, Array, TypedArray | String, Buffer, Uint8Array | String only |
| Incremental Hashing | ❌ | ✅ | ✅ | ❌ |
| API Style | Object-oriented | Functional | Streaming (Node-like) | Functional |
| Bundle Impact | High | Very Low | Medium | Low (but old) |
js-sha256. It’s tiny, fast, supports modern data types, and has a dead-simple API.crypto-js for AES or HMAC: Stick with it for consistency, but know you’re pulling in extra weight.sha.js to keep your hashing logic identical across environments.sha256 — it’s outdated and unmaintained.Remember: client-side hashing is about convenience or protocol compliance, not security. Always validate and re-hash on the server when it matters.
Choose crypto-js if you need a full-featured cryptography library that includes SHA-256 alongside many other algorithms (AES, HMAC, PBKDF2, etc.) and utilities like encoders and word arrays. It’s well-suited for applications requiring multiple cryptographic operations beyond just hashing, though its broader feature set comes with increased bundle size and complexity.
Choose js-sha256 if you want a lightweight, zero-dependency, and modern implementation focused exclusively on SHA-256 (and related variants like SHA3-256). It supports strings, arrays, and typed arrays out of the box, offers a clean functional API, and is actively maintained — ideal for performance-sensitive frontend applications where minimal footprint matters.
Choose sha.js if you prefer a Node.js-compatible stream-based API that mirrors the standard crypto module and supports multiple hash algorithms including SHA-256. It’s useful when you need consistent hashing logic across both Node.js and browser environments, especially in isomorphic applications, though its streaming model may be overkill for simple one-off hashes.
Do not choose sha256 for new projects. The package is deprecated (as noted on its npm page) and unmaintained. While it works for basic string hashing, it lacks support for modern input types like Uint8Array, has no updates since 2016, and offers no advantages over actively maintained alternatives.
JavaScript library of crypto standards.
Active development of CryptoJS has been discontinued. This library is no longer maintained.
Nowadays, NodeJS and modern browsers have a native Crypto module. The latest version of CryptoJS already uses the native Crypto module for random number generation, since Math.random() is not crypto-safe. Further development of CryptoJS would result in it only being a wrapper of native Crypto. Therefore, development and maintenance has been discontinued, it is time to go for the native crypto module.
Requirements:
npm install crypto-js
ES6 import for typical API call signing use case:
import sha256 from 'crypto-js/sha256';
import hmacSHA512 from 'crypto-js/hmac-sha512';
import Base64 from 'crypto-js/enc-base64';
const message, nonce, path, privateKey; // ...
const hashDigest = sha256(nonce + message);
const hmacDigest = Base64.stringify(hmacSHA512(path + hashDigest, privateKey));
Modular include:
var AES = require("crypto-js/aes");
var SHA256 = require("crypto-js/sha256");
...
console.log(SHA256("Message"));
Including all libraries, for access to extra methods:
var CryptoJS = require("crypto-js");
console.log(CryptoJS.HmacSHA1("Message", "Key"));
Requirements:
bower install crypto-js
Modular include:
require.config({
packages: [
{
name: 'crypto-js',
location: 'path-to/bower_components/crypto-js',
main: 'index'
}
]
});
require(["crypto-js/aes", "crypto-js/sha256"], function (AES, SHA256) {
console.log(SHA256("Message"));
});
Including all libraries, for access to extra methods:
// Above-mentioned will work or use this simple form
require.config({
paths: {
'crypto-js': 'path-to/bower_components/crypto-js/crypto-js'
}
});
require(["crypto-js"], function (CryptoJS) {
console.log(CryptoJS.HmacSHA1("Message", "Key"));
});
<script type="text/javascript" src="path-to/bower_components/crypto-js/crypto-js.js"></script>
<script type="text/javascript">
var encrypted = CryptoJS.AES(...);
var encrypted = CryptoJS.SHA256(...);
</script>
See: https://cryptojs.gitbook.io/docs/
var CryptoJS = require("crypto-js");
// Encrypt
var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();
// Decrypt
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
var originalText = bytes.toString(CryptoJS.enc.Utf8);
console.log(originalText); // 'my message'
var CryptoJS = require("crypto-js");
var data = [{id: 1}, {id: 2}]
// Encrypt
var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123').toString();
// Decrypt
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
console.log(decryptedData); // [{id: 1}, {id: 2}]
crypto-js/corecrypto-js/x64-corecrypto-js/lib-typedarrayscrypto-js/md5crypto-js/sha1crypto-js/sha256crypto-js/sha224crypto-js/sha512crypto-js/sha384crypto-js/sha3crypto-js/ripemd160crypto-js/hmac-md5crypto-js/hmac-sha1crypto-js/hmac-sha256crypto-js/hmac-sha224crypto-js/hmac-sha512crypto-js/hmac-sha384crypto-js/hmac-sha3crypto-js/hmac-ripemd160crypto-js/pbkdf2crypto-js/aescrypto-js/tripledescrypto-js/rc4crypto-js/rabbitcrypto-js/rabbit-legacycrypto-js/evpkdfcrypto-js/format-opensslcrypto-js/format-hexcrypto-js/enc-latin1crypto-js/enc-utf8crypto-js/enc-hexcrypto-js/enc-utf16crypto-js/enc-base64crypto-js/mode-cfbcrypto-js/mode-ctrcrypto-js/mode-ctr-gladmancrypto-js/mode-ofbcrypto-js/mode-ecbcrypto-js/pad-pkcs7crypto-js/pad-ansix923crypto-js/pad-iso10126crypto-js/pad-iso97971crypto-js/pad-zeropaddingcrypto-js/pad-nopaddingChange default hash algorithm and iteration's for PBKDF2 to prevent weak security by using the default configuration.
Custom KDF Hasher
Blowfish support
Fix module order in bundled release.
Include the browser field in the released package.json.
Added url safe variant of base64 encoding. 357
Avoid webpack to add crypto-browser package. 364
This is an update including breaking changes for some environments.
In this version Math.random() has been replaced by the random methods of the native crypto module.
For this reason CryptoJS might not run in some JavaScript environments without native crypto module. Such as IE 10 or before or React Native.
Rollback, 3.3.0 is the same as 3.1.9-1.
The move of using native secure crypto module will be shifted to a new 4.x.x version. As it is a breaking change the impact is too big for a minor release.
The usage of the native crypto module has been fixed. The import and access of the native crypto module has been improved.
In this version Math.random() has been replaced by the random methods of the native crypto module.
For this reason CryptoJS might does not run in some JavaScript environments without native crypto module. Such as IE 10 or before.
If it's absolute required to run CryptoJS in such an environment, stay with 3.1.x version. Encrypting and decrypting stays compatible. But keep in mind 3.1.x versions still use Math.random() which is cryptographically not secure, as it's not random enough.
This version came along with CRITICAL BUG.
DO NOT USE THIS VERSION! Please, go for a newer version!
The 3.1.x are based on the original CryptoJS, wrapped in CommonJS modules.