普通视图

发现新文章,点击刷新页面。
昨天 — 2026年5月23日技术

CryptoJS:数据安全的JavaScript加密利器

2026年5月23日 18:56

image

前言

  在传统的客户端-服务器交互中,用户在前端输入的敏感信息(如用户名、密码、信用卡号等)通常会以明文通过 HTTPS 提交到后台,即便在 HTTPS 保护下,仍有安全隐患。如果用户的浏览器或网络受到攻击,可能篡改或窃取表单数据,甚至被浏览器插件劫持。而且如果后端在日志中意外记录了明文敏感信息,可能存在泄露风险。因此,在前端对敏感数据进行加密,并在后端对其解密,能够为安全防护增加一道“保险层”,即便数据在传输层被截获,也难以被攻击者直接获取明文。

一、CryptoJS 快速入门

1.1 CryptoJS 是什么

  随着前端技术的不断发展,安全性问题越来越受到重视。在这样的背景下,加密技术成为了保护数据安全的重要手段。crypto-js 是一个功能强大的 JavaScript 加密库,它提供了多种加密算法,包括AES、DES、MD5等。这些算法可以帮助开发者轻松地实现数据的加密和解密操作,从而保护敏感数据的安全性。

⚠️ CryptoJS 作为一个成熟的 JavaScript 加密库,虽然官方已停止维护,但其稳定性和丰富的功能使其仍然是许多项目的可靠选择。通过合理的使用和配置,可以在项目中构建强大的安全防护体系。

CryptoJS 官方文档:cryptojs.gitbook.io/

1.2 主要功能概览

  CryptoJS 是一套纯 JavaScript 实现的常用加密算法库,包含以下常见模块:

graph TD
A[输入数据]
A-->B{加密类型}
B-->C1[哈希算法]
B-->C2[对称加密]
B-->C3[编解码]
C1-->D1["MD5/SHA1/SHA256"]
C2-->D2["AES/DES/Rabbit"]
C3-->D3["Base64/Hex"]
D1-->E1[输出哈希值]
D2-->E2[输出密文]
D3-->E3[输出编码结果]

style B fill:#FFA500,stroke:#333,stroke-width:2px;

  由于 CryptoJS 纯前端可用,不依赖于 Node 内置模块,体积较小、使用方便,常用于浏览器环境的数据加密、签名和哈希操作。

1.3 在 Vue 中安装并引入

安装 CryptoJS

  要在 Vue 项目中使用 crypto-js,首先需要通过 npm 将其安装到项目中。打开终端,进入项目目录,执行以下命令:

npm install crypto-js --save-dev

# # 安装核心库与类型声明
npm install @types/crypto-js --save-dev

⚠️ crypto-js 4.x 版本依赖原生 crypto 模块,不支持IE10及以下浏览器。如需支持旧浏览器,建议使用 3.x 版本

在组件中引入 CryptoJS

  在需要进行加密操作的 Vue 组件中,引入相关模块。

import CryptoJS from 'crypto-js';

  引入后,我们就能得到 CryptoJS 这个对象,它包含了各种各样的加密算法。

1.4 CryptoJS 加密模式

  在 CryptoJS 中,加密模式指的是在加密过程中使用的特定算法模式。这些模式决定了如何组织和处理明文和密钥,以及如何生成密文。CryptoJS 支持多种加密模式,每种模式都有其特定的用途和安全性。以下是一些常见的加密模式:

加密模式 简要说明
ECB 将明文分割成独立的块,然后使用相同的密钥对每个块进行独立加密。
安全性较低,因为相同的明文块会产生相同的密文块,在实际生产中不推荐使用
CBC 最常用的 AES 模式,通常用于加密较长的数据。
它需要 IV(初始化向量),并且每个数据块的加密依赖于前一个数据块
广泛使用,适用于大多数需要一定安全性的应用。
CFB 提供与CBC相似的安全性,但实现起来可能更复杂
OFB 使用一个初始向量(IV)和一个密钥流生成器。
密钥流生成器基于密钥和一系列迭代产生的输出。
提供与CFB相似的安全性,但实现上更简单
CTR 使用一个计数器来生成密钥流。
每个块的加密都是独立的,与前一个块无关。
提供高强度的安全性,并且易于实现并行处理
GCM 结合了计数器模式和Galois乘法的认证加密模式。
提供认证加密功能,即同时保证数据的机密性和完整性。
是目前推荐用于需要同时保证数据安全和完整性的应用(如TLS)

