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("密码匹配")
    }
}
相关推荐
间彧17 小时前
Kubernetes的Pod与Docker Compose中的服务在概念上有何异同?
后端
间彧17 小时前
从开发到生产,如何将Docker Compose项目平滑迁移到Kubernetes?
后端
间彧17 小时前
如何结合CI/CD流水线自动选择正确的Docker Compose配置?
后端
间彧17 小时前
在多环境(开发、测试、生产)下,如何管理不同的Docker Compose配置?
后端
间彧17 小时前
如何为Docker Compose中的服务配置健康检查,确保服务真正可用?
后端
间彧17 小时前
Docker Compose和Kubernetes在编排服务时有哪些核心区别?
后端
间彧17 小时前
如何在实际项目中集成Arthas Tunnel Server实现Kubernetes集群的远程诊断?
后端
brzhang18 小时前
读懂 MiniMax Agent 的设计逻辑,然后我复刻了一个MiniMax Agent
前端·后端·架构
草明19 小时前
Go 的 IO 多路复用
开发语言·后端·golang
蓝-萧19 小时前
Plugin ‘mysql_native_password‘ is not loaded`
java·后端