bcryptUtil
工具类
ts
// src/utils/bcryptUtil.ts
import bcrypt from 'bcryptjs'
const saltRounds = 10
// $2a$10$K06X0zR9/K6xe2qKT1IqXO(盐值) + vPOyank6cYHv4iWjS8U5Ail/XfY5mEy哈希值
// 盐值是一串随机生成的字符串,它会被加入明文密码中一起进行哈希,从而增强密码的安全性
// 不是加密它,而是参与加密的“调料”。
// 假设你有两个用户都设置了相同的密码 123456
// bcrypt 自动会把盐值“夹带”进最终哈希中,所以你不需要单独存储它,验证时它会自动提取出来
// 盐值是一段“额外随机信息”,参与加密,防止同样的密码生成同样的哈希,从而提升安全性
export class BcryptUtil {
/**
* 加密明文密码
*/
static async hashPassword(plainText: string): Promise<string> {
const salt = await bcrypt.genSalt(saltRounds)
return bcrypt.hash(plainText, salt)
}
/**
* 使用指定盐生成特定 hash(可复现)
*/
static hashWithSalt(plainText: string, salt: string): string {
return bcrypt.hashSync(plainText, salt)
}
/**
* 验证密码是否匹配 hash 自动盐值
*/
static async comparePassword(plainText: string, hash: string): Promise<boolean> {
return bcrypt.compare(plainText, hash)
}
}
使用
ts
// 加密
const password = ref('123.com')
const hashed = ref('')
const isMatch = ref()
const salt = ref('$2a$10$K06X0zR9/K6xe2qKT1IqXO')
// $2b$10$c5RoTi6l96QX5lvODvAYEOrZbs/RGxEQWKXbxhkc.cMw.d0FWyxje
// $2a$10$K06X0zR9/K6xe2qKT1IqXOvPOyank6cYHv4iWjS8U5Ail/XfY5mEy
// $2a$10$K06X0zR9/K6xe2qKT1IqXOvPOyank6cYHv4iWjS8U5Ail/XfY5mEy
// 指定盐值 生成Hash
const generateHash = async () => {
hashed.value = await BcryptUtil.hashWithSalt(password.value,salt.value)
console.log("hashed.value",hashed.value)
}
// 明文和hash值是否匹配
const checkPassword = async () => {
if (!hashed.value) return
isMatch.value = await BcryptUtil.comparePassword(password.value, hashed.value)
console.log(isMatch.value)
}
onMounted(async() => {
await generateHash()
checkPassword()
})
加密
ts
import crypto from 'crypto'
const key = crypto.createHash('sha256').update('fixed_secret_key').digest() // 32字节密钥
const iv = Buffer.alloc(16, 0) // 初始向量(示例)
function encrypt(text: string) {
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv)
let encrypted = cipher.update(text, 'utf8', 'hex')
encrypted += cipher.final('hex')
return encrypted
}
function decrypt(encrypted: string) {
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
let decrypted = decipher.update(encrypted, 'hex', 'utf8')
decrypted += decipher.final('utf8')
return decrypted
}
const encrypted = encrypt('123.com')
console.log('加密:', encrypted)
console.log('解密:', decrypt(encrypted))
ts
bcrypt 是哈希算法,不是加密算法,不能用密钥解密。
bcrypt 只能单向哈希,无法解密。
如果需要“密钥”控制加密,应该用对称加密算法(如 AES)或者基于密钥的哈希(HMAC)等。
ts
哈希算法(Hash Algorithm)是一种单向散列函数,它将任意长度的输入数据通过计算,映射成固定长度的输出(称为哈希值、摘要、散列值),而且具有以下几个核心特性
单向性(不可逆)
从输入计算出哈希值非常容易,但从哈希值“反向推算”原始输入几乎不可能。
所以哈希算法不是“加密算法”,它不支持解密。
2. 固定长度输出
无论输入数据大小是多少,输出的哈希值长度是固定的,比如:
MD5 输出 128 位(16 字节)
SHA-256 输出 256 位(32 字节)
bcrypt 输出 60 字符的字符串(经过编码)
3. 碰撞阻力
两个不同的输入数据产生相同哈希值(碰撞)的概率非常低。
4. 雪崩效应
输入哪怕有一点点变化,输出的哈希值也会发生巨大变化。
哈希算法和加密算法
ts
MD5 128 位 校验文件完整性(已不安全)
SHA-1 160 位 版本控制、数字签名(逐渐被弃用)
SHA-256 256 位 安全加密、数字签名、区块链等
bcrypt 192 位(经编码) 密码哈希(内含盐值和成本因子)
哈希算法不是加密算法,不能解密,只能验证数据是否一致。
bcrypt 是一种加盐哈希算法,专门用于密码存储,防止暴力破解。
哈希算法 vs 加密算法
特点 | 哈希算法 | 加密算法 |
---|---|---|
方向 | 单向(不可逆) | 双向(可加密和解密) |
目的 | 验证数据完整性、认证密码等 | 数据保密,信息传输安全 |
典型算法 | SHA-256、MD5、bcrypt | AES、RSA、DES、ChaCha20 |