二、编码转换

  在 CryptoJS 中,编码转换是加密操作的基础环节,它负责在不同数据表示形式之间进行转换。CryptoJS 提供了完整的编码器体系,其中Base64、Hex、UTF-8、UTF-16是最常用的编码方式。

2.1 UTF-8、UTF-16

  在现代 Web 开发和密码学应用中,字符编码处理是至关重要的基础环节。CryptoJS 提供了强大的 UTF-8 和 UTF-16 编码支持,使得我们能够轻松处理多语言文本的加密和解密操作。这些编码器不仅支持基本的 ASCII 字符,还能够正确处理复杂的 Unicode 字符,包括 emoji 表情和特殊符号。

// 字符串转换为WordArray
const wordArray = CryptoJS.enc.Utf8.parse("Hello 世界");
console.log("WordArray:", wordArray.toString());
 
// WordArray转换回字符串
const originalString = CryptoJS.enc.Utf8.stringify(wordArray);
console.log("Original String:", originalString);

2.2 Base64编解码

  在Web开发过程中,Base64 编码是用于传输 8bit 字节数据的常见编码方式之一,能够将二进制数据转换为 ASCII 字符序列,广泛应用于数据加密、文件传输和图片处理等场景。CryptoJS 库提供了完整且高效的 Base64 加解密功能,包括Base64编码和解码。

方法 参数 返回值 说明
CryptoJS.enc.Utf8.parse() 字符串 WordArray 将字符串转换为WordArray格式
CryptoJS.enc.Base64.stringify() WordArray Base64字符串 执行Base64编码
CryptoJS.enc.Base64.parse() Base64字符串 WordArray 解析Base64字符串
toString() 编码类型 字符串 将WordArray转换为指定编码的字符串
// 待编码的字符串
const originalText = "Hello World";

// 字符串转 WordArray
const wordArray = CryptoJS.enc.Utf8.parse(originalText);

// Base64 编码(解决特殊字符传输问题)
const base64Encoded = CryptoJS.enc.Base64.stringify(wordArray);
console.log("Base64 编码:", base64Encoded);

const parsedWordArray = CryptoJS.enc.Base64.parse(base64Encoded);
// Base64 解码
const base64Decoded = parsedWordArray.toString(CryptoJS.enc.Utf8);
console.log("Base64 解码:", base64Decoded);

⚠️ 需要确保在编码和解码过程中使用相同的编码方式(如UTF-8),以避免出现乱码。虽然 Base64 编码可以用于加密数据的传输,但它本身并不提供加密功能。

2.3 Hex

  在密码学和数据安全领域,十六进制(Hex)编码扮演着至关重要的角色。CryptoJS 库中的 CryptoJS.enc.Hex 编码器专门用于处理二进制数据与十六进制字符串之间的转换,这种编码方式在多个关键场景中发挥着不可替代的作用。以下是 Hex 编码解码的完整使用示例:

const message = "Hello World";

// Hex 编码
const hexEncoded = CryptoJS.enc.Hex.stringify(CryptoJS.enc.Utf8.parse(message));
console.log("Hex 编码:", hexEncoded);

// Hex 解码
const hexDecoded = CryptoJS.enc.Hex.parse(hexEncoded).toString(CryptoJS.enc.Utf8);
console.log("Hex 解码:", hexDecoded);

三、哈希算法

  哈希函数主要用于生成数据的“数字指纹”,常用于密码存储(需配合加盐)和数据完整性校验,保证信息在传输过程中不被篡改。

