做 app 做网站,难免要和服务器、后台、数据打交道,那么作为一名后台开发,当涉及到注册登录,你最应当想到的应该是用户的安全,尤其是密码安全。
现在安全界几乎天天都有某网站、某公司被脱裤,也就是整站的数据库被偷走被下载。那么你的用户数据全部落入了歹徒手中,应该怎么防范即使如此,歹徒也不能拿到用户的真实密码呢?
这里我们定义,“不能拿到”指的是在“有生之年”他得不到,理论上如果有足够的时间(比如10000000年)那么任何的密码总能解密的,那么如果一个加密方案在当今现有算力的前提下几百年不能被算出来,那我们就认为这个加密是安全的;“真实密码”这里我们指的不是用户输入了的那个密码,而是能够用来登录我们网站的那个字符串(你要是真的明文保存了用户的密码……那就真的是明文的了)。
通信安全
这一点是最大的前提,否则任何人都能获取用户和服务器之间的通信,那你安全就很难做了,最基本的要用个 HTTPS,如果追求高质量,那么可以自己签发一个证书。
信息摘要 MD5 SHA1
这应该是大家最熟悉的哈希算法,它们被广泛用于数据库密码安全领域——当然,还有黑客的密码破解字典、彩虹表等等。一旦你的数据库泄露,如果你直接把用户的密码进行了一个 md5 或者 sha1,那几乎等同于明文。
固定盐
密码哈希前加盐是业界安全通用做法,给用户做信息摘要之前,先加入特定的内容,然后合在一起做哈希,这样就得到了一个不同的哈希字符串,看起来似乎很美妙,但注意,你的盐是固定的(不然用户下次登录怎么对比?),那么黑客拿到你的数据库(甚至逆向等得到了你的盐),你的加密依旧一定程度上等同与明文——因为黑客很容易就能根据你的盐制作生成一份全新的字典。
用户是不可信的
无论是开发网站,还是开发移动应用,请在心里时刻谨记这一标题——用户是不可信的。我们不能双手合十或者放到膝盖上来祈祷用户都是道德高尚的圣人,所以你单纯在客户端做加密,是万万不足以保护用户的安全的。另外,就算你保护的很好,那么中间人攻击呢?所以,我们一定要保证,所有的必要加密操作,都要在服务端实现,客户端可以进行简单的加密以避免用户的明文密码在传输过程中被窃取,但这个简单的加密绝对不能直接存入数据库。
真正的密码加盐
那么到底怎么做才能达到必要的,或者说业界规范的安全呢?首先是合适的摘要算法,MD5或者SHA1已经过时了,使用更安全的 SHA256 进行加密。
那么选择了加密算法,该加密什么内容呢?加密的是 用户的密码 a 以及我们在服务器端实时生成的随机盐 b,即 a+b
这样的好处是什么呢?用户a 和 用户b 同时使用了弱密码 123 作为他们的密码,那么如果你直接进行哈希,得到的字符串毫无疑问是相同的,那么黑客至少可以直接判断这两个用户使用了相同的密码。如果你加了随机生成的字符串,那么这两个用户即使使用了相同的密码,也会在数据库存入完全不同的字符串,这样就保证了当黑客窃取了你的数据库,他完全无法判断哪些人的密码一致从而进行针对性的弱口令破解。
可是,这样是安全了,那么上文说的,下次用户登录,我又该如何才能判断用户输入的密码正确呢?毕竟创建的时候是随机的,总不能每次都找回密码吧!
所以,这个盐你不能扔,得同样存在数据库里,当用户输入密码,你就要把密码和盐合并,然后计算哈希,把得到的结果和数据库中的密码对比,如果一致,那就说明密码是正确的啦!同时,如果黑客拿到了你的数据库,他们依旧无法得到用户真正的密码,得到的是一堆完全不重复的密码哈希以及完全随机的盐。
过短的盐和不加没啥区别
你的随机字符串太短,那基本上和没有是一样的,使用长一点的随机盐才更有意义,另外,不要使用你代码基本框架里提供的普通伪随机数生成器,那些随机数不是为密码安全准备的,应该使用专门的随机生成,比如 Python 中的 os.urandom(n) 具体的使用方法:
1 2 3 4 |
from os import urandom from base64 import b64encode salt = b64encode(urandom(64)).decode('utf8') |
扩展性
别以为这就收工了,你的加密方式最好也顺便存入数据库与用户对应,这样方便你日后如果做了加密方式升级(SHA256 也总有过期的一天),那么你依旧可以新旧同时进行兼容,不至于强制所有用户立即修改密码。
总结
总之,通过真正的密码加盐哈希,你得到了业界标准的安全要求,当然,这个哈希算法也决定了你根本上的安全程度。这只是作为一个服务器安全的最基本的一环,比如你所有提交的数据应该经过签名,用户登录应该得到一个 token 每次用 token 进行验证而不是本地保存用户的账号密码……
想要更进一步了解密码加盐,移步:正确使用密码加盐散列[译]
本文由 落格博客 原创撰写:落格博客 » 如何给服务器端做最基本的密码安全
转载请保留出处和原文链接:https://www.logcg.com/archives/2759.html