编辑
2025-02-28
技术学习
00
请注意,本文编写于 59 天前,最后修改于 57 天前,其中某些信息可能已经过时。

目录

Bcrypt 加密算法原理
MD5算法
过程
缺陷
不可逆的MD5为什么是不安全的?
Bcrypt算法
Bcrypt 的优势
工作原理
加密流程
验证流程
Golang代码示范
加密(哈希)密码
验证密码

Bcrypt 加密算法原理

Tags: 加密算法, 项目内容

Published: 2024年6月21日

概要: 本页博客概述了 Bcrypt 加密算法,包括其优点以及用于hash和验证密码的 Golang 代码演示。

MD5算法

MD5(Message Digest Algorithm 5)是一种广泛应用的哈希函数,于1991年由罗纳德·李维斯特(Ronald Rivest)设计。它将任意长度的数据输入(通常是字符串)转化为一个128位(16字节)长的哈希值(散列值),也称为消息摘要。这一哈希值通常用32位十六进制数表示。

过程

  1. 填充数据: 在数据末尾进行填充,使数据长度满足长度是512的倍数。这是通过在数据末尾添加一个 "1" 位,后跟若干个 "0" 位,直到数据长度正好满足512比特块的要求。最后添加一个64位的整数,表示填充前的原始数据长度。

  2. 初始化 MD5 缓冲区: 初始化四个32位的缓冲区,分别为A、B、C、D。其初始值是固定的。

  3. 处理每个512位的数据块:

    ◦ 分配64轮变换,每一轮使用一个非线性函数,对当前数据块和缓冲区的值进行处理。

    ◦ 在每一轮中,这些缓冲区值将彼此混合,并与当前处理的512位数据块中的32位子块相加。

  4. 输出: 经过所有数据块的处理后,缓冲区 A、B、C、D 中的值合并起来,形成最终的128位哈希值。

缺陷

虽然 MD5 在设计时是作为一种快速、高效的哈希算法,但是在安全性上有一些缺陷:

  1. 碰撞攻击: 研究表明,攻击者可以在可用的计算时间内找到两个不同的输入,使它们产生相同的哈希值(称为碰撞)。
  2. 不适合密码学应用: 由于碰撞攻击的存在,MD5 已经被认为不适合用于保密性要求很高的任务,比如数字签名和安全认证。
  3. 存在快速碰撞算法: 有研究表明,可以通过特定的算法快速生成使得MD5哈希值相同的两个不同的数据块。

不可逆的MD5为什么是不安全的?

因为hash算法是固定的,所以同一个字符串计算出来的hash串是固定的,所以,可以采用如下的方式进行破解。

  • 暴力枚举法:简单粗暴地枚举出所有原文,并计算出它们的哈希值,看看哪个哈希值和给定的信息摘要一致。
  • 字典法:黑客利用一个巨大的字典,存储尽可能多的原文和对应的哈希值。每次用给定的信息摘要查找字典,即可快速找到碰撞的结果。
  • 彩虹表(rainbow)法:在字典法的基础上改进,以时间换空间。是现在破解哈希常用的办法。

Bcrypt算法

Bcrypt 是专为密码哈希设计的算法,其目的是提供一种更加安全的存储方式来保护用户密码。Bcrypt 是由 Niels Provos 和 David Mazieres 基于 Blowfish 加密算法设计的密码哈希算法,专注于抵抗暴力破解和彩虹表攻击。

Bcrypt 的优势

  1. 可调节的计算强度: Bcrypt 允许设置一个“工作因子”(cost factor),这个因子决定了哈希计算的复杂度。随着计算能力的提升,你可以增加工作因子来增强哈希的安全性。
  2. 盐值(Salt): Bcrypt 自动生成一个盐值,并将其加入到每个密码哈希中,防止预计算攻击(例如,彩虹表攻击)。
  3. 抗击硬件加速攻击: 由于 Bcrypt 的设计和计算复杂性,它可以有效地防止 ASIC 和 GPU 等硬件加速器的大规模并行暴力破解。

工作原理

加密流程

  1. 生成盐值: 为每个密码哈希生成一个独特的盐值。这个盐值通常是 128-bit。
  2. 加入盐值: 将盐值与密码组合起来,以确保相同的密码每次生成的哈希值都是不同的。
  3. 哈希计算: 通过设定的工作因子,通过多轮变换来计算哈希值。每轮的计算都会消耗一定的时间,这在抵御暴力破解时显得尤为重要。
  4. 输出格式: Bcrypt 的输出是以 $ 符号分隔的字符串,包括版本信息、工作因子、盐值和最终的哈希值。

验证流程

  1. 获取存储的哈希密码: 从数据库中获取的哈希密码为 stored_hashed_password

  2. 使用 Bcrypt 的校验函数进行比对:

    ◦ Bcrypt 自动从存储的哈希密码中提取盐值和工作因子。

    ◦ Bcrypt 使用提取的盐值和工作因子,对用户输入的密码进行哈希计算。

    ◦ 将计算出的哈希值与存储的哈希值进行比较。

  3. 返回校验结果: 如果计算出的哈希值与存储的哈希值匹配,则表示密码正确;否则,密码不正确。

Golang代码示范

在 Go 语言中,可以使用 golang.org/x/crypto/bcrypt 包来进行 Bcrypt 密码哈希和验证。

加密(哈希)密码

go
package main import ( "fmt" "golang.org/x/crypto/bcrypt" ) func main() { // 用户输入的密码 password := "my_password" // 哈希密码,使用成本因子 14(可以根据需求调整) hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { fmt.Println("Error hashing password:", err) return } // 输出哈希密码(存储在数据库中) fmt.Println("Hashed Password:", string(hashedPassword)) }

验证密码

go
package main import ( "fmt" "golang.org/x/crypto/bcrypt" ) func main() { // 用户输入的原始密码 password := "my_password" // 从数据库中获取的存储的哈希密码 storedHashedPassword := "$2a$10$.7u0Y17IZEUw3pswrIXISeBgk.EKQdxGvU31H3yMRolDyyl/T4wKG" // 示例哈希密码,需要替换为实际存储的值 // 验证密码 err := bcrypt.CompareHashAndPassword([]byte(storedHashedPassword), []byte(password)) if err != nil { fmt.Println("Password is incorrect.") } else { fmt.Println("Password is correct.") } }

本文作者:AstralDex

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!