3.1 MD5 加密

  MD5 是一种广泛使用的散列函数,可以产生出一个128位(16字节)的不可逆的散列值,用于确保信息传输完整一致。它被用于各种安全应用,也通常用于校验文件的完整性。MD5算法具有以下特点:

特点 简要说明
压缩性 任意长度的消息都可以被压缩成一个128位的摘要
容易计算 MD5 算法的计算速度比较快,适用于对大量数据进行哈希计算
抗修改性 对原始数据进行任何修改,都会导致哈希值的变化
抗碰撞性 对不同的原始数据,哈希值相同的概率非常小

  在CryptoJS中,MD5加密非常简单,以下是 CryptoJS 实现 MD5 算法的示例代码:

const message = 'Hello, World!';
const encrypted = CryptoJS.MD5(message).toString();
// 输出MD5加密后的字符串
console.log("MD5:", encrypted);

  上述代码的意思是将字符串“hello world”使用 MD5 算法进行加密,并将结果以字符串的形式输出到控制台中。需要注意的是,在输出字符串时,需要使用 toString 方法将加密结果转换为字符串,否则将无法正常输出。

  传入CryptoJS.MD5 的参数除了字符串外,还可以是 CryptoJS 定义的一种叫做 WordArray 的数据类型。比如:

const wordArray = CryptoJS.enc.Utf8.parse('Hello World');
CryptoJS.MD5(wordArray).toString();

⚠️ 虽然 MD5 计算速度快,但已被证实存在安全隐患,仅建议用于非安全场景的本地文件校验。

3.2 SHA-1 加密

  SHA1 是一种常用的哈希算法,用于将任意长度的消息压缩成一个160位的摘要。SHA1算法具有以下特点:

特点 简要说明
压缩性 任意长度的消息都可以被压缩成一个160位的摘要
容易计算 SHA1 算法的计算速度比较快,适用于对大量数据进行哈希计算
抗修改性 对原始数据进行任何修改,都会导致哈希值的变化
抗碰撞性 对不同的原始数据,哈希值相同的概率非常小

  以下是 CryptoJS 实现 SHA1 算法的示例代码:

const wordArray = CryptoJS.enc.Utf8.parse('Hello World');
console.log("SHA1:", CryptoJS.SHA1(message).toString());

3.3 SHA-2 加密

  SHA-224、SHA-256、SHA-384和SHA-512合称为SHA-2,虽然 SHA-2 提供了更好的安全性,但是它的应用不如 SHA-1 广泛,通常用于数据签名和身份验证等场合。

SHA-256

  SHA256 是一种比较常见的哈希算法,它是一种单向加密算法,不提供解密方法,用于将任意长度的消息压缩成一个256位的摘要。SHA256算法具有以下特点:

特点 简要说明
压缩性 任意长度的消息都可以被压缩成一个256位的摘要
容易计算 SHA256 算法的计算速度比较快,适用于对大量数据进行哈希计算
抗修改性 对原始数据进行任何修改,都会导致哈希值的变化
抗碰撞性 对不同的原始数据,哈希值相同的概率非常小

  以下是 CryptoJS 实现 SHA3 算法的示例代码:

const message = "Hello World";
console.log("SHA3:", CryptoJS.SHA3(message).toString());

SHA-512

  SHA3 是一种比较常见的哈希算法,用于将任意长度的消息压缩成一个固定长度的摘要。。SHA256算法具有以下特点:

特点 简要说明
压缩性 任意长度的消息都可以被压缩成一个固定长度的摘要
容易计算 SHA512 算法的计算速度比较快,适用于对大量数据进行哈希计算
抗修改性 对原始数据进行任何修改,都会导致哈希值的变化
抗碰撞性 对不同的原始数据,哈希值相同的概率非常小

  以下是 CryptoJS 实现 SHA256 算法的示例代码:

const message = "Hello World";
console.log("SHA512:", CryptoJS.SHA512(message).toString());

