1password的安全认证机制

简介:不羁对安全比较感兴趣,最近研究了1password的安全机制,特写篇文章分享出来。本文主要介绍1password的安全机制,以及它的实现原理;1password机制涉及的知识点比较多,本文限于篇幅有限,主要着眼于对其基本原理的介绍。本文不是宣传、或者鼓励大家去使用1password。

1password是一款用于储存和管理个人密码的应用,可以将个人的私密信息存储在里面,比如登录密码,银行卡信息,钱包私钥等。通过它,我们可以很好的管理自己在网络上和生活中的所有密码,对于经常会忘记密码的小伙伴来说是很有用处的。

作为现代人,我们差不多每个人都有很多的账号和密码,如果所有的网站都用同一个密码,这样记忆简单,但不够安全;如果我们在每个网站的密码都不同,我们又很难记住。1password可以允许你保存每个网站的密码,并只需记住一个密码(称为主密码,实际上还有一个隐私密码,但除了第一次登陆或者换设备时,需要输入隐私密码外,其他时间都只需要输入主密码即可,稍后会详细介绍隐私密码),即可以查看和编辑这些密码。而且,它还带有自动填充密码的功能,当你需要登陆网页的时候,它能自动填充对应的密码,无需你手动输入。

但这个过程中,1password并不会把你的密码或者其他你的隐私内容保存在服务端,而是保存在你的客户端,并且是以加密的形式保存;甚至,你的主密码和隐藏秘码也只保存在你的客户端。

关于隐私密码,实际上一串较长且较随机的字符串,它只保存在客户端,它是在账户创建时生成的,用户登陆1password的时候,只需要输入主密码即可,1password客户端会把主密码和隐私密码进行一定的计算,然后再去1password服务端认证。由于人们习惯于把主密码设置的比较简单,所以1password弄这么一个隐私密码,也是为了增强安全性。

1password不在服务端保存主密码和隐私密码,而只保存在客户端,这样就极大的保证了用户数据的隐私,任何第三方,甚至1password的服务端也没有办法获取用户的数据明文,只有用户自己才能查看自己的数据,这也意味着,用户必须牢记的自己的主密码和隐私密码,否则他的数据将无法恢复(准确的说,针对单用户版本是这样的,如果使用的团队版本或者家庭版本,则可以由其他成员帮忙恢复;本文的分析,只针对于单用户版本)。

但这样就会有这么个问题了:服务端在不保存用户密码的情况下,如何对用户进行认证?

我们先看下传统的认证流程。

传统认证流程

传统的认证流程,是通过把用户名和密码发送给服务器,服务端从数据库中查询是否存在这样的一个用户名,并验证密码是否匹配,如果匹配,则认证通过。

然而这种方式,依赖于用户把密码发送给服务端,有被窃听的风险;另一方面,服务端保存了用户的密码,如果服务端被黑了,那么用户的信息也不安全了。

当然,基于TLS方案,可以一定程度上解决这个问题。不过1password有自己的一套方案,同时还能保证不用把密码泄漏给服务端。

1password的认证流程

为了解决传统认证方式的风险,1password采用了一种“密码认证交换秘钥”(Password Authenticated Key Exchange)的方案,具体地,是一种称为SRP(Secure Remote Password)的方案,具体过程是这样的:

  1. 客户端根据主密码和隐私密码以及其他一些东西(比如加入一些随机数),计算出一个数字,我们记为x
  2. 在注册阶段,客户端根据x 计算出一个v;然后把v发送给服务器。注意,v类似于hash(x),具体的方式,可能对x做一点其他运算再hash;不管具体是哪种方案,窃听者都无法通过v计算出x,而且他因为不知道x,所以也无法做碰撞分析;甚至是,即便窃听者知道了主密码,只要他不知道隐私密码,他仍无法做碰撞分析
  3. 自此,客户端任何时候,都可以根据主密码和隐私密码计算出x;同时,server那边有了一个通过x计算出的v;因为x和v之间这种特殊的关系,那么此后在登陆阶段:
  • client可以向server证明它有一个和v对应的x
  • server可以向client证明它有一个和x对应的v
  • 同时让client和server协定出一个S作为后续通信信息的加密秘钥

数学原理

上面是一个综述,下面我们来具体分析一下。
首先,看下客户端计算x和v的具体方式:

x= SHA1(s || SHA1(I || ':' || P))
v = g^x mod N

其中,s是随机数字(也叫随机盐),I代表用户名,P代表密码。N和g都是精心选择的数字,N是个大整数。我们可以看到,在g和N已知(公开)的情况下,通过x计算出v很容易,但是通过v计算x就非常困难了,密码学者通常把这类问题叫做离散对数难题。也就是说,即便v在传输的过程中,被窃听了,黑客也很难从v计算出x。

那么如何实现上面所说的双向认证呢?
非常简单了,方法大致是这样的:

  • client向server挑战,client向server发送一个随机的数字d,server计算出R = v^d,返回给client。client校验R ==? g^(xd) mod N即可。
  • server向client挑战,server向client发送一个随机的数字的e,client计算出R = g^(xd) mod N,返回给server。server校验R == ? v^e即可。

原理应该比较明显了,就不做解释了。下面详细解释下,client和server是如何安全地协定出一个公共的秘钥S的?

在登录阶段,client随机生成一个秘密的a,计算出 A = g^a,然后把这个值连同用户的邮件地址发送给server,然后,server随机生成一个秘密的b,并计算 B=3v + g^b,然后发送给client。此时双方都有了A和B,然后通过对A和B按照约定的方式计算出一个u,具体什么方式都不要紧,关键是按照约定的方法计算即可。如此,server就可以计算出:

S = (Av^u)^b

client也可以计算出同样的:

S = (B - kg^x)^(a + ux)

为什么这两个S是相等的,不羁就留给聪明的你去证明了。

是不是很神奇?client和server在没有传输S的情况下,就可以约定出一个公共的秘钥S。任何在中间窃听的人,只得到了A, B,而窃听者仅凭A和B怎么也不可能计算出S,所以对于client和server之间后续的消息,就可以用S来加解密了,因为窃听者因为无法知道S,所以即便窃听了后续的消息,也无法破解。

其实这种方法不是1password的原创,这种方式叫做“Diffie-Hellman key exchange”,只不过1password在其上做了点微创新。


今天,因为不羁的个人兴趣,穿插了一篇1password安全机制的文章。明天我们继续《EOS智能合约开发系列》。

你可能感兴趣的:(1password的安全认证机制)