我正在为我公司的当前产品实施一个新的密码存储过程。它是一个带有MS SQL Server的ASP.NET应用程序。
在他们使用相同的公共种子加密3DES加密并检查用户身份验证之前,他们只是使用相同的种子解密密码。
我正在使用无法解密的salt实现SHA256哈希。
首先,我知道每个用户的每种盐应该是不同的,但我不明白这种盐的储存地点在哪里?如果它存储在数据库中,这是否会使其无效?
我的想法是通过取用户名的前4个字母,第一个名字的前3个字母和姓氏的前3个字母来创建一个盐,并将其转换为md5哈希,然后将其用作没有存储在数据库中的盐。
此序列将是服务器端,因此没有黑客可以在没有源代码的情况下知道序列。
我在这里做的有什么问题吗?
SHA256也可以接受,或者我应该关注SHA512。
由于
答案 0 :(得分:2)
如果你必须自己实现这一点(我个人是MembershipReboot的粉丝,那么你应该看看PBKDF2密码存储。
它不仅可以正确实现盐,还支持多次迭代,以帮助阻止暴力攻击。您可以找到迭代次数here的指导。
另外值得注意的是,如果验证是一个问题,PBKDF2是可接受的NIST standard。
要回答关于将盐保存在数据库中的问题,不需要保密。盐的目的只是为了防止哈希的预先计算,而不是混淆或加密。以任何方式。
Rainbow tables通过预先计算密码来工作,然后在强制执行时查找彩虹表中的相应散列。通过Google搜索MD5哈希,您实际上可以看到它有多简单,并且通常在搜索结果中您可以找到原始输入。
例如,如果你谷歌字符串' 5f4dcc3b5aa765d61d8327deb882cf99',你会发现它对应于'密码'。
通过使用salt,攻击者必须为每个可能的密码计算唯一的哈希值,而不仅仅是通用列表。
答案 1 :(得分:2)
“我在这里做的事情有什么问题吗?”
是的,有。不安全不是安全。仅仅因为盐很难找到并不意味着它非常安全。与强制哈希相比,弄清楚如何创建盐将是一块蛋糕。
没有必要保密盐,只需为每个用户创建一个随机数,并与密码一起存储。盐的目的是消除使用彩虹表来破解表中所有密码的优点。对于大多数用户来说,盐必须是不同的(最好是唯一的,但这并不重要)。
答案 2 :(得分:0)
盐不应该是私人的。它与哈希一起分发,通常在它之前。盐的唯一目的是确保如果相同的数据被加密两次,您将永远得不到相同的输出。根据定义,它必须是唯一的,但不需要随机性或保密性。
您也不应该为每个用户创建一个随机数。 每个加密的盐需要不同,即使对于同一个用户也是如此。只需生成随机盐,使用它来创建哈希,将盐添加到哈希,将所有内容编码为base64,然后存储它。要验证您解码为二进制的哈希,请提取salt,使用它来哈希输入数据并与解码后的哈希进行比较。
像盐一样有效的东西是GUID。根据定义,128位是唯一的,虽然不是完全随机的,并且可以立即使用而无需任何额外的代码以下是AES-256加密和解密的示例。请记住,在实际的实现中,您希望将纯文本和密钥存储在SecureString对象中......
Private blockSize = 128
Private keySize = 256
Private cipherMode = CipherMode.CBC
Protected Function AESEncryptStringToBase64(strPlainText As String, strKey As String) As String
Dim Algo As AesManaged = AesManaged.Create()
With Algo
.BlockSize = blockSize
.FeedbackSize = blockSize
.KeySize = keySize
.Mode = cipherMode
.IV = Guid.NewGuid().ToByteArray()
.Key = Encoding.ASCII.GetBytes(strKey)
End With
Using Encryptor As ICryptoTransform = Algo.CreateEncryptor()
Using MemStream As New MemoryStream
Using CryptStream As New CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write)
Using Writer As New StreamWriter(CryptStream)
Writer.Write(strPlainText)
End Using
AESEncryptStringToBase64 = Convert.ToBase64String(Algo.IV.Concat(MemStream.ToArray()).ToArray())
End Using
End Using
End Using
End Function
Protected Function AESDecryptBase64ToString(strCipherText As String, strKey As String) As String
Dim arrSaltAndCipherText As Byte() = Convert.FromBase64String(strCipherText)
Dim Algo As AesManaged = AesManaged.Create()
With Algo
.BlockSize = blockSize
.FeedbackSize = blockSize
.KeySize = keySize
.Mode = cipherMode
.IV = arrSaltAndCipherText.Take(16).ToArray()
.Key = Encoding.ASCII.GetBytes(strKey)
End With
Using Decryptor As ICryptoTransform = Algo.CreateDecryptor()
Using MemStream As New MemoryStream(arrSaltAndCipherText.Skip(16).ToArray())
Using CryptStream As New CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read)
Using Reader As New StreamReader(CryptStream)
AESDecryptBase64ToString = Reader.ReadToEnd()
End Using
End Using
End Using
End Using
End Function