3.4 SHA-3 加密

  SHA512 是一种比较常见的哈希算法,它是一种单向加密算法,不提供解密方法,用于将任意长度的消息压缩成一个 512 位的摘要。SHA256算法具有以下特点:

特点 简要说明
压缩性 任意长度的消息都可以被压缩成一个 512 位的摘要
容易计算 SHA512 算法的计算速度比较快,适用于对大量数据进行哈希计算
抗修改性 对原始数据进行任何修改,都会导致哈希值的变化
抗碰撞性 对不同的原始数据,哈希值相同的概率非常小

  以下是 CryptoJS 实现 SHA256 算法的示例代码:

const message = "Hello World";
console.log("SHA512:", CryptoJS.SHA512(message).toString());

四、对称加密算法

  加密是为了保证数据安全传输,使得其他人不能获取的具体信息内容。以某种特殊的算法,将原本信息数据进行改变,使得即使没有权限的人看到消息也不能从中得到任何有用信息,但是加密的信息是保证可逆的,即可加密必可解密(其长度与目标文本成正比)。所谓对称,指的是加密和解密使用的是相同的秘钥,常见的有 DES、3DES、AES等。对称加密主要用于对敏感数据进行加密和解密,确保数据的机密性。其加解密速度快、计算量小,适合对大量数据进行加密处理。

4.1 AES加密解密的实现

  AES 是一种常见的对称加密算法,通过相同的密钥进行加密和解密,常用于数据保护和机密信息存储等场合。AES 的出现,是用于取代已经被证明不安全的 DES 算法。AES 或者说对称加密算法的优点是速度快,缺点就是不安全。为了最大程度地兼容性与安全性,我们采用 AES-256-CBC 模式对称加密。AES 算法具有以下特点:

特点 简要说明
安全性高 AES 算法使用固定长度的密钥进行加密和解密,可以有效防止数据被破解
灵活性强 AES 算法可以使用多种密钥长度,如128位、192位或256位
计算速度快 AES 算法的计算速度比较快,适用于对大量数据进行加密和解密
// 加密:数据 → 密钥 → 密文
const ciphertext = CryptoJS.AES.encrypt("要加密的敏感数据", "自定义密钥").toString();

// 解密:密文 → 密钥 → 原始数据
const bytes = CryptoJS.AES.decrypt(ciphertext, "自定义密钥");
const plaintext = bytes.toString(CryptoJS.enc.Utf8);

密钥和偏移量的设置

  加密需要一把“钥匙”,这把钥匙就是密钥。另外还有一个叫“偏移量”的东西,它可以帮助我们更好地加密信息。AES 加密需要密钥(Key)和初始向量(IV),这些参数可以自定义,以确保加密解密的正确性。

  • key是对称加密算法的核心参数,同一个明文和密钥加密后得到的密文是相同的,因此密钥必须保密并且不易被破解。key的长度可以是128位、192位或256位,不同长度的key对应着不同的安全级别。
  • iv是用于增加加密强度的参数,它需要与key一起作为输入参数传递给加密算法。iv的长度为128位,它在每次加密时都会改变,并与key一起参与加密过程。iv的作用是将相同的明文使用不同的iv加密后生成不同的密文,从而增加破解的难度和安全性。
// 密钥
const secretKey = CryptoJS.enc.Utf8.parse("12345678901234567890123456789012");
// 偏移量
const secretIv = CryptoJS.enc.Utf8.parse("abcdefghijklmnop");

⚠️ 注意:生产环境中,密钥(key)和初始向量(iv)强烈建议从后端接口动态获取,与后端开发保持一致,绝对不要硬编码在前端!

加密解密函数封装

  我们需要创建一个加密函数来加密信息,这个函数接收一段明文(也就是正常能看懂的文字),然后返回加密后的文字。使用 CryptoJS 的 AES 模块对数据进行加密,使用相同的密钥和配置参数创建解密函数。

