@
binbinyouliiii 你“加密”(加引号,因为正确的说法是哈希)的意义在于把你的代码 /算法和数据都交给别人的情况下,别人依然无法轻易获得你用户的密码。为什么要把代码和数据给别人?因为你有信心永远不被黑么。。。
然后再来说一些上面已经有人提到的内容。彩虹表的原理是什么?因为 md5 的结果是确定的,也就是说对于 A 输入,它得出的结果一定是 A',那么我就可以预先计算好。这样子当你给我一个 md5 的结果时,我就能反向找出它对应的明文是什么。而且在实际上,很多人用的密码都很常见,所以很容易就被找到了(也就是破解了)
然后就有了加盐的概念,既然用户自己的密码很容易被破解,那么我就在用户的密码上增加点什么。考虑到彩虹表的原理是预先算好,所以应对的方法很简单,我使用户的密码变得很长(例如在最后加上个 32 位字符串)。← 这也是为什么你提出的『用户密码第二位+1 』这种方案没有意义,在知道你的算法后,别人的计算量并没有提高
然后之所以不要重复用盐, 是因为如果你对于所有用户的盐值都一样,那么入侵者就可以针对你的盐值,专门打造一份彩虹表来进行破解。而如果每个用户的盐值都不一样,那么他破解的代价将高很多很多( 不存在绝对安全的算法,我们能做的就是在自己能够承受的情况下,尽可能提高入侵者的成本)
最后说下换算法以及加 hash 次数。 md5 之所以以前没问题,现在不行了的原因是计算力的不断提高。所以首先增加 hash 的次数这种做法是有意义的,因为它会增加彩虹表生成的时间。然而这种意义不大。。。因为计算力依然在继续提高。。。但这个思路是完全正确的,例如 bcrypt 或者 pbkdf2 都是这种思路。假如每次函数调用增加到半秒,对于正常的业务来说影响不大(只需要在登录时验证),但对于彩虹表来说,哪怕只计算 8 位的纯数字就需要 10,000,000*.5/86400=57.87 天了。别觉得这个时间好像很短,因为这只是 8 位纯数字,换成 8 位的数字+大小写字母就是 62^8*0.5/86400/365=3461759 年了。。。而且配合上面说的不要重复用盐,对于每个用户都重新计算彩虹表,这个代价就更加的大了。。。