谈谈网站密码的保存

21 Dec, 2011

黑客公开600万名CSDN用户明文数据

CSDN自己并不常去,不过搜索技术文章的时候常常会搜索到上面的文章,没想到一个作为开发者的社区,用户的密码这样非常敏感的信息居然用明文保存,这肯定不是技术上的原因,肯定是CSDN自己有一些不太好说的用处吧。

存储密码,一般都需要经过不可逆的散列之后保存散列值,下面就说一下一些具体的方法。哈希函数主要就是用来求摘要的,用的比较多的就是md5和sha1了。普通的md5和sha1安全度已经不是太高了,现在有些网站提供字典猜解,如果你的密码很简单,很容易破解。

第一种比较简单的方法就是,先求一个定长的随机字符串,然后和用户密码接上再求sha1摘要,保存的时候同时保存这个随机字符串和得到的散列值。比如我常使用的实现如下: ​

def hexpassword(password):
    salt = ''.join([(string.ascii_letters+string.digits) [x] for x in random.sample(range(0,62),8)])
    enpass = sha1((salt+password).encode('utf-8')).hexdigest()
    return str(salt)+'$'+str(enpass)

这样就可以加密用户密码了,验证的时候只需要将用户输入的密码和数据库中保存的加密密码前面的字符串一起加密再比较就可以了,实现如下:

def is_password(passwd,enpass):
    salt = enpass[ :8]
    password = sha1((salt+passwd).encode('utf-8')).hexdigest()
    p = str(salt)+'$'+str(password)
    return p == enpass

上面这种是比较简单的方法,还有一种就是直接利用HMAC(加密散列消息确认),在Python中可以比较轻易的使用这种方法,实现如下: ​

def hmacpassword(password):
     salt = ''.join([(string.ascii_letters+string.digits) [x] for x in random.sample(range(0,62),8)])
     enpass = hmac.new(salt,password,sha1).hexdigest()
     return str(salt)+'$'+str(enpass)

检验的方法和第一种的检验方法类似,这里就不在写具体方法了,当然,为了安全性,你可以求多次散列或者使用HMAC多次。不过也不必过多了,毕竟,这样已经很难得到用户的明文密码了。

看来,以后注册不太信任的网站,密码还是瞎扯比较好,以免遭到利用。