众所周知,存储明文密码是一种很糟糕的做法。如果把明文密码保存在数据库里,一旦数据库遭到破坏,用户的账号信息就很危险。早在1976年,软件行业就对存储密码的安全机制进行了标准化,也就是使用单向的散列机制(从Unix的Crypt开始)。不过可惜的是,虽然这种方式避免了明文密码被直接读取,但攻击者仍然可以对散列值进行离线暴力破解。他们使用一系列可能的密码,对它们进行散列,并把它们与原始散列值进行比较,从而找出密码的明文。这么说来,使用哈希算法SHA对密码进行散列就存在一定的瑕疵:SHA算法速度太快,这样会加快暴力破解的速度。一个现代商用CPU每秒钟可以生成数百万个SHA256散列值,而一些特定的GPU集群每秒钟可以生成数十亿个。
在过去几年,Dropbox多次悄无声息地对他们的密码散列机制进行了升级,确保把那些不怀好意的攻击者甩在身后。在这篇文章里,Dropbox的安全团队分享了他们目前正在使用的密码存储机制并披露了背后的原因。他们的密码存储机制包含了三层加密保护,如下图所示。为了方便说明,图中省略掉了二进制编码环节(base64)。
Dropbox使用bcrypt作为散列算法的核心组件,并结合用户salt和密钥(全局的pepper),这些salt和pepper独立于密码进行保存。Dropbox所使用的bcrypt与基本的bcrypt有几个关键的不同点。
首先,他们使用SHA512对明文密码进行散列,这样可以解决bcrypt存在的两个问题。有些bcrypt实现版本会把输入值截至72个字节,这样会降低密码的熵数。有些实现版本则不会截短输入值,它们允许任意长度的密码,不过这样容易遭受DoS攻击。使用SHA算法可以把任意长短的密码快速转化成定长为512字节的散列值,从而避免了上述两个问题。
接下来,他们通过bcrypt对经过SHA512散列过的值进行再次散列,这次散列会用到用户salt,并且散列成本为10。bcrypt跟SHA不太一样的地方在于,它的速度比较慢,无法通过硬件加速来加快生成速度。在Dropbox的服务器上,工作因子10就相当于差不多100毫秒的生成时间。
最后,他们使用一个密钥对bcrypt散列过的散列值进行AES256加密,这个密钥是全局的,称为pepper。pepper通过深度来衡量安全性,而且是独立保存的(不在同一个数据库表里),这样攻击者很难获得该密钥。如果攻击者获取了密码,但是在没有这个密钥的前提下,他们也没办法进行暴力破解。
Dropbox团队曾经考虑过使用scrypt,不过他们对bcrypt有更多的使用经验。关于这两种算法孰优孰劣的讨论仍然没有定论,不过大部分专家认为这两种算法提供的安全性是差不多的。
不过Dropbox团队正在考虑在后续的升级版本中使用argon2:在开发当前的加密机制时,argon2还没有在密码散列竞赛中胜出。而且尽管argon2是一个优秀的散列算法,但bcrypt在安全和稳定性方面做得也很不错,从1999年以来都没有出现过重大缺陷。
pepper从深度上来加强安全性,并且是单独保存的。不过尽管是单独保存,仍然有可能遭到泄露。而且一旦使用了全局的pepper进行散列,就不能轻易对它进行变更。不过使用pepper进行加密,不仅可以增强安全性,而且可以对其进行变更。加密函数的输入值可以是随机的,不过他们提供了一个随机初始化向量。
Dropbox团队往后会考虑把全局pepper保存在硬件安全模块(HSM)里。对于Dropbox来说,这样会给他们带来一定的复杂性,不过也会极大地降低pepper泄露的可能性。他们还计划在下一个版本中加强bcrypt的健壮性。
Dropbox团队相信,使用SHA512、bcrypt和AES256来保护用户密码在目前看来是最为安全的方式。不过攻击者也在不断演化,加密与反加密的斗争在持续进行。不过上述的密码散列过程只是Dropbox在保护用户敏感信息方面采取的手段之一。他们还额外部署了一些保护层来应对在线暴力攻击,比如速率限定、验证码等等。
今日荐文
点击下方图片即可阅读
哪个技术火就选哪个?切记知乎驱动的技术选型不靠谱!
QCon北京将邀请来自Google、Facebook、阿里巴巴、腾讯、百度、美团点评、爱奇艺等典型互联网公司的技术专家,分享他们在相关技术领域最新成果。具体详戳 「 阅读原文 」惊喜不停!