移動App該怎樣保存用戶password

版權聲明:本文爲橫雲斷嶺原創文章,未經博主贊成不得轉載。微信公衆號:橫雲斷嶺的專欄 https://blog.csdn.net/hengyunabc/article/details/34623957


update 2018-06-04php

2015年出的一個規範 JSON Web Token (JWT)  https://tools.ietf.org/html/rfc7519 
css

JWT 官網: https://jwt.io/  
html

八幅漫畫理解使用JSON Web Token設計單點登陸系統: http://blog.leapoahead.com/2015/09/07/user-authentication-with-jwt/ 
linux

JSON Web Encryption (JWE) : https://tools.ietf.org/html/rfc7516 
android

JSON Web Signature (JWS) : https://tools.ietf.org/html/rfc7515 
git


update 2017-9-6 github

微信交互協議和加密模式研究:https://github.com/hengyunabc/hengyunabc.github.io/files/1280081/wechat.pdf算法


---數據庫


移動App該怎樣保存用戶password?瀏覽器

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

先看下一些軟件是怎樣保存用戶password的:

  • 咱們先來看下QQ是怎麼保存password的:

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

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

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

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

手機淘寶是經過本地DES加密,再把password保存到本地文件中的,假設拿到ROOT權限,能破解出password明文。

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

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

我實際測試了下。可以輕鬆獲得所有賬號的password明文。

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

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

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

貌似曾經的發行版是md5 hash,如今的發行版都是SHA-512 hash。

linux用戶password的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 來查看支持的算法。

用戶password該怎樣保存,還有能作到哪一種程度?

看完上面一些軟件的作法以後,咱們來探討下,用戶password該怎樣保存。還有能作到哪一種程度?

  • 假定本地存儲的hash串/加密串,和加密算法,攻擊者都可以獲得,或者逆向分析到。
實際上也是如此,經過上面QQ和淘寶的樣例,允分說明了加密串是可以獲得的。Linux更是一切都是公開的,僅僅要有權限就可以讀取到。包含salt值,shah算法,(salt+password) hash以後的結果。


  • 防止攻擊者獲得用戶password的明文。

    這個其實是從用戶的角度出發。即便數據泄露了。影響降到最低。

  • 防止攻擊者拿到hash串或者加密串以後。一直都可以登錄。

    這點對於移動設置是很是重要的。比如今天用戶連到了一個惡意的wifi,假設攻擊者截獲到請求,要防止攻擊者潛伏几天,或者幾個月以後的攻擊。

    必須要讓請求的憑據在一天或者幾天內失效。

加鹽(salt)

假如不加鹽,那麼攻擊者可以依據相同的hash值獲得很是多信息。

比方站點1的數據庫泄露了,攻擊者發現用戶A和用戶B的hash值是同樣的,而後攻擊者經過其餘途徑拿到了用戶A的password。那麼攻擊者就可以知道用戶B的password了。

或者攻擊者經過彩虹表。暴力破解等方式可以直接知道用戶的原來password。

因此。每個用戶的salt值都要是不同的,這點參考linux的/etc/shadow文件就知道了。

client本地存儲password的算法

應該用哪一種算法來存儲?

從上面的資料來看。手機淘寶是本地DES對稱加密,顯然很是easy就可以破解到用戶的真實password。

QQ也是對稱加密的數據庫裏,存儲了用戶password的md5值。

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

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

  1. client用公鑰加密用戶password。保存到本地;
  2. 用戶要登錄時,發送加密串到server;
  3. server用私鑰解密,獲得用戶的password。再驗證。

有的人會說。假設server的私鑰泄露怎麼辦?

server端換個新的密鑰,強制client下載新的公鑰或者升級。

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

固然。即便真的私鑰泄露,世界同樣運轉。像OpenSSL的心血漏洞就可能泄露server私鑰。但你們日子同樣過。

非對稱加密算法的優勢:

  • 即便數據被盜。攻擊者拿不到password的明文
  • 假設發現有部分用戶的數據被盜了(公鑰加密後的數據),可以經過升級server和client的版本號。讓用戶又一次輸入password。用戶仍是原來的password。但是攻擊者卻登錄不了了。
  • 對於安全要求嚴格的應用,還可以按期更新私鑰,來保證用戶的數據安全。

怎樣防止本地加密串泄露以後,攻擊者可能潛伏很是久?

這點其實是怎樣讓client保存的加密串及時的失效。

比方:

  1. 強制要求client保存的加密串一週失效;
  2. 用戶手機中病毒了,攻擊者竊取到了加密串。但是清除病毒以後。用戶沒有夠時的改動password。

    攻擊者是否會潛伏很是久?

  3. 發現某木馬大規模竊取到了大量的用戶本地加密串,可否夠強制用戶的本地加密串失效,client不用升級,用戶不用改動password,也不會泄露信息?

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

  1. 用戶填寫password。client隨機生成一個salt值(注意這個salt僅僅是防止中間人攔截到原始的password的加密串)。用公鑰把 (salt + password)加密,設置首次登錄的參數。發送到server。
  2. server檢查參數,發現是首次登錄,則server用私鑰解密,獲得password(拋棄salt值),驗證,假設經過。則隨機生成一個salt值,並把salt值保存起來(保存到緩存裏。設置7天過時)。而後用公鑰把(salt + username)加密,返回給client。

  3. client保存server返回的加密串。完畢登錄。
  4. client下次本身主動登錄時。把上次保存的加密串直接發給server。並設置二次登錄的參數。

  5. server檢查參數。發現是二次登錄。用私鑰解密。獲得salt + username。而後檢查salt值是否過時了(到緩存中查找,假設沒有。即過時)。假設過時,則通知client。讓用戶又一次輸入password。假設沒有過時,再驗證password是否正確。假設正確。則通知client登錄成功。

  6. 假設發現某賬戶異常,可以直接清除緩存中相應用戶的salt值。這樣用戶再登錄就會失敗。

    同理,假設某木馬大規模竊取到了大量的用戶本地加密串,那麼可以把緩存中所有用戶的salt都清除,那麼所有用戶都要又一次登錄。注意用戶的password不用改動。

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

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

詳細的登錄流程:

瀏覽器登錄的流程:

瀏覽器的登錄過程比較簡單,僅僅要用RSA公鑰加密password就可以了。

防止中間人截取到明文的password。 

 


App登錄保存數據流程

App因爲要實現本身主動登錄功能。因此一定要保存一些憑據。因此比較複雜。

 

App登錄要實現的功能: 

  • password不會明文存儲,並且不能反編繹解密; 
  • 在server端可以控制App端的登錄有效性,防止攻擊者拿到數據以後,可以長久地登錄。 
  • 用戶假設password沒有泄露,不用改動password就可以保證安全性; 
  • 可以區分不一樣類型的client安全性;比方Android用戶受到攻擊。僅僅會讓Android用戶的登錄失效。IOS用戶不受影響。

     


App第一次登錄流程:

  • 用戶輸入password,App把這些信息用RSA公鑰加密:(username,password,時間,mac,隨機數),併發送到server。 
  • server用RSA私鑰解密。推斷時間(可以動態調整1天到7天)。假設不在時間範圍以內,則登錄失敗。假設在時間範圍以內,再調用coreservice推斷username和password。

     

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

  • 假設server推斷用戶成功登錄。則用AES加密:(隨機salt,username,client類型,時間)。以(username+Android/IOS/WP)爲key,存到緩存裏。

    再把加密結果返回給client。 

  • client保存server返回的加密串 

App本身主動登錄的流程:

  • App發送保存的加密串到server,(加密串,username。mac,隨機數)==>RSA公鑰加密 
  • server用RSA私鑰解密。再用AES解密加密串。推斷username是否一致。假設一致。再以(username+Android/IOS/WP)爲key到緩存裏查詢。假設推斷緩存中的salt值和client發送過來的一致,則用戶登錄成功。不然登錄失敗。 
不用AES加密,用RSA公鑰加密也是可以的。AES速度比RSA要快。RSA僅僅能存儲有限的數據。



其餘的一些東東:

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

RSA算法最好選擇2048位的。

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

怎樣防止登錄過程的中間人攻擊。可以參考,魔獸世界的叫SPR6的登錄算法。

總結:

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

  • 不支持JS的。用原始password登錄。

  • 支持JS的,可以考慮傳遞hash算法加密字符串。

    嚴格要求的應用,最好用JS實現RSA加密。在github上找到的一個JS RSA庫:https://github.com/travist/jsencrypt

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

server用salt(存數據庫的) + hash算法來保存用戶的password。


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

這樣server可以靈活控制風險,控制用戶登錄憑據的有效期,即便用戶數據泄露。也不須要改動password。

相關文章
相關標籤/搜索