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

前言

在传统的客户端-服务器交互中,用户在前端输入的敏感信息(如用户名、密码、信用卡号等)通常会以明文通过 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 将其安装到项目中。打开终端,进入项目目录,执行以下命令:

bash 复制代码
npm install crypto-js --save-dev

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

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

在组件中引入 CryptoJS

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

JavaScript 复制代码
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 表情和特殊符号。

javascript 复制代码
// 字符串转换为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转换为指定编码的字符串
javascript 复制代码
// 待编码的字符串
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 编码解码的完整使用示例:

javascript 复制代码
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 算法的示例代码:

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

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

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

javascript 复制代码
const wordArray = CryptoJS.enc.Utf8.parse('Hello World');
CryptoJS.MD5(wordArray).toString();

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

3.2 SHA-1 加密

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

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

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

javascript 复制代码
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 算法的示例代码:

javascript 复制代码
const message = "Hello World";
console.log("SHA3:", CryptoJS.SHA3(message).toString());

SHA-512

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

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

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

javascript 复制代码
const message = "Hello World";
console.log("SHA512:", CryptoJS.SHA512(message).toString());

3.4 SHA-3 加密

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

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

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

javascript 复制代码
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 算法的计算速度比较快,适用于对大量数据进行加密和解密
javascript 复制代码
// 加密:数据 → 密钥 → 密文
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加密后生成不同的密文,从而增加破解的难度和安全性。
javascript 复制代码
// 密钥
const secretKey = CryptoJS.enc.Utf8.parse("12345678901234567890123456789012");
// 偏移量
const secretIv = CryptoJS.enc.Utf8.parse("abcdefghijklmnop");

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

加密解密函数封装

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

javascript 复制代码
/**
 * 使用 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。这个函数接收加密后的文字,然后返回正常的明文。

javascript 复制代码
/**
 * 使用 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 组件,让用户输入一些信息,然后可以加密和解密。

html 复制代码
<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 解密方法:

java 复制代码
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 加密示例:

javascript 复制代码
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 方法:

javascript 复制代码
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)
}

加密解密工具组件

html 复制代码
<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 算法的示例代码:

javascript 复制代码
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)构建,通过对密码和盐值进行多次迭代计算来增强密钥的安全性。其数学表达式可以表示为:

javascript 复制代码
PBKDF2(password: WordArray | string, salt: WordArray | string, cfg?: KDFOption)
配置项 简要说明
password 用户输入的密码
salt 随机盐值,确保即使是相同密码产生不同的派生密钥,有效防止预计算攻击
cfg
keySize 密钥大小(以字为单位)
hasher 使用的哈希算法
iterations 迭代次数
javascript 复制代码
// 使用默认配置(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进行封装可以让我们更好地组织和管理代码,提高开发效率和代码质量。

相关推荐
发现一只大呆瓜2 小时前
一文搞懂 Vite 处理CommonJS包、按需编译逻辑及 Rollup 插件兼容规则
前端
Edwardwu2 小时前
写了个y-mxgraph:给 draw.io 接上了 Yjs,顺便解决了部署在 iframe 里的一堆问题
前端·typescript
其实防守也摸鱼3 小时前
软件安全与漏洞--软件安全编码
java·前端·网络·安全·网络安全·web·工具
发现一只大呆瓜3 小时前
Vite 开发预构建机制详解,搞懂 esbuild 与 Rollup 分工差异
前端·面试·vite
九九落4 小时前
前端获取经纬度完全指南:从Geolocation API到地图集成
前端·获取经纬度
来恩10035 小时前
jQuery选择器
前端·javascript·jquery
前端繁华如梦5 小时前
树上挂苹果还是挂玻璃球?Three.js 程序化果实的完整实现指南
前端·javascript
墨痕诉清风5 小时前
Web浏览器客户端检测网站网络健康(代码)
前端·网络·测试工具
IMPYLH5 小时前
Linux 的 wc 命令
linux·运维·服务器·前端·bash