鉴于googling "membership provider hashing algorithm"会出现这个答案作为第一个结果的事实,以及将要推断的福音,我理应警告人们不要像这样使用会员提供程序,并使用SHA-1、MD5等散列来混淆数据库中的密码.
100 with a work factor sufficient to necessitate the hashing time for a single password to be as close to 1000ms or more.
如今,哈希很容易被强行使用,在最近的历史中,有大量数据泄露的例子.为了防止用户的密码在下一次黑客攻击中出现在pastebin上,请确保使用一个sufficiently long time to compute!的函数对密码进行哈希处理
请至少try IdentityReboot或newer implementations from Microsoft that Troy Hunt talks about,而不是会员提供程序.
同样有趣的是,在上面提到的谷歌搜索结果中,我发现有tutorial showing folks preciously how easy it is%的人可以使用流行的工具,如JTR或Hashcat来暴力破解这些密码散列.在一个定制的GPU平台上,SHA1可以用像rockyou or the like这样的免费字典破解到staggering rate of 48867 million hashes per second!,一个有动力的人会很快拥有你的大部分用户密码.作为一名开发人员,采取必要措施保护用户密码的安全是您的道德责任.
默认哈希是SHA1,但他们也会对其进行盐分和base64:
public string EncodePassword(string pass, string salt)
{
byte[] bytes = Encoding.Unicode.GetBytes(pass);
byte[] src = Encoding.Unicode.GetBytes(salt);
byte[] dst = new byte[src.Length + bytes.Length];
Buffer.BlockCopy(src, 0, dst, 0, src.Length);
Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
Hash算法rithm algorithm = Hash算法rithm.Create("SHA1");
byte[] inArray = algorithm.ComputeHash(dst);
return Convert.ToBase64String(inArray);
}
如果你想知道更多关于如何更改它的信息,我仍然需要了解(除非使用自定义提供程序,请参见下文),但是现在SHA-1非常好.如果你想把它翻过来,或者从中查找,这些人做了一些工作:http://forums.asp.net/p/1336657/2899172.aspx
这个问题将有助于逆转或复制这项技术,如果这是可能需要的.Reimplement ASP.NET Membership and User Password Hashing in Ruby个
如果你正在创建一个自定义的提供者,你可以创建你的哈希和加密算法和方法.
private byte[] ConvertPasswordForStorage(string Password)
{
System.Text.UnicodeEncoding ue =
new System.Text.UnicodeEncoding();
byte[] uePassword = ue.GetBytes(Password);
byte[] RetVal = null;
switch (_PasswordFormat)
{
case MembershipPasswordFormat.Clear:
RetVal = uePassword;
break;
case MembershipPasswordFormat.Hashed:
HMACSHA1 SHA1KeyedHasher = new HMACSHA1();
SHA1KeyedHasher.Key = _ValidationKey;
RetVal = SHA1KeyedHasher.ComputeHash(uePassword);
break;
case MembershipPasswordFormat.Encrypted:
TripleDESCryptoServiceProvider tripleDes = new
TripleDESCryptoServiceProvider();
tripleDes.Key = _DecryptionKey;
tripleDes.IV = new byte[8];
MemoryStream mStreamEnc = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(mStreamEnc,
tripleDes.CreateEncryptor(),
CryptoStreamMode.Write);
cryptoStream.Write(uePassword, 0, uePassword.Length);
cryptoStream.FlushFinalBlock();
RetVal = mStreamEnc.ToArray();
cryptoStream.Close();
break;
}
return RetVal;
}
private string GetHumanReadablePassword(byte[] StoredPassword)
{
System.Text.UnicodeEncoding ue = new System.Text.UnicodeEncoding();
string RetVal = null;
switch (_PasswordFormat)
{
case MembershipPasswordFormat.Clear:
RetVal = ue.GetString(StoredPassword);
break;
case MembershipPasswordFormat.Hashed:
throw new ApplicationException(
"Password cannot be recovered from a hashed format");
case MembershipPasswordFormat.Encrypted:
TripleDESCryptoServiceProvider tripleDes =
new TripleDESCryptoServiceProvider();
tripleDes.Key = _DecryptionKey;
tripleDes.IV = new byte[8];
CryptoStream cryptoStream =
new CryptoStream(new MemoryStream(StoredPassword),
tripleDes.CreateDecryptor(), CryptoStreamMode.Read);
MemoryStream msPasswordDec = new MemoryStream();
int BytesRead = 0;
byte[] Buffer = new byte[32];
while ((BytesRead = cryptoStream.Read(Buffer, 0, 32)) > 0)
{
msPasswordDec.Write(Buffer, 0, BytesRead);
}
cryptoStream.Close();
RetVal = ue.GetString(msPasswordDec.ToArray());
msPasswordDec.Close();
break;
}
return RetVal;
}