密碼的儲存

2021-09-01 10:47:53 字數 3828 閱讀 2035

在各種線上應用中,使用者名稱密碼是使用者身份認證的關鍵,它的安全重要性不言而喻。一方面,作為保護使用者敏感資料的「鑰匙」,一旦被破解,系統將敞開大門完全不設防。另一方面,密碼這把「鑰匙」本身就是非常重要的資料:使用者經常會在多個應用中使用相同或相似的密碼。一旦某乙個應用的密碼被破解,很可能,壞人就因此而掌握了使用者的「萬鑰匙」,這個使用者的其它應用也相當危險了。

這篇博文就重點討論對於密碼原文本身的儲存的安全性考慮,而系統自身的安全性不在此文的範圍之內。

那麼,對於如此重要的使用者密碼,究竟該怎樣在系統中儲存呢?

「君子不立危牆」,對於使用者密碼這個燙手的山芋,乙個極端的選擇是系統完全不接觸密碼,使用者的身份認證轉而交由受信任的第三方來完成,比如 openid 這樣的解決方案。系統向受信任的第三方求證使用者身份的合法性,使用者通過密碼向第三方證明自己的身份。

這樣,密碼完全不經過系統,系統也就不用絞盡腦汁保證密碼的安全了。這個作法對使用者來說還有個額外的好處:再也不用為每個應用註冊帳號了,同乙個 openid 就可以登入所有支援 openid 的系統了。

好雖好,可在今天這樣乙個各自為戰,劃分地盤的網路戰國時代,作為乙個自主的系統,自己的使用者資源居然不能掌握在自己的手上,而要與別人分享,甚至 「受制於人」,這多少有點讓人難以接受。(據稱,現在全球有 27000 個 web site 支援 openid 登入,雖然還在持續增長中,但在茫茫「網海「中無疑還是屬於小眾)

好吧,既然網路大同時代還沒來臨,系統還是要自己負責使用者的認證,那密碼該如何儲存呢?按照安全性由低到高,有這樣幾種選擇:

密碼名文直接儲存在系統中 這種方法下密碼本身的安全性比系統本身還低,系統管理員可以直接看到所有使用者的密碼名文。除非你是做惡意**故意套取使用者密碼,否則不要用這種方式。

密碼名文經過對稱轉換後再儲存的

這跟上面的直接明文的方式沒有多少本質改進,任何知道或破解出轉換方法的人都可以通過相應的逆轉換得到密碼原文。

密碼經過對稱加密後再儲存 使用者密碼明文的安全性等同於加密金鑰本身的安全性。對稱加密的金鑰會同時用於加密和解密,所以它會直接出現在加密**中,破解的可能性也相當大。而且,知道金鑰的人很可能就是系統管理員,所有人的密碼原文他都能算出來。

密碼經過非對稱加密後再儲存 密碼的安全性等同於私鑰的安全性。密碼明文經過公鑰加密,而要還原名文,則必須要私鑰才行。因此只要保證私鑰的安全,密碼名文就會安全。私鑰可以由某個受信任的人或機構來掌管,普通的身份驗證只需要用公鑰加密就可以了。

實際上,這也是 https/ssl 的理論基礎。這裡的關鍵是私鑰的安全,如果私鑰洩露,那密碼名文就危險了。

以上 4 種方法的乙個共同特點是可以從儲存的密碼形式還原到密碼的明文。

如果你註冊了乙個**,當你忘了密碼後,**可以很貼心地通過你註冊的 email 告訴你原來的密碼是什麼,那麼,它肯定就是用了上面的4種方法中的一種了。這時候你就得小心了:既然**能知道你的密碼明文,那**的工作人員就可能知道你的密碼明文,任何攻入了這個**的人也有了還原你密碼明文的可能,甚至於,**本身就是惡意的釣魚**。

所以,最好的儲存密碼的方式是以連系統自己都不可能還原明文的方式來儲存,也就是常用的利用雜湊演算法的單向性來保證明文的資訊以不可還原的有損方式進行儲存。

這大類的各個方式按安全性由低到高為:

使用自己獨創的雜湊演算法對密碼進行雜湊,儲存雜湊過的值。 雜湊演算法的要求很高,一般來說,自己獨創的雜湊演算法肯定沒有公開的經過時間檢驗的演算法質量高,除非你是天才。

使用 md5 或 sha-1 進行雜湊然很儲存。 md5 和 sha-1 已經被破解。這意味著雖然不能還原密碼原文,但很容易找到乙個能同樣生成相同雜湊值的密碼原文的碰撞。還有一點,這兩個演算法相對速度較快,這就意味著對暴力破解來說消耗的資源少。 所以建議不要使用它們。

直接使用更安全的 sha-256 等成熟演算法。 這個只是在一定程度上增加了暴力破解的時間。如果遇到簡單密碼,通過常用密碼字典的暴力破解法,很快就可以還原密碼原文。

加入了隨機 salt 的雜湊演算法。

密碼原文(或進過hash後的值)和隨機生成的 salt 字串混淆,然後再進行 hash,最後把 hash 值和 salt 值一起儲存。驗證密碼的時候,只要用儲存的 salt 值再做一次相同的 hash 再與儲存的 hash 值比較就可以了。

這樣一來,就算使用者使用簡單的密碼,但進過 salt 混淆過的字串就是乙個很不常見的串,一般不會出現在密碼常用字典中。salt 的程度越長,暴力破解的難度就越大。

具體的 hash 過程也可以進行若干次疊代,雖然 hash 疊代會增加碰撞率,但也增加暴力破解的資源消耗。

最後,就算真被暴力破解了,被破解的也只是這個隨機 salt 混淆過的密碼,破解者不能用它來登入該使用者的其它應用(如果其它應用也用了自己的隨機 salt)

上面這幾種方法都不可能還原密碼的明文,這意謂著,就算是系統管理員也不知道密碼原文。這也意謂著,這個世界上只有你知道你自己的密碼。**再也沒有辦法提醒你原來的密碼是什麼了。對於那些真的忘了自己密碼的使用者,**可以提供乙個重置密碼的功能,幫使用者隨機生成乙個臨時密碼,讓使用者通過這個臨時密碼來登入到系統中重新設定新的密碼。

下面的 python 程式就是使用了 salt hash 來加密密碼明文

import

osfrom 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)

ifisinstance(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

這裡先通過標準隨機庫生成 64 bits 的隨機 salt,使用了標準的 sha-256 做為基本的 hash 演算法,使用標準 hmac 演算法作為 salt 混淆。並且進行了 10 次混淆 hash。最後將 salt 和 hash 結果一起返回。

使用的方法很簡單:

hashed = encrypt_password('secret password')

下面是驗證函式

def validate_password(hashed, input_password):

return hashed == encrypt_password(input_password, salt=hashed[:8])

它直接使用 encrypt_password 來對待檢驗的密碼進行相同的 salt 混淆 hash 並與出口儲存的值比較。

使用示例:

assert validate_password(hashed, 'secret password')

上面的實現雖然只有簡單幾行,但借助了 python 標準庫的力量,已經是乙個可用於生產環境的高安全的密碼儲存方案了。

總結一下使用者密碼的儲存:

說完了密碼的儲存,後面的一篇會接著聊聊密碼的傳輸。

文章資訊

SAP GUI ShortCut 儲存密碼

1.修改登錄檔 hkey current user software sap sapshortcut security enablepassword 1 it must be string value 測試ok 2.如果發現沒有以上鍵值,可以手工照著建乙個即可.注 在gui710時,hkey loc...

漫話密碼儲存

密碼是用來進行鑑權 身份認證 一種手段,說白了就是證明你是誰。一般鑑權都可以總結為下面3種形式 你知道什麼?如密碼,密碼提示問題等 你有什麼?如信用卡,token卡等 你是什麼?如指紋識別,瞳孔識別等 常見的針對密碼的攻擊方式有 暴力破解 brute force 字典攻擊 dictionary at...

git密碼儲存

我之前就是每一次操作都要輸入使用者名稱和密碼,繁瑣得很。現在給各位分享下git永久儲存賬戶名和密碼。方法一 安裝好git之後一般會在c盤的c users administator目錄下生成 gitconfig配置檔案。用文件編輯工具開啟該檔案 新增 user name wb ly409739 你的使...