/**
 * 使用 AES-256-CBC 进行加密
 * @param originalText 待加密的数据,支持字符串、对象等
 * @param secretKey - 加密密钥
 * @param secretIv - 初始向量
 * @returns 加密后的 Base64 字符串
 */
export const encryptAES = (originalText: any, secretKey: string, secretIv: string): string => {
    if (!originalText) {
        return "";
    }
    const key = CryptoJS.enc.Utf8.parse(secretKey);
    const iv = CryptoJS.enc.Utf8.parse(secretIv);

    // 统一将数据转为 JSON 字符串
    const dataStr = typeof originalText === 'string' ? originalText : JSON.stringify(originalText);

    // 使用AES算法进行加密
    const encrypted = CryptoJS.AES.encrypt(dataStr, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });

    // encrypted.toString() 默认返回 Base64 编码
    return encrypted.toString();
}

  我们还需要一个函数来解密信息,解密的写法和加密差不多,只是把 encrypt 方法名改为 decrypt。这个函数接收加密后的文字,然后返回正常的明文。

/**
 * 使用 AES-256-CBC 进行解密
 * @param cipherText 加密后的字符串
 * @param secretKey - 解密密钥
 * @param secretIv - 初始向量
 * @returns {any} 解密后的原始数据
 */
export const decryptAES = (cipherText: string, secretKey: string, secretIv: string): any => {
    if (!cipherText) {
        return "";
    }
    // 将 Key 与 IV 转成 WordArray
    const key = CryptoJS.enc.Utf8.parse(secretKey);
    const iv = CryptoJS.enc.Utf8.parse(secretIv);

    // 执行解密
    const decrypted = CryptoJS.AES.decrypt(cipherText, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
    });
    // 将解密结果转为 UTF-8 字符串
    const decryptedStr = decrypted.toString(CryptoJS.enc.Utf8);
    // 尝试还原为 JSON 对象,如果不是对象则直接返回字符串
    try {
        return JSON.parse(decryptedStr);
    } catch {
        return decryptedStr;
    }
}

⚠️ 如果之前在加密时没有将明文进行 parse 而是直接传入的,那么在解密时,传入 toString() 的解析方式就是写默认的 CryptoJS.enc.Utf8。

  既然有了上面的加密和解密函数,现在要在 Vue 项目中使用它们。创建一个简单的 Vue 组件,让用户输入一些信息,然后可以加密和解密。

<script setup lang="ts">
import { ref } from 'vue';
import {decryptAES, encryptAES} from "@/hooks/CryptoJSUtils.ts";

const plaintext = ref('');
const ciphertext = ref('');
const decryptedText = ref('');
// ⚠️ 注意:生产环境中,密钥(key)和初始向量(iv)强烈建议从后端接口动态获取,绝对不要硬编码在前端!
const secretKey = "12345678901234567890123456789012";
const secretIv = "abcdefghijklmnop";

// 加密
const handleEncrypt = () => {
  ciphertext.value = encryptAES(plaintext.value, secretKey, secretIv);
}

// 解密
const handleDecrypt = () => {
  decryptedText.value = decryptAES(ciphertext.value, secretKey, secretIv);
}
</script>

<template>
  <div>
    <input type="text" v-model="plaintext" placeholder="请输入明文" />
    <button @click="handleEncrypt">加密</button>
    <button @click="handleDecrypt">解密</button>
    <p>加密后的文本: {{ ciphertext }}</p>
    <p>解密后的文本: {{ decryptedText }}</p>
  </div>
</template>

Java 加解密基础

  Java 中的加解密 API 集中在 javax.crypto 包内,核心类包括:

