C#——如何正确散列密码(字符串)

C# -- How To Properly Hash A Password (String)

我目前正在使用 C#Form 应用程序,它有一个登录系统,用户必须在其中输入用户名和密码才能使用该程序。这些用户帐户 存储在 XML 文件中 ,目前以纯文本形式存储(我仅处于原型阶段)。我正在寻找一种方法来 散列密码(可能还有用户名),然后将它们存储在 XML 文件中。

我已经对此进行了一些研究,但每次我进行另一次搜索时,我都会找到一种不同的加密 sting 的方法。有些方法能够加密和解密字符串,而其他方法只能加密字符串。我正在尝试找到最适合我情况的方法。

对于我的代码,我只需要散列密码。据我所知,这将有助于确保它们更安全。我显然可以在登录时散列密码然后进行比较,因此解密不是真正的问题。此外,该过程需要在任何计算机上运行。我看到一些答案只能在一台机器上运行,我正在寻找尽可能跨机器兼容的东西。另一件事是,散列的输出必须能够序列化为 XML 文件,而无需对用于写入 XML 文件的代码进行大量修改.目前我正在使用 XMLSerializer 和 StreamWriter 写入 XML 文件。

同样,我见过很多加密或散列密码的方法,但我对加密和散列内容比较陌生,所以我不知道执行此操作的好方法。任何帮助将不胜感激,如果需要,我可以添加一些示例代码。

  1. 您应该生成名为“salt”的随机字符串
  2. 将您的普通密码字符串与盐和哈希结果结合起来

详情:

  1. 生成一个长随机盐。注意:每个登录密码对的盐必须不同!
  2. hash = sha(salt + password) //伪代码
  3. 在您的文件中保存散列和盐

登录时:

  1. 再次计算哈希值。 hash = sha(salt_in_file + password_input)
  2. 将哈希值与您的 hash_in_file
  3. 进行比较

并且不要使用 MD5!更好看 here 另请参阅 this 文章

更新: 好吧,也许这种方法还不够好。如果你想要真正强大的安全性,你应该使用特殊的慢散列算法。其中一些已经保持盐分。我并不声称自己是密码学专家。在这方面永远不要依赖单一意见。

不管怎样,在很多情况下以上应该足够了。

散列密码的正确方法是使用像 bcrypt or scrypt 这样的专门函数。

像 MD5、SHA-1 甚至 SHA-256 这样的快速散列算法都不是散列密码的好选择,因为它们太快了而且很容易被暴力破解。用普通硬件可以计算出大约3 Giga SHA-1 per second

相反,您可以使用慢速密钥派生函数,如 BCrypt 或 PBKDF2。 CSharp 原生支持 PBKDF2,可以使用 Rfc2898DeriveBytes class 实现,您可以找到 here.

的示例

同样好用的是这个BCrypt library。通常人们不确定使用此类库是否安全,但我认为没有理由反对使用它。只要库 returns 正确的值并正确生成盐,就应该没问题,因为安全性来自算法而不是实现。