crypto-js、js-sha256、sha.js、sha256 はすべて JavaScript 環境で SHA-256 ハッシュを生成するための npm パッケージですが、設計思想や使用方法、依存関係、メンテナンス状況に大きな違いがあります。これらのライブラリは、パスワードのハッシュ化、データ整合性チェック、署名生成などのセキュリティ関連タスクで利用されることが多く、フロントエンド開発者が軽量かつ安全な実装を選ぶ際に重要な選択肢となります。
フロントエンドで SHA-256 を使う理由はさまざまです — パスワードのクライアント側ハッシュ化、ファイルの整合性チェック、署名付きリクエストの生成など。しかし、npm 上には似たような名前のパッケージが複数存在し、どれを選ぶべきか迷う開発者も多いでしょう。ここでは、crypto-js、js-sha256、sha.js、そして非推奨の sha256 の4つを、実際のコードと使い勝手を中心に比較します。
sha256 は使わないまず最初に明確にしておきます:sha256 パッケージは公式に非推奨(deprecated)です。npm ページには「Use js-sha256 instead」と明記されており、GitHub リポジトリもアーカイブ済みです。このパッケージは新しいプロジェクトで使用すべきではありません。
// ❌ sha256 — 非推奨のため使用禁止
import sha256 from 'sha256';
const hash = sha256('hello'); // 動作はするが、セキュリティアップデートなし
代わりに、後述する js-sha256 を使うことで、同じ API で安全かつメンテナンスされた実装を利用できます。
js-sha256:最小限で高速js-sha256 は SHA-256 に特化しており、API が非常にシンプルです。文字列や Uint8Array を直接ハッシュ化でき、戻り値は16進数文字列です。
// ✅ js-sha256
import { sha256 } from 'js-sha256';
const hash = sha256('hello');
console.log(hash); // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
オブジェクト指向スタイルもサポートされており、ストリーム処理も可能です。
const hasher = sha256.create();
hasher.update('hel');
hasher.update('lo');
console.log(hasher.hex()); // 同じ結果
crypto-js:多機能だが重めcrypto-js は SHA-256 以外にも多数の暗号アルゴリズムを提供します。ただし、全体をインポートすると不要なコードがバンドルに含まれるため、個別モジュールのインポートが推奨されます。
// ✅ crypto-js(個別インポート)
import sha256 from 'crypto-js/sha256';
import encHex from 'crypto-js/enc-hex';
const hash = sha256('hello');
console.log(hash.toString(encHex)); // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
注意点として、crypto-js の戻り値は WordArray オブジェクトであり、文字列にするには .toString() とエンコーダ(例: encHex)が必要です。これは学習コストを少し高めます。
sha.js:Node.js 互換の柔軟性sha.js は Node.js の crypto.createHash('sha256') と似たインターフェースを持ち、ストリーム処理に強いです。
// ✅ sha.js
import { sha256 } from 'sha.js';
const hash = sha256().update('hello').digest('hex');
console.log(hash); // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
update() を複数回呼び出せるため、大容量データをチャンク単位で処理するのに適しています。
各ライブラリは異なる入力形式をサポートしています。
// js-sha256
sha256('こんにちは');
// crypto-js
sha256('こんにちは').toString(encHex);
// sha.js
sha256().update('こんにちは').digest('hex');
すべて問題なく動作しますが、内部エンコーディングはいずれも UTF-8 です。
バイナリデータ(例: ファイルの Blob)をハッシュ化する場合:
// js-sha256
const uint8 = new TextEncoder().encode('hello');
sha256(uint8);
// crypto-js
import WordArray from 'crypto-js/lib-typedarrays';
const wa = WordArray.create(uint8);
sha256(wa).toString(encHex);
// sha.js
sha256().update(uint8).digest('hex');
js-sha256 と sha.js は直接 Uint8Array を受け入れますが、crypto-js は一旦 WordArray に変換する必要があります。この点で、バイナリ処理が多いアプリでは js-sha256 や sha.js の方がコードが簡潔になります。
js-sha256:ESM 対応で、import { sha256 } とすれば SHA-256 だけがバンドルされます。極めて軽量。sha.js:CommonJS が基本ですが、ESM ビルドも提供。sha256 だけをインポートすれば他のアルゴリズムは含まれません。crypto-js:個別モジュール(例: crypto-js/sha256)をインポートしないと、全アルゴリズムがバンドルされてしまいます。たとえば、Vite や Webpack でビルドする場合、js-sha256 は最も小さい出力サイズを実現します。
大規模データやネットワークストリームをハッシュ化する必要がある場合:
// js-sha256
const hasher = sha256.create();
hasher.update(chunk1);
hasher.update(chunk2);
const result = hasher.hex();
// sha.js
const hasher = sha256();
hasher.update(chunk1);
hasher.update(chunk2);
const result = hasher.digest('hex');
// crypto-js
// ストリーム処理は非対応。一度に全データを渡す必要あり。
crypto-js は逐次更新に対応していないため、ストリーム処理が必要なら js-sha256 または sha.js を選ぶ必要があります。
js-sha256:組み込みの型定義があり、import { sha256 } from 'js-sha256' で即時利用可能。sha.js:DefinitelyTyped による @types/sha.js が必要。crypto-js:組み込み型定義あり。TypeScript プロジェクトでは、追加の型定義インストール不要という点で js-sha256 が有利です。
| パッケージ | 推奨シナリオ |
|---|---|
js-sha256 | SHA-256 だけが必要で、軽量・シンプル・TypeScript 対応を求める場合。フロントエンド向けに最適化されています。 |
sha.js | Node.js とのコード共有が必要、または複数の SHA アルゴリズム(SHA-1, SHA-512 など)を将来的に使う可能性がある場合。ストリーム処理も柔軟。 |
crypto-js | SHA-256 以外にも AES 暗号化や HMAC など複数の暗号機能が必要な場合。ただし、個別モジュールのインポートを忘れずに。 |
sha256 | 非推奨。新規プロジェクトでは絶対に使用しないでください。 |
ほとんどのフロントエンドプロジェクトでは、js-sha256 が最良の選択肢です。理由は3つ:
一方、Node.js との共通コードを書く必要がある、あるいは将来的に SHA-384 や SHA-512 に拡張する可能性があるなら、sha.js を検討してください。crypto-js は「他の暗号機能も必要」でない限り、オーバースペックです。
そして、もう一度強調します:sha256 は使わないでください。
crypto-js は AES、HMAC、PBKDF2 など多数の暗号アルゴリズムを含む包括的なライブラリです。SHA-256 だけでなく他の暗号機能も必要で、かつバンドルサイズが許容できるプロジェクトに適しています。ただし、フルセットをインポートすると不要なコードが含まれるため、個別モジュールのインポートが推奨されます。
js-sha256 は SHA-256 専用の軽量ライブラリで、API がシンプルで直感的です。TypeScript サポートも充実しており、フロントエンドで単一のハッシュ関数だけが必要な場合に最適です。ESM/CJS の両方に対応し、ツリーシェイキングにも親和性が高いです。
sha.js は Node.js 標準の crypto モジュールと互換性のあるインターフェースを持ち、SHA-1 から SHA-512 まで幅広いアルゴリズムをサポートします。Node.js とのコード共有や、複数の SHA ファミリーが必要なプロジェクトに向いています。ストリーム処理も可能で、大規模データのハッシュ計算に柔軟性があります。
sha256 パッケージは非推奨(deprecated)であり、npm および GitHub で明確にその旨が記載されています。新規プロジェクトでは絶対に使用せず、代わりに js-sha256 や sha.js などの代替手段を検討すべきです。既存コードで使用されている場合は早急に移行を検討してください。
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.