我使用我的.NET(C#)客户端中的CryptSharp Library使用随机生成的盐(Blowfish)来哈希用户的密码。
然后我继续将散列密码发送到我的远程服务器,并将其存储在MySQL数据库中。
当我尝试使用相同的纯文本密码登录时,发送的内容与数据库中存储的内容之间存在哈希不匹配。 (很可能是因为盐每次都在变化)
我不想向我的PHP端发送未加密的纯文本密码,如何在不使用静态盐的情况下实现此目的?
哈希(C#):
string passHash = Crypter.Blowfish.Crypt(Password.Text, Crypter.Blowfish.GenerateSalt());
我不想在注册时创建一个新列来存储客户端的盐,但如果我必须,我会这样做。
答案 0 :(得分:0)
答案很简单,与使用的语言无关:
如果您希望服务器在数据库中存储散列密码,您可以使用任何散列函数存储它们(如果您想使暴力破坏需要更长时间,我建议使用SHA256或BCrypt。到BCrypt是盐,迭代次数直接存储在哈希中,因此数据库中不需要额外的列)。
如果您想加盐,您需要存储盐柱并将其传输到客户端以便在散列过程中使用。通常,您将为每个用户使用随机盐,并且只有在更改密码时才会更改。这是推荐但不是必需的 - 它使得彩虹表攻击变得毫无用处。
如果您担心通过网络传输,而不是特别关注数据库,您可以在身份验证期间在服务器上生成随机盐,并且只使用一次 - 但服务器需要用于比较的原始密码。
你也可以结合所有这些方法,虽然我不认为这是任何地方的标准做法。
答案 1 :(得分:0)
您可以使用:
*ngIf="project"
var result = string.Empty;
using (var sha1 = new SHA1Managed())
{
result = ToHex(sha1.ComputeHash(Encoding.ASCII.GetBytes(Password.Text)));
}
看起来像这样:
ToHex
以前的代码在多次调用时确实产生相同的哈希,而不需要涉及盐。
.NET框架中还支持其他更安全的SHA算法版本,例如public static string ToHex(byte[] bytes)
{
return string.Concat(bytes.Select(b => b.ToString("X2")));
}
。使用SHA1或SHA256取决于您的安全要求。
答案 2 :(得分:0)
加密密码的目的是将密码安全地存储在数据库中。 CryptSharp不会帮助您确保通过电线传输。
您可以采取多种方法,但最简单的方法可能是通过SSL与服务器进行通信。如果您不想使用公共CA,请使用自签名证书并挂钩ServicePointManager.ServerCertificateValidationCallback以接受您自己的CA或证书。
答案 3 :(得分:0)
要将密码从客户端传输到服务器,需要加密的HTTPS / SSL连接。它会在将用户输入发送到客户端之前对其进行加密,因此ManInTheMiddle无法进行窃听。散列必须在服务器端完成,至少是散列的一部分。
CryptSharp支持通用存储格式,并在生成的哈希中包含salt。不幸的是,似乎没有一种验证方法,它会提取用过的盐,至少我找不到。
我可以推荐的另一个库是BCrypt.Net,盐也与哈希一起存储(不需要额外的字段),验证非常简单:BCrypt.Verify(password, stored_hash)