移動App該如何保存用戶密碼

移動App該如何保存用戶密碼?

這個實際上和桌面程序是一樣的。

先看下一些軟件是如何保存用戶密碼的:

  • 我們先來看下QQ是怎麼保存密碼的:

 

參考:http://bbs.pediy.com/archive/index.php?t-159045.html,

桌面QQ在2012的時候把密碼md5計算之後,保存到本地加密的Sqlite數據庫裏。

 

  • 再來看下手機淘寶是怎麼做的:

 

參考:http://blog.csdn.net/androidsecurity/article/details/8666954

手機淘寶是通過本地DES加密,再把密碼保存到本地文件裏的,如果拿到ROOT權限,能破解出密碼明文。

 

  • 再來看下微軟是怎麼保存用戶密碼的:

 

參考:http://www.freebuf.com/tools/37162.html

我實際測試了下,可以輕鬆得到所有帳號的密碼明文。

 

  • 再來看下Linux是怎麼保存用戶密碼的:

 

參考:http://blog.csdn.net/lqhbupt/article/details/7787802

linux是通過加鹽(salt),再hash後,保存到/etc/shadow文件裏的。

貌似以前的發行版是md5 hash,現在的發行版都是SHA-512 hash。

linux用戶密碼的hash算法: http://serverfault.com/questions/439650/how-are-the-hashes-in-etc-shadow-generated

實際上是調用了glic裏的crypt函數,可以在man手冊裏查看相關的信息。

可以用下面的命令來生成:
mkpasswd --method=SHA-512 --salt=xxxx

其中salt參數,可以自己設置,最好是隨機生成的。
可以用 mkpasswd --method=help 來查看支持的算法。

用戶密碼該如何保存,還有能做到哪種程度?

看完上面一些軟件的做法之後,我們來探討下,用戶密碼該如何保存,還有能做到哪種程度?

 

  • 假定本地存儲的hash串/加密串,和加密算法,***者都可以得到,或者逆向分析到。

實際上也是如此,通過上面QQ和淘寶的例子,允分說明了加密串是可以得到的。Linux更是一切都是公開的,只要有權限就可以讀取到,包括salt值,shah算法,(salt+密碼) hash之後的結果。

  • 防止***者得到用戶密碼的明文。這個實際上是從用戶的角度出發,即使數據泄露了,影響降到最低。

  • 防止***者拿到hash串或者加密串之後,一直都可以登陸。這點對於移動設置是很重要的,比如今天用戶連到了一個惡意的wifi,如果***者截獲到請求,要防止***者潛伏几天,或者幾個月之後的***。必須要讓請求的憑據在一天或者幾天內失效。

 

加鹽(salt)

假如不加鹽,那麼***者可以根據同樣的hash值得到很多信息。

比如網站1的數據庫泄露了,***者發現用戶A和用戶B的hash值是一樣的,然後***者通過其它途徑拿到了用戶A的密碼,那麼***者就可以知道用戶B的密碼了。

或者***者通過彩虹表,暴力破解等方式可以直接知道用戶的原來密碼。

所以,每個用戶的salt值都要是不一樣的,這點參考linux的/etc/shadow文件就知道了。

客戶端本地存儲密碼的算法

應該用哪種算法來存儲?

從上面的資料來看,手機淘寶是本地DES對稱加密,顯然很容易就可以破解到用戶的真實密碼。QQ也是對稱加密的數據庫裏,存儲了用戶密碼的md5值。

顯然對稱加密算法都是可以逆向得到原來的數據的。那麼我們嘗試用非對稱加密算法,比如RSA來傳輸用戶的密碼。

那麼用戶登陸的流程就變爲:

 

  1. 客戶端用公鑰加密用戶密碼,保存到本地;

  2. 用戶要登陸時,發送加密串到服務器;

  3. 服務器用私鑰解密,得到用戶的密碼,再驗證。

 

有的人會說,如果服務器的私鑰泄露怎麼辦?

服務器端換個新的密鑰,強制客戶端下載新的公鑰或者升級。

可以考慮有一個專門的硬件來解密,這個硬件只負責計算,私鑰是一次性寫入不可讀取和修改的。搜索 rsa hardware,貌似的確有這樣的硬件。

當然,即使真的私鑰泄露,世界一樣運轉,像OpenSSL的心血漏洞就可能泄露服務器私鑰,但大家日子一樣過。

 

非對稱加密算法的好處:

 

  • 即使數據被盜,***者拿不到密碼的明文

  • 如果發現有部分用戶的數據被盜了(公鑰加密後的數據),可以通過升級服務器和客戶端的版本,讓用戶重新輸入密碼,用戶還是原來的密碼,但是***者卻登陸不了了。

  • 對於安全要求嚴格的應用,還可以定期更新私鑰,來保證用戶的數據安全。

 

如何防止本地加密串泄露之後,***者可能潛伏很久?

這點實際上是如何讓客戶端保存的加密串及時的失效。

比如:

 

  1. 強制要求客戶端保存的加密串一週失效;

  2. 用戶手機中病毒了,***者竊取到了加密串。但是清除病毒之後,用戶沒有夠時的修改密碼。***者是否會潛伏很久?

  3. 發現某***大規模竊取到了大量的用戶本地加密串,是否可以強制用戶的本地加密串失效,客戶端不用升級,用戶不用修改密碼,也不會泄露信息?

 

