mysql能否一句sql验证加盐的密码?
table
uid username password salt
1 admin ce7ba70a8a7bdf9b6cc10beeff2b3e03 qwe123
正常流程需要三步
表单提交的用户名$username和 密码$psw
步骤1先查出盐$salt
select salt from table where username = '$username'
步骤2然后加密
$password = md5($psw.$salt);
步骤3最后再查是否有符合条件的数据
select * from table where username='' and password='$password'
有结果就说明密码正确
没结果就说明密码错误或者没这个用户名的账号
请问以上三步能否用mysql的子查询或者什么高级方法一句话就能验证结果呢?
谢谢
1
liprais 2015-05-27 09:43:54 +08:00
$password = md5($psw.$salt);
这一步做成udf |
2
TangMonk 2015-05-27 09:44:45 +08:00
可以加味精吗
|
3
yangqi 2015-05-27 09:45:09 +08:00
select md5(concat(password, salt)) from table
|
4
wy315700 2015-05-27 09:45:27 +08:00
1 根据 username查出记录
2 读取salt 3 加密 4 判断password是否一致 只需要一次读取啊。 你的步骤3完全没必要啊 |
5
warlock 2015-05-27 09:48:16 +08:00
mysql 提供了 md5 和 字符串连接的方法,不过你为什么要放到数据库去做呢,这不是给数据库施压么。。。。。
|
6
ven 2015-05-27 09:55:02 +08:00
好奇问一下,salt直接存在数据库,安全么?
|
7
BuilderQiu 2015-05-27 09:56:29 +08:00
一般都是内存处理吧,同 @wy315700 那样,
我只是一直在想,SALT在库里,脱裤了之后还不是一顿暴力破... |
8
coosir 2015-05-27 09:59:19 +08:00 1
select count(*) from table where username='$username' and password=md5(concat('$username',salt))
|
9
wy315700 2015-05-27 10:02:26 +08:00 3
@BuilderQiu
@ven salt的作用在于阻止 一次多密,防止直接通过彩虹表进行爆破,但是阻止不了暴力破解。 不同的用户 如果使用相同的密码,但是salt不一样了,hash的结果是不一样的。 所以有了salt以后,对每个用户要单独进行破解, 当然,如果觉得不安全,可以用RSA或者ECC,使用公钥加密或者私钥签名都可以。 @jookr 再提醒一下,直接把pass和salt进行拼接是非常非常不安全的做法,salt的正确做法请使用 hmac |
10
stiekel 2015-05-27 10:04:55 +08:00 1
目前我觉得最好的做法是:
1、浏览器端,先对密码取两遍md5,传输的时候传md5,就算传输的时候数据泄露,用户的明文密码是安全的。 2、服务器端接收到传过来的密码(取名为GET_PWD),再加一遍md5,取出用户对应的盐(每个用户盐不一样),相加后再取md5,得到数据库中存储的密码密文(取名为DB_SAVED_PWD) 3、用户登陆成功后,生成新的盐,并在GET_PWD的基础上,生成新的DB_SAVED_PWD,分别存储用户的新盐和新DB_SAVED_PWD 盐和数据库中的用户密码是分开存储的。 |
11
xenme 2015-05-27 10:05:43 +08:00
1. 从前台收到用户名,根据规则计算出 salt
2. 计算出密码 MD5 3. 查表比对 |
12
Septembers 2015-05-27 10:06:37 +08:00 via Android 1
@stiekel 请不要使用md5, sha1
|
13
xenme 2015-05-27 10:07:40 +08:00
@stiekel 你这是自欺欺人啊。
取100秒 MD5,意思就是密码其实不是用户的123,而是100遍后的 md5, 中间传输拦截到100遍后的结果,对其他人来说就是密码了。 只是不需要填写,直接 post 而已。 |
14
Septembers 2015-05-27 10:09:13 +08:00 via Android
@xenme 恩,md5,sha1,都密码学上存在缺陷。。。
|
15
BOYPT 2015-05-27 10:15:39 +08:00
嗯,js端做md5都是自欺欺人,然而在业界似乎还挺流行的。
|
16
BuilderQiu 2015-05-27 10:19:10 +08:00
还是很多在前端RSA加密的吧。。安全。。也不算太慢。。
|
18
armoni 2015-05-27 10:21:34 +08:00 1
BCrypt加密 不需要自己设置盐
|
19
jiongjionger 2015-05-27 10:37:35 +08:00
select salt,password from table where username = '$username'
这样不就好了么 $password = md5($psw.$salt); 验证$password和取回来一不一样不就完了 |
20
dallaslu 2015-05-27 10:46:41 +08:00
|
22
dallaslu 2015-05-27 11:06:40 +08:00 1
引用楼主:
正常流程需要三步 表单提交的用户名$username和 密码$psw 步骤1先查出盐$salt select salt from table where username = '$username' 步骤2然后加密 $password = md5($psw.$salt); 步骤3最后再查是否有符合条件的数据 select * from table where username='' and password='$password' 有结果就说明密码正确 没结果就说明密码错误或者没这个用户名的账号 这里的描述有逻辑漏洞: * 如果步骤 1 没有查到盐,就说明用户号不存在; * 如果步骤 1 中查到盐,步骤 3 没有结果则只可能是密码错误; 不如把加密过程留在脚本里做: 1. 先一次查询出盐和密码: select salt, password from table where username = '$username' 2. 再加密对比: $result = ($password == md5($psw.$salt) ? 'success' : 'failed'); 这样,加密方式有很多种选择。比如: sha1( password + sha1( salt ) ) |
23
wy315700 2015-05-27 11:14:14 +08:00
|
24
yanze0613 2015-05-27 11:14:40 +08:00 1
加密解密用程序来解决,数据库存放加密结果和盐
|
25
dallaslu 2015-05-27 11:26:10 +08:00
@wy315700 本贴中的数据库存放盐和 hash 值的做法是传统 B/S 验证的典型方案。hmac 需要客户端自行实现加密方法吧?
|
27
hgc81538 2015-05-27 12:06:51 +08:00 via iPhone
|
30
s51431980 2015-05-27 12:29:45 +08:00 1
|
31
zhicheng 2015-05-27 12:40:00 +08:00
请问楼主和楼们上你们知道有个东西叫 PBKDF2 吗?
|
34
dallaslu 2015-05-27 12:51:40 +08:00
@wy315700 我理解的 hmac ,是用一定的 hash 算法和随机数,解决了密钥在客户端和服务端传输的风险问题。自然要求客户端实现加密算法啊。
如果只在 B/S 架构的 Server 端应用 hmac 来验证用户提交的密码是否与数据库中一致,hmac 的客户端和服务端角色都由 Server Script 扮演,不会多此一举吗? |
36
stiekel 2015-05-27 13:34:59 +08:00 1
|
37
wy315700 2015-05-27 13:42:04 +08:00
|
39
loading 2015-05-27 13:53:46 +08:00 via Android
|
40
BuilderQiu 2015-05-27 14:14:18 +08:00 1
|
41
loading 2015-05-27 14:21:52 +08:00 via Android
@BuilderQiu 嗯,感谢提醒!
|
42
loading 2015-05-27 14:25:26 +08:00 via Android
|
43
loading 2015-05-27 14:30:27 +08:00 via Android
@BuilderQiu 取到数据库的盐,和知道我统一的盐,对于暴力破解似乎没什么不同!
那每个用户对一个盐有什么好处呢? 难道就是防止被脱裤时被大家知道来源? 个人认为,用可逆算法存密码和明文一样令人讨厌! 下次简单密码还是加域名区分吧,不然都不知道哪个站掉的。 |
44
akstrom 2015-05-27 14:36:20 +08:00
06年做的用户密码体系,md5("用户名"+"_"+"用户密码"+"_"+"系统码"),用户名唯一,系统码一套系统一个随机的N位字符,有想的那么复杂吗?
|
45
dallaslu 2015-05-27 14:36:39 +08:00
@stiekel 关于 md5 这段,我突然想到:
如果「浏览器端对密码进行md5」被普遍采用,一旦 md5 值被截取,那将势必「影响到用户在其它场合中的密码安全」。因为密码作为明文输入 md5 函数做参,得到的摘要是一样的。所以,要想各种场合密码互不影响,则要保证: 每一个应用,各自采用不同的 md5 加密次数,你两遍我三遍,猪八戒三十六遍、孙悟空七十二便,以保证网络中传输的 md5 值不被用做其他场合上。 所以,与其这样,不如也在客户端「加盐」,只一遍 md5 就不会影响到其他场合了。再进一步,如果每次会话都由服务器生成一个随机数,作为「胡椒」加到明文后面做出哈西摘要拿去验证,那么,「别人拿到这个md5」也因为再次请求时随机数不同,而不能「直接在应用中登陆」了,岂不更妙。具体实现上,可以参考 hmac。 |
46
wy315700 2015-05-27 14:37:25 +08:00 1
|
47
loading 2015-05-27 14:40:40 +08:00 via Android
@wy315700 哦,对! 如果一样,那么弱密码的概率就很高了,我没想过这个问题。
我一般会把用户名也一起算,有空再好好看看各位的方法。 |
49
dallaslu 2015-05-27 14:51:48 +08:00
@wy315700 hmac 里服务端生成的随机数,才是其关键吧!这样不用传输敏感的密码原文,即可完成对密码的验证。
如果只是因为盐与密码原文拼接后有碰撞,而采用 hmac,我觉得大可不必,因为: 1. 盐由服务器管理,每用户唯一,对于单个用户来说,因为盐是固定的(如 ef),所以不存在相似密码与盐拼接后碰撞的问题(abc 永远不会通过验证,盐不可变更); 2. 盐在生成时,可以技术手段保证位数相同,不给掌握密码前半部分的攻击者以瞎蒙之机; 3. 在用盐计算哈希值时,可以用明文与盐的哈希值拼接,然后再取哈希值。 |
50
quix 2015-05-27 14:58:38 +08:00
@stiekel 就是为了防止监听..才有了 SSL / TLS ,这是真正能确安全的方案, 而且无需你写一行代码... md5这种方法属于耍小聪明... 只能在一定程度上保护一点点信息而已.
|
51
dallaslu 2015-05-27 15:00:14 +08:00
引用 @wy315700:
「你这样如何检验密码正确性,每次提交的MD5都不一样。」 服务器也用这个随机数,和之前存储的用户密钥放在一起,用相同的算法计算结果,与客户端相同,则认为其是授权用户。所以,在上面我也说这要求客户端也实现加密算法,从而不适用传统 Web 应用。 https://en.wikipedia.org/wiki/Hash-based_message_authentication_code |
52
jsq2627 2015-05-27 15:02:53 +08:00 2
@wy315700
@zhicheng 用 HMAC 代替手写 hash+salt 算法并没有什么明显的安全优势。 用 PBKDF2 代替手写 hash+salt 算法是安全的。 这里举例说明: 假定攻击者已经取得了完整的数据库权限,但是没法看到代码实现。 攻击者想要获取用户 foo 的明文密码,下面分别讨论针对几种种密码存储方式攻击方式: 1. 密码明文存储 直接从数据库读出来,最不安全,大家都知道。 2. 不加盐 hash 攻击者知道 hash。但是不知道用什么哈希算法生成的 hash,可能是 md5(password),可能是 md5(sha1(password))。攻击者可以利用已知的彩虹表查出 hash 可能对应的明文,分别去尝试登录。如果不是复杂的哈希算法,都有对应的现成彩虹表可查。 3. HMAC 攻击者知道 hash 和 salt。接下来和 2 是类似的,只不过哈希算法在 2 的基础上套了一层 HMAC,变成了这样 hash = HMAC(originalHash, salt)。因为 salt 是随机的,需要自己针对这个 salt 生成彩虹表,没法利用现成的彩虹表。 4. 加盐 hash 攻击者知道 hash 和 salt。和 3 类似,区别就是,在 3 里 hash = HMAC(originalHash, salt),在这里 hash = myFunc(originalHash, salt),攻击者需要想办法知道 myFunc 是什么,这个在不看代码的情况下是很难推出的。 5. PBKDF2 攻击者知道 hash 和 salt。同上,这次换成 hash = PBKDF2(password, salt)。注意 PBKDF2 算法的第一个参数直接就是 password,不需要先计算 originalHash。与 3 相比,攻击者无需推算 originalHash 是怎么得出的,可以直接计算针对此 salt 的彩虹表。但关键的地方来了,PBKDF2 是一个非常慢的算法,这个算法内部会进行多次 HMAC 的迭代,如果指定的迭代次数足够大,通常计算一次哈希值需要 500ms 以上,这时计算足够大的彩虹表是非常困难的。 对上面各种方式的安全性从低到高来个排序,大概是这样: 1<2<3=4<5 3 的难点在于 HMAC 算法通常也不是很快,计算彩虹表成本较高,但是只要有足够时间和设备还是可以计算出来的。4 的难点在于没法知道 myFunc 是什么,攻击具有不确定性,但通常低水平开发者写出的 myFunc 很简单,比如 md5($originalHash . $salt) 这样,这是非常容易猜出来的。所以上面给 3 和 4 画了个等号,两种方式可比性不强,安全性相当。 PBKDF2 算法是可以指定迭代次数的,只要有需要,完全可以把每个哈希值的计算时间调到 10s 以上,大大增加了彩虹表的计算难度。 |
53
quix 2015-05-27 15:02:57 +08:00
@stiekel 对于未加密的 http连接, 真的要截数据包, 完全可以截你的 session id, 这样你整个安全验证系统都形同虚设, 你在客户端怎么md5都没用...
|
55
jsq2627 2015-05-27 15:07:22 +08:00
此外 HMAC 原本的设计就不是用于密码保存的,它是用于带身份验证的完整性校验的。HMAC 的输入应该是 hash 和 key,而不是 hash 和 salt。key 和 salt 的区别是 key 应该是保密的,由传送接受双方预共享,私下保存。salt 是存在数据库的,对攻击者是公开的。
https://news.ycombinator.com/item?id=1998198 这里有一个很好的解释 |
57
BuilderQiu 2015-05-27 15:11:22 +08:00
|
58
dallaslu 2015-05-27 15:17:32 +08:00
@jsq2627 那这样是正确的用法吗:HMAC(myFunc(originalHash, salt), randomString)
|
59
jsq2627 2015-05-27 15:18:41 +08:00
client / server 之间的通信安全,TLS / HTTPS 算是实现起来成本最低,最安全的一种方式。
为了节省一张 SSL 证书的钱,各位也真拼。。。 |
60
gamexg 2015-05-27 15:22:27 +08:00 1
好奇怪的思路,为什么要查询2次?
直接把用户的密码和盐都取出来程序比较就可以了啊... 数据库密码部分建议增加一个密码加密版本,类似与这样保存“密码加密版本$盐$加密后的密码”。 当前使用的加密算法出现缺陷时可以随时部署新的版本的加密算法。在用户登录时发现是旧版本的加密算法,直接使用用户登录提供的密码用新的算法加密保存到数据库即可无痛升级。 |
61
jsq2627 2015-05-27 15:24:25 +08:00
@dallaslu 上面只讨论了攻击者没有取得代码的情况。遇到这种私有的复杂哈希函数的话,攻击者会想办法取得代码的。
我觉得正确的思路应该是 PBKDF2 那样,大大增加计算彩虹表的时间成本。即使有了代码也没法破解。 |
62
wy315700 2015-05-27 15:25:11 +08:00
@jsq2627 其实吧,现在的TLS都是形同虚设,以前好像有过调查,排名前1000的APP,大多没有正确使用TLS,也就是说,大部分APP里的TLS都没有校验证书正确性,,,,
|
63
jsq2627 2015-05-27 15:30:33 +08:00
@wy315700 那也不能怪 TLS 喽,明明是大家的使用姿势不正确~
不过我以前也干过这样的事,客户端配置 TLS 的时候不验证服务器证书,以为这样就能省张 SSL 证书的钱了~ 正确的省钱姿势是安装自己的根证书。 |
64
wy315700 2015-05-27 15:33:15 +08:00
@jsq2627 其实不单单是省证书钱,我们现在用了TLS以后发现个问题,客户端如果时间不对,比如手机的时间跑到了证书生效之前,然后就连不上了。。。。。
|
66
leyle 2015-05-27 17:20:51 +08:00
安全分为不同的阶段,比如传输阶段的数据安全;获取了数据库内容后,暴力破解还原原始密码的密码破解安全,是两个不同的概念。
前面使用 https 的来传输数据,后面使用上面大家的讨论方法来将暴力破解的成本尽可能的提高,让 cracker 的投入产出比差距太大,他自己都会放弃了。 |
67
picasso250 2015-05-27 18:32:13 +08:00
PHP有专门的(一个)函数来做这个事情。
|
68
maja 2015-05-27 18:37:28 +08:00 1
扯那么多没用,三句话总结:
Use the fucking bcrypt! Use the fucking bcrypt! Use the fucking bcrypt! |
70
benjiam 2015-05-27 23:21:20 +08:00 via Android
太沉重的加密算法会被cc攻击 。 https可以解决所有问题,HTTP的话,hash最大问题是彩虹表,万一被脱裤了,和裸奔没啥两样,所以要加盐。还有一种解决办法,多次hash迭代。比如md5 20次。其实没啥鸟用,最多让攻击者没办法利用现有彩虹表。加盐的hash最大问题是没办法让客户端提前拿到自己的盐,比如Web端。HTTP另一个比较大的问题是被监听抓包,拿到session,但是可以把权限控制分层。普通权限用一个权限,别的用一个权限。类似支付宝支付密码,但是其实没个卵用。还是HTTPS吧 。这个才是活好
|
71
gkiwi 2015-05-28 02:08:15 +08:00
为了各种大家也是够拼了,大家可以参考微软的kerberos机制,保准恶心到出血,但是有个卵用啊。。
看看人家支付宝的登陆,各种加密手段都上了。你自己得有那个时间啊。 密码安全这块,很多时候根本用不了那么复杂的机制。HTTPS+盐就够用了。。 |
72
Daniel65536 2015-05-28 07:41:06 +08:00 via iPhone
@benjiam 你以为md5 20次迭代就没法用现成彩虹表了毕竟还是图样。
彩虹表是这么做的: 1.选定一个初始值x 2.连续md5 k次 3.保留结果y 破解时连续md5 k次,检查过程中是否出现过y,不管你迭代了几次,只要次数小于k就能用原来的彩虹表。 这手法是彩虹表的时间换空间,另外有些彩虹表还会不断用函数把md5值映射回一般的a-Z0-9字符串,也有奇效。 |
73
benjiam 2015-05-29 09:25:57 +08:00 via Android
@Daniel65536 很简单的办法 每次md5 结果加在前一次结果里 继续迭代,你的彩虹表还能继续用吗?
|
74
benjiam 2015-05-29 09:29:13 +08:00 via Android
@Daniel65536只要每次修改每次迭代算法就可以,20次 10次md5 10次sha1 你的虹表可以破解吗?
|
75
Daniel65536 2015-05-29 14:12:07 +08:00
@benjiam 你首先得知道彩虹表是怎么产生的,才提得出来这个很“简单”的办法,想出这个很简单的办法仅仅值一毛钱啊。于是你用刚刚得到的新的信息又拍了一次脑门,可是讨论安全问题真不能随便拍脑门的。
|
76
benjiam 2015-05-29 15:01:11 +08:00
@Daniel65536 讨论安全问题的前提 是成本, 你有现成的虹表可以利用,我只是让你将成本提高,重建一个虹表。 这个方案本来就不是完全安全的。
|