核心类 简要说明
Cipher 加解密的核心类,指定算法、模式、填充方式后,可调用 init、doFinal 进行加密解密
SecretKeySpec 用来将字节数组转换成对称密钥(SecretKey)
IvParameterSpec 用来封装初始化向量(IV)
Base64 Java 8 内置的 Base64 编解码类

  如果使用 Spring Boot,可在 pom.xml 中引入 Web 依赖即可,无需额外加密库,因为 JCE 已内置于 JDK。创建一个工具类 EncryptUtils,封装 AES 解密方法:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class EncryptUtils {
  // 加密算法
    private static String algorithm = "AES";
  // 加解密算法/工作模式/填充方式
    private static String algorithmProvider = "AES/CBC/PKCS5Padding";
  
  public static String encrypt(String src, String uniqueKey) {
      
    }
  
    /**
     * 使用 AES/CBC/PKCS5Padding 对 Base64 编码的密文进行解密
     *
     * @param base64CipherText 前端加密后的 Base64 密文
     * @param aesKey           与前端约定的 32 字节(256 位)Key
     * @param aesIv            与前端约定的 16 字节 (128 位) IV
     * @return 解密后的明文字符串
     */
    public static String decryptAES(String base64CipherText, String aesKey, String aesIv) {
        try {
            // 1. 将 Base64 密文解码成字节数组
            byte[] cipherBytes = Base64.getDecoder().decode(base64CipherText);

            // 2. 准备 Key 和 IV
            byte[] keyBytes = aesKey.getBytes(StandardCharsets.UTF_8);
            byte[] ivBytes = aesIv.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, algorithm);
            IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

            // 3. 初始化 Cipher
            Cipher cipher = Cipher.getInstance(algorithmProvider);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

            // 4. 执行解密
            byte[] plainBytes = cipher.doFinal(cipherBytes);

            // 5. 转为字符串并返回
            return new String(plainBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
            return null; // 解密失败返回 null,可根据实际情况抛出异常
        }
    }
}

⚠️ 注意:Java 默认使用 PKCS5Padding,而 CryptoJS 使用的是 PKCS7Padding。二者在实现上是兼容的,所以无需额外配置即可互通。

4.2 3DES加解密

  在现代的互联网时代,数据安全性备受关注。为了保护敏感数据的机密性,对称加密算法是一种常用的方法。3DES(Triple DES)一种常用的对称加密算法,是 DES 加密算法的一种增强版本,通过对数据进行三次DES加密来提高安全性。TripleDES 算法的全称是“三重数据加密标准”,它使用固定长度的密钥对数据进行加密和解密,密钥长度为192位。TripleDES 算法具有以下特点:

特点 简要说明
安全性较高 TripleDES 算法使用三个不同的密钥进行加密和解密,密钥长度较长,安全性较高
灵活性较差 TripleDES 算法只能使用168位的密钥长度,不够灵活
计算速度较慢 TripleDES 算法的计算速度比较慢,适用于对数据进行加密和解密

3DES加密的基本用法

  在 CryptoJS 中,3DES 加密需要指定密钥和加密模式。以下是一个简单的 3DES 加密示例:

export const encrypt3DES = (originalText: string, publicKey: string, secretIv: string, mode: string) => {
  if (!originalText || !publicKey) {
    throw new Error('内容和密钥不能为空');
  }
  if (publicKey.length !== 8) {
    throw new Error('密钥必须为8个字符');
  }

  const options = {
    mode: mode === 'ECB' ? CryptoJS.mode.ECB : CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  }
  if (secretIv) {
    if (secretIv.length !== 8) {
      throw new Error('IV必须为8个字符')
    }
    options.iv = CryptoJS.enc.Utf8.parse(secretIv)
  }

  // 执行加密
  const encryptData = CryptoJS.TripleDES.encrypt(originalText, publicKey, options)

  // 返回 Base64 格式的密文
  return encryptData.toString()
}

3DES解密的基本用法

  3DES 解密与加密类似,只是调用的是 decrypt 方法:

