密码加盐哈希 (Salted Hashing),这是前端加密的首选方案。
原理:
哈希 (Hash):对密码执行一个单向的哈希函数(如 SHA-256, SHA-512)。这个过程是不可逆的,即无法从哈希值反推出原始密码。
加盐 (Salt):为每一个密码生成一个唯一的随机字符串(称为 “盐”)。将这个盐与密码混合后再进行哈希。
为什么需要 “盐”?
防止彩虹表攻击:如果没有盐,攻击者可以预先计算好常见密码的哈希值(彩虹表),然后直接比对数据库中的哈希值。
相同密码不同哈希:即使两个用户使用了相同的密码,由于盐值不同,它们最终的哈希值也会完全不同。
在前端使用 SHA-256 加密,通常有两种主流方案:使用第三方库(如 CryptoJS) 和 使用浏览器原生的 Web Crypto API。下面将为你详细讲解CryptoJS。
CryptoJS 是一个非常流行的加密算法库,它封装了包括 SHA-256 在内的多种哈希算法和加密算法,使用起来简单直观,并且兼容性非常好,支持所有现代浏览器甚至一些旧版浏览器。
步骤 1:安装 CryptoJS
npm install crypto-js
# 或者
yarn add crypto-js
然后在你的 JavaScript 文件中引入:
import CryptoJS from 'crypto-js';
// 或者使用 require
// const CryptoJS = require('crypto-js');
步骤 2:使用 SHA-256 进行加密
CryptoJS 的 API 设计非常友好。
1. 基本用法(直接哈希)
const message = "Hello, World!";
// 使用 SHA-256 对字符串进行哈希
const hash = CryptoJS.SHA256(message);
// 默认返回的是一个 WordArray 对象,我们通常需要将其转换为十六进制字符串
const hashHex = hash.toString(CryptoJS.enc.Hex);
console.log("SHA-256 哈希结果 (十六进制):", hashHex);
// 输出: SHA-256 哈希结果 (十六进制): b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace...
2. 加盐哈希(Salted Hashing)- 推荐用于密码
直接对密码进行哈希是不够安全的。为了防止彩虹表攻击,必须进行加盐哈希。
// 1. 定义一个函数来生成一个随机的盐 (例如,16字节)
function generateSalt() {
// CryptoJS.lib.WordArray.random(n) 会生成 n 个字节的随机数据
return CryptoJS.lib.WordArray.random(16).toString(CryptoJS.enc.Hex);
}
// 2. 定义一个函数来对密码进行加盐哈希
function hashPassword(password, salt) {
// 将密码和盐拼接在一起
const saltedPassword = password + salt;
// 进行 SHA-256 哈希
return CryptoJS.SHA256(saltedPassword).toString(CryptoJS.enc.Hex);
}
// --- 使用示例 ---
const userPassword = "mySecretPassword123";
// 注册时
const salt = generateSalt(); // 生成一个新的盐
const hashedPassword = hashPassword(userPassword, salt);
console.log("生成的盐:", salt);
console.log("加盐哈希后的密码:", hashedPassword);
// 将 hashedPassword 和 salt 一起发送给后端存储
// --- 登录时 ---
// 假设从后端获取了该用户的 salt 和 storedHashedPassword
const storedSalt = "从数据库获取的盐";
const storedHashedPassword = "从数据库获取的哈希值";
// 使用用户输入的密码和存储的盐重新计算哈希
const loginHashedPassword = hashPassword(userPassword, storedSalt);
// 比较新计算的哈希值和存储的哈希值
if (loginHashedPassword === storedHashedPassword) {
console.log("密码正确,登录成功!");
} else {
console.log("密码错误,登录失败!");
}