侧边栏壁纸
博主头像
ERSHI的个人网站

记录一下

  • 累计撰写 5 篇文章
  • 累计创建 5 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

密码安全:加盐(slat)原理及TypeScript实践

ERSHI
2025-06-03 / 0 评论 / 0 点赞 / 4 阅读 / 0 字

密码加盐(Salting)技术详解

什么是密码加盐?

想象你在做一道秘制腌肉🥩。盐就是那味秘方调料,让每块肉都有独特风味。
密码加盐就是在用户密码中添加随机数据(称为"盐"),就像给密码穿上定制防护衣,即使两个用户密码相同,存储结果也完全不同。

为什么需要加盐?举个🌰

假设有3个用户都使用密码 123456

// 不加盐的哈希结果(危险!):
用户A: 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
用户B: 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 // 完全相同!
用户C: 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92

// 加盐后的哈希结果(安全✅):
用户A(盐=abc): 7f9d8e...  // 盐+密码 = "abc123456"
用户B(盐=xyz): 2b4a6c...  // 盐+密码 = "xyz123456"
用户C(盐=123): d8e2f7... // 盐+密码 = "123123456"

三大核心作用

  1. 防彩虹表攻击
    🏳️‍🌈彩虹表是黑客的"密码字典",加盐后每个密码都变独特,字典直接失效
  2. 防相同密码暴露
    如上例所示,避免"一个密码泄露,所有相同密码用户遭殃"
  3. 增加破解成本
    黑客必须为每个用户单独破解,不能批量操作

加盐四步走🚶‍♂️

graph TD
    A[生成随机盐值] --> B[组合密码+盐]
    B --> C[哈希计算]
    C --> D[存储盐+哈希]

1. 生成随机盐值

// 就像抽盲盒,每个用户获得专属盐
const salt = randomBytes(16).toString('hex'); 
// 生成16字节随机值 → 类似“4f9c2a3d8b1e7f0a”

2. 组合密码和盐值

// 盐+密码 → 像调制特饮
const saltedPassword = salt + password; 
// 得到“4f9c2a3d8b1e7f0amyPassword123”

3. 哈希计算

// 用SHA-256等算法“粉碎”混合体
const hash = createHash('sha256')
    .update(saltedPassword) // 喂入混合体
    .digest('hex'); // 输出64位哈希值

4. 存储

// 盐和哈希存一起,用冒号分隔
`${salt}:${hash}` → "4f9c2a3d8b1e7f0a:9c2f4d8a1b..."

TypeScript 实战:两种加盐方式

方法1:原生SHA-256加盐

import { randomBytes, createHash } from 'crypto';

// 🔐 密码加密函数
export function hashPasswordWithSHA(password: string): Promise<string> {
  return new Promise((resolve, reject) => {
    try {
      // 步骤1:生成16字节随机盐(32位16进制字符串)
      const salt = randomBytes(16).toString('hex');
    
      // 步骤2+3:组合盐+密码 → 哈希计算
      const hash = createHash('sha256')
        .update(salt + password) // 盐放密码前
        .digest('hex'); // 转16进制字符串
    
      // 步骤4:返回“盐:哈希”格式
      resolve(`${salt}:${hash}`);
    } catch (err) {
      reject(err);
    }
  });
}

// 🔍 密码验证函数
export function verifyPasswordWithSHA(
  storedPassword: string, // 数据库存的“盐:哈希”
  inputPassword: string   // 用户输入密码
): Promise<boolean> {
  return new Promise((resolve) => {
    // 从存储值拆分盐和哈希
    const [salt, storedHash] = storedPassword.split(':');
  
    // 用相同算法计算输入密码
    const hash = createHash('sha256')
      .update(salt + inputPassword)
      .digest('hex');
  
    // 比较新哈希 vs 存储哈希
    resolve(hash === storedHash);
  });
}

方法2:专业选手 bcrypt(推荐✨)

# 先安装依赖
npm install bcrypt
npm install --save-dev @types/bcrypt
import bcrypt from 'bcrypt';

const SALT_ROUNDS = 12; // 加密强度,值越大越安全(但越慢)

// 🔐 加密密码(bcrypt自动处理盐!)
export async function hashPasswordWithBcrypt(
  password: string
): Promise<string> {
  // 一步完成:生成盐+哈希+组合存储
  return await bcrypt.hash(password, SALT_ROUNDS); 
}

// 🔍 验证密码
export async function verifyPasswordWithBcrypt(
  inputPassword: string,
  storedHash: string   // bcrypt自动包含盐
): Promise<boolean> {
  // 智能对比:自动提取盐值计算验证
  return await bcrypt.compare(inputPassword, storedHash);
}

使用示例

async function main() {
  const password = '我的密码123';

  // SHA-256演示
  const shaHash = await hashPasswordWithSHA(password);
  console.log('SHA加盐结果:', shaHash); // 输出"盐:哈希"
  console.log('验证结果:', 
    await verifyPasswordWithSHA(shaHash, password)); // true

  // bcrypt演示
  const bcryptHash = await hashPasswordWithBcrypt(password);
  console.log('bcrypt结果:', bcryptHash); // 自动包含盐的哈希
  console.log('验证结果:',
    await verifyPasswordWithBcrypt(password, bcryptHash)); // true
}
main();

为什么推荐 bcrypt?🚀

特性 SHA-256加盐 bcrypt
专业度 通用哈希算法 专为密码设计
盐值处理 需手动管理 自动处理
抗暴力破解 中等 非常强
速度控制 固定速度 可调节成本

bcrypt 四大优势

  1. 自动加盐 - 不用操心盐的生成存储
  2. 可调成本 - 通过salt_rounds控制计算强度
  3. 故意变慢 - 拖慢黑客破解速度(1秒验1次 vs 10万次/秒)
  4. 全副武装 - 内置抵抗GPU/ASIC等高级攻击

安全红绿灯🚦

🟢 该做的

// ✅ 使用专业库
import bcrypt from 'bcrypt'; 

// ✅ 设置合适强度(12是2023年推荐值)
const SAFE_SALT_ROUNDS = 12; 

// ✅ 定期更新安全策略
function updateSecurity() {
  if (year > 2025) considerArgon2(); // 未来可升级
}

🔴 禁止做

// ❌ 自己造轮子(除非你是密码学专家)
function myUnsafeHash() { /* 危险操作 */ }

// ❌ 使用弱哈希(如MD5、SHA1)
const weakHash = createHash('md5'); 

// ❌ 盐值过短(小于16字节)
const toySalt = randomBytes(2); // 太短!

📌 黄金法则:就像不会自己配药治病一样,不要自研密码算法!使用经过实战检验的bcrypt/Argon2等方案。


通过这个指南,你已经掌握了密码加盐的核心原理和实战技能!关键记住三点:

  1. 加盐=给密码穿定制防护衣
  2. 优先用bcrypt等专业工具
  3. 永远不要存储明文密码
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区