Delphi中的密码加密

时间:2020-03-06 14:43:16  来源:igfitidea点击:

我需要将数据库密码存储在配置文件中。出于明显的原因,我想对它们进行加密(最好使用AES)。有谁知道可以轻松将Delphi实现引入到现有项目中,而该项目具有超过10,000行历史增长(URGH!)源代码?

澄清:简单意味着将单元添加到项目中,增加最大值。 5行代码,可读取并完成配置文件。不应超过15分钟。

另一个说明:需要密码才能创建与db的连接,而不是支持应用程序的用户管理方案。因此,使用哈希值无济于事。数据库引擎检查密码是否有效,而不是应用程序。

解决方案

我使用了这个库,真的很容易添加。但是维基只显示了很少的解决方案。

即使我们进行了加密,在我看来,解密密钥以及加密的密码也都将在可执行文件中,这意味着从任何意义上说,安全都不是唯一。任何人都可以获取解密密钥和加密的密码并生成原始密码。

我们想要的是单向哈希。

我第二次推荐了David Barton的DCPCrypt库。我已经在多个项目中成功使用了它,并且在阅读了用法示例之后,不会超过15分钟。它使用MIT许可证,因此我们可以在商业项目或者其他方面自由使用它。 DCPCrypt实现了许多算法,包括Rijndael,它是AES。

还有很多可谷歌搜索的独立(单单元)实现,问题是我们信任哪一个,除非我们准备自己验证特定库的正确性。

Nick当然是对的,我只是假设我们知道要花15分钟的时间来实施安全解决方案时,我们知道自己在做什么。如果我们决定走(更好的)路线,DCPCrypt库还实现了许多哈希算法。

我认为Turbopower LockBox是一个出色的密码学图书馆:

http://sourceforge.net/projects/tplockbox/

我不知道它对使用而言是否太大,但是它非常易于使用,并且我们可以使用5行代码对字符串进行加密。一切都在示例中。

出于典型的身份验证目的,我们不需要存储密码,仅需要检查用户输入的密码是否正确。如果是这种情况,则可以只存储一个哈希签名(例如MD5),然后将其与输入密码的签名进行比较。如果两个签名匹配,则输入的密码正确。

存储加密的密码可能很危险,因为如果有人获得了"主"密码,他们便可以检索所有用户的密码。

如果决定使用MD5,则可以使用Delphi附带的MessageDigest_5.pas(至少我的Delphi 2007副本中包含了该消息)。我们还可以从Delphi源代码中选择其他实现。

TOndrej有正确的做法。我们永远不要使用可逆密码来存储密码。正如正确指出的那样,如果"主"密钥被盗用,则整个系统都将被盗用。使用不可逆的哈希(例如MD5)更加安全,我们可以将哈希值存储为明文。只需对输入的密码进行哈希处理,然后将其与存储的哈希进行比较即可。

只是提醒。

如果我们不需要与其他crypt库互操作,则DCP或者LockBox可以完成此工作。

如果我们需要它完全符合rinjdael规范,请忘记免费的组件,大多数情况下它们有点"糟糕"。

我一直使用Turbopower密码箱。它运作良好,并且非常易于使用。我实际上将它用于完全相同的事情,将密码存储在配置文本文件中。

http://sourceforge.net/projects/tplockbox/

正如其他人指出的那样,出于身份验证的目的,应避免使用可逆加密来存储密码,即,应仅存储密码哈希,并对照已存储的哈希检查用户提供的密码的哈希。但是,这种方法有一个缺点:如果攻击者掌握了密码存储数据库,它很容易受到彩虹表攻击。

我们应该做的是存储预先选择的(和秘密的)盐值和密码的哈希值。即,将盐和密码连接起来,对结果进行哈希处理,然后存储此哈希值。进行身份验证时,将盐值和用户提供的密码(哈希)连接在一起,然后检查是否相等。这使彩虹表攻击变得不可行。

当然,如果用户通过网络发送密码(例如,如果我们使用的是Web或者客户端服务器应用程序),则我们不应以明文形式发送密码,因此不要存储哈希(盐+密码),则应存储并检查哈希(盐+哈希(密码)),并让客户端预先对用户提供的密码进行哈希处理,然后通过网络发送该密码。如果用户(与许多用户一样)将同一密码用于多个目的,这也可以保护用户密码。

我建议使用某种类型的盐。不要将crypt(密码)存储在配置文件中,而是插入该存储crypt(salt + password)。作为"盐",我们可以使用打开数据库所需的内容,例如。 db_name +用户名。对于crypt函数,我们可以使用一些众所周知的算法,例如AES,Idea,DES,或者诸如将每个字节与其他字符串中的字节异或者的简单操作,该字符串将成为密钥。为了使解决方案更加不同,我们可以使用一些随机字节并将其存储。

因此要存储:

  • init_str:= 5个随机字节
  • new_password:=盐+密码//盐:= db_name +用户名
  • crypted_pa​​ssword = xor_bytes(init_str + new_password,"我的密码")
  • crypted_pa​​ssword:= init_str + crypted_pa​​ssword
  • 将crypted_pa​​ssword存储在配置中,因为这将是字节,我们可以将其十六进制或者以base64进行存储

并连接:

  • 从配置读取的数据分为init_str和crypted_pa​​ssword
  • new_password = xor_bytes(init_str + crypted_pa​​ssword,'我的密钥短语')
  • 密码:=从new_password中删除(db_name + user_name)

TurboPower LockBox 3(http://lockbox.seanbdurkin.id.au/)使用自动加盐功能。
我建议不要使用Barton的DCPCrypt,因为IV不会加盐。在某些情况下,这是一个非常严重的安全缺陷。

与先前的评论相反,LB3的AES实施完全符合该标准。

几个解决方案:

  • 完全不存储密码。如果数据库支持集成身份验证,请使用它。可以将进程设置为以特定身份运行,并由数据库自动进行身份验证
  • 使用Windows证书存储区和证书对密码进行加密。如果我们将用于加密密码的密钥存储在应用程序中,那么安全性就很少,还必须保护密钥。

我们需要将其存储在也只有当前用户访问的地方。

基本上有两种方法可以做到这一点:

  • 将其存储在EFS加密文件中。
  • 将其存储在安全的本地存储中。

Internet Explorer使用2. 但是,如果我们具有本地访问权限,则可以解密1.和2.如果我们具有正确的主密钥和算法(例如,iepv可以使用Internet Explorer密码)。

所以:
如果可以,请避免存储密码。
首先寻找替代方法(例如Windows身份验证,目录服务等)。

--jeroen