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 は使わないでください。
sha.js は Node.js 標準の crypto モジュールと互換性のあるインターフェースを持ち、SHA-1 から SHA-512 まで幅広いアルゴリズムをサポートします。Node.js とのコード共有や、複数の SHA ファミリーが必要なプロジェクトに向いています。ストリーム処理も可能で、大規模データのハッシュ計算に柔軟性があります。
crypto-js は AES、HMAC、PBKDF2 など多数の暗号アルゴリズムを含む包括的なライブラリです。SHA-256 だけでなく他の暗号機能も必要で、かつバンドルサイズが許容できるプロジェクトに適しています。ただし、フルセットをインポートすると不要なコードが含まれるため、個別モジュールのインポートが推奨されます。
js-sha256 は SHA-256 専用の軽量ライブラリで、API がシンプルで直感的です。TypeScript サポートも充実しており、フロントエンドで単一のハッシュ関数だけが必要な場合に最適です。ESM/CJS の両方に対応し、ツリーシェイキングにも親和性が高いです。
sha256 パッケージは非推奨(deprecated)であり、npm および GitHub で明確にその旨が記載されています。新規プロジェクトでは絶対に使用せず、代わりに js-sha256 や sha.js などの代替手段を検討すべきです。既存コードで使用されている場合は早急に移行を検討してください。
Node style SHA on pure JavaScript.
var shajs = require('sha.js')
console.log(shajs('sha256').update('42').digest('hex'))
// => 73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049
console.log(new shajs.sha256().update('42').digest('hex'))
// => 73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049
var sha256stream = shajs('sha256')
sha256stream.end('42')
console.log(sha256stream.read().toString('hex'))
// => 73475cb40a568e8da8a045ced110137e159f890ac4da883b6b17dc651b3a8049
sha.js currently implements:
Note, this doesn't actually implement a stream, but wrapping this in a stream is trivial. It does update incrementally, so you can hash things larger than RAM, as it uses a constant amount of memory (except when using base64 or utf8 encoding, see code comments).
This work is derived from Paul Johnston's A JavaScript implementation of the Secure Hash Algorithm.