前端数据加密常用方法解析

63 阅读4分钟

一、分类概览

1. 按加密强度分类

弱加密(编码/混淆):Base64、URL编码、简单替换

对称加密:AES、DES

非对称加密:RSA、ECC

哈希算法:MD5、SHA系列

混合加密:HTTPS、JWE

2. 按用途分类

传输加密:TLS/SSL、混合加密

存储加密:对称加密、哈希加盐

认证加密:JWT、数字签名

二、详细方法与对比分析

1. 编码类(弱保护)

// 编码
function base64Encode(str) {
    return btoa(unescape(encodeURIComponent(str)));
}

// 解码
function base64Decode(encodedStr) {
    return decodeURIComponent(escape(atob(encodedStr)));
}

// 使用示例
const original = "敏感数据123";
const encoded = base64Encode(original); // "5oOz5p2l5pWw5o2uMTIz"
const decoded = base64Decode(encoded); // "敏感数据123"

URL编码

// 编码
const urlEncode = encodeURIComponent("用户数据?key=value"); // "%E7%94%A8%E6%88%B7%E6%95%B0%E6%8D%AE%3Fkey%3Dvalue"

// 解码
const urlDecode = decodeURIComponent("%E7%94%A8%E6%88%B7%E6%95%B0%E6%8D%AE");

特点:不是真正的加密,仅用于数据格式转换,无安全性

2. 哈希算法

SHA-256(使用Web Crypto API)

async function sha256Hash(message) {
    // 将字符串转换为Uint8Array
    const encoder = new TextEncoder();
    const data = encoder.encode(message);
    
    // 计算哈希
    const hashBuffer = await crypto.subtle.digest('SHA-256', data);
    
    // 转换为十六进制字符串
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

// 使用示例
sha256Hash('password123').then(hash => {
    console.log('SHA-256哈希:', hash);
});

加盐哈希(用于密码存储)

async function saltedHash(password, salt) {
    const encoder = new TextEncoder();
    const passwordBuffer = encoder.encode(password + salt);
    
    const hashBuffer = await crypto.subtle.digest('SHA-256', passwordBuffer);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

// 使用示例
const salt = crypto.getRandomValues(new Uint8Array(16));
saltedHash('userPassword', salt).then(hashedPassword => {
    console.log('加盐哈希:', hashedPassword);
});

3. 对称加密

AES-GCM(推荐)

async function aesEncrypt(plaintext, password) {
    // 生成密钥
    const encoder = new TextEncoder();
    const keyMaterial = await crypto.subtle.importKey(
        'raw',
        encoder.encode(password),
        { name: 'PBKDF2' },
        false,
        ['deriveKey']
    );
    
    // 派生密钥
    const key = await crypto.subtle.deriveKey(
        {
            name: 'PBKDF2',
            salt: crypto.getRandomValues(new Uint8Array(16)),
            iterations: 100000,
            hash: 'SHA-256'
        },
        keyMaterial,
        { name: 'AES-GCM', length: 256 },
        false,
        ['encrypt', 'decrypt']
    );
    
    // 加密
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const encrypted = await crypto.subtle.encrypt(
        { name: 'AES-GCM', iv },
        key,
        encoder.encode(plaintext)
    );
    
    return {
        iv: Array.from(iv),
        encrypted: Array.from(new Uint8Array(encrypted))
    };
}

async function aesDecrypt(encryptedData, password) {
    // 类似加密过程,使用decrypt方法
    // 具体实现略
}

4. 非对称加密

RSA加密

async function generateRSAKeys() {
    return await crypto.subtle.generateKey(
        {
            name: 'RSA-OAEP',
            modulusLength: 2048,
            publicExponent: new Uint8Array([1, 0, 1]),
            hash: 'SHA-256'
        },
        true,
        ['encrypt', 'decrypt']
    );
}

async function rsaEncrypt(publicKey, plaintext) {
    const encoder = new TextEncoder();
    const data = encoder.encode(plaintext);
    
    return await crypto.subtle.encrypt(
        { name: 'RSA-OAEP' },
        publicKey,
        data
    );
}

// 使用示例
generateRSAKeys().then(async keys => {
    const encrypted = await rsaEncrypt(keys.publicKey, '敏感数据');
    console.log('RSA加密结果:', new Uint8Array(encrypted));
});

5. 混合加密实践

前端数据加密传输

class SecureDataTransmitter {
    constructor(serverPublicKey) {
        this.serverPublicKey = serverPublicKey;
        this.sessionKey = null;
    }
    
    async initSession() {
        // 生成会话密钥
        this.sessionKey = await crypto.subtle.generateKey(
            { name: 'AES-GCM', length: 256 },
            true,
            ['encrypt', 'decrypt']
        );
        
        // 用服务器公钥加密会话密钥
        const exportedKey = await crypto.subtle.exportKey('raw', this.sessionKey);
        const encryptedSessionKey = await crypto.subtle.encrypt(
            { name: 'RSA-OAEP' },
            this.serverPublicKey,
            exportedKey
        );
        
        return encryptedSessionKey;
    }
    
    async encryptData(data) {
        const encoder = new TextEncoder();
        const iv = crypto.getRandomValues(new Uint8Array(12));
        
        const encrypted = await crypto.subtle.encrypt(
            { name: 'AES-GCM', iv },
            this.sessionKey,
            encoder.encode(JSON.stringify(data))
        );
        
        return {
            iv: Array.from(iv),
            data: Array.from(new Uint8Array(encrypted))
        };
    }
}

6. 实用库封装

使用crypto-js库

// 安装: npm install crypto-js
import CryptoJS from 'crypto-js';

// AES加密
const encryptAES = (data, secretKey) => {
    return CryptoJS.AES.encrypt(JSON.stringify(data), secretKey).toString();
};

// AES解密
const decryptAES = (ciphertext, secretKey) => {
    const bytes = CryptoJS.AES.decrypt(ciphertext, secretKey);
    return JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
};

// 使用示例
const data = { userId: 123, name: '张三' };
const key = 'my-secret-key-123';
const encrypted = encryptAES(data, key);
const decrypted = decryptAES(encrypted, key);

三、对比分析表

在这里插入图片描述 四、选择建议

密码存储:使用加盐哈希(如bcrypt、PBKDF2)

数据传输:

简单场景:HTTPS + Base64编码

高安全场景:HTTPS + 客户端加密(AES/RSA混合)

本地存储:AES加密敏感数据

API安全:JWT签名 + HTTPS

文件加密:AES-CTR或AES-GCM模式

五、安全注意事项

永远不要在前端存储加密密钥

使用HTTPS作为基础传输层

定期更新加密算法和密钥

实施完整的密钥生命周期管理

进行安全审计和渗透测试

遵循最小权限原则

// 安全实践示例
class SecureStorage {
    constructor() {
        this.key = this.getKeyFromSecureSource();
    }
    
    async setItem(key, value) {
        const encrypted = await aesEncrypt(value, this.key);
        localStorage.setItem(key, JSON.stringify(encrypted));
    }
    
    async getItem(key) {
        const encrypted = JSON.parse(localStorage.getItem(key));
        return await aesDecrypt(encrypted, this.key);
    }
    
    getKeyFromSecureSource() {
        // 从安全来源获取密钥,如服务器下发或用户输入
        // 不要硬编码在代码中
    }
}

前端加密只是安全链条中的一环,必须与后端安全措施、网络传输安全、安全开发流程等结合,才能构建完整的安全体系。

在这里插入图片描述