1.实例测试
package mainimport ( "fmt" "golang.org/x/crypto/bcrypt"
) func main ( ) { password := [ ] byte ( "mysecretpassword" ) hashedPassword, err := bcrypt. GenerateFromPassword ( password, bcrypt. DefaultCost) if err != nil { fmt. Println ( err) } fmt. Println ( string ( hashedPassword) ) err = bcrypt. CompareHashAndPassword ( hashedPassword, [ ] byte ( "mysecretpassword" ) ) if err != nil { fmt. Println ( "密码错误" ) } else { fmt. Println ( "密码正确" ) }
}
2.代码解读
a.main函数开始解读
1. 生成哈希值:使用 bcrypt. GenerateFromPassword 函数将明文密码转换为哈希值。
2. 打印哈希值:将生成的哈希值打印到控制台。
3. 验证密码:使用 bcrypt. CompareHashAndPassword 函数将生成的哈希值与明文密码进行比对,验证密码是否正确,并输出相应的结果。
b.查看函数 GenerateFromPassword
1. 检查输入的密码长度是否超过 72 字节,如果超过则返回错误 ErrPasswordTooLong。
2. 调用 newFromPassword 函数生成一个哈希对象,如果生成过程中出现错误,则返回该错误。
3. 返回生成的哈希值。
c.查看函数 newFromPassword
1. 检查并设置成本参数 cost,如果 cost 小于最小值 MinCost,则设置为默认值 DefaultCost。
2. 创建一个新的 hashed 结构体实例 p,并初始化其版本信息。
3. 验证 cost 是否有效,如果无效则返回错误。
4. 生成一个随机盐值 salt,并进行Base64编码。
5. 使用 bcrypt 算法对密码进行哈希处理,生成哈希值 hash。
6. 将生成的 salt 和 hash 存储在 p 中,并返回 p。
d.查看函数 Hash
1. 创建一个长度为60 的字节切片 arr。
2. 设置 arr[ 0 ] 为 $,arr[ 1 ] 为 p. major。
3. 如果 p. minor 不为0 ,则设置 arr[ 2 ] 为 p. minor,并将索引 n 增加到3 。
4. 设置 arr[ n] 为 $,并增加 n。
5. 将 p. cost 格式化为两位数字符串,并复制到 arr[ n: ] 中,增加 n。
6. 设置 arr[ n] 为 $,并增加 n。
7. 将 p. salt 复制到 arr[ n: ] 中,增加 n。
8. 将 p. hash 复制到 arr[ n: ] 中,增加 n。
9. 返回 arr 的前 n 个元素。
e.查看函数 CompareHashAndPassword
1. 解析哈希密码:通过 newFromHash 函数解析存储的哈希密码,生成一个包含盐值和成本的结构体。
2. 生成新的哈希值:使用相同的盐值和成本对用户输入的明文密码进行哈希处理,生成新的哈希值。
3. 比较哈希值:使用 subtle. ConstantTimeCompare 函数在常量时间内比较两个哈希值是否相等。
4. 返回结果:如果哈希值相等,返回 nil 表示密码匹配;否则返回 ErrMismatchedHashAndPassword 表示密码不匹配。
f.查看函数 newFromHash
1. 检查哈希长度:首先检查传入的 hashedSecret 长度是否小于最小哈希长度 minHashSize,如果是则返回错误 ErrHashTooShort。
2. 初始化结构体:创建一个新的 hashed 结构体实例 p。
3. 解码版本信息:调用 decodeVersion 方法解码版本信息,并更新 hashedSecret。
4. 解码成本信息:调用 decodeCost 方法解码成本信息,并再次更新 hashedSecret。
5. 提取盐值:从 hashedSecret 中提取盐值并存储在 p. salt 中。
6. 提取哈希值:从剩余的 hashedSecret 中提取哈希值并存储在 p. hash 中。
7. 返回结果:返回初始化好的 hashed 结构体实例。
g.查看函数 bcrypt
1. 初始化密文数据:创建并初始化一个与magicCipherData相同长度的cipherData数组。
2. 设置Blowfish加密:调用expensiveBlowfishSetup函数,根据给定的密码、成本和盐值设置Blowfish加密器。如果设置过程中出现错误,则返回错误。
3. 加密循环:对cipherData的前24 个字节进行多次加密操作,每次加密8 个字节,共执行64 次。
4. 编码结果:将加密后的前23 个字节进行Base64编码,生成最终的哈希值。