crypto-js 和 node-forge 都是纯 JavaScript 实现的加密库,旨在为 Node.js 和浏览器环境提供加密功能。crypto-js 专注于标准算法(如 AES、SHA、MD5),API 设计简洁,适合快速集成。node-forge 功能更全面,支持 PKI、X.509 证书、ASN.1 解析等高级特性,适合需要复杂密钥管理或协议模拟的场景。两者均为软件实现,在现代浏览器中应优先考虑 Web Crypto API。
在前端架构中处理敏感数据时,选择合适的加密库至关重要。crypto-js 和 node-forge 都是纯 JavaScript 实现的经典方案,但它们的设计目标和适用场景有明显区别。本文将从实际工程角度对比两者的核心能力。
crypto-js 提供了高度封装的 API,只需一行代码即可完成加密。
import CryptoJS from 'crypto-js';
const message = 'secret data';
const key = 'my-secret-key';
// 自动处理 IV 和模式,返回 Base64 字符串
const ciphertext = CryptoJS.AES.encrypt(message, key).toString();
node-forge 需要手动配置模式、IV 和缓冲区,控制更细但代码更多。
import forge from 'node-forge';
const message = 'secret data';
const key = forge.util.createBuffer('my-secret-key');
const iv = forge.random.getBytesSync(16);
// 手动创建 cipher 并启动
const cipher = forge.aes.createCipher('CBC', key);
cipher.start({ iv: iv });
cipher.update(forge.util.createBuffer(message));
cipher.finish();
const ciphertext = forge.util.encode64(cipher.output.getBytes());
crypto-js 的哈希调用非常直观,链式调用即可。
import CryptoJS from 'crypto-js';
// 直接传入字符串,输出 Hex 字符串
const hash = CryptoJS.SHA256("user-input").toString();
node-forge 需要创建摘要对象并更新数据。
import forge from 'node-forge';
// 创建 md 对象,更新数据后 digest
const md = forge.md.sha256.create();
md.update('user-input');
const hash = md.digest().toHex();
crypto-js 主要关注对称加密和哈希,原生不支持 RSA 密钥生成或 X.509 证书操作。
// crypto-js 没有内置 RSA 密钥生成 API
// 通常需要依赖其他库或扩展
node-forge 内置了完整的 PKI 工具集,可生成密钥对和证书。
import forge from 'node-forge';
// 生成 RSA 密钥对
const keys = forge.pki.rsa.generateKeyPair(2048);
// 创建自签名证书
const cert = forge.pki.createCertificate();
cert.publicKey = keys.publicKey;
// 进一步配置证书字段...
两者都是纯 JavaScript 实现,这意味着它们运行在主线程上,且容易受到侧信道攻击。对于高安全需求,应优先使用浏览器原生的 Web Crypto API。
// 推荐:使用 Web Crypto API (浏览器原生)
const key = await crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, true, ['encrypt']);
const encrypted = await crypto.subtle.encrypt({ name: 'AES-GCM', iv: iv }, key, data);
crypto-js 适合旧浏览器兼容或简单场景。
// 适用:需要支持 IE11 或简单哈希
import CryptoJS from 'crypto-js';
const hash = CryptoJS.SHA256('data').toString();
node-forge 适合需要复杂协议交互的场景。
// 适用:需要在 JS 中解析 PEM 或生成 CSR
import forge from 'node-forge';
const pki = forge.pki;
const csr = pki.createCertificationRequest();
| 特性 | crypto-js | node-forge |
|---|---|---|
| API 风格 | 简洁,高层封装 | 详细,底层控制 |
| 主要用途 | 哈希,对称加密 | PKI, 证书,ASN.1 |
| 学习曲线 | 低,上手快 | 高,需理解密码学概念 |
| 浏览器支持 | 广泛,兼容旧版 | 广泛,兼容旧版 |
crypto-js 像是一把瑞士军刀 🔪 — 适合日常快速任务,如密码哈希或简单数据加密。如果你的需求仅限于标准算法且追求开发效率,它是不错的选择。
node-forge 像是一个专业工具箱 🧰 — 适合处理复杂的密钥管理和证书操作。如果你的架构需要在前端处理 PKI 或模拟安全协议,它提供了必要的底层能力。
最终建议:在现代前端项目中,如果目标环境支持,请优先使用 window.crypto.subtle。只有在需要兼容旧环境或特殊协议支持时,再考虑这两个库。
如果你的项目只需要标准的对称加密(如 AES)或哈希算法(如 SHA-256),且希望 API 简单易懂,选择 crypto-js。它的文档清晰,社区用例丰富,适合大多数常规的前端加密需求,例如密码哈希或简单数据混淆。
如果你的项目需要处理公钥基础设施(PKI)、生成 X.509 证书、解析 ASN.1 数据或模拟 TLS 握手,选择 node-forge。它在密钥管理和协议底层操作上提供了更细粒度的控制,适合需要复杂安全协议集成的企业级应用。
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.