export const decrypt3DES = (ciphertext: string, publicKey: string, secretIv: string, mode: string) => {
  if (!ciphertext || !publicKey) {
    throw new Error('密文和密钥不能为空')
  }
  if (publicKey.length !== 8) {
    throw new Error('密钥必须为8个字符')
  }

  const options = {
    mode: mode === 'ECB' ? CryptoJS.mode.ECB : CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  }

  if (secretIv) {
    if (secretIv.length !== 8) {
      throw new Error('IV必须为8个字符')
    }
    options.iv = CryptoJS.enc.Utf8.parse(secretIv)
  }

  // 执行解密
  const encryptData = CryptoJS.TripleDES.decrypt(ciphertext, publicKey, options)

  // 将解密后的数据转换为 UTF-8 字符串
  return encryptData.toString(CryptoJS.enc.Utf8)
}

加密解密工具组件

<script setup lang="ts">
import CryptoJS from 'crypto-js';
import { ref} from 'vue';
import {decrypt3DES, encrypt3DES} from "@/hooks/CryptoJSUtils.ts";

const mode=ref('ECB');
const key= ref('12345678');
const iv=ref('');
const plainText= ref('');
const encryptedText= ref('');
const decryptedText= ref('');

/**
 * 生成随机密钥
 */
const generateKey = () => {
  key.value = CryptoJS.lib.WordArray.random(8).toString();
}

/**
 * 加密
 */
const encrypt = () => {
  encryptedText.value = encrypt3DES(plainText.value, key.value, iv.value,mode.value)
}

/**
 * 解密
 */
const decrypt = () => {
  decryptedText.value = decrypt3DES(encryptedText.value, key.value, iv.value,mode.value)
}
</script>

<template>
  <div class="container mx-auto p-6 max-w-2xl">
    <h1 class="text-2xl font-bold mb-6 text-blue-600">3DES 加密解密工具</h1>

    <!-- 加密模式选择 -->
    <div class="bg-white rounded-lg shadow-md p-6 mb-6">
      <div class="mb-4">
        <label class="block text-gray-700 mb-2">加密模式</label>
        <select v-model="mode" class="w-full p-2 border rounded">
          <option value="ECB">ECB模式</option>
          <option value="CBC">CBC模式</option>
        </select>
      </div>

      <!-- 密钥生成 -->
      <div class="mb-4">
        <label class="block text-gray-700 mb-2">密钥 (8字节)</label>
        <div class="flex">
          <input v-model="key" type="text" class="flex-1 p-2 border rounded-l" placeholder="输入8位密钥">
          <button @click="generateKey" class="bg-blue-500 text-white px-4 rounded-r hover:bg-blue-600">
            <i class="fas fa-sync-alt"></i> 生成
          </button>
        </div>
      </div>

      <!-- CBC模式IV -->
      <div v-if="mode === 'CBC'" class="mb-4">
        <label class="block text-gray-700 mb-2">IV偏移量 (8字节)</label>
        <input v-model="iv" type="text" class="w-full p-2 border rounded" placeholder="输入8位IV">
      </div>

      <!-- 文本输入 -->
      <div class="mb-4">
        <label class="block text-gray-700 mb-2">原始文本</label>
        <textarea v-model="plainText" rows="3" class="w-full p-2 border rounded" placeholder="输入要加密的内容"></textarea>
      </div>

      <!-- 操作按钮 -->
      <div class="flex space-x-3 mb-6">
        <button @click="encrypt" class="flex-1 bg-green-500 text-white py-2 rounded hover:bg-green-600">
          <i class="fas fa-lock"></i> 加密
        </button>
        <button @click="decrypt" class="flex-1 bg-purple-500 text-white py-2 rounded hover:bg-purple-600">
          <i class="fas fa-unlock"></i> 解密
        </button>
      </div>

      <!-- 结果展示 -->
      <div class="mb-4">
        <label class="block text-gray-700 mb-2">加密结果</label>
        <textarea v-model="encryptedText" rows="3" readonly class="w-full p-2 border rounded bg-gray-50"></textarea>
      </div>

      <div class="mb-4">
        <label class="block text-gray-700 mb-2">解密结果</label>
        <textarea v-model="decryptedText" rows="3" readonly class="w-full p-2 border rounded bg-gray-50"></textarea>
      </div>
    </div>
  </div>
</template>

<style>
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css');
@import url('https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css');

body {
  background-color: #f7fafc;
}
</style>

小结

  在 3DES 加密中,加密模式和填充方式的选择会影响加密结果的安全性。常见的加密模式有ECB、CBC等,填充方式有Pkcs7、ZeroPadding等。在实际应用中,应根据具体需求选择合适的加密模式和填充方式。虽然 3DES 比 DES 更安全,但在现代加密标准中,3DES已经逐渐被AES等更安全的算法取代。如果对安全性要求较高,建议使用AES等更现代的加密算法。|

五、HMAC 数据验证

5.1 HMAC加密

  对称加密只能保证机密性,即对手无法从密文恢复明文,但并不能保证数据在传输过程中未被篡改。为此,可在密文外层再加一层签名(HMAC)。HMAC 是一种基于密钥的消息认证码算法,用于验证消息在传输过程中是否被篡改,以及确认消息来源的真实性,通常用于消息身份验证、API 签名等。HMAC 算法具有以下特点:

特点 简要说明
安全性高 HMAC 算法使用密钥对原始数据进行加密,可以有效防止数据被篡改
灵活性强 HMAC 算法可以使用多种哈希函数,如SHA256、SHA512等
计算速度快 HMAC 算法的计算速度比较快,适用于对大量数据进行认证计算

  以下是 CryptoJS 实现 HMAC 算法的示例代码:

const plaintitle = 'hello world'
const key = CryptoJS.enc.Utf8.parse('1234567890123456')
const hmac = CryptoJS.HmacSHA256(plaintitle , key).toString()

5.2 PBKDF2加密

  PBKDF2 是一种常用的密码加密算法,用于将用户密码转换成一个固定长度的密钥。PBKDF2 算法的全称是“基于密码的密钥派生函数”,它通过在用户密码上附加一个随机盐值,然后对附加了盐值的密码进行多次哈希计算,最后将计算结果作为密钥。PBKDF2 算法具有以下特点:

特点 简要说明
安全性高 PBKDF2 算法使用随机盐值和多次哈希计算,可以有效防止密码被破解
灵活性强 PBKDF2 算法可以使用多种哈希函数,如SHA256、SHA512等
计算速度慢 PBKDF2 算法的计算速度比较慢,适用于对密码进行加密计算

  PBKDF2 基于伪随机函数(PRF)构建,通过对密码和盐值进行多次迭代计算来增强密钥的安全性。其数学表达式可以表示为:

PBKDF2(password: WordArray | string, salt: WordArray | string, cfg?: KDFOption)
配置项 简要说明
password 用户输入的密码
salt 随机盐值,确保即使是相同密码产生不同的派生密钥,有效防止预计算攻击
cfg
keySize 密钥大小(以字为单位)
hasher 使用的哈希算法
iterations 迭代次数
// 使用默认配置(SHA256, 250000次迭代)
var derivedKey = CryptoJS.PBKDF2("password", "somesalt");
 
// 自定义配置
var customKey = CryptoJS.PBKDF2("password", "somesalt", {
    keySize: 256/32,       // 256位密钥
    iterations: 1000000,   // 100万次迭代
    hasher: CryptoJS.algo.SHA512  // 使用SHA512
});

六、总结

  CryptoJS 解决的是在不受控的客户端环境中实施可控安全策略的矛盾命题,它无法替代 HTTPS 传输层加密,也不能弥补弱密钥管理、明文密钥硬编码、缺乏服务端二次校验等架构缺陷,其真正价值在于赋能开发者在“最小信任模型”下构建纵深防御。因此,通过合理地引入和使用 crypto-js,我们可以有效地保护前端数据的安全性,为用户提供更加安全、可靠的服务。同时,对crypto-js进行封装可以让我们更好地组织和管理代码,提高开发效率和代码质量。

❌
❌