确保密码安全

发布于 2024-07-29 21:15:03 字数 604 浏览 6 评论 0原文

情况 1 - 将服务器连接到数据库:
它总是说密码不应该以纯文本形式存储,但是连接到 mysql 数据库需要密码,似乎以纯文本形式......我猜最好的解决方案是以加密形式存储它,根据需要在我的应用程序中解密它,然后从内存中删除它(我猜 Windows 中的 SecureZeroMemory 所以编译器无法优化它)。

情况 2 - 用户从远程计算机登录服务器:
至于用户密码,我的计划是根本不实际存储原始密码。 相反,我将为每个用户存储一个随机生成的“盐”,在密码前加上它,然后对其进行哈希处理,这似乎是一种相对常见的方式。 但是我目前没有可用的 SSL 连接,所以我猜测纯文本密码可能会被拦截,对此有什么好的解决方案吗?

有哪些好的算法(如果有的话,C/C++ 实现的链接也很方便)可以做到这一点,在网上一看,有 100 个这样的算法?

编辑:
如果我获得了 SSL,以下内容是否安全(假设使用强哈希算法),或者应该使用不同的方法?

  1. 客户端请求用户名的 salt
  2. 客户端在密码前添加 salt,然后对其进行哈希处理,然后将哈希值发送到服务器
  3. 服务器将收到的哈希值与服务器上该用户名的哈希值进行比较

Situation 1 - Connecting the server to the database:
Its always said that passwords should not be stored in plain text, however to connect to the mysql database requires the password, in plain text it seems... I'm guessing the best solution to this is to store it in an encrypted form, decrypt it in my app as needed and then erase it from memory (SecureZeroMemory in windows I guess so the compiler cant optimise it out).

Situation 2 - Users logging into the server from a remote computer:
As for users passwords my plan is to never actually store the original password at all.
Instead I will store a randomly generated "salt", for each user, prefix there password with it then hash it, which seems to be a relatively common way. However I don't have an SSL connection available at this point, so I'm guessing the plain text passwords could be intercepted, what's a good solution to this?

What are good algorithms (links to C/C++ implementations would be handy as well if you have them) for doing this, a look on the net comes up with 100's of them?

EDIT:
If I got SSL, would the following be secure (assuming a strong hash algorithm is used), or should a different method be used?

  1. Client requests salt for a user name
  2. Client prefixes password with salt, then hashes it before sending the hash to the server
  3. Server compares hash recieved to the one on the server for that user name

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我三岁 2024-08-05 21:15:03

将服务器连接到数据库

仅将数据库密码存储在服务器中(无论是否加密)都是一个坏主意。 当然,以纯文本形式存储它是显而易见的。 如果你只是加密存储,服务器仍然需要密钥来解码它。 在服务器代码中找到密钥通常并不难。 最好的解决方案是让启动服务器的用户输入密码并将其存储在任何地方。 或者 - 甚至可能更好 - 您可以加密存储所有敏感信息 - 例如数据库用户、密码等,并让启动服务器的用户输入主密钥来解密此信息。

将用户连接到服务器

这确实是一个难题,而且很容易搞砸。 引用这篇很棒的文章关于我绝对推荐阅读的主题。

不,真的。 使用别人的密码系统。 不要构建自己的。

一个好的解决方案可能是使用安全远程密码协议

Connecting the server to the database

Just storing the database password in the server - encrypted or not - is a bad idea. It is obvious storing it in plain text, of course. And if you just store it encrypted, the server still needs the key to decode it. It is usually not very hard to find the key in the server code. The best solution is to let the user starting the server enter the password and store it nowhere. Alternatively - and probably even better - you can store all sensitive information - for example database users, passwords, and so on - encrypted and let the user starting the server enter a master key to decrypt this information.

Connecting a user to the server

This is really a hard problem and easy to mess up. A quote from this great article article on the topic I absolutely recommend reading.

No, really. Use someone else’s password system. Don’t build your own.

A good solution might be using the Secure Remote Password Protocol.

疯到世界奔溃 2024-08-05 21:15:03

您是对的,如果您不使用 SSL,那么密码可能会被拦截。

通常的做法是永远不会解密用户的密码,因此请使用盐对其进行哈希存储,当用户输入密码时,您将添加盐并对其进行哈希处理,将其与存储的哈希密码进行比较。 这将使您永远不会拥有密码的解密版本。

您确实应该考虑保护连接,以便用户输入密码时密码是安全的。

更新以回答已编辑的问题:
如果您使用 SSL 保护通信,您仍然可以使用任意数量的您喜欢的额外安全措施,包括散列密码。 为了增加安全性,最好记住您存储的密码应该使用盐进行散列存储。 该盐应该安全保存,并且除了您的应用程序之外,绝不能在任何地方访问。 这样,当用户提交密码时,您只需添加盐和哈希值,然后将该版本与存储的版本进行比较。

You are correct that if you're not using SSL then the passwords can be intercepted.

It is common practice to never decrypt a user's password, so keep it stored hashed with a salt and when the user types in their password you will add the salt and hash it, comparing it with the stored, hashed password. This will allow you to never have the decrypted version of the password every.

You really should look into securing the connection so that the password is secure when the user types it in.

Update to answer edited question:
If you have the communication secured using SSL you can still use any number of extra measures of security you like including hashing the password. As added security it is a good idea to remember that the password you store should be stored hashed with a salt. That salt should be kept safe and never be accessible anywhere except by your application. This way when the user submits the password you just add the salt and hash and you compare that version with the stored version.

三人与歌 2024-08-05 21:15:03

情况 1 - 将服务器连接到数据库

这里没有一个简单的答案。 为了连接,服务器需要密码(或对称密钥,或私钥或其他)。 它必须从磁盘或某种外部方式(例如管理员在启动时键入它)获取它。 添加一些间接方法,例如在主密码下加密所有敏感内容,可以增加一些便利,但不会改变情况。

通常,将密码或密钥放在服务器上的文件中就可以了。 如果执行此操作,请确保设置该文件的权限,以便只有需要该文件的用户才能访问该文件。 这是让系统上的不同进程以不同的用户身份运行,并为每个进程设置单独的角色/帐户和密码的一个很好的理由。

情况 2 - 用户从远程计算机登录服务器

我认为您的方向是正确的。 听起来您要求的是安全身份验证协议。 您需要一种能够提供相互身份验证并防止中间人攻击的方法,如果尝试进行此类攻击,就会失败。 当然有很多可供选择。

还值得考虑的是,您的身份验证是否应该基于“您知道的东西”(密码)或“您拥有的东西”(公钥/私钥)进行操作。 假设根据你的问题,我们正在寻找的是密码,我喜欢的两个是 SRP 和 Kerberos。

前面提到了 SRP,但它并没有得到应有的关注。 SRP 的优点是它不需要服务器知道密码、密钥或攻击者可以用来获取访问权限的任何内容。 如果您使用 SRP 侵入了正确配置的服务器并窃取了所有数据,那么您仍然需要对每个密钥单独执行字典攻击之类的操作,然后才能使用任何东西来模拟用户。

我还喜欢 Kerberos,因为它受到大量软件的支持(我知道 Postgres 支持它,我只发现提到 mysql 不支持任何好的身份验证技术),并且有一个提供单点登录功能的“票据”系统。 Kerberos 需要一些其他技术来帮助加强其初始身份验证交换,SRP 对此非常有用,但我不确定他们是否已经这样做了。 我认为它使 KDC(密钥服务器)具有状态。

Kerberos 的弱点是您必须更加警惕存储密钥的服务器。 虽然它不以明文形式存储密码,但它确实存储密钥,这些密钥本质上是密码的哈希版本。 虽然客户端在身份验证时并不直接发送密码或密钥(毕竟这是真正的身份验证协议),但它确实使用散列密码作为密钥,因此任何了解算法并知道的人都知道钥匙也可以做同样的事情。 我们说服务器存储了“等效密码”。 因此,所有手册都告诉管理员将 kerberos 服务放在各自独立的锁定框中,以最大程度地减少其内容受到损害的可能性。

好处是,一旦您选择了强大的身份验证交换,其他好东西通常会免费出现。 最终双方共享一个共同的“秘密”,该“秘密”可以在会话期间使用一次,永远不会通过网络发送,并且第三方无法知道。 想要加密吗? 钥匙到了,一切准备就绪,可以出发了。 这正是 RFC 5054 中定义 SRP 安全 SSL 的方式。

Situation 1 - Connecting the server to the database

There isn't an easy answer here. In order to connect, the server needs the password (or symmetric key, or private key or whatever). It must get it either from the disk or some external means (like an administrator typing it at startup). Adding some indirection, such as encrypting all the sensitive stuff under a master password, can add some convenience but otherwise doesn't change the situation.

Typically, it is fine to put the password or key in a file on a server. If you do this, make sure to set the permissions on the file so that only the users that need it have access to it. This is an excellent reason to have different processes on your system run as different users, and to set up separate roles/accounts and passwords for each.

Situation 2 - Users logging into the server from a remote computer

You are headed in the right direction here, I think. What it sounds like you're asking for is a secure authentication protocol. You want one that provides mutual authentication and prevents a man-in-the-middle attack by failing if such an attack is attempted. There are many to choose from of course.

It is also worth mulling whether your authentication should operate based on "something you know" (passwords) or "something you have" (public/private keys). Assuming based on your question that what we're looking for is passwords, two that I like are SRP and Kerberos.

SRP was mentioned earlier, and that doesn't get nearly the attention it deserves. SRP has the advantage that it doesn't require the server to know the password, or key, or anything that an attacker could use to gain access. If you broke into a correctly configured server using SRP and stole all the data, you'd still need to do something like a dictionary attack on each key individually before you had anything you could use to impersonate a user.

I also like Kerberos because it is supported by tons of software (I know Postgres supports it, I've only found mentions of mysql not supporting any good authentication technology) and has a system of 'tickets' that provides a single sign on capability. Kerberos needs some other technology to help strengthen its initial authentication exchange and SRP would be great for that but I'm not sure they've done that yet. Something about it making the KDC (key server) stateful I think.

Kerberos' weakness is that you have to be more wary of the server storing the keys. While it doesn't store the passwords in plaintext, it does store the keys, which are essentially hashed versions of the passwords. And while the client doesn't exactly send either the password or the key straight over when authenticating (this is a Real auth protocol after all), it does use the hashed password as the key, and so anyone else who knows the algorithm and knows the key could do the same. We say that the server stores a "password equivalent". As a result, all the manuals tell administrators to put the kerberos services on their own separate, locked-down boxes to minimize the chance of compromising their contents.

The nice thing is, once you settle on a strong authentication exchange, other good things typically fall out of it for free. You end up with both parties sharing a mutual 'secret' that can be used once for the duration of the session, never sent over the wire, and can't be known by a third party. Want encryption? There's the key, all ready to go. This is exactly how SRP-secured SSL is defined in RFC 5054.

活雷疯 2024-08-05 21:15:03

较新的 MySQL 通过网络使用散列密码,因此您不必担心中间人。

如果您担心配置文件中存储的密码,可以使用密码对配置文件进行加密。 但是,问题是您必须输入密码才能启动应用程序。

15 年前我编写了一个类似的应用程序。 那时,PGP 是我的选择。 我什至不确定它是否还存在。

Newer MySQL uses hashed password over the wire, so you don't have to worry about man-in-the-middle.

If you worry about the password stored in your configuration file, you can encrypt the configuration file with a password. However, the problem is that you have to enter a password to start your application.

I wrote a similar application over 15 years ago. Back then, PGP was my choice. I am not even sure it's still around.

挽梦忆笙歌 2024-08-05 21:15:03

不确定这是否是您所要求的。
但是一个使用内置 sha1 函数的简单 PHP 示例:

// Check the hashed password from the database
if (sha1($salt.$password) == $providedPassword)
{
    // User is authenticated
    return TRUE;
}
else
{
    // User is not authenticated    
    return FALSE;
}

您可以做的一件事是在通过网络发送密码之前使用 javascript 对密码进行哈希处理。 问题是客户端和服务器之间如何共享盐字符串? 一种可能性是使用会话变量。 然后使用会话变量在服务器上对密码进行哈希处理。 这意味着中间的人需要知道另一条信息才能理解密码。 不像 SSL 那样安全,但可能是针对随意网络嗅探者的额外防御层。

我还可以想象一个与某种验证码系统相关联的哈希方案,用于在通过网络发送之前对本地客户端上的密码加盐。 客户端将通过完成验证码来提供盐字符串的文本。 你可以自己查一下。

主要担心的是中间人不理解纯文本密码。

应使用 SSL,但在无法使用 SSL 的情况下,上述技术可能会很有用。

Not sure if this is what you are asking for.
But a simple PHP example using the built in sha1 function:

// Check the hashed password from the database
if (sha1($salt.$password) == $providedPassword)
{
    // User is authenticated
    return TRUE;
}
else
{
    // User is not authenticated    
    return FALSE;
}

One thing you could do is also hash the password with javascript before it is sent over the wire. The question is how is the salt string shared between client and server? One possibility is to use a session variable. And then use the session variable to unhash the password afterwards on the server. This would mean that the man in the middle would need to know one other piece of info to make sense of the password. Not as secure as SSL, but perhaps an extra layer of defense against casual network sniffers.

I could also imagine a hashing scheme linked to some sort of captcha system used to salt the password on the local client before sending over the wire. The client would be providing the text for the salt string by completing the captcha. You could look it up on your end.

The main concern is the man in the middle not understanding the plain text password.

SSL should be used, but the above techniques might be useful where SSL is not possible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文