前言
今天n8n密码忘记了,疯狂去找n8n的用户表。
【虽然后面发现官方提供了一个更简单的重置用户账户的方式,但是我当时不知道】
邮箱、密码在SQLite数据库中找到了,但是是被哈希的状态
一顿操作,得知n8n的账户密码是用Bcrypt进行10轮的哈希进行处理的,并且有随机加盐防止彩虹表攻击
这些东西之前有通过文章零零散散地进行积累
比如:
正好在这个地方,借用了解【Bcrypt哈希算法】的机会,再复习总结下相关的知识
正文
一、Bcrypt哈希算法初印象
- 专门为密码哈希而设计的算法
- Niels Provos 和 David Mazières 在 1999 年基于 Blowfish 密码设计
- 内置盐值(Salt),所以同一个密码经过加密,结果不一定相同,免得坏人拿着生成好的原值和哈希后的值去一个个比对从而窃取内容
- 自适应成本因子(Work Factor),一些地方也叫做Round。我一般习惯叫做"处理轮次"
二、关于彩虹表(Rainbow Table)
是一种预先计算(Precomputed) 的用于破解哈希密码的数据表
上面也有提到了,假设我现在知道了你用一种哈希算法,且这个算法没有加盐。
我就去提前生成一个表,如:
text
12345:wsdnf
11111:oweh
然后我拿着这个表去数据库看,如果真被我找到了个wsdnf
,那我就知道你的密码是12345
怎么办?????
加盐就完事了
三、关于加盐(Salt)
随机加盐(Salt) 【盐值】是一段随机生成的数据,在哈希之前与密码拼接在一起。
因为你的Salt是随机的
如果我的密码是 12345
没加盐进行哈希的话结果就是
wsdnf
但是不好意思,我加了随机盐值了,那么密码可能就变成
i_am_salt_12345
了
那再进行哈希,结果早就不知道编程啥样了。
这个时候,如果有一个坏人拿着表去一个个找,即使找到了一个他彩虹表里的映射,那也只是加盐之后进行哈希的值,真正的密码他也推算不出来,因为就连盐值也是随机的。
这个时候你可能要问了
既然盐值是随机的
那么我的12345
这个密码加密两次,这两次的盐值都不一样,最后生成的哈希值也不一样,那还怎么通过校验?
莫慌,系统在验证的时候,自然会使用对应的那个盐值进行验证的操作!
当系统为你的密码 12345
进行哈希的时候,它做了以下三件事:
- 生成一个随机盐值 (例如,生成了
salt_A
)。 - 将盐值和密码组合 :得到
salt_A + "12345"
。 - 将组合后的字符串进行哈希计算 :使用 Bcrypt 算法计算
Bcrypt(salt_A + "12345")
,得到最终的哈希值hash_A
。
最关键的一步来了:
系统不会只存储 hash_A
。它会将算法版本、成本因子、随机生成的盐值 salt_A
和最终的哈希值 hash_A
打包成一个字符串,然后存入数据库的用户表里。
这个字符串看起来就像这样(这是一个模拟例子):
$2b$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
在这个字符串里,nOUIs5kJ7naTuTFkBy1veu
就是盐值 salt_A
。
解释这个多,只想说明,我们不用担心"无法验证"的问题,大胆地去用这个算法就OK!
四、再来说说易错点:加密与哈希
哈希(Hashing)和加密(Encryption)是完全不同的两个概念,但经常被混淆。包括我有的时候说着说着,就把哈希算法说成加密算法了。
首先哈希(Hashing)是单向的"指纹"生成器,目的是验证数据完整性(如校验文件)或密码是否正确,其过程【不可逆】,无法从哈希值恢复原数据。
加密(Encryption)是双向的"加锁"机制,目的是保密,确保只有持有密钥者能读取原内容,其过程可逆,必须用密钥解密。
切记:哈希值不能"解密",而密文可以。
五、常见的哈希算法与加密算法
常见哈希算法 中,MD5 和SHA-1 已不安全且遭淘汰;SHA-256 是当前主流的数据完整性校验算法;存储密码必须用慢哈希函数,如 Bcrypt 或 Argon2。
常见加密算法 分为两类:对称加密 (加解密同key)如速度飞快的 AES ;非对称加密 (公钥加密私钥解密)如最通用的 RSA 和更现代的 ECC。这个我之前写过文章,感兴趣的伙伴可以去康康:
对称加密?非对称加密?混合加密?什么是对称加密 对称加密也叫做共享密钥加密。 A和B要一起进行通信。他们手里分别都有一个 - 掘金
最后
最后提醒大家,密码一定要记好!!
虽然我也有记密码到记事本,但是后面我发现记事本里密码的大小写写错了,导致试了半天也试不出来,这才有了文章开头的一幕,可恶啊💢