下面提出一種 salt + 非對稱加密算法的方案來解決這個問題:

 

  1. 用戶填寫密碼,客戶端隨機生成一個salt值(注意這個salt只是防止中間人攔截到原始的password的加密串),用公鑰把 (salt + password)加密,設置首次登陸的參數,發送到服務器;

  2. 服務器檢查參數,發現是首次登陸,則服務器用私鑰解密,得到password(拋棄salt值),驗證,如果通過,則隨機生成一個salt值,並把salt值保存起來(保存到緩存裏,設置7天過期),然後用公鑰把(salt + 用戶名)加密,返回給客戶端。

  3. 客戶端保存服務器返回的加密串,完成登陸。

  4. 客戶端下次自動登陸時,把上次保存的加密串直接發給服務器,並設置二次登陸的參數。

  5. 服務器檢查參數,發現是二次登陸,用私鑰解密,得到salt + 用戶名,然後檢查salt值是否過期了(到緩存中查找,如果沒有,即過期),如果過期,則通知客戶端,讓用戶重新輸入密碼。如果沒有過期,再驗證密碼是否正確。如果正確,則通知客戶端登陸成功。

  6. 如果發現某帳戶異常,可以直接清除緩存中對應用戶的salt值,這樣用戶再登陸就會失敗。同理,如果某***大規模竊取到了大量的用戶本地加密串,那麼可以把緩存中所有用戶的salt都清除,那麼所有用戶都要重新登陸。注意用戶的密碼不用修改。

  7. 第2步中服務器生成的salt值,可以帶上用戶的mac值,os版本等,這樣可以增強檢驗。

 

注意,爲了簡化描述,上面提到的用戶的password,可以是先用某個hash算法hash一次。

具體的登陸流程:

瀏覽器登陸的流程:

瀏覽器的登陸過程比較簡單,只要用RSA公鑰加密密碼就可以了。防止中間人截取到明文的密碼。


App登陸保存數據流程

App因爲要實現自動登陸功能,所以必然要保存一些憑據,所以比較複雜。

App登陸要實現的功能:

  • 密碼不會明文存儲,並且不能反編繹解密;

  • 在服務器端可以控制App端的登陸有效性,防止***者拿到數據之後,可以長久地登陸;

  • 用戶如果密碼沒有泄露,不用修改密碼就可以保證安全性;

  • 可以區分不同類型的客戶端安全性;比如Android用戶受到***,只會讓Android用戶的登陸失效,IOS用戶不受影響。


App第一次登陸流程:

 

 

  • 用戶輸入密碼,App把這些信息用RSA公鑰加密:(用戶名,密碼,時間,mac,隨機數),併發送到服務器。

  • 服務器用RSA私鑰解密,判斷時間(可以動態調整1天到7天),如果不在時間範圍之內,則登陸失敗。如果在時間範圍之內,再調用coreservice判斷用戶名和密碼。

 

這裏判斷時間,主要是防止***者截取到加密串後,可以長久地利用這個加密串來登陸。

  • 如果服務器判斷用戶成功登陸,則用AES加密:(隨機salt,用戶名,客戶端類型,時間),以(用戶名+Android/IOS/WP)爲key,存到緩存裏。再把加密結果返回給客戶端。

  • 客戶端保存服務器返回的加密串

 

App自動登陸的流程:

 

  • App發送保存的加密串到服務器,(加密串,用戶名,mac,隨機數)==>RSA公鑰加密

  • 服務器用RSA私鑰解密,再用AES解密加密串,判斷用戶名是否一致。如果一致,再以(用戶名+Android/IOS/WP)爲key到緩存裏查詢。如果判斷緩存中的salt值和客戶端發送過來的一致,則用戶登陸成功。否則登陸失敗。

不用AES加密,用RSA公鑰加密也是可以的。AES速度比RSA要快,RSA只能存儲有限的數據。

 



其它的一些東東:

多次md5或者md5 + sha1是沒什麼效果的。

RSA算法最好選擇2048位的。搜索" rsa 1024 crack"有很多相關的結果,google已經將其SSL用的RSA算法升級爲2048位的。

如何防止登陸過程的中間人***,可以參考,魔獸世界的叫SPR6的登陸算法。

總結:

對於網頁登陸,可以考慮支持多種方式:

 

  • 不支持JS的,用原始密碼登陸。

  • 支持JS的,可以考慮傳遞hash算法加密字符串。嚴格要求的應用,最好用JS實現RSA加密。在github上找到的一個JS RSA庫:https://github.com/travist/jsencrypt

  • 客戶端應用,一律應當用RSA算法,並加鹽來保存用戶密碼。單純的hash或者對稱加密算法都不靠譜。

 

服務器用salt(存數據庫的) + hash算法來保存用戶的密碼。

用salt(存緩存的,注意和上一行的salt是不同的)+ RSA算法來加密用戶登陸的憑證。

這樣服務器可以靈活控制風險,控制用戶登陸憑據的有效期,即使用戶數據泄露,也不需要修改密碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章