关掉了 Google 账户的 passkey
最近,Google账户新增了一种叫做 passkey 的登录方式。
传统的采用密码登录的登录方式中,用户需要用某种方式证明自己知道密码,而绝大多数实现中这意味着网站必须保存用户的密码,或是密码的hash值(通常是HMAC),这意味着网站如果发生了拖库的情况,有可能会将用户的密码或其hash值泄漏出去。此外,用户可能必须输入密码,并将密码通过某种方式传输到服务器上,这样一来在这个过程中便有可能由于本地的木马,或是网站采用的SSL/TLS实现的漏洞导致密码泄漏。除此之外,即使用户十分小心地在每一个不同的网站都使用了不同的密码,他们仍然需要担心被「钓鱼」的问题,所谓「钓鱼」是这样一种攻击方式:攻击者架设一个看起来很像是用户希望登录的网站的网站,并诱骗用户输入密码。
许多网站提供了二次认证的功能。在二次认证中,用户除了密码之外还需要一个能够证明是其本人进行操作的东西再确认一次身份。采用过时技术的网站往往会使用SMS短信进行二次认证,很明显,这种方式并不能彻底阻止「钓鱼」攻击:攻击者通过架设一个假的网站诱使用户输入密码之后,可以直接模拟用户的操作去向真正的网站提出请求,并要求用户输入收到的短信中的数字。更为严重的是,采用SMS短信进行二次认证时,用户手机的安全性也十分重要,对于一些高价值的受害人来说,攻击者完全可以设法欺骗运营商让它们把用户的短信发到自己控制的SIM卡上,从而收到这些验证短信,并利用之前钓鱼获得的密码完成登录。
与此类似,使用TOTP(例如Google Authenticator)作为2FA尽管不会有短信那样的安全问题,但也无法彻底杜绝「钓鱼」攻击。
为了解决这个问题,Google和Yubico提出了采用 U2F 作为2FA。在这种验证模式通过公钥密码学的方法,在用户硬件上保存一个私钥,而网站只保存用来验证它的公钥。在验证时,网站和用户采用挑战-应答认证,网站每次生成不同的挑战值,而用户用私钥签名,从而避免了同一数值被多次使用。更进一步,在这个设计中,网站的URL作为application ID,大幅提高了制作钓鱼网站的门槛(想要成功的攻击,不仅需要制作一个样子类似的网站,还得能成功劫持域名;如果只是注册一个域名类似的网站进行钓鱼,则无法获得正确的U2F应答)。
前面说了这么多,passkey又是什么呢?和U2F的工作方式类似,passkey同样使用了公钥密码学的方法,将公钥交给网站。目前最新版本的Apple iOS和Google的Android上都完全实现了passkey。其中,Apple的实现会将passkey自动通过iCloud Keychain同步到所有登录了同一个Apple ID的支持该功能的iOS设备,与其密码管理器类似,这些passkey受生物信息(指纹或刷脸)保护,并可使用屏幕解锁密码来解锁。Android的实现与此类似,通过Password Manager同步,可以用生物信息或屏幕解锁密码来解锁,而登录Google账户时,Android会自动生成一个passkey,在Google账户中不能将其删除。
总体上,passkey要比密码要安全得多:首先,采用公钥密码学的方法进行验证,意味着网站只掌握用于确认用户身份的公钥,即使发生数据泄漏,该数据对于攻击者来说也只是能用来验证发到这个网站的用户回应是否是由用户私钥签署,其危害远小于泄漏的密码或密码的hash。其次,passkey可以提供比密码多得多的熵,并且无需记忆。最后,passkey的验证回应只会发给域名能匹配的上的网站,从而杜绝了钓鱼。
不过,我认为和密码 + U2F的验证方式相比,passkey实际上类似于在手机等设备上实现了一个U2F,并使用它代替了两者的组合。对于普通用户来说这固然是比只用密码要安全的多的(因为passkey证明了用户拥有一个登录了该Apple ID或Google账户的设备,并且知道其解锁密码,或是向设备以生物信息证明了身份),但由于完全去掉了密码,设备本身的安全性就很重要了,在 Google的实现中 ,锁屏密码用于生成端到端加密的密钥,因此一个能够登录Google账户,并且获知了锁屏PIN的人便能恢复出passkey。根据文章的说法,通过硬件保证了PIN只能尝试最多十次,但总体上,无论是Google还是Apple的实现都依赖于一直在线的手机本身的安全性,而U2F设备通常并不是连接在设备上的,因此我认为尽管对普通人来说passkey已经足够好,但对于需要持续提高电击电压的人群来说,使用密码 + U2F会更安全一些。