第1.9题:Python对密码加密
题目来自:Python 练习册。题目1.9: 通常,登陆某个网站或者 APP,需要使用用户名和密码。密码是如何加密后存储起来的呢?请使用 Python 对密码加密。
查看更多于本人博客:李飞阳
思路:salt 加 hash 来单向转换密码明文
参考代码
以下给出Py2和Py3两段代码,输出的内容是一样的。因为加密之后的内容不是unicode代码,所以存储可能不方便,可以使用base64.b64encode(hashed)
转化为base64编码格式。
Python2代码
import os,base64
from hashlib import sha256
from hmac import HMAC
def encrypt_password(password, salt=None):
"""Hash password on the fly."""
if salt is None:
salt = os.urandom(8) # 64 bits.
assert 8 == len(salt)
assert isinstance(salt, str)
if isinstance(password, unicode):
password = password.encode('UTF-8')
assert isinstance(password, str)
result = password
for i in xrange(10):
result = HMAC(result, salt, sha256).digest()
return salt + result
def validate_password(hashed, input_password):
return hashed == encrypt_password(input_password, salt=hashed[:8])
if __name__=="__main__":
hashed = encrypt_password('secret password')
assert validate_password(hashed, 'secret password')
print (hashed)
print (base64.b64encode(hashed))
print (base64.b64decode(base64.b64encode(hashed)))
Python3代码
import os, base64
from hashlib import sha256
from hmac import HMAC
def encrypt_password(password, salt=None):
"""Hash password on the fly."""
if salt is None:
salt = os.urandom(8) # 64 bits.
assert 8 == len(salt)
assert isinstance(salt, bytes)
assert isinstance(password, str)
if isinstance(password, str):
password = password.encode('UTF-8')
assert isinstance(password, bytes)
result = password
for i in range(10):
result = HMAC(result, salt, sha256).digest()
return salt + result
def validate_password(hashed, input_password):
return hashed == encrypt_password(input_password, salt=hashed[:8])
if __name__ == "__main__":
hashed = encrypt_password('secret password')
assert validate_password(hashed, 'secret password')
print (hashed)
print (base64.b64encode(hashed))
print (base64.b64decode(base64.b64encode(hashed)))
Python编码问题
一开始直接在Python3环境运行第一段代码的时候,总会报错NameError: global name 'unicode' is not defined
,百思不得其解。
查了资料,才发现是因为Python更新的时候,Python 3 renamed the unicode type to str, the old str type has been replaced by bytes。在Python升级文档内可以查到相关内容,也就是unicode直接改名str,str改名成bytes。
Python2和Python3,在编码方面挖下太多的坑
举个简单的例子:
isinstance(u'中文', unicode) #python2内是正确的
isinstance(u'中文', str) #python3内是正确的
Python3内的unicode和bytes
Python 3最重要的新特性大概要算是对文本和二进制数据作了更为清晰的区分。文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。
在将字符串存入磁盘和从磁盘读取字符串的过程中,Python 自动地帮你完成了编码和解码的工作,你不需要关心它的过程,例如你能把一个中文赋值给字符串。而使用 bytes 类型,实质上是告诉 Python,不需要它帮你自动地完成编码和解码的工作,而是用户自己手动进行,并指定编码格式。
参考链接:
http://zhuoqiang.me/password-storage-and-python-example.html
http://www.ituring.com.cn/article/61192