第1.9題:Python對密碼加密

題目來自: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直接改名strstr改名成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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容