点击上方 Java后端,选择 设为星标
优质文章,及时送达
作者:小蒋不素小蒋
www.cnblogs.com/xjnotxj/p/12716981.html
最早在大学的时候,只知道用 MD5 来存用户的账号的密码,但其实这非常不安全,而所用到的哈希函数,深入挖掘,也发现并不简单……
一、普通的 Hash 函数
哈希(散列)函数是什么就不赘述了。
1、不推荐
RC4, MD4, MD5, SHA-0, SHA-1, DES, 2DES 等
2、推荐
SHA-2(SHA-256, SHA-384, SHA-512)、SHA-3、Blake2 等
美国国家标准和技术协会(NIST)宣布,2010 年后开始逐步取消 SHA-1 作为安全哈希算法的资格,取而代之的是其更强大的变异算法:SHA-224、SHA-256、SHA-384 和 SHA-512。无论是否遵循 NIST 的标准,至少使用 SHA-256 算法加密密码总是好的。
二、应对普通哈希容易被破解的策略
就像攻与矛的互相增强,哈希函数哪怕用到 SHA-3 以上,都还是有被轻易破解的风险。于是我们有其他额外的办法来解决这个问题。
1、加盐(salt)
加盐就是对目标字段哈希前,拼接上另一个字段(salt)。
注:盐值加到字段之前较为普遍。
加盐对防彩虹表很有效。
注意点:
-
盐不能太短
-
盐不能重复使用(否则一破解,所有的都遭殃)
-
盐随机变化(例如,虽用户名不重复,但用户名不能拿来当盐)
-
盐的本质是将无差别攻击转化为针对性攻击。
1.1、【拓展】针对 salt 的另一种做法 —— HMAC
https://www.cnblogs.com/xjnotxj/p/11934756.html
2、慢哈希
-
2000 年 9 月,建议迭代一千次
-
2015 年 - 2018年,建议迭代一万次
-
2017 年 6 月,建议迭代十万次
三、密码哈希函数(Password Hash)
1、PBKDF2
2、Bcrypt
(1)介绍
(2)使用(Node.js)
npm i bcryptjs
//Sync 方法(Async 方法略):
const bcryptjs = require('bcryptjs');
// 1、生成 安全因子
const salt = bcrypt.genSaltSync(10);
// 2、执行 哈希函数
const password = bcryptjs.hashSync(plainPassword, bcryptjs.genSaltSync(salt));
// 另一种方法:快速执行
const SALT_FACTOR = 10;
const password = bcryptjs.hashSync(plainPassword, bcryptjs.genSaltSync(SALT_FACTOR));
// 3、比较是否相等
bcryptjs.compareSync(plainPassword, password);
3、Scrypt
4、Argon2
(1)介绍
-
哈希算法破解(原值还原、哈希碰撞等);
-
查询表/彩虹表攻击;
-
CPU 优化攻击;
-
GPU、FPGA、ASIC 等专用硬件攻击;
-
旁路攻击;
(2)使用(Node.js)
You can skip this section if the prebuilt binaries work for you.
You MUST have a node-gyp global install before proceeding with install, along with GCC >= 5 / Clang >= 3.3. On Windows, you must compile under Visual Studio 2015 or newer.
node-argon2 works only and is tested against Node >=10.0.0.
---
OSX
To install GCC >= 5 on OSX, use homebrew:
$ brew install gcc
Once you've got GCC installed and ready to run, you then need to install node-gyp, you must do this globally:
$ npm install -g node-gyp
Finally, once node-gyp is installed and ready to go, you can install this library, specifying the GCC or Clang binary to use:
$ CXX=g++-6 npm install argon2
NOTE: If your GCC or Clang binary is named something different than g++-6, you'll need to specify that in the command.
npm i argon2
const argon2 = require('argon2');
(async () => {
try {
// const hash = await argon2.hash("password");
// 更多选项(以下都是默认值)
const hash = await argon2.hash("password", {
type: argon2.argon2i,
hashLength: 32, // 哈希函数输出的字节长度(请注意,生成的哈希是使用Base64编码的,因此长度将增加约1/3)
timeCost : 3, // 时间成本是哈希函数使用的通过次数(迭代次数)
memoryCost: 2 ** 16, // 默认 4096(单位 KB,即 4MB)
parallelism :1, //用于计算哈希值的线程数量。每个线程都有一个具有memoryCost大小的内存池
})
console.log("hash", hash)
const is = await argon2.verify(hash, "password")
console.log("is", is) // true
} catch (err) {
console.error("err", err)
}
})()
(3)参数
-
argon2d 更快且对GPU攻击具有高度抵抗力,这对于加密货币很有用
-
argon2i 速度较慢且可以抵御权衡攻击,因此首选用于密码哈希和密钥派生
-
argon2id 是上述内容的混合组合,可以抵抗GPU和权衡攻击
2、(慢)哈希相关参数
memoryCost
内存开销,它定义了内存的使用情况
parallelism
并行程度,它定义了线程的数量
timeCost
时间开销,它定义了执行的时间
3、其他参数
-
salt:默认值是未设置,将生成加密安全的随机盐。
-
saltLength:默认16。
-
version:您不应更改此设置,因为最新版本更强大。
5、密码哈希是如何解决普通哈希容易被破解的问题
(1)针对 salt
注:盐值本身就在存在于哈希后的字符串中(其实还可能包括版本、慢哈希迭代次数等),当调用跟明文比对的方法时,模块内部会提取出盐值进行验证。
(2)针对 慢哈希
6、结论
四、常见问题
-
你自己实现的再古怪,毕竟你不是密码专家,很难确保不被坏人破解(可能自己实现后看似复杂,实际更容易破解了)。
-
如果自己包含哈希算法的代码泄露,它很脆弱,难保不会被坏人破解。
五、实操
1、password
2、SHA512
3、bcrypt
4、AES256
。同时标星(置顶)本公众号可以第一时间接受到博文推送。
本文分享自微信公众号 - Java后端(web_resource)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
相关文章
暂无评论...