Bcrypt 简介与加密和验证示例【加密知多少系列_8】

〇、简介

Bcrypt 是一种基于 Blowfish 加密算法的单向哈希函数,专为密码存储设计 。它通过**随机盐值(salt)和可调节的工作因子(cost factor)**实现高安全性,是目前主流的密码哈希算法之一。

核心原理:

  • 随机盐值(Salt) :每次加密时生成一个随机盐值(16 字节),与密码混合后生成哈希值 。确保相同密码生成不同哈希值,防止彩虹表攻击(Rainbow Table Attack)
  • 可调节的工作因子(Cost Factor) :通过调整工作因子(log2:迭代次数),控制哈希计算的复杂度。范围通常为 4~31(默认 10),值越大,计算时间越长 ,安全性越高。计算公式:迭代次数 = 2^cost(例如 cost=12 表示 4096 次迭代)。增加了暴力破解的时间成本,适应硬件性能提升。
  • 基于 Blowfish 的密钥扩展:大概流程,首先将密码和盐值组合,生成 EksBlowfish 密钥(Expensive Key Schedule)。对固定字符串 "OrpheanBeholderScryDoubt" 进行多次 Blowfish 加密(根据工作因子决定迭代次数)。最终生成哈希值(60 字符的固定格式字符串)。

工作因子配置和计算耗时的大概规律:(注:基于博主当前机器的性能,仅供参考!)

|----------------|----------|
| workFactor | 计算用时 |
| 8 | 16ms |
| 10(默认值,推荐) | 55ms |
| 12 | 210ms |
| 14 | 840ms |
| 16 | 3000ms+ |

复制代码
// 密文的格式:
$2b$<cost>$<salt><hash>
// 示例:
$2b$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
// 各个部分的含义:
// $2b$:版本标识(2b 表示当前标准版本)。
// 10:工作因子(2^10 = 1024 次迭代)。
// N9qo8uLOickgx2ZMRZoMye:盐值(22 字符,Base64 编码)。
// IjZAgcfl7p92ldGxad68LJZdL17lhWy:哈希结果(31 字符)。

安全性:

抗彩虹表攻击。 每次加密使用随机盐值,相同密码生成不同哈希值。彩虹表(预计算的哈希值表)无法直接匹配,需逐个尝试破解。
抗暴力破解。 工作因子控制计算时间(默认约 0.3 秒/次)。即使使用 GPU 并行计算,暴力破解成本极高(例如:cost=12 时,破解百万级密码需数年)。
**自适应性。**随着硬件性能提升,可动态增加工作因子(如从 10 调整为 12),保持安全性。

与传统哈希算法的对比:

特性 Bcrypt MD5/SHA 系列
抗彩虹表攻击 强(通过盐值和多次迭代) 弱(容易受彩虹表攻击)
计算速度 慢(故意设计为"慢哈希") 快(适合文件校验,但不适合密码)
工作因子 支持(可调) 不支持
不可逆性 是(单向哈希) 是(单向哈希)
适用场景 密码存储 文件校验、数字签名(不推荐密码)

主要应用场景:

  • **用户密码存储:**注册和登录时加密密码,防止数据库泄露后密码被窃取。
  • **企业级安全框架:**Spring Security 推荐使用 BCryptPasswordEncoder,默认支持 Bcrypt。
  • **数据保护:**对敏感信息(如 API 密钥)进行哈希处理,确保即使数据泄露也无法直接获取明文。

一、C# 语言实现

先安装依赖:Install-Package BCrypt.Net-Next

复制代码
using BCrypt.Net;
try
{
    string password = "MySecurePassword123";
    int workFactor = 16; // 默认值 10,取值范围 4~31
    // 加密
    string hashedPassword = BCrypt.Net.BCrypt.EnhancedHashPassword(password, workFactor);
    Console.WriteLine("Hashed Password:" + hashedPassword);
    // $2a$10$n3WUdgGrTSVEZ1L3pTxkweeHXqUaWEXwvBI.gOnkTO17eL/ZqhBaG

    // 验证
    bool isMatch = BCrypt.Net.BCrypt.EnhancedVerify(password, hashedPassword);
    Console.WriteLine("Password Match:" + (isMatch ? "匹配" : "不匹配"));
}
catch (Exception ex)
{
    Console.WriteLine("验证失败: " + ex.Message);
}
//Hashed Password:$2a$12$h8EnoQF6QYZDtbrCSGuDxeKjMt.Y0dcnWjFrz4sgEyhXlt.5VQs7G
//Password Match:匹配

二、js 语言实现

引用第三方库 bcryptjs 实现加密和验证。安装命令:

复制代码
npm install bcryptjs

加密和验证的简单示例代码:

复制代码
const bcrypt = require('bcryptjs');
try {
	// 要加密的密码
	const password = 'MySecurePassword123';
	// 工作因子(cost factor):控制哈希复杂度,推荐值 10
	const saltRounds = 10;
	// 【加密】生成盐并哈希密码(异步)
	const hashedPassword = await bcrypt.hash(password, saltRounds)
	console.log('Hashed Password:', hashedPassword);

	// 【解密】
	const bcrypt = require('bcryptjs');
	// 用户输入的密码
	const inputPassword = 'MySecurePassword123';
	// 数据库中存储的哈希值
	const storedHashedPassword = '$2a$12$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy';
	// 验证密码是否匹配
	const isMatch = await bcrypt.compare(inputPassword, storedHashedPassword);
}
catch (error) {
	console.error('Error:', error);
}

三、go 语言实现

在 Go 语言中使用 Bcrypt 进行密码哈希和验证,通常依赖官方推荐的第三方库 golang.org/x/crypto/bcrypt。该库提供了安全、高效的 Bcrypt 实现,适合用于密码存储和验证场景。

复制代码
// 安装
go get golang.org/x/crypto/bcrypt

加密和验证简单示例:

复制代码
package main

import (
    "fmt"
    "golang.org/x/crypto/bcrypt"
)

func main() {
    // 明文密码
    password := "MySecurePassword123"
    // 【生成】哈希密码(使用默认工作因子)
    hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	// hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), 12) // 自定义工作因子
    if err != nil {
        panic("生成哈希失败: " + err.Error())
    }
    fmt.Println("Hashed Password:", string(hashedPassword))

    // 【验证】密码是否匹配
    err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
    if err != nil {
        fmt.Println("密码不匹配:", err)
    } else {
        fmt.Println("密码匹配")
    }
}
相关推荐
小青年4695 分钟前
springboot3 vue3校园失物招领系统实战开发教程
后端
天天摸鱼的java工程师8 分钟前
如何实现一个分布式锁?——来自 Java 老兵的实战总结 🚀🔐
java·后端·面试
_杨瀚博15 分钟前
MAVEN构建分离依赖JAR
后端
zero_face19 分钟前
记录一次Spring5中事件通知机制bug引起的生产事故
后端·spring·debug
37手游后端团队42 分钟前
AI生成回流文案在《凡人修仙传:人界篇》应用
人工智能·后端·云原生
用户3074596982071 小时前
PHP 自动加载机制详解
后端·php
Java水解1 小时前
SpringDoc 基本使用指南
后端·spring
zero_face1 小时前
elk原理简述 - filebeat
大数据·后端
big_eleven1 小时前
JVM入门基础
java·后端·面试
用户9096783069431 小时前
python 统计一个字符串中某个字符的出现次数
后端