很久以前看到一篇文章,讲某个大网站储存用户口令时,会经过十分复杂的处理。怎么个复杂不记得了,大概就是将口令先 Hash,结果加上一些特殊字符再 Hash,然后中间插入些字符再 Hash、再怎么怎么的。。。看的眼花缭乱。

当时心想这么复杂应该很安全了吧。事实上即使现在,仍有不少人是这么认为的。所以在储存账号口令时,经常会弄些千奇百怪的组合。

不过,千奇百怪的 Hash 算法究竟有意义吗?在什么情况下能派上用场?是否有更简单合理的替代方案?这问题先从拖库说起。

知道算法才能破解

数据库中的口令,都是以 Hash 形式储存的。拖下数据库后,如果要猜某个账号的明文口令,得通过跑字典的方式:

for each word in 常用词汇
if H(word) == E
print "明文:",word
exit

不过,光有泄露的数据 E 不够,还得知道算法 H 才能跑的起来。光有 Hash 值,却不知道用的是那种 Hash 算法,仍然无从下手。

当然很多小网站,数据库和算法在同个系统里,一旦入侵两者都泄露了;但若数据库和算法不在同个系统里,即使能拖库也未必知道算法。

猜算法

不过即使搞不到算法,也可以尝试猜测。比如先在网站上注册个账号 —— 例如口令为 123456,然后在泄露的库中,根据用户名找到对应口令的 Hash 值,例如 dd6e5e5918e94d997c686fcebc56922f。

这时,就可以暴力猜算法了:

for each fn in 常用算法
if fn("123456") == dd6e5e5918e94d997c686fcebc56922f
print "算法:", fn
exit

不难猜出,fn 为 f(x) = md5(sha256(x))。知道了算法,就可愉快的跑字典了。

奇怪算法

这时「奇怪算法」的优势就体现出来了。 如果使用的算法十分奇葩,比如:

f(x) = md5("hello~" + sha1(sha256(x)) + "world!")

根本不在常用算法里,几乎难以穷举到,于是就能躲过「猜算法」这种攻击方式。

所以,奇怪的算法是有意义的!

不过奇怪、奇葩、变态...这些都是人的主观感觉,并不能用理性来衡量。比如说刚才那个算法有多复杂?你只能说很复杂,而难以给出一个准确的程度。

算法简单,数据复杂

通过混合拼凑多个函数,来制造复杂程度,终究不是最合适的。

不妨把复杂转移到数据上,例如上述的 "hello~" 和 "world!",如果换成更长、更没意义、更难猜测的数据,不也能制造复杂吗?

所以,最终可以把函数精简到只剩一个,取而代之的是复杂的数据,例如:

f(x) = sha256(x + "18bc0a594ab5f65d868820b238b696e391eabb962e1d15c2c474a04735c1128f")

这串数据称之为密钥。密钥是随机生成的,没有任何意义,并且绝不能对外透露。

这样,复杂程度就能在密钥空间上体现出来,而不是难以衡量的奇怪函数组合


不过这里有个疑惑,为什么「密钥」加在原文后面,而不是前面、或者夹在中间?如果仅仅是看着舒服,那还是存在主观因素的。

HMAC

事实上,密码学家早已提供支持两个参数的 Hash 用法 —— HMAC,它比简单粗暴的拼接靠谱得多。于是上述可改进成:

f(x) = hmac_sha256(x, "18bc0a594ab5f65d868820b238b696e391eabb962e1d15c2c474a04735c1128f")

HMAC 第二个参数本身就是 Key 的意思,所以用在这里恰到好处。

当然,如果不保护好算法以至于很容易泄露,那么无论用奇怪组合还是这种方式,也都无济于事。

保护算法

很多人对算法保护的并不好,甚至直接写在了诸如 PHP 脚本里,只要有文件读取权限,就能搞到算法。

如果稍加隐蔽,例如通过本地服务,并控制好可执行程序的权限,或许就更难找到了。

更进一步,可以单独部署一台服务器,专门提供 HMAC 计算。通信接口足够简单,简单到几乎不可能出漏洞;并且不开放其他任何服务,只能人工管理。这样,被入侵的可能性就更小了。

当然,管理员人为泄密也是有可能的。如果要有一个终极方案,或许应该将计算交给一个独立的硬件。这个硬件是个黑盒设备,输入明文、输出 Hash 结果。算法、密钥这些都隐藏在其内部,拆开即自毁,这样管理员也无从知晓。例如 HSM(hardware security module)设备,就能将算法以及密钥进行物理隔离。

  password  |-------------------------|
----------->| 黑盒设备 |
| KEY = ***************** |
<-----------| hmac_sha(password, KEY) |
hash |-------------------------|

其他策略

如果算法能保证 100% 不泄露,那么加盐、慢 Hash 这些都可以省略了,因为密钥本身就足以对抗暴力破解。

当然现实中没有绝对的事。如果算法真的泄露了,现有数据的风险就大幅增加。所以本该有的策略还是得有,不能把风险全押在一个点上。

