題目來自:Python 練習冊。題目1.9: 通常,登陸某個網站或者 APP,需要使用用戶名和密碼。密碼是如何加密后存儲起來的呢?請使用 Python 對密碼加密。
查看更多于本人博客:iii.run
思路: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