溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

web開發(fā)中密碼加密存儲技術(shù)有哪些

發(fā)布時間:2022-01-20 10:10:10 來源:億速云 閱讀:178 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“web開發(fā)中密碼加密存儲技術(shù)有哪些”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“web開發(fā)中密碼加密存儲技術(shù)有哪些”文章能幫助大家解決問題。

從最早的明文保存密碼,到md5 sha1 sha256 sha512加密,到加salt、加pepper、多次hash計算,再到現(xiàn)代的密碼加密算法Bcrypt PBKDF2 Argon2id。在保護用戶密碼的過程中,軟件工程師作出了巨大的努力,為網(wǎng)絡(luò)安全的建設(shè)添磚加瓦。

介紹

大多數(shù)用戶在不同的網(wǎng)站或應(yīng)用中使用相同的密碼,因此當(dāng)網(wǎng)站的數(shù)據(jù)庫被盜取,存儲的密碼也不應(yīng)該被攻擊者獲取。與密碼學(xué)大多數(shù)領(lǐng)域一樣,需要考慮很多因素;幸運的是,大多數(shù)現(xiàn)代編程語言和框架都提供了內(nèi)置的功能來幫助存儲密碼,讓問題變得簡單很多。

背景

哈希與加密(Hashing vs Encryption)

哈希和加密是兩個經(jīng)常被混淆或錯誤使用的術(shù)語。它們之間的主要區(qū)別在于哈希是單向的(不可能“解密”哈希值并獲得原始值),而加密是雙向的。

在幾乎所有情況下,都應(yīng)該對密碼進行哈希處理而不是加密,因為這會使攻擊者很難或不可能從哈希中獲取原始密碼。

只有在必須獲取原始密碼的極端情況下才使用加密??赡苄枰@樣做的一些情景是:

  • 如果應(yīng)用程序需要使用密碼對不支持單獨登錄(SSO)的外部遺留系統(tǒng)進行身份驗證。

  • 如果需要從密碼中檢索單個字符。

能夠解密密碼意為著嚴重的安全風(fēng)險,因此應(yīng)進行充分的風(fēng)險評估。在可能的情況下,應(yīng)使用其它代替方案,以避免需要以加密形式存儲密碼。

本文章專注于密碼哈希,有關(guān)加密密碼的更多指導(dǎo),請參閱Cryptographic Storage Cheat Sheet。

攻擊者如何破解密碼哈希

盡管無法“解密”密碼散列以獲得原始密碼,但是在某些情況下可以“破解”哈希?;静襟E是:

  • 選擇一個常用的密碼(例如“password”)。

  • 計算輸入的哈希值。

  • 將其與目標哈希值進行比較。

使用所有候選密碼重復(fù)此過程,直到找到匹配項。有很多不同的方法可用于選擇候選密碼,包括:

  • 暴力破解(嘗試所有可能的密碼)。

  • 常用密碼的詞典或單詞表。

  • 從其它被攻擊站點獲得的密碼列表。

  • Markov chains或PRINCE之類的更復(fù)雜的算法。

  • 常用模式(例如“1個大寫字母,6個小寫字母,1個數(shù)字”)。

哈希概念(Hashing Concepts)

加鹽(Salting)

每個salt都是獨一無二的,隨機生成的字符串,在哈希過程中添加到每個密碼中。由于salt對于每個用戶而言都是唯一的,因此攻擊者對每一個密碼都必須使用相應(yīng)的salt進行破解,而不能一次性破解整個數(shù)據(jù)庫的密碼。這使得破解大量哈希變得非常困難,所需時間與哈希數(shù)量成正比增長。

salt還可以防止攻擊者使用預(yù)先計算的彩虹表。最后,使用salt意味著無法在不破解哈希的情況下確定兩個用戶是否具有相同的密碼,因為即使密碼相同,不同的salt也會導(dǎo)致不同的哈希。

Argon2或Bcrypt之類的現(xiàn)代哈希算法會自動對密碼加salt,因此使用它們時無需其他步驟。 但是,如果您使用的是舊式密碼哈希算法,則需要手動實施加鹽。執(zhí)行此操作的基本步驟是:

  • 使用安全隨機數(shù)生成鹽。使用java.security.SecureRandom,而不是java.util.Random()。

    • 鹽的長度至少應(yīng)為16個字符。

    • 將鹽編碼為安全字符集,例如hexadecimal或Base64。

  • 結(jié)合salt和密碼。

    • 可以使用簡單的拼接或HMAC來完成。

  • 對組合后的密碼和salt進行哈希運算。

  • 存儲哈希值。

安全隨機數(shù)的生成方法

web開發(fā)中密碼加密存儲技術(shù)有哪些

加胡椒(Peppering)

除了加salt,還可以加pepper以提供額外的保護。它類似于salt,但有四個主要區(qū)別:

  • 所有密碼共享pepper,不像鹽一樣對每個密碼都是唯一的。這使得pepper可預(yù)測,并可嘗試破解密碼。pepper的靜態(tài)特性也“減弱了”哈??箾_突的能力,而salt則使用獨一無二的字符串來擴展長度,提高了哈??箾_突能力,增加了對哈希函數(shù)的輸入熵。

  • pepper不存儲在數(shù)據(jù)庫中,不像salt一樣(但salt也并非總是如此)。

  • pepper并不是使密碼破解變得過于困難使攻擊變得不可行,這是其它許多密碼存儲保護措施(如salt)的目標。

  • salt可防止攻擊者制作已知密碼的彩虹表,但是pepper沒有這樣的作用。

pepper的目的是防止攻擊者僅獲得數(shù)據(jù)庫時(例如,如果他們利用SQL注入漏洞或獲得數(shù)據(jù)庫的備份)便無法破解任何哈希。

pepper的長度不應(yīng)少于32個字符,并使用安全隨機生成器(CSPRNG)隨機生成(如:java.security.SecureRandom)。應(yīng)該使用安全訪問API將它安全地存儲在“秘密文件庫”中(不能放在應(yīng)用的配置文件中,因為容易受到SSRF的攻擊),或者將pepper存儲在硬件安全模塊(HSM)中,以獲得最佳的安全保障。

pepper的用法和salt類似,在hash之前將papper和密碼拼接起來,如hash($pepper . $password)。salt可以用拼接的方式,但papper只能以前綴的形式拼接。不要將papper作為后綴,因為這可能會導(dǎo)致諸如與截斷和長度擴展攻擊有關(guān)的漏洞。這些威脅使密碼通過驗證,因為獨一無二的密碼永遠不會被截斷,只有papper會被截斷。

備選方案

pepper的另一種可選方案是,照常hash密碼然后使用對稱加密對hash進行加密,加密后再保存到數(shù)據(jù)庫中。這種加密充當(dāng)pepper,以不直接影響密碼或hash的方式發(fā)揮作用。這避免了拼接/前綴方法的已知問題,并且如果您認為pepper已被泄露,在您更換pepper密鑰時,它允許密碼保持有效。

另一個解決方案是以ID的方式存儲pepper。當(dāng)存儲密碼時,將關(guān)聯(lián)的pepperID一起保存到數(shù)據(jù)庫中。這樣可以做到更換pepper時,不會泄露pepper。當(dāng)需要更換pepper時,可以使用新的pepperID替換之前的值。這要求應(yīng)用程序?qū)epperID與外部存儲關(guān)聯(lián)起來。

工作因子(Work Factors)

工作因子是指為每個密碼進行hash運算的次數(shù)(通常是2^work次)。工作因子的目的是使計算hash更加費時,從而降低了攻擊者的破解速度。工作因子通常和hash值存儲在一起。

選擇工作因子時,需要在安全性和性能之間取得平衡。較高的工作因子將使hash值更難以被攻擊者破解,但也會使登錄驗證的過程變慢。如果工作因子過高,會降低應(yīng)用程序的性能,并且攻擊者還可以通過進行大量的登錄嘗試來耗盡服務(wù)器的CPU性能,對它進行拒絕服務(wù)攻擊。

理想的工作因子沒有黃金法則,它取決于服務(wù)器的性能和用戶數(shù)量。確定最佳工作因子將需要在實際使用的服務(wù)器上進行實驗。通常,計算哈希值應(yīng)少于一秒鐘,但在流量較高的站點上,則應(yīng)大大少于此值。

更新工作因子

隨著時間的推移,硬件的性能不斷提升而價格則不斷下降。按照摩爾定律,工作因子每18個月應(yīng)該加1。

更新工作因子的最常見方法是等用戶下次登錄時,使用新的工作因子重新hash密碼。這意味著不同的密碼具有不同的工作因子,并且如果用戶不重新登錄到應(yīng)用程序,則可能導(dǎo)致密碼hash永遠無法升級。某些情況下,刪除較舊的密碼,要求用戶在下次登錄時重置密碼可能是適當(dāng)?shù)模员苊獯鎯^舊且安全性較低的密碼hash。

在某些情況下,可能不需要原始密碼即可提高hash的工作因子,盡管普通的哈希算法(例如Bcrypt和PBKDF2)不支持此功能。

最大密碼長度

某些哈希算法(例如Bcrypt)的最大輸入長度為72個字符(有報告稱有的實現(xiàn)甚至更短,但在撰寫本文時尚未確定)。在使用Bcrypt的情況下,最大長度應(yīng)限制為64個字符,因為它提供了足夠的限制,同時仍允許出現(xiàn)字符串終止問題,并且不能揭示應(yīng)用程序使用了Bcrypt。

此外,由于現(xiàn)代哈希函數(shù)在計算上的非常消耗性能,如果用戶可以提供非常長的密碼,則可能存在拒絕服務(wù)漏洞,例如2013年在Django中發(fā)布的漏洞。

為了防止這兩個問題,應(yīng)設(shè)置最大密碼長度。對于Bcrypt,應(yīng)該是64個字符(由于算法和實現(xiàn)方面的限制),而對于其他算法,則應(yīng)該在64和128個字符之間。

限制最大密碼長度確實會減少密碼空間,但限制為64個字符仍然有至少2^420的密碼空間,攻擊者不可能利用這個進行攻擊。因此,這不會明顯地降低安全性。

預(yù)哈希密碼

另一種方法是使用快速算法(例如SHA-256)對用戶提供的密碼進行預(yù)哈希處理,然后使用諸如Bcrypt(即bcrypt(sha256($password)))等更安全的算法對所得哈希值進行hash處理。盡管此方法解決了用戶輸入任意長度的密碼,導(dǎo)致哈希算法較慢的問題,但它還引入了一些漏洞,這些漏洞可能使攻擊者更容易破解密碼。

如果攻擊者能夠從兩個不同的站點中獲取密碼哈希,其中一個使用bcrypt(sha256($password))存儲密碼,另一個使用sha256($password),則攻擊者可以使用從第二個站點未經(jīng)破解的SHA-256哈希作為候選密碼嘗試嘗試從第一個(更安全)站點破解這些哈希。如果在兩個站點之間重復(fù)使用密碼,則攻擊者可以有效地剝離Bcrypt層,然后將精力集中在破解更容易的SHA-256哈希上。

使用預(yù)哈希時,請確保將第一個hash結(jié)果安全地編碼為十六進制或base64,因為如果輸入包含空,則某些哈希算法(例如Bcrypt)可能會以不良方式運行。

由于這些問題,通常首選的方法是限制最大密碼長度。僅在有特定要求的情況下才應(yīng)執(zhí)行密碼的預(yù)哈希處理,并且已經(jīng)采取了適當(dāng)?shù)拇胧﹣頊p輕上述問題。

密碼哈希算法

現(xiàn)代算法

有許多專門設(shè)計用于安全存儲密碼的現(xiàn)代哈希算法。這意味著它們應(yīng)該很慢(不像MD5和SHA-1這樣設(shè)計得很快的算法),并且可以通過更改工作因子來配置它們有多慢。

有三種主要算法:

Argon2id

Argon2是2015年密碼哈希競賽的獲勝者。該算法有三種不同版本,應(yīng)使用Argon2id變體,因為它提供了一種平衡的方法來抵御旁通道攻擊和基于GPU的攻擊。

Argon2具有三個可以配置的參數(shù),而不是像其它算法只能設(shè)置的工作因子,這意味著設(shè)置正確的參數(shù)更為復(fù)雜。如果您無法正確的設(shè)置參數(shù),則應(yīng)該使用Bcrypt之類的更簡單算法。

PBKDF2

PBKDF2是NIST推薦的,并且具有經(jīng)過FIPS-140驗證的實現(xiàn)。因此,當(dāng)需要這些算法時,它應(yīng)該是首選算法。此外,它在.NET框架中是開箱即用的,因此通常在ASP.NET應(yīng)用程序中使用。

PBKDF2可以基于多種不同的哈希算法與HMAC一起使用。HMAC-SHA-256被NIST廣泛支持并推薦使用。

PBKDF2的工作因子通過循環(huán)計算實現(xiàn),循環(huán)次數(shù)應(yīng)至少為10,000(在安全性要求更高的環(huán)境中,100,000可能更合適)。

Bcrypt

Bcrypt是得到最廣泛支持的算法,除非有對PBKDF2有特殊的需求或有調(diào)優(yōu)Argon2的知識,否則它應(yīng)該是默認選擇。

Bcrypt的默認工作因子是10,除非在較舊或性能較差的系統(tǒng)上運行,否則通常應(yīng)將其提高到12。

傳統(tǒng)算法

在某些情況下,通常是由于使用傳統(tǒng)語言或環(huán)境而無法使用現(xiàn)代哈希算法。如果可能,應(yīng)使用第三方庫來提供這些算法。但是,如果只能使用舊算法,例如MD5和SHA-1,則應(yīng)該采取許多措施來提高存儲密碼的安全性。

  • 使用最強大的算法(SHA-512 > SHA-256 > SHA-1 > MD5)。

  • 用pepper。

  • 為每個密碼使用唯一的salt,使用安全隨機數(shù)生成器生成。

  • 進行多次hash計算(至少10,000次,如果硬件性能好的話,應(yīng)該更多)。

應(yīng)該強調(diào)的是,這些步驟都不如使用現(xiàn)代哈希算法好,僅在沒有其它選項可用的情況下才應(yīng)采用這種方法。

升級舊式哈希

對于使用安全性較低的哈希算法(例如MD5或SHA-1)構(gòu)建的遺留程序,應(yīng)將這些哈希值升級為更現(xiàn)代和安全的哈希值。當(dāng)用戶下一次輸入密碼(如登錄)時,使用新算法重新加密它。最好使用戶的當(dāng)前密碼過期,并要求他們輸入一個新密碼,以使用戶密碼的哈希值對攻擊者而言不再有用。

但是,這種方法意味著舊的(安全性較低)密碼哈希將存儲在數(shù)據(jù)庫中,直到用戶下次登錄為止,并且可能會無限期地存儲。有兩種主要方法可以解決此問題。

一種方法是使長時間不活動的用戶失效并刪除其密碼哈希值,并要求他們重置密碼以再次登錄。盡管安全,但是這種方法并不是特別用戶友好,并且使大量用戶的密碼過期可能會給支持人員造成麻煩,或者可能被用戶認為是違規(guī)的行為。但是,如果在登錄時進行密碼哈希升級與刪除舊密碼哈希之間存在合理的間隔時間,則大多數(shù)活動用戶應(yīng)該已經(jīng)更改了密碼。

另一種方法是將現(xiàn)有的密碼哈希值作為更安全算法的輸入。例如,如果應(yīng)用程序最初將密碼存儲為md5($password),則可以輕松將其升級為bcrypt(md5($password))。以這種方式對哈希進行分層可以不用知道原始密碼。但是如“預(yù)哈希密碼”部分所述,這種方式會使哈希更容易破解。因此,下次用戶登錄時,應(yīng)直接使用用戶密碼進行哈希,用于替換舊的密碼哈希值。

自定義算法

編寫自定義的加密代碼(例如哈希算法)確實很困難,并且絕不應(yīng)該在學(xué)術(shù)活動之外進行。使用未知算法或定制算法可能帶來的任何潛在好處將大大地被其中存在的弱點所削弱。

不要這樣做(Do not do this)。

Java哈希實現(xiàn)(Hashing Java)

代碼范例

public static byte[] hashPassword( final char[] password, final byte[] salt, final int iterations, final int keyLength ) {
    try {
        SecretKeyFactory skf = SecretKeyFactory.getInstance( "PBKDF2WithHmacSHA512" );
        PBEKeySpec spec = new PBEKeySpec( password, salt, iterations, keyLength );
        SecretKey key = skf.generateSecret( spec );
        byte[] res = key.getEncoded( );
        return res;
    } catch( NoSuchAlgorithmException | InvalidKeySpecException e ) {
        throw new RuntimeException( e );
    }
}

代碼指南

password和salt參數(shù)是數(shù)組,是由hashPassword函數(shù)所決定的。使用后應(yīng)清除敏感數(shù)據(jù)(將數(shù)組元素設(shè)置為零)。

該示例使用Password Based Key Derivation Function 2 (PBKDF2),如前所述。

salt參數(shù)應(yīng)該是隨機數(shù),對每個密碼都是唯一的。長度至少應(yīng)為32個字節(jié)。請記住,將salt與密碼哈希值存儲在一起!

iterations參數(shù)指定PBKDF2執(zhí)行多少次hash計算。值越高越安全。您需要在實際運行的硬件上進行實驗。找到需要半秒才能執(zhí)行加密運算的值。請記住,將iterations值與密碼哈希值存儲在一起!

256的keyLength是安全的。(生成的是32位的哈希值)

如果示例代碼拋出NoSuchAlgorithmException異常,可以將PBKDF2WithHmacSHA512替換為PBKDF2WithHmacSHA1。兩者都足以勝任這項任務(wù),但是當(dāng)人們看到“SHA1”時,您可能會受到批評(在PBKDF2之外使用SHA1是不安全的)。

自JDK 1.4版以來,SecretKeyFactory和PBEKeySpec類已成為Java SE的一部分。

關(guān)于“web開發(fā)中密碼加密存儲技術(shù)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI