likes
comments
collection
share

从 crypto-js 了解加密-解密知识点

作者站长头像
站长
· 阅读数 5

一、开始之前

网站应用中,对敏感的内容进行加密、解密十分常见。本文将探索 crypto-js 库中的加密和解密能力。crypto-js主要专注于对称加密(如 AES、DES)、哈希算法(如 MD5、SHA 等)和流式加密(如 RC4、Rabbit 等)等方面的支持。

二、crypto-js 安装

pnpm add crypto-js

三、顶层 api

以下是 crypto-js 提供的顶层 api

import cj from 'crypto-js'

console.log("cj", Object.keys(cj))

输出的结果是:

[
  'lib',        'enc',           'algo',
  'x64',        'MD5',           'HmacMD5',
  'SHA1',       'HmacSHA1',      'SHA256',
  'HmacSHA256', 'SHA224',        'HmacSHA224',
  'SHA512',     'HmacSHA512',    'SHA384',
  'HmacSHA384', 'SHA3',          'HmacSHA3',
  'RIPEMD160',  'HmacRIPEMD160', 'PBKDF2',
  'EvpKDF',     'mode',          'pad',
  'format',     'kdf',           'AES',
  'DES',        'TripleDES',     'RC4',
  'RC4Drop',    'Rabbit',        'RabbitLegacy',
  'Blowfish'
]

crypto-js 支持众多的 api, 下面对以上各种 api 的部分内容进行解析。

四、lib 核心库

lib 是核心 api 中的库,承担者主要的加密和解密功能,一般不直接使用。

五、enc 指定字符编码模式

import cj from "crypto-js";

console.log(Object.keys(cj.enc));

包含以下的 8 个 API:

["Hex", "Latin1", "Utf8", "Utf16BE", "Utf16", "Utf16LE", "Base64", "Base64url"];

使用示例(以下示例以常用的 MD5 形式,以及 16 进制和 base64 两种常见的加密形式):

import cj from "crypto-js";

const message = "hello world";
const hash = cj.MD5(message).toString(cj.enc.Hex); // 16 进制形式进行编码
console.log(hash); // 5eb63bbbe01eeed093cb22bb8f5acdc3

const hash = cj.MD5(message).toString(cj.enc.Base64); // base64 形式进行编码
console.log(hash); // XrY7u+Ae7tCTyyK7j1rNww==

const hash = cj.MD5(message).toString(cj.enc.Base64url); // base64 url 形式进行编码
console.log(hash); // XrY7u-Ae7tCTyyK7j1rNww

六、algo 算法

import cj from "crypto-js";

console.log(Object.keys(cj.algo))[
  ("MD5",
  "SHA1",
  "SHA256",
  "SHA224",
  "SHA512",
  "SHA384",
  "SHA3",
  "RIPEMD160",
  "HMAC",
  "PBKDF2",
  "EvpKDF",
  "AES",
  "DES",
  "TripleDES",
  "RC4",
  "RC4Drop",
  "Rabbit",
  "RabbitLegacy",
  "Blowfish")
];
类型算法说明
哈希算法MD5 (常用)生成 128 位哈希值,用于校验数据完整性。
SHA1 (常用系列)生成 160 位哈希值。
SHA256生成 256 位哈希值。
SHA224生成 224 位哈希值。
SHA512生成 512 位哈希值。
SHA384生成 384 位哈希值。
SHA3SHA-3 哈希算法。
RIPEMD160另一种生成 160 位哈希值的算法。
HMAC基于密钥的哈希消息认证码。
PBKDF2密码基于密钥派生函数。
EvpKDF另一种密钥派生函数。
对称加密算法AES (常用)高级加密标准,用于对称加密和解密数据。
DES数据加密标准,较早的对称加密算法。
TripleDES对 DES 进行多次加密以增加安全性。
流式加密算法RC4流式加密算法。
RC4DropRC4 的变种。
Rabbit另一种流式加密算法。
RabbitLegacyRabbit 算法的旧版本。
其他Blowfish对称加密算法,用于加密和解密数据。

七、mode 模式

模式说明
ECB (Electronic Codebook)将整个明文分成块,每个块独立加密。可能存在安全性问题。
CBC (Cipher Block Chaining)前一个块的密文作为下一个块的加密向量,提高了安全性。
CFB (Cipher Feedback)前一个密文块作为密钥加密当前明文块,可按比块更小单位加密。
OFB (Output Feedback)使用函数产生的密钥流进行异或运算,提供加密流。
CTR (Counter)使用计数器的值加密,并与明文进行异或运算,提供加密效果。
CTRGladmanCTRGladman 模式
import cj from "crypto-js";

const mode = cj.mode;
console.log(mode.CBC);
console.log(mode.CFB);
console.log(mode.CTR);
console.log(mode.CTRGladman);
console.log(mode.ECB);
console.log(mode.OFB);

八、pad 天秤模式

