Aes

數據庫中的密碼加密

  • October 4, 2022

我想以一種可以重用它們來驗證使用者身份的方式將密碼儲存在數據庫中(對稱加密)。

我在這裡閱讀了一些很好的資訊:https ://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#cryptographic-storage-cheat-sheet

閱讀後,這是我(認為我)需要的:

  • 對稱加密(非散列),
  • 將我的加密密鑰安全地儲存在我的應用程序中(將是另一個主題),
  • 用鹽,
  • 使用加密版本控制和密鑰輪換,
  • 無需保證數據的完整性和真實性:如果我的密碼損壞和錯誤,這對我的案例來說很好,
  • 加密數據不應與密碼長度相同(如果是 8 個字元長,潛在的攻擊者不應該知道),
  • 邏輯應該在我的程式碼中(不依賴於數據庫加密功能)

我發現 AES 加密應該適用於我的案例,但我不確定密碼方法。顯然,CTR 在加密前後提供了相同的數據長度。CBC 沒有,但據說會增加程式碼的複雜性。AES 適合我的案例嗎?如果是,我應該使用什麼密碼方法(CBC、CTR、GCM、CCM …)?

編輯 2022-10-03:我確實需要檢索明確的資訊。提供更多上下文:我為每個使用者儲存一個公鑰/私鑰文件,每個文件都受密碼保護。一旦使用者登錄到我的服務,我的服務就會對其他服務進行身份驗證,因此使用者不必管理他的私鑰。

編輯 2022-10-04:多個使用者可能共享同一個 PKCS#12,該 PKCS#12 實際用於對組進行身份驗證。使用者不一定知道 PKCS#12 密碼。

從評論中,我們了解到該應用程序儲存了受密碼保護的 PKCS#12 私鑰。最佳實踐不是對保護 PKCS#12 私鑰的密碼進行對稱加密;但標準密碼散列(例如 Argon2),並在新密鑰下重新加密 PKCS#12 私鑰,這是 Argon2 的副產品。

例如(可能有許多變化):

  • 在使用者註冊時,我們獲取他們的 PKCS#12 私鑰和原始密碼,並檢查原始密碼是否允許解密 PKCS#12 文件;我們讓使用者有機會保留該密碼,或輸入一個新密碼作為目前密碼;

  • 我們生成隨機鹽;Argon2-hash 目前密碼、鹽和胡椒(替換問題的“加密密鑰”),使用

    • 生成的散列的第一部分(例如,12 字節 base64 編碼為 16 個字元)用作重新加密 PKCS#12 私鑰的密鑰(我們在某種程度上儲存它;它仍然符合 PKCS#12,但它的密鑰很強大)
    • 另一部分(與 salt 和 Argon2 參數一起)儲存在數據庫中,與密碼加密一樣。
  • 當我們需要對使用者進行身份驗證時,我們詢問使用者密碼,從數據庫中檢索 salt 和 Argon2 參數,重新計算 Argon2 雜湊,使用儲存在數據庫中的另一半來驗證密碼,然後可以使用前半部分需要 PKCS#12 私鑰。

這種方法的優點是,在數據庫內容、胡椒和加密的 PKCS#12 證書洩露後,目前使用者密碼仍然是一道防線,使用 Argon2 進行密鑰拉伸。此外,可以有意義地更新該使用者密碼。


現在,如果我們忽略該建議並希望在不使用數據庫加密功能且不洩露密碼長度的情況下將對稱加密的密碼儲存在數據庫中,這是可能的(如果不是最佳的)。我們定義了最大密碼長度,將密碼填充到該長度(例如,在解密後刪除零字節),並使用標準的身份驗證加密方法,將使用者 ID(或其雜湊)作為附加身份驗證數據。如果使用安全的 TRNG 生成隨機 IV(替換鹽),則AES-GCM將執行;如果有疑問,請使用AES-GCM-SIV

注意:我建議使用經過身份驗證的加密並將使用者 ID 輸入為 AAD,以避免將未知密碼的加密版本替換為已知密碼的加密版本的攻擊。

首先請注意,並不是說 PKCS#12 應該受密碼保護;用密鑰來保護它是完全有效的。OpenSSL似乎確實需要密碼,這是值得的,這可能是最兼容的選項。

如果您的使用者已經使用密碼登錄,您可能想知道為什麼不使用從該密碼派生的(十六進制編碼)密鑰直接在 PKCS#12 中執行加密。另外,您將如何編碼該密鑰?您可以為此使用 PKCS#12,但擁有兩個 PKCS#12 容器似乎有點奇怪。


但是讓我們假設這種雙重加密是必要的。在那種情況下,是的,我會使用 AES 進行加密。如果您不需要完整性保護/身份驗證,則哪種模式無關緊要,只要它不是 ECB。您可以將 AES-CTR 用於簡單選項,將 AES-SIV 或 AES-GCM-SIV 與關聯數據中的隨機 nonce 用作複雜選項。您將需要儲存隨機 IV 或隨機數,否則(部分)相同的密碼將加密為相同的密文值。

關於密碼的大小:如果您直接加密密碼,那麼您可能應該在應用加密模式之前填充,即不依賴密碼為您執行此操作。要不洩漏任何大小,請確定最大大小並始終(零)填充到該大小(例如 128 字節以允許密碼片語)。然後,您可以在解密後取消填充或修剪到正確的大小。

引用自:https://crypto.stackexchange.com/questions/102104