本地儲存密碼的安全設計介紹
有些應用需要把使用者密碼儲存在本地,本方案設計了一種較為安全的密碼本地儲存的方案。
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本來就不同。