填充方式说明
AnsiX923在数据末尾填充零字节,最后一个字节表示需要填充的字节数。
Iso10126在数据末尾填充随机字节,最后一个字节表示需要填充的字节数。
Iso97971使用 ISO/IEC 9797-1 填充方案,在数据末尾填充 \x80 加上零或多个 \x00 直到块的大小。
NoPadding不进行任何填充,要求数据长度必须是块大小的整数倍。
Pkcs7使用 PKCS#7 填充方案,在数据末尾填充字节,字节的值表示需要填充的字节数。
ZeroPadding在数据末尾填充零字节,直到数据长度满足块大小的整数倍。
import cj from "crypto-js";

const a = cj.pad.AnsiX923;
const b = cj.pad.Iso10126;
const c = cj.pad.Iso97971;
const d = cj.pad.NoPadding;
const e = cj.pad.Pkcs7;
const f = cj.pad.ZeroPadding;

九、对称加密

对称加密是一种加密方式,使用相同的密钥(也称为对称密钥)同时对数据进行加密和解密。这意味着使用相同的密钥,发送方对数据进行加密,接收方使用相同的密钥对加密后的数据进行解密。

AES 加密算法

AES(Advanced Encryption Standard,高级加密标准)是一种对称加密算法,被广泛用于加密和解密数据。它是由美国国家标准技术研究所(NIST)在 2001 年公布的一种加密标准,用来替代之前的 DES(Data Encryption Standard)算法。使用最为常见的算法。按照长度可以分为:128/192/256 位三种。其中 128 使用最为广泛。

  • AES.encrypt
  • AES.decrypt

将 AES 封装成一个类

import CryptoJS from "crypto-js";
import Utf8 from "crypto-js/enc-utf8";
import AES from "crypto-js/aes";
import Pkcs7 from "crypto-js/pad-pkcs7";

class AESCipher {
  constructor(key, mode = CryptoJS.mode.ECB, padding = Pkcs7) {
    this.key = Utf8.parse(key);
    this.mode = mode;
    this.padding = padding;
  }

  // 加密函数
  encrypt(plaintext) {
    const encrypted = AES.encrypt(plaintext, this.key, {
      mode: this.mode,
      padding: this.padding,
    }).toString();
    return encrypted;
  }

  // 解密函数(可选)
  decrypt(encryptedText) {
    const decrypted = AES.decrypt(encryptedText, this.key, {
      mode: this.mode,
      padding: this.padding,
    }).toString(Utf8);
    return decrypted;
  }
}
  • 使用
import CryptoJS from "crypto-js";
import Utf8 from "crypto-js/enc-utf8";
import AES from "crypto-js/aes";
import Pkcs7 from "crypto-js/pad-pkcs7";

// 使用示例
const key = "ThisIsASecretKey123";
const aesCipher = new AESCipher(key, CryptoJS.mode.ECB, Pkcs7);
const encryptedText = aesCipher.encrypt("Hello, world!");
console.log("Encrypted:", encryptedText);

// 解密示例(如果需要解密)
const decryptedText = aesCipher.decrypt(encryptedText);
console.log("Decrypted:", decryptedText);

DES 算法

DES(Data Encryption Standard,数据加密标准)是一种对称加密算法,最初在 1977 年被美国政府确定为加密标准,但由于其使用 56 位密钥长度(实际上是 64 位中的 8 位用于校验),密钥长度较短,安全性逐渐变弱,因此在现代安全需求下已不再推荐使用。

  • DES.encrypt
  • DES.decrypt

封装成类:

import CryptoJS from "crypto-js";
import Utf8 from "crypto-js/enc-utf8";

class DESCipher {
  constructor(key) {
    this.key = Utf8.parse(key);
  }

  // 加密函数
  encrypt(plaintext) {
    const encrypted = CryptoJS.DES.encrypt(plaintext, this.key).toString();
    return encrypted;
  }

  // 解密函数
  decrypt(encryptedText) {
    const decrypted = CryptoJS.DES.decrypt(encryptedText, this.key).toString(
      Utf8
    );
    return decrypted;
  }
}
  • 使用示例
// 使用示例
const key = "12345678"; // 这里示范的密钥长度是 8 位
const desCipher = new DESCipher(key);

// 加密示例
const encryptedText = desCipher.encrypt("Hello, world!");
console.log("Encrypted:", encryptedText);

// 解密示例
const decryptedText = desCipher.decrypt(encryptedText);
console.log("Decrypted:", decryptedText);

TripleDES 算法

TripleDES(Triple Data Encryption Standard)是 DES 的一种改进版本,它对 DES 进行了三重加密,以提高安全性。它的密钥长度是 DES 的三倍,即 168 位(56 位 * 3)。

三阶段:

  1. 第一个阶段(Encrypt) :使用第一个密钥对数据进行加密。
  2. 第二个阶段(Decrypt) :使用第二个密钥对加密后的数据进行解密。
  3. 第三个阶段(Encrypt) :使用第三个密钥再次对解密后的数据进行加密。
  • TripleDES.encrypt
  • TripleDES.decrypt

封装成类:

import CryptoJS from "crypto-js";
import Utf8 from "crypto-js/enc-utf8";

class TripleDESCipher {
  constructor(key) {
    this.key = Utf8.parse(key);
  }

  // 加密函数
  encrypt(plaintext) {
    const encrypted = CryptoJS.TripleDES.encrypt(
      plaintext,
      this.key
    ).toString();
    return encrypted;
  }

  // 解密函数
  decrypt(encryptedText) {
    const decrypted = CryptoJS.TripleDES.decrypt(
      encryptedText,
      this.key
    ).toString(Utf8);
    return decrypted;
  }
}
  • 使用
// 使用示例
const key = "123456789012345678901234"; // 密钥长度为 24 字符(192 位)
const tripleDESCipher = new TripleDESCipher(key);

// 加密示例
const encryptedText = tripleDESCipher.encrypt("Hello, world!");
console.log("Encrypted:", encryptedText);

// 解密示例
const decryptedText = tripleDESCipher.decrypt(encryptedText);
console.log("Decrypted:", decryptedText);

十、MD5 算法

MD5(Message Digest Algorithm 5)是一种常见的哈希算法,用于生成 128 位(16 字节)的哈希值。它通常用于数据完整性校验、密码存储等场景,被设计为单向散列函数,意味着它将任意长度的输入数据转换为固定长度的输出。

md5 基础用法:

import cj from "crypto-js";

console.log(cj.MD5("sdf").toString());

注意: MD5 方法调用之后,还需要调用 toString 方法。MD5 方法得到的是一个对象 {words: array, sigBytes: number}。MD5 方法的特点非常简单固定输入有固定的输出。

十一、SHA 系列算法

算法哈希值长度特点
SHA-1160 位(20 字节)存在碰撞漏洞,不再被认为是安全的哈希算法。
SHA-256 (常用)256 位(32 字节)比 SHA-1 更安全,广泛用于数字签名、SSL 证书等领域。
SHA-224224 位(28 字节)SHA-256 的截断版,用于特定应用场景。
SHA-512512 位(64 字节)比 SHA-256 更安全,提供更长的哈希值,适用于敏感的应用。
SHA-384384 位(48 字节)提供比 SHA-256 更长的哈希值,适用于高安全性要求的场景。
SHA-3-一种与 SHA-2 系列不同的哈希算法,被认为更为安全。
import cj from "crypto-js";

console.log(cj.SHA256(123));
console.log(cj.SHA256(123, {}));
console.log(cj.SHA256([123]));
console.log(cj.SHA256(cj.enc.Utf8.parse("Hello, World!")));

SHA256 函数的参数类型,可以是 string | cj.lib.WordArray, 也可接受第二个可选的参数 config 对象。

十二、基于 hash 的 HMAC 算法

算法哈希函数哈希值长度密钥长度要求特点
HMAC-MD5MD5128 位(16 字节)任意长度安全性较低,不推荐使用,存在碰撞攻击风险。
HMAC-SHA1SHA-1160 位(20 字节)任意长度安全性较低,不推荐使用,存在碰撞攻击风险。
HMAC-SHA256SHA-256256 位(32 字节)推荐大于 256 位安全性高,广泛应用于数字签名、SSL 证书等领域。
HMAC-SHA512SHA-512512 位(64 字节)推荐大于 512 位安全性更高,适用于对安全性要求极高的场景。

在实际应用中,HMAC-SHA256 是最常用的 HMAC 算法之一。它具有较高的安全性和广泛的应用场景,在数字签名、SSL 证书、API 认证等许多领域都被广泛采用。HMAC-SHA256 提供了 256 位(32 字节)的哈希值长度,适中的长度同时提供了较高的安全性和较快的计算速度,适合大多数安全性要求不是特别高的场景。

以 HmacSHA256 为例:

const CryptoJS.HmacSHA256: HmacHasherHelper
(message: string | cj.lib.WordArray, key: string | cj.lib.WordArray) => cj.lib.WordArray

HmacSHA256 可以接受两个参数: message 需要加密,key

十三、其他加密算法

RC4、RC4Drop、Blowfish、Rabbit 等:一些其他的加密算法,用于特定场景的加密和解密。

算法密钥长度块大小安全性特点
RC4可变(1-256 字节)早期加密算法,由于存在严重的安全漏洞,不再推荐使用。
RC4Drop固定为 128 位(16 字节)是 RC4 的一个变种,通过舍弃初始几个字节来提高初始输出的随机性。
Blowfish32-448 位(4-56 字节)64 位(8 字节)中等对称分组密码算法,安全性较高,但因为比较老旧,在某些场景可能不够。
Rabbit128 位(16 字节)较高流密码算法,用于加密通信。在一些应用中,比如 WPA 和蓝牙加密中被使用。

十四、RSA

RSA 算法属于非对称加密算法,其实现通常比较复杂,并不在crypto-js的范畴之内。

十五、小结

本文从 crypto-js 库的角度看 JS 中的各种加密和解密的方法。全局了解 crypto-js 的 api, 其中包含了 enc、algo、mode 和 pad 属性,以及对称加密 AES/DES 等对称加密。hash 散列计算方法 MD5 以及 SHA 系列算法。

转载自:https://juejin.cn/post/7308925069916897332
评论
请登录