移动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。

相关文章
相关标签/搜索