〇、简介

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("密码匹配")
}
}

Bcrypt 简介与加密和验证示例【加密知多少系列_8】的更多相关文章

  1. Yii2处理密码加密及验证

    在Yii2中提供了密码加密以及验证的一系列方法,方便我们的使用,它使用的是bcrypt算法.查看源码我们可以发现它使用的是PHP函数password_hash()和crypt()生成. 加密: /** ...

  2. RSA加密传输代码示例

    RSA加密传输代码示例 涉及敏感数据的传输,双方最好约定使用加密解密.那RSA非对称加密就大有作为了.服务端可以保留自己的私钥,发给客户端对应的公钥.这样就可以互相加解密了.php中rsa加解密实现: ...

  3. WCF使用安全证书验证消息加密

    首先安装 服务端安全证书  代码如下:  // 下面第一行是安装证书,第二行是将证书列入信任 makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=lo ...

  4. RSA 签名、验证、加密、解密帮助类

    import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyFactor ...

  5. shiro盐值加密并验证

    在数据表中存的密码不应该是123456,而应该是123456加密之后的字符串,而且还要求这个加密算法是不可逆的,即由加密后的字符串不能反推回来原来的密码,如果能反推回来那这个加密是没有意义的.著名的加 ...

  6. SHA-256 简介及 C# 和 js 实现【加密知多少系列】

    〇.简介 SHA-256 是 SHA-2 下细分出的一种算法.截止目前(2023-03)未出现"碰撞"案例,被视为是绝对安全的加密算法之一. SHA-2(安全散列算法 2:Secu ...

  7. AES Java加密 C#解密 (128-ECB加密模式)

    在项目中遇到这么一个问题: java端需要把一些数据AES加密后传给C#端,找了好多资料,算是解决了,分享一下: import sun.misc.BASE64Decoder; import sun.m ...

  8. Cognos10.2.1配置加密信息不能被加密

    好奇心害死猫,可是我不是猫.这个问题已经不是第一次出现了,之前是从10.1.1到10.2.0出现的,这次是从10.2.0到10.2.1出现的,上次由于时间的问题被搁置了,这次竟然再次遇到同样的问题,已 ...

  9. Shiro-Base64加密解密,Md5加密

    Shiro权限框架中自带的加密方式有Base64加密,MD5加密 在Maven项目的pom.xml中添加shiro的依赖: <dependency> <groupId>org. ...

  10. iOS HmacSHA1加密 和 MD5 Base64加密 --iOS开发系列---项目中成长的知识五

    项目中开发中需要对一些数据进行加密后和服务器验证是否是我们客户端发出的请求! 方案是服务器定的,使用HmacSHA1加密和MD5 Base64加密 加密过程比较复杂 1.获取格林威治时间 2.用bas ...

随机推荐

  1. 基于Python运用PyComCAD进行Autocad二次开发实例汇集

    本文将对运用Pycomcad库(Pycomcad详见,https://github.com/JohnYang1210/PycomCAD)做的一些项目及其效果图进行展示(欢迎各位老铁pull reque ...

  2. 1 MyBatis动态SQL之综述和 if 语句

    摘要:使用 MyBatis 动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach和bind等标签,可组合成非常灵活的SQL语句 ...

  3. LLM 上下文长度详细介绍

    1.概述 在<Token:大语言模型的"语言乐高",一切智能的基石>与<LLM 输出配置 (LLM output configuration)>这两篇博文中 ...

  4. 现在的AI工具还能写剧本杀了?

    本文由 ChatMoney团队出品 近年来,剧本杀作为一种新兴社交游戏,收到了越来越多人的喜爱,它不仅需要玩家们发挥自身演技,还需运用逻辑思维推理,分析所获得的线索,找出案件真凶.然而你是否想过,你在 ...

  5. 我是一名数学专业的应届博士,我该如何选择offer?

    这是IC男奋斗史的第5篇原创 关注公众号[IC男奋斗史],让我们一起撸起袖子加油干! 本文1396字,预计阅读4分钟. 本文来自私信咨询问答.杰哥已征得对方同意把内容展示在公众平台. 感谢对杰哥的信任 ...

  6. Elastic学习之旅 (12) .NET 6应用集成ES - 下

    大家好,我是Edison. 上一篇:.NET集成ES进行CRUD 写在开头 在.NET应用中集成ES一般涉及两个方面: (1)将ES当存储用,类似于MongoDB,做文档的增删查改,这一类操作偏CRU ...

  7. C# HttpWebRequest 请求返回 The remote server returned an error: (400) Bad Request.

    可以看下他的响应Body catch (WebException ex)            {                if (ex.Status == WebExceptionStatus ...

  8. Codeforces Round #674 (Div. 3) ABCD 题解

    A. Floor Number 题意:一开始的数为2,问加多少次x才能加到超过n. 思路:水题,循环一遍就行. view code #include<iostream> #include& ...

  9. 【HDU 1505】 City Game 单调栈

    传送门 HDU-1505 题意:找到矩阵中的最大子矩阵(有些点为障碍物). 思路: 看到网上清一色的dp,我就写一下这个题的单调栈做法.其实这个题和HDU-1506这个题是基本一样的. 1.在1506 ...

  10. python 二维数组取值

    简介 a = np.ones((5,5)) 可以通过 a[1,1] a[1][1] 这两种方式取出数值,本质上是一样的.