Pbkdf-2
從偽隨機字元串派生密鑰
我想知道通過單次迭代從偽隨機字元串派生密鑰是否安全。
具體來說,我正在設計一個系統,其中密鑰在客戶端派生,然後發送到伺服器進行身份驗證。步驟如下:
- 使用者輸入電子郵件和密碼
- 派生
k0
<- pbkdf2(密碼:密碼,鹽:電子郵件,alg:‘sha256’,迭代:10000)- 派生
k1
<- pbkdf2(密碼:k0,鹽:密碼,alg:‘sha256’,迭代:1)- 發送到伺服器:(電子郵件,
k1
)- 伺服器導出 pbkdf2(password:
k1
, salt: somerandomstring, alg: ‘sha256’, iteration: 20000) 並將其與數據庫中的雜湊值進行比較
k0
是 256 位的密鑰。客戶端使用它使用分組密碼來加密事物。客戶端需要向伺服器發送一些東西以進行身份驗證。但是伺服器不應該知道客戶端的密鑰。我的想法是第 3 步可以防止伺服器知道客戶端的密鑰。但我想知道 pbkdf2 的 1 次迭代是否足夠。我認為這就足夠了,因為它
k0
是偽隨機的,攻擊者應該無法從k1
. (窮舉搜尋需要 2^256 步)。這個對嗎?編輯
為了澄清起見,這是我到目前為止的設計:
## Register Client * User enters email and password * Derive k0 <- pbkdf2(password: password, salt: email, alg: 'sha256', iteration: 10000) * Derive k1 <- pbkdf2(password: k0, salt: password, alg: 'sha256', iteration: 1) * POST to '/register': (email, k1, kdf, kdf_iteration) Server * Generate salt <- 256bit random string * Derive k2 <- pbkdf2(password: k1, salt: salt, alg: 'sha256', iteration: 20000) * Create a user with (hashed_password, salt) = (k2, salt) * Login the user and reply with a session key ## Login Client * User enters email and password * GET '/prelogin': (kdf, kdf_iteration) * Derive k0 <- pbkdf2(password: password, salt: email, alg: 'sha256', iteration: 10000) * Derive k1 <- pbkdf2(password: k0, salt: password, alg: 'sha256', iteration: 1) * POST to '/login': (email, k1) Server * Look up user (hashed_password, salt) * Derive k2 <- pbkdf2(password: k1, salt: salt, alg: 'sha256', iteration: 20000) * Check k2 == hashed_password, and reply with a session token
編輯2
澄清這是為了什麼:
這是為開源筆記應用程序( https://github.com/dnote/cli)添加端到端加密。
基本上,客戶端可以與伺服器同步數據。
k0
在離開客戶端之前,所有數據都使用哪個伺服器不知道進行加密。伺服器應該不知道如何解密數據,所以我決定派生
k1
髮送k0
到伺服器而不是k0
直接發送到伺服器。
這個方案的問題在於 $ k_1 $ 可以從計算 $ k_0 $ . 這可能不是一個大問題,但很容易避免。
您可以確保 $ k_0 $ 和 $ k_1 $ 源自原主 $ k $ 這是從密碼派生的。所以你會有
k = PBKDF2(password, mail, iteration_count)
andk0 = KDF(k, "Enc")
和k0 = KDF(k, "Auth")
。如果您只是使用 SHA-256 的 PBKDF2,則可以將第二個定義
KDF(k, label)
為PBKDF2(password: k, salt: label, alg: 'sha256', iteration: 1)
.其他選項在我對後續問題的其他答案中給出。