所以加盐、慢 hash 这些仍然是需要的。最终方案应该类似这样:

# 业务逻辑
hash = pbkdf(password, salt, cost...)

######## 隐蔽的黑盒系统 ########
hash = hmac(hash, KEY)
##############################

# 返回业务

这样即使黑盒算法遭到泄露,破解仍然需要很大成本。

破解成本

不过,奇怪算法也有一个优势,那就是破解软件支持程度不高。

传统的权威算法,早已成为众矢之的,有各种高度优化的破解方案,因此破解速度会非常快;而奇怪算法,则不在优化范围中,因此速度会慢的多。

所以,在权威算法之后,可以考虑再混合少量奇怪算法。这样,就能再增加一层破解障碍。

总结

  • 奇怪算法是有意义的,但效果难以衡量

  • HMAC 的密钥需要足够长、足够随机、足够保密

  • 保护好算法,和保护数据库同样重要

复杂的 Hash 函数组合有意义吗?的更多相关文章

  1. Hash 函数及其重要性

    不时会爆出网站的服务器和数据库被盗取,考虑到这点,就要确保用户一些敏感数据(例如密码)的安全性.今天,我们要学的是 hash 背后的基础知识,以及如何用它来保护你的 web 应用的密码. 申明 密码学 ...

  2. Scalaz(14)- Monad:函数组合-Kleisli to Reader

    Monad Reader就是一种函数的组合.在scalaz里函数(function)本身就是Monad,自然也就是Functor和applicative.我们可以用Monadic方法进行函数组合: i ...

  3. 各种字符串Hash函数比较(转)

    常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...

  4. 理解php Hash函数,增强密码安全

    1.声明 密码学是一个复杂的话题,我也不是这方面的专家.许多高校和研究机构在这方面都有长期的研究.在这篇文章里,我希望尽量使用简单易懂的方式向你展示一种安全存储Web程序密码的方法. 2.“Hash” ...

  5. [转]各种字符串Hash函数比较

    转自:https://www.byvoid.com/zht/blog/string-hash-compare 常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些 ...

  6. 【转】各种字符串Hash函数比较

    常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...

  7. [T]各种字符串Hash函数比较

    常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...

  8. 各种字符串Hash函数比较

    常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎 ...

  9. 密码学Hash函数

    定义: Hash函数H将可变长度的数据块M作为输入,产生固定长度的Hash值h = H(M). 称M是h的原像.因为H是多对一的映射,所以对于任意给定的Hash值h,对应有多个原像.如果满足x≠y且H ...

随机推荐

  1. Recurrent Neural Network系列1--RNN(循环神经网络)概述

    作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 本文翻译自 RECURRENT NEURAL NETWORKS T ...

  2. UWP中实现自定义标题栏

    UWP中实现自定义标题栏 0x00 起因 在UWP开发中,有时候我们希望实现自定义标题栏,例如在标题栏中加入搜索框.按钮之类的控件.搜了下资料居然在一个日文网站找到了一篇介绍这个主题的文章: http ...

  3. 很多人很想知道怎么扫一扫二维码就能打开网站,就能添加联系人,就能链接wifi,今天说下这些格式,明天做个demo

    有些功能部分手机不能使用,网站,通讯录,wifi基本上每个手机都可以使用. 在看之前你可以扫一扫下面几个二维码先看看效果: 1.二维码生成 网址 (URL) 包含网址的 二维码生成 是大家平时最常接触 ...

  4. 隐马尔科夫模型python实现简单拼音输入法

    在网上看到一篇关于隐马尔科夫模型的介绍,觉得简直不能再神奇,又在网上找到大神的一篇关于如何用隐马尔可夫模型实现中文拼音输入的博客,无奈大神没给可以运行的代码,只能纯手动网上找到了结巴分词的词库,根据此 ...

  5. SELECT INTO 和 INSERT INTO SELECT 两种表复制语句

    Insert是T-sql中常用语句,Insert INTO table(field1,field2,...) values(value1,value2,...)这种形式的在应用程序开发中必不可少.但我 ...

  6. CRL快速开发框架系列教程三(更新数据)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  7. CSS 3 学习——transform 3D转换渲染

    以下内容根据官方规范翻译,没有翻译关于SVG变换的内容和关于矩阵计算的内容. 一般情况下,元素在一个无景深无立体感的平面(flat plane)上渲染,这个平面就是其包含块所处的平面.同时,页面上的其 ...

  8. 使用CocosSharp制作一个游戏 - CocosSharp中文教程

    注:本教程翻译自官方<Walkthrough - Building a game with CocosSharp>,官方教程有很多地方说的不够详细,或者代码不全,导致无法继续,本人在看了G ...

  9. 我的MYSQL学习心得(二) 数据类型宽度

    我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  10. ABP(现代ASP.NET样板开发框架)系列之16、ABP应用层——数据传输对象(DTOs)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之16.ABP应用层——数据传输对象(DTOs) ABP是“ASP.NET Boilerplate Project ...