本地儲存密碼的安全設計介紹

  有些應用需要把使用者密碼儲存在本地,本方案設計了一種較為安全的密碼本地儲存的方案。

  1 安全要求

  1.1 要實現的

  1.防止攻擊者得到使用者密碼的明文 防止攻擊者拿到自動登入token後,一直都可以登陸 即使兩個使用者的密碼相同,伺服器儲存的密文密碼也不一樣 可在伺服器端清除salt,讓使用者的自動登入token失效,需手動登入 使用者在多個終端登入同一個帳號,各終端的自動登入功能都生效

  1.2 不實現的

  1.更安全的方案能做到“把本地儲存的檔案複製到其他客戶端”登入就會失效,這依賴於客戶端做處理,本方案不實現 有的方案採用RSA非對稱加密,本方案直接採用AES對稱加密

  2 APP場景分析

  2.1 註冊時A

  AesKey = 前後端約定好的金鑰 ClientSalt = 客戶端隨機生成8個字元從0-9A-Za-z中選 HashedPassword = SHA1明文密碼 EncryptedPassword = Base64AesEncryptClientSalt + HashedPassword, AesKey說明:

  1.註冊時客戶端在註冊接口裡提交EncryptedPassword 伺服器用AesKey解出ClientSalt + HashedPassword,因為ClientSalt固定22位元組,能計算得到HashedPassword

  註冊成功後,伺服器儲存的使用者密碼是SavedPassword。生成方法如下:

  ServerSalt = 伺服器隨機生成8個字元從0-9A-Za-z中選 SavedPassword = Base64AesEncryptServerSalt + HashedPassword, 伺服器專用金鑰說明:

  1.有了ServerSalt,即使兩個使用者的密碼相同,最後的EncryptedPassword也會不一樣。 使用者密碼在資料庫中沒有明文儲存。

  2.2 手動登入時

  說明:

  1、客戶端在手動登入接口裡提交EncryptedPassword生成方法同2.1註冊時

  2、伺服器驗證的過程:

  1 用AesKey從客戶端的EncryptedPassword裡解出HashedPassword

  2 用伺服器專用金鑰從資料庫的SavedPassword裡解出HashedPassword

  3 比較兩個HashedPassword

  4 驗證成功後返給客戶端SaltExpire和AutoLoginToken,生成方式如下:

  Salt = 隨機8字元從0-9A-Za-z中選 SaltExpire = 該Salt最後有效時間 AutoLoginToken = Base64AesEncryptSalt + HashedPassword, 伺服器專用金鑰5 把使用者ID、Salt和SaltExpire儲存在Salt快取表中

  3、客戶端本地儲存的是SaltExpire和AutoLoginToken,沒有儲存明文密碼

  4、客戶端因為不知道伺服器的Aes金鑰,無法解出HashedPassword

  2.3 自動登入時

  1、客戶端先根據本地儲存的SaltExpire來判斷是否已過期,過期需要手動登入

  2、未過期時,客戶端在自動登入接口裡提交AutoLoginToken

  3、伺服器驗證的過程:

  1 從AutoLoginToken解出Salt和HashedPassword

  2 在Salt快取表裡查詢該使用者ID的此Salt是否已過期

  3 未過期的情況下對比兩個HashedPassword

  4 驗證成功時,構造新的Salt、SaltExpire及AutoLoginToken,把SaltExpire和AutoLoginToken返回給客戶端

  5 把使用者ID、新的Salt和SaltExpire儲存在redis中,老的Salt清除掉

  4、客戶端更新本地儲存的SaltExpire和AutoLoginToken

  5、在出現風險需要使用者手動登入時,可以把使用者的SaltExpire清零來實現

  2.4 多終端自動登陸的時間

  多終端在執行2.2手動登入過程時,會生成多份Salt/SaltExpire,一個終端自動登入後會產生新的Salt老的那個Salt會清除掉,但不會影響另一個終端的自動登入,因為用的Salt本來就不同。