其他

加密算法bcrypt的使用

背景


在用户模块,对于用户密码的保护,通常都会进行加密。我们通常对密码进行加密,然后存放在数据库中,在用户进行登录的时候,将其输入的密码进行加密然后与数据库中存放的密文进行比较,以验证用户密码是否正确。 目前,MD5和BCrypt比较流行。相对来说,BCrypt比MD5更安全。因为其内部引入的加盐机制
bcrypt是一种加盐的加密方法,每次加密的时候会先生成一个随机数,之后将这个随机数与密码进行hash,形成密文。

BCrypt 官网http://www.mindrot.org/projects/jBCrypt/

bcrypt hash 字符串结构


一个 bcrypt hash 字符串应该像下面这样(摘自 Wikipedia):


举个栗子:

2a: 算法的标识符,代表是 bcrypt 的版本,有 2a、2y、2b 三个版本。

10: 成本因子:代表轮询加密 2^10 = 1024 次。

N9qo8uLOickgx2ZMRZoMye: 16-byte (128-bit) 的 salt, 用 Radix-64 编码成为 22 个字符。

IjZAgcfl7p92ldGxad68LJZdL17lhWy: 24-byte (192-bit) 的 hash, 用 Radix-64 编码成为 31 个字符。

特点


bcrypt 有三个特点:

– 每一次 Hash 出来的值不一样。
– 计算非常缓慢。
– 每次的 salt 是随机的生成的,不用担心 salt 会泄露。

 bcrypt 对同一个密码每次加密时使用的 salt 是不一样的, 因此每次生成的 Hash 也是不一样的,但是 Hash 中包含了 salt,在下次校验时,从 Hash 中取出 salt,salt 跟password 进行 Hash 得到密文。密文和保存在 DB 中的 Hash 是同样的原文和 salt 加密出来的,所以必定是相同的字符串。bcrypt 算法将 salt 随机并混入最终加密后的密码,验证时也无需单独提供之前的 salt。

bcrypt与MD5的区别


MD5加密算法同一个密码加密后的密文是一样的,这样很容易被破解;bcrypt加密算法同一个密码加密之后的密文是不一样的,相对来说更加安全一些。

bcrypt使用(nodejs)


// 导入bcrypt
const bcrypt = require('bcrypt')
async function run() {
    // 生成随机字符串
    // genSalt方法接收一个数值作为参数 数值越大 生成的随机字符串复杂度越高 数值越小 复杂度越低
    // 默认值是10 
    // 返回生成的随机字符串
    const salt = await bcrypt.genSalt(10)
    console.log(salt);

    // 对密码进行加密
    // 第一个参数是:要进行加密的明文
    // 第二个参数是:随机字符串
    // 返回值是加密后的密码
    const result = await bcrypt.hash('123456', salt)   
    console.log(result);
}

第一次输出结果:

$2b$10$dNjP0okhVYb5EiGG2TWBuu
$2b$10$dNjP0okhVYb5EiGG2TWBuu3HrYxrgG7sPOuxZeBsx7rcUHwBFz.zW

第二次输出结果:

$2b$10$8E6E3OFbZ0JCz7inZ2TZ7u
$2b$10$8E6E3OFbZ0JCz7inZ2TZ7uZ21NDmyU.VeRfh/fJKrRIr55vE2qXLe

可以看出,同样的明文经过加密后的生成的密文是不一样的,在一定程度上增加了安全性。

密码的比对

// 将客户端传过来的密码和数据库中的密码比较 true 比对成功 false 比对失败
// password 明文密码  user.password 加密密码(数据库中的密码)
let isValid = await bcrypt.compare(password, user.password)