前端如何使用CryptoJS来做好加密

明文传一个手机号怎么了,反正都开户了

0.前言

某次面试了一家银行的前端,被问到了关于前端安全方面的问题,具体就是前端如何做好加密解密,尤其是涉及到了用户信息,比如用户的手机号、身份证号之类的数据怎么处理。这确实是一个很重要的问题,尤其在金融类项目中,对数据安全性要求极高。今天就来详细讲解前端加密解密的相关知识。

1.CryptoJS

首先需要了解一下CryptoJS:这是一个强大的加密库,提供了多种加密算法,包括 AES、MD5、SHA 等。在前端项目中使用非常广泛。

1.1 基础使用

// 引入
import CryptoJS from 'crypto-js';

// 加密
function encrypt(data, key) {
    return CryptoJS.AES.encrypt(data, key).toString();
}

// 解密
function decrypt(encryptedData, key) {
    const bytes = CryptoJS.AES.decrypt(encryptedData, key);
    return bytes.toString(CryptoJS.enc.Utf8);
}

// 使用示例
const key = 'secret key 123';
const text = '要加密的内容';

const encrypted = encrypt(text, key);
console.log('加密后:', encrypted);

const decrypted = decrypt(encrypted, key);
console.log('解密后:', decrypted);

1.2 进阶使用

// 使用CBC模式的AES加密
const encrypted = CryptoJS.AES.encrypt('hello', 'key', {
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7,
    iv: CryptoJS.enc.Utf8.parse('1234567890123456')
}).toString();

// 对应的解密
const decrypted = CryptoJS.AES.decrypt(encrypted, 'key', {
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7,
    iv: CryptoJS.enc.Utf8.parse('1234567890123456')
}).toString(CryptoJS.enc.Utf8);

1.3 其他功能

// MD5哈希
const md5Hash = CryptoJS.MD5('要哈希的内容').toString();

// SHA256哈希
const sha256Hash = CryptoJS.SHA256('要哈希的内容').toString();

// Base64编码
const base64 = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse('hello'));

2.AES对称加密

AES是一种对称加密算法,所谓对称加密,就是加密和解密使用相同的密钥。就像一把钥匙开一把锁,这个钥匙既可以用来锁门,也可以用来开门。

AES加密有几种不同的工作模式:

2.1ECB模式

最简单的加密模式,但安全性较低,因为相同的明文会产生相同的密文。

const encryptedECB = CryptoJS.AES.encrypt('hello', 'key', {
    mode: CryptoJS.mode.ECB
}).toString();

2.2 CBC模式

更安全的加密模式,需要提供一个初始向量(IV),相同的明文会产生不同的密文。

const encryptedCBC = CryptoJS.AES.encrypt('hello', 'key', {
    mode: CryptoJS.mode.CBC,
    iv: CryptoJS.enc.Utf8.parse('1234567890123456')
}).toString();

对称加密的优点是速度快适合加密大量数据,但缺点是密钥的传输和保管比较困难。因为如果把秘钥直接写到前端项目中,可能会有泄露的风险。

在实际的项目中,比较推荐使用CBC模式,更加的安全可靠。

3.RSA非对称加密

RSA是一种非对称加密算法,它使用一对密钥:公钥和私钥。公钥可以公开给任何人,用于加密数据;而私钥必须严格保密,用于解密数据。

3.1 基本原理

使用公钥加密的数据只能用私钥解密,这就保证了数据的安全性。即使黑客获取了公钥,也无法解密数据。

3.2 使用场景

RSA主要用于:

  1. 加密密钥的传输
  2. 数字签名
  3. 加密敏感信息(如密码)

3.3 示例代码

// 使用公钥加密
const encrypted = crypto.publicEncrypt(
    publicKey,
    Buffer.from('要加密的内容')
).toString('base64');

// 私钥解密在服务器端进行

4.实际项目中的应用

在实际项目中,尤其是金融类项目,通常会结合使用这两种加密方式。让我们来看几个具体的场景:

(具体使用哪种方式,还是要看项目的要求,可以只使用AES,也可以只使用RSA,当然也可以两个结合一起)

AES的例子就不列举了,前面列举过了。

4.1 密码加密

密码直接使用 RSA 加密就可以了,原因是:

  1. 密码数据量小,RSA 的性能问题影响不大
  2. 密码安全要求高,需要更强的加密方式
  3. 只需要从客户端传到服务器,不需要双向通信
  4. 使用公钥加密,私钥解密的方式非常适合密码传输
// 从服务器获取公钥
async function getPublicKey() {
   const response = await fetch('/api/getPublicKey');
   const { publicKey } = await response.json();
   return publicKey;
}

// 加密密码
async function encryptPassword(password) {
   const publicKey = await getPublicKey();
   return crypto.publicEncrypt(
       publicKey,
       Buffer.from(password)
   ).toString('base64');
}

4.2 敏感信息传输

对于身份证号、银行卡号等敏感信息,通常使用 AES + RSA 的组合加密方式:

class SecurityService {
    async encryptSensitiveData(data) {
        // 1. 生成随机的 AES 密钥
        const aesKey = CryptoJS.lib.WordArray.random(16).toString();
        
        // 2. 用 AES 加密数据
        const encryptedData = CryptoJS.AES.encrypt(JSON.stringify(data), aesKey, {
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
            iv: CryptoJS.enc.Utf8.parse('1234567890123456')
        }).toString();
        
        // 3. 用 RSA 加密 AES 密钥
        const publicKey = await this.getPublicKey();
        const encryptedKey = crypto.publicEncrypt(
            publicKey,
            Buffer.from(aesKey)
        ).toString('base64');
        
        // 4. 返回加密后的数据和密钥
        return {
            data: encryptedData,
            key: encryptedKey
        };
    }
}
kucha
“ 大冬天的非常冷,打工人很辛苦,需要一杯奶茶暖暖肚子。 ”
 喜欢文章
头像