我相信我误解了SecureString
的基本部分。我知道string
是不可变的,并且在堆上找到密码或敏感数据作为明文。
我很难理解的是,如何在需要验证数据库中哈希密码的客户端应用程序中使用SecureString
?
这是我的背景:
SecureString
属性将密码存储在SecurePassword
中。现在怎样? 如何散列SecureString
而不首先将其强制转换为字符串?
到目前为止,我收到的所有建议都是编写将SecureString
转换为String
的扩展方法,对其进行哈希处理,然后将其发送到db进行验证。 但这会使整个练习失败!
我必须接受SecureString
在我提到的上下文中无用并使用普通string
吗?
答案 0 :(得分:4)
SecureString表示为byte [],您可以对字节进行编码,例如使用bitconverter并保存结果。 此外,SecureString是加密而不是哈希,因为它可以被解密。 (见下文)
SecureString主要用于将敏感数据存储在内存中。 如果您有服务/网站,则这不如存储在数据库中的值那么重要。这些永远不应该是纯文本,并且您或任何管理员都不能解密 此外,我不确定另一台服务器是否可以解密字符串,因此您在更改服务器或拥有某种群集方案时可能会遇到问题。
特别是对于密码,我更喜欢使用哈希算法(例如SHA256)。 这些不能被加密(就像数字的总和)。 在登录功能的用例中,您将加密用户输入并比较用户和数据库中的哈希值。 (详情见下文) 我还建议在hashinput中添加像userid这样的动态条件,这样两个具有相同密码的用户就会有不同的哈希值。
使用此策略,您不会有使用userpasswords的risc,因此如果数据泄露,此时就不会出现问题。
以下是使用哈希算法
的简短概述所以(如果给出了securestring)首先decrypt the SecureString
String SecureStringToString(SecureString value){
IntPtr valuePtr = IntPtr.Zero;
try{
valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value);
return Marshal.PtrToStringUni(valuePtr);
}
finally{
Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
}
}
比使用SHA256哈希它。 From this post
using (SHA256 hash = SHA256Managed.Create()) {
Encoding enc = Encoding.UTF8;
//the user id is the salt.
//So 2 users with same password have different hashes.
//For example if someone knows his own hash he can't see who has same password
string input = userInput+userId;
Byte[] result = hash.ComputeHash(enc.GetBytes(input));
foreach (Byte b in result)
Sb.Append(b.ToString("x2")); //You could also use other encodingslike BASE64
}
存储此hashsum。根据您的编码,它可能会像这样:
ac5b208b4d35ec79fa7c14b7a31f9c80392cdab2bc58bc5b79bcfe64b044d899
在您的数据库中。 如果用户登录,则从其输入创建哈希,并将其与数据库中的哈希进行比较。如果它们相等则密码正确。 因此,您无需在任何地方存储明文用户密码。
如果客户端使用哈希值,那么它应该是absolut,如果不存在明文(如果文本框不支持securestring则除外)
PS:这只是一个选择。但主要的是从不在任何地方存储明文密码。为了最好,永远不会知道它们,也没有变化让它们解密。
另一种策略是使用非对称加密,例如RSA,但这可能会变得更加复杂。如果您需要帮助,我会推荐一个专门的帖子。
根据您的要求和环境,大多数情况下hashsums应该是可接受的解决方案。 (但那不是法律建议,因为我不是律师)