`

密码的存储

阅读更多

在各种线上应用中,用户名密码是用户身份认证的关键,它的安全重要性不言而喻。一方面,作为保护用户敏感数据的“钥匙”,一旦被破解,系统将敞开大门完全不设防。另一方面,密码这把“钥匙”本身就是非常重要的数据:用户经常会在多个应用中使用相同或相似的密码。一旦某一个应用的密码被破解,很可能,坏人就因此而掌握了用户的“万钥匙”,这个用户的其它应用也相当危险了。

这篇博文就重点讨论对于密码原文本身的存储的安全性考虑,而系统自身的安全性不在此文的范围之内。

那么,对于如此重要的用户密码,究竟该怎样在系统中存储呢?

 

“君子不立危墙”,对于用户密码这个烫手的山芋,一个极端的选择是系统完全不接触密码,用户的身份认证转而交由受信任的第三方来完成,比如 OpenID 这样的解决方案。系统向受信任的第三方求证用户身份的合法性,用户通过密码向第三方证明自己的身份。

这样,密码完全不经过系统,系统也就不用绞尽脑汁保证密码的安全了。这个作法对用户来说还有个额外的好处:再也不用为每个应用注册帐号了,同一个 OpenID 就可以登录所有支持 OpenID 的系统了。

好虽好,可在今天这样一个各自为战,划分地盘的网络战国时代,作为一个自主的系统,自己的用户资源居然不能掌握在自己的手上,而要与别人分享,甚至 “受制于人”,这多少有点让人难以接受。(据称,现在全球有 27000 个 Web Site 支持 OpenID 登录,虽然还在持续增长中,但在茫茫“网海“中无疑还是属于小众)

好吧,既然网络大同时代还没来临,系统还是要自己负责用户的认证,那密码该如何存储呢?按照安全性由低到高,有这样几种选择:

  1. 密码名文直接存储在系统中

     

    这种方法下密码本身的安全性比系统本身还低,系统管理员可以直接看到所有用户的密码名文。除非你是做恶意网站故意套取用户密码,否则不要用这种方式。

  2. 密码名文经过对称转换后再存储的

    这跟上面的直接明文的方式没有多少本质改进,任何知道或破解出转换方法的人都可以通过相应的逆转换得到密码原文。

  3. 密码经过对称加密后再存储

     

    用户密码明文的安全性等同于加密密钥本身的安全性。对称加密的密钥会同时用于加密和解密,所以它会直接出现在加密代码中,破解的可能性也相当大。而且,知道密钥的人很可能就是系统管理员,所有人的密码原文他都能算出来。

  4. 密码经过非对称加密后再存储

     

    密码的安全性等同于私钥的安全性。密码明文经过公钥加密,而要还原名文,则必须要私钥才行。因此只要保证私钥的安全,密码名文就会安全。私钥可以由某个受信任的人或机构来掌管,普通的身份验证只需要用公钥加密就可以了。
    实际上,这也是 HTTPS/SSL 的理论基础。这里的关键是 私钥的安全 ,如果私钥泄露,那密码名文就危险了。

以上 4 种方法的一个共同特点是可以从存储的密码形式还原到密码的明文。

如果你注册了一个网站,当你忘了密码后,网站可以很贴心地通过你注册的 email 告诉你原来的密码是什么,那么,它肯定就是用了上面的4种方法中的一种了。这时候你就得小心了:既然网站能知道你的密码明文,那网站的工作人员就可能知道你的密码明文,任何攻入了这个网站的人也有了还原你密码明文的可能,甚至于,网站本身就是恶意的钓鱼网站。

所以,最好的保存密码的方式是以连系统自己都不可能还原明文的方式来保存,也就是常用的利用哈希算法的单向性来保证明文的信息以 不可还原的有损方式 进行存储。

这大类的各个方式按安全性由低到高为:

  1. 使用自己独创的哈希算法对密码进行哈希,存储哈希过的值。

     

    哈希算法的要求很高,一般来说,自己独创的哈希算法肯定没有公开的经过时间检验的算法质量高,除非你是天才。

  2. 使用 MD5 或 SHA-1 进行哈希然很存储。

     

    MD5 和 SHA-1 已经被破解。这意味着虽然不能还原密码原文,但很容易找到一个能同样生成相同哈希值的密码原文的碰撞。还有一点,这两个算法相对速度较快,这就意味着对暴力破解来说消耗的资源少。 所以建议不要使用它们。

  3. 直接使用更安全的 SHA-256 等成熟算法。

     

    这个只是在一定程度上增加了暴力破解的时间。如果遇到简单密码,通过常用密码字典的暴力破解法,很快就可以还原密码原文。

  4. 加入了随机 Salt 的哈希算法。

    密码原文(或进过hash后的值)和随机生成的 salt 字符串混淆,然后再进行 hash,最后把 hash 值和 salt 值一起存储。验证密码的时候,只要用存储的 salt 值再做一次相同的 hash 再与存储的 hash 值比较就可以了。

    这样一来,就算用户使用简单的密码,但进过 Salt 混淆过的字符串就是一个很不常见的串,一般不会出现在密码常用字典中。Salt 的程度越长,暴力破解的难度就越大。

    具体的 hash 过程也可以进行若干次叠代,虽然 hash 叠代会增加碰撞率,但也增加暴力破解的资源消耗。
    最后,就算真被暴力破解了,被破解的也只是这个随机 salt 混淆过的密码,破解者不能用它来登录该用户的其它应用(如果其它应用也用了自己的随机 salt)

上面这几种方法都不可能还原密码的明文,这意谓着,就算是系统管理员也不知道密码原文。这也意谓着,这个世界上只有你知道你自己的密码。网站再也没有办法提醒你原来的密码是什么了。对于那些真的忘了自己密码的用户,网站可以提供一个重置密码的功能,帮用户随机生成一个临时密码,让用户通过这个临时密码来登录到系统中重新设置新的密码。

下面的 python 程序就是使用了 salt hash 来加密密码明文

import os
from hashlib import sha256
from hmac import HMAC
 
def encrypt_password(password, salt=None):
    """Hash password on the fly."""
    if salt is None:
        salt = os.urandom(8) # 64 bits.
 
    assert 8 == len(salt)
    assert isinstance(salt, str)
 
    if isinstance(password, unicode):
        password = password.encode('UTF-8')
 
    assert isinstance(password, str)
 
    result = password
    for i in xrange(10):
        result = HMAC(result, salt, sha256).digest()
 
    return salt + result

这里先通过标准随机库生成 64 bits 的随机 salt,使用了标准的 SHA-256 做为基本的 hash 算法,使用标准 HMAC 算法作为 salt 混淆。并且进行了 10 次混淆 hash。最后将 salt 和 hash 结果一起返回。

使用的方法很简单:

hashed = encrypt_password('secret password')

下面是验证函数

def validate_password(hashed, input_password):
    return hashed == encrypt_password(input_password, salt=hashed[:8])

它直接使用 encrypt_password 来对待检验的密码进行相同的 salt 混淆 hash 并与出口存储的值比较。
使用示例:

assert validate_password(hashed, 'secret password')

上面的实现虽然只有简单几行,但借助了 python 标准库的力量,已经是一个可用于生产环境的高安全的密码存储方案了。

总结一下用户密码的存储:

  • 如果可能,不要存任何密码信息
    让别人来帮你做事(OpenID)
  • 如果非要自己认证,也只能存 有损的密码信息 。通过单向 hash 和 salt 来保证密码明文只存在用户手中

  • 绝对不能存可还原密码原文的信息 。如果因为种种原因一定要可还原密码原文,请使用非对称加密,并保管好私钥

     

说完了密码的存储,后面的一篇会接着聊聊密码的传输

文章信息

分享到:
评论

相关推荐

    本地密码储存读取器本地密码储存读取器

    它的工作原理是通过解析操作系统或特定应用程序的密码存储格式,获取到加密后的密码数据,然后通过解密过程,以明文形式展示给用户。 在实际使用中,本地密码储存读取器可以帮助用户检查和审计他们的密码安全状况。...

    密码存储工具测试版Beta

    标题中的“密码存储工具测试版Beta”表明这是一个用于安全存储密码的应用程序的早期版本,旨在帮助用户管理和保护他们的各种账号密码。在当前的网络安全环境中,密码管理器是至关重要的,因为人们往往需要记住多个...

    VC++ MD5 加 数据库密码存储!

    在给定的"VC++ MD5 加 数据库密码存储!"项目中,我们看到一个使用Visual Studio 2010(VS2010)编写的示例,它展示了如何通过MD5哈希算法来处理数据库中的密码。MD5(Message-Digest Algorithm 5)是一种广泛使用的...

    简单的密码例子,让密码储存在程序中.zip_VB 密码

    为了实现密码存储,VB程序通常会使用`Const`关键字定义常量来储存密码,以避免在代码中明文显示。例如: ```vb Const PASSWORD As String = "mysecret" ``` 然后,当用户点击“验证”按钮时,VB代码会检查输入的...

    自用密码储存器

    2. **密码储存安全**:密码储存器的核心在于安全地存储用户密码。通常,不应明文存储密码,而是使用加密算法如bcrypt或scrypt对密码进行哈希处理,然后存储哈希值。在用户登录时,将输入的密码进行同样的哈希处理,...

    代码中密码存储sskeychain

    在iOS开发中,安全地存储用户敏感信息,如密码、API密钥或证书,是至关重要的。`SSKeychain`是一个流行的开源库,它简化了与iOS内置的安全服务——钥匙串(Keychain)的交互。钥匙串是苹果操作系统提供的一种安全...

    密码储存神器

    【密码储存神器——深入了解 KeePass】 KeePass,被誉为密码储存神器,是当前最流行的密码管理工具之一。这款软件在2022年八月进行了最新版本的更新,旨在为用户提供更加安全、便捷的方式来存储和管理他们的数字...

    基于STM32的家用密码存储系统设计.pdf

    本篇论文讲述了基于STM32微控制器设计的家用密码存储系统的设计过程与实现。该系统能够实现密码的输入、存储、读取,并在LCD1602显示屏上展示系统运行过程和结果。文章中提到的关键技术和组件包括STM32微控制器、IIC...

    简单的密码例子,让密码储存在程序中.rar_网密码例子

    "简单的密码例子,让密码储存在程序中"这个主题涉及到基础的密码处理和存储方式,这是一个非常基础但也是非常重要的话题,因为不正确的处理方式可能导致严重的安全风险。 首先,我们需要明确的是,直接在程序中明文...

    pass密码存储系统.zip

    pass是一个简单的密码存储机制,它使用GPG加密技术保护密码安全。通过创建一个加密的密码存储库,用户可以轻松地管理和存储各种账号的密码。该项目提供了方便的命令行工具,使得用户可以轻松地添加、查询和更新密码...

    Java中安全密码存储实践:加密、散列与最佳策略

    密码存储是任何需要用户认证的系统的关键部分。在Java中实现安全的密码存储需要考虑多种因素,包括使用强散列函数、盐值、密钥拉伸技术以及安全存储实践。本文将详细介绍如何在Java应用程序中安全地存储密码,包括...

    高度便携的极轻量级密码管理器可将您的所有密码存储在本地加密文件中

    描述进一步强调了该密码管理器的主要特性,即“将所有密码存储在本地加密文件中”。这表明该软件采用了一种安全的数据存储策略,通过加密技术来保护用户的敏感信息。用户的所有密码都被储存在一个单一的文件中,这个...

    密码存储中MD5算法的安全性分析1

    密码存储中MD5算法的安全性分析 摘要:本文分析了哈希算法MD5在密码存储中的安全隐患,并讨论了不同的解决方案,如盐和迭代散列。我们提出了一种新方法,在密码存储中使用MD5,使用外部信息,计算盐和随机密钥在MD5...

    密码存储管理系统

    sqlserver C# VS2005密码管理系统

    密码存储中MD5算法的安全性分析2

    综上所述,MD5算法在密码存储中的安全性已不再可靠,需要结合盐值和其他强化措施,如使用更安全的哈希算法(如SHA系列),以及密码加盐、迭代哈希等方法,以提升密码存储的安全性。在实际应用中,应当重视密码策略,...

    KeePass(本地密码管理)v2.50一款个人信息密码电脑管理软件.exe

    KeePass 是一款管理密码的开源的免费软件,KeePass 将密码存储为一个数据库,而这个数据库由一个主密码或密码文件锁住,也就是说我们只需要记住一个主密码,或使用一个密码文件,就可以解开这个数据库,就可以获得...

    基于51单片机+AT24C02密码存储+LCD1602显示的电子密码锁软件设计源码+文档说明资料.rar

    基于51单片机+AT24C02密码存储+LCD1602显示的电子密码锁软件设计源码+文档说明资料 main() { u8 data1,a; // ShowString(0x00," Pechin Science "); // At24c02Write(0,0); //开机显示密码 LcdWriteCom(0x01);...

    keepass密码储存

    KeePass Password Safe 就是专门为了解决人类记不得众多密码的问题所产生的,它包含了一个强大的密码产生引擎与加密储存机能,能够提供一个安全的密码储存空间。当你开始使用 KeePass Password Safe 时,要先决定一...

    Tkinter+SQLite实现账号密码存储

    Tkinter+SQLite实现账号密码存储。由于生活中用到的账号密码太多了,因此开发这个工具,实现账号密码存储在数据库中,忘记了就可以查询。

    基于STM32的家用密码存储系统设计.zip

    标题中的“基于STM32的家用密码存储系统设计”揭示了这个项目的核心是利用STM32微控制器开发一个用于家庭环境的密码管理装置。STM32是一款广泛应用的微控制器,由意法半导体(STMicroelectronics)生产,具有高性能...

Global site tag (gtag.js) - Google Analytics