从原理上分析,把明文进行 100 轮 [SHA512->SHA256] 这样哈希计算,随机性会比直接 SHA256 更差吗?运算后结果可能性不都是 2^256 种吗?照这么说的话加 salt 也会影响随机性?

111 天前
 drymonfidelia

记得在本站一篇讨论在前端给用户密码加密是不是脱裤子放屁的帖子中有人说把明文变长后 hash 会一定程度上影响随机性,从而导致安全性降低,当时我就很怀疑这种说法,觉得毫无根据,当时没空发帖,现在又想到了这个问题,并且想改成更极端的情况,先更长的 SHA512 再 SHA256 再 SHA512 ,重复 100 轮。

3079 次点击
所在节点    信息安全
33 条回复
rekulas
110 天前
@dzdh 你自己都说了是 hash 了,看下源码就知道任何输入都会映射到固定区间,在数学上不存在输入更复杂就更安全的情况


所以“任意字符输入的组合的 hash 结果” 跟 hash 的结果再次 hash 仅从概率上是一样安全的
edward1987
110 天前
@rekulas #21 应该是有影响随机性的。比如先 hash 成 256 个字符的 A ,A 再 hash 成 512 字符的 B , 这时候 B 最多只有 16^256 种结果,但是如果是不限制输入,B 有 16^512 种结果
rekulas
110 天前
@edward1987 come on, 你这个推理有点钻牛角尖了,我说的“ hash 的结果再次 hash”当然是指同一个 hash 算法,包括输入应该是同样范围的

你这个我再翻译下,相当于把任何输入映射为 0-9 的数字,再对这个数字进行 hash ,那 hash 结果当然只有 9 种

如果你第二次 hash 的算法也是同一种,那数学安全性是没有区别的
rekulas
110 天前
@rekulas 抱歉是 10 种
edward1987
110 天前
@rekulas 如果是相同算法,那我赞成你说的。我是看楼主的提问里面确实是用不同 hash 算法 [并且想改成更极端的情况,先更长的 SHA512 再 SHA256 再 SHA512 ,重复 100 轮]
rekulas
110 天前
@edward1987 好吧,那确实是的,我只是针对上面的评论回复,不是针对 op 的 hash 算法变化的情况
ryan4yin
110 天前
本质上仍旧是成本跟安全的平衡,客户端弄个 Hash 就加几行代码的事,就能提升整条链路的安全性,何乐而不为呢?我不明白这事有什么可争的。
ryan4yin
110 天前
#4

「前端加密是形式主义安全的要求,前端加密完全阻止不了被劫持或者被恶意浏览器插件直接注入 js 读取输入框里的明文密码。」

没有什么技术能解决所有问题啊,你不能因为一项技术没解决掉个别问题,就认为它完全是形式主义。
类似深信服之类的技术在你电脑里装它的证书从而监控你所有 HTTPS 流量的明文内容,而前端加密至少能保证你的明文密码不会泄漏给公司。
上面也有 v2 友提了,明文密码泄漏要比 Hash 泄漏严重得多,用户其他站点也可能因为你们前端没做 Hash ,被黑客一举攻破。

另外一点是,HTTPS 并不总是安全的,不要总觉得用了 HTTPS 就多安全,TLS 从 SSL1.0 迭代到现在 TLS1.3 ,一堆的弱密码,实际安全性还是得看客户端与服务端的两边的具体配置。

对 OP 引用的前一个帖子一些观点的反驳:

1. https + 后端加密入库足够安全:这得看具体的流量链路架构,单纯从你前后端看可能感觉都很安全,但中间是否过了 CDN 加速?是否做了 TLS 的边缘端及早截止( https://0xffff.one/d/968 )?即使你做这个决定时系统是够安全的,但 infra 团队不一定知道啊,他们对中间这些链路做的任何变更都可能会破坏你的安全假设。所以为了避免沟通成本,强制前端做 Hash 是很合理的选择。
2. 增加开发成本,没必要:前端对密码做个 Hash 就几行代码的事,调用个现成的库就行,这个东西很复杂吗???要增加多少开发成本???
3. 加密后导致密码强度的下降(因为密文的信息熵下降了):所有 ASCII 字符数字符号加一起是 94 个,简单计算你的密码需要至少 40 个字符,它的排列数量才能超过 2^256 钟,我还从来没见过谁的密码有这么复杂...


如果你是在什么无所谓安全的小公司工作,公司也没啥要求,那你确实怎么折腾都无所谓,不用管什么哪里加密,想怎么写就怎么写,功能实现了就 OK. 但我个人还是建议养成一点技术上的品味。
yianing
110 天前
会减小随机性,摘要是多对少的,你用少的结果再去摘要,值域只会更少
zizon
110 天前
f_1(f_2(f_3....f_n(input))) 等价于存在一个 g(input)
g 的离散性直觉上取决于 f chain 中的离散性分布.

直观的例子就是传统机器学习所谓收敛 local minimal 的概念.

比如如果你其中一个或者几个 f 在空间分布式存在某种形式的倾斜,那么逻辑上就是多余某个 f_k 的输出存在一定的偏向性.

极端情况累积下,可能存在你的 f chain 的等价形式 g 就是一个常数.
skallz
110 天前
@drymonfidelia 我猜前端加密应该是避免中间人攻击?之前做金融行业的网站的时候,前端就会对密码采用动态加密以防止中间人攻击,为什么这么做?因为真的有人被攻击了。。。
restkhz
110 天前
@ryan4yin 我认为你说的有道理。这种场景这么做是有意义的。送一个感谢。

摸个大鱼,写个长文。
很多人都在说:
”多次迭代 hash 很多人都在说第二次输入范围变小“。我就不一一 at 了。

@YGHMXFAL 关于多次迭代的问题我先说,多算法嵌套的问题我下文说。
我们来做一个脑内实验:
如果我们用同一个 hash 算法,进行几乎[无穷]多次迭代,那么一定会在某一次碰撞,对吧?毕竟 hash 值域空间有限。

而且,根据鸽巢原理,随着迭代次数增加,和之前迭代过程中 hash 碰撞概率也随之增加。比如迭代了 1 亿次,
这个碰撞来临的可能比我们预想的快(生日悖论)。

我们这样写:a 经过 hash 成为 b ,b 再 hash 成 c ,我们在这里写成 a->b->c

a->b->c->d->e->f->g

到此为止,一切都好。但是在下一时刻,g 经过 hash 后发生了碰撞成了[e]
于是最后这个 hash 就成了

a->b->c->d-> e->f->g-> e->f->g-> e->f->g-> e->f->g......

你会发现这个 hash 碰撞后会不可避免地陷入了一个循环。
最后结果就在 efg 这三个结果之间,实际上的值域变小。此后再多迭代次数也没有意义。我只要知道这个环里的元素 efg ,知道迭代次数,我们就可以推算出具体哪个元素可以构成碰撞。

比如上面就是 hash(a)*8=f, 我们不知道 a, 但是我们可以 8mod3=2 ,hash(g)*8=f=hash(a)*8 这样构造出碰撞。

然而对于一个健壮的 hash 算法来说出现上述情况很难,或者说你只迭代一千次一万次完全没问题。甚至就算有碰撞,这个环也可能大到难以探测。


再说组合不同算法:
假设一个不安全 hash 叫做 weak, 只输出 1 位。不是 0 就是 1.碰撞概率五五开。
你 sha-512 然后 weak ,会怎么样?碰撞概率依旧五五开。组合 hash 算法安全性取决于最差的那个 hash 。调换顺序也没用。

@gbadge 不可以替代 salt 。多次迭代会增加算力消耗没错。salt 让彩虹表无法复用,而且在空间和计算上都制造难度。
@jim9606 长度扩展攻击...可能不会让破解变得容易。至少我不知道。因为长度扩展攻击可以在我只知道 MD5(pwd)和 salt 的情况下算出 MD5(pwd+salt)但是我的确不知道怎么算 pwd 或者 MD5(pwd)...不管怎样,反正 MD5 ,SHA-1 的确就别再用了。

其他人懒得一个个回复了。

最后好好回复给 OP:
理论上:OP 的做法意义不大。虽然应该不会更不”随机“,但是安全性取决于最差的那个算法。而且只要有一个算法有问题那整个都变弱。迭代是有意义的,代价就是可以忽略的碰撞概率增加。

实际上:OP 的做法很有意义。黑客喜欢用现成的服务比如 hash 查询。黑客看到你这种骚操作很可能骂娘后直接放弃。但是弱密码依旧有可能被破解。
把黑客恶心死,也是一种安全。

多次迭代拖慢暴力,奇葩嵌套无法查询,加盐对抗彩虹表,密码策略防止弱密码对抗字典。

(所以...为什么不用 bcrypt 这些呢?)
yukunyi
93 天前
主要是防彩虹表

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1070316

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX