【问题标题】:Create a password encrypted and store it in sqlite to use in authentication创建一个加密的密码并将其存储在 sqlite 中以用于身份验证
【发布时间】:2012-06-30 00:15:47
【问题描述】:

我有一个带有登录表单的 WinForms 应用程序,我想将加密的用户名和密码存储在 SQLite 数据库中。看到可以使用salt和hash,但是不知道代码里的密码怎么加密,认证的时候对比一下。

有什么帮助吗?

【问题讨论】:

  • 如果您使用加密来保护密码,那么您做错了。

标签: c# winforms saltedhash


【解决方案1】:

您将需要获取用户名和密码(来自屏蔽文本框的密码,最好使用第二个框进行确认)对其进行加盐,并从密码创建哈希,然后插入明文用户名和加盐哈希数据库中的密码。然后,您可以通过将数据库存储的版本与用户输入的加盐(相同的盐!)哈希值进行比较来验证用户密码。

请注意,每个用户都应该有自己的盐,您在创建帐户时会为该用户随机生成这些盐。 (这比黑客可以发现的全局盐值更安全。

看看this article。它几乎涵盖了所有基础,但不要使用文章中推荐的 SHA-1。您需要一个计算量很大的慢速散列函数,例如 BCrypt 或 PBKDF2(包含在 .NET 中)。见"What makes a good hash function for passwords"。 (感谢@CodeInChaos 指出这一点)。

您可以在 System.Security.Cryptography 中使用Rfc2898DeriveBytes 来创建密码的加盐哈希,PBKDF2 样式。

byte[] salt = Guid.NewGuid().ToByteArray[];
Rfc2898DeriveBytes saltedHash = new Rfc2898DeriveBytes("P@$$w0rd", salt, 1000);

一个好的经验法则是迭代次数应该使散列操作花费大约一秒钟。

【讨论】:

  • -1 因为文章中的代码很弱。单次迭代 SHA1 实在是太快了。
  • @Ostorlabi 我已经编辑了我的示例,将您指向 PBKDF2 - 包含在 .NET 框架中,因此比第三方解决方案更值得信赖。
  • @Idlemind 谢谢 Idlemind,还有一个问题,现在我必须在数据库中存储用户名和 saltedHash 或 salt (byte[] salt = saltedHash.Salt;)?我必须比较什么?
  • @Ostorlabi 您将在数据库中存储用户名、salt 和 saltedhash。当用户登录时,将他们提供的密码与该用户的 salt 进行哈希处理,然后比较结果。如果两个哈希值相等,则用户提供了正确的密码。
【解决方案2】:

您需要将哈希密码和盐存储在数据库中。为每个用户使用随机盐(GUID 应该没问题) 你可以用类似的东西来散列你的密码:

记得添加using System.Security.Cryptography;命名空间。

    public static string ComputeHash(string passwordPlainText, string saltString)
    {
        // Convert plain text into a byte array.
        byte[] saltBytes = Encoding.UTF8.GetBytes(saltString);

        // Convert plain text into a byte array.
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

        // Allocate array, which will hold plain text and salt.
        byte[] plainTextWithSaltBytes =
                new byte[plainTextBytes.Length + saltBytes.Length];

        // Copy plain text bytes into resulting array.
        for (int i = 0; i < plainTextBytes.Length; i++)
            plainTextWithSaltBytes[i] = plainTextBytes[i];

        // Append salt bytes to the resulting array.
        for (int i = 0; i < saltBytes.Length; i++)
            plainTextWithSaltBytes[plainTextBytes.Length + i] = saltBytes[i];

        // Because we support multiple hashing algorithms, we must define
        // hash object as a common (abstract) base class. We will specify the
        // actual hashing algorithm class later during object creation.
        HashAlgorithm hash;

        hash = new SHA256Managed();

        // Compute hash value of our plain text with appended salt.
        byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes);

        // Create array which will hold hash and original salt bytes.
        byte[] hashWithSaltBytes = new byte[hashBytes.Length +
                                            saltBytes.Length];

        // Copy hash bytes into resulting array.
        for (int i = 0; i < hashBytes.Length; i++)
            hashWithSaltBytes[i] = hashBytes[i];

        // Append salt bytes to the result.
        for (int i = 0; i < saltBytes.Length; i++)
            hashWithSaltBytes[hashBytes.Length + i] = saltBytes[i];

        // Convert result into a base64-encoded string.
        string hashValue = Convert.ToBase64String(hashWithSaltBytes);

        // Return the result.
        return hashValue;
    }

您可以将SHA256Managed 更改为任何其他受支持的哈希算法。

更新:我认为您需要先了解这个概念。我会试着解释一下:

在登录之前,您需要在数据库中创建用户。要创建它们,您需要用户名和密码。

  1. 生成随机 SALT,例如 Guid.NewGuid().ToString();
  2. 现在您将这个盐添加到您的密码中并对结果进行哈希处理,这意味着您可以提高密码对暴力攻击的安全性。 (这一步可以通过我之前发的string ComputeHash(string passwordPlainText, string saltString)函数来完成。
  3. 在数据库中保存用户名(由用户提供)、salt(guid) 和密码(computeHash 的结果)。
  4. 使用包含用户数据的表登录!

【讨论】:

  • 首先,谢谢你的回答,我在这个线程中比较新,所以我有一种登录形式(目前,我在代码中有一个用户登录和 psw,我与用户进行比较输入),如果我想使用你的建议,我应该如何处理?
  • @Ostorlabi 我在答案中解释了这背后的概念。
  • -1 用于使用单次迭代散列。使用 PBKDF2、bcrypt 或 scrypt。
猜你喜欢
  • 2014-02-04
  • 1970-01-01
  • 2023-03-21
  • 2014-05-30
  • 1970-01-01
  • 2021-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多