我正在努力将非常旧网站从经典ASP升级到ASP.NET Core。部分原因是将用户(其密码以明文形式存储)自然地迁移到Identity中。我们正在使用单元测试项目来处理迁移,但该项目无法访问Identity,这是可以理解的。
这里最好的选择是什么?我看到的主要问题是将密码设置为正确的格式,但我认为我可以查看ASP.NET身份的来源并模仿正确散列迁移中的所有内容的功能。还有更好的方法吗?
答案 0 :(得分:2)
ASP.NET Identity 3使用的哈希算法是here。但是,除非您将其依赖项复制到项目中,否则在ASP.NET Idetity之外运行并不是 easy 。
private static byte[] HashPasswordV3(string password,
RandomNumberGenerator rng, KeyDerivationPrf prf,
int iterCount, int saltSize, int numBytesRequested)
{
// Produce a version 3 (see comment above) text hash.
byte[] salt = new byte[saltSize];
rng.GetBytes(salt);
byte[] subkey = KeyDerivation.Pbkdf2(
password, salt, prf, iterCount, numBytesRequested);
var outputBytes = new byte[13 + salt.Length + subkey.Length];
outputBytes[0] = 0x01; // format marker
WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
WriteNetworkByteOrder(outputBytes, 5, (uint)iterCount);
WriteNetworkByteOrder(outputBytes, 9, (uint)saltSize);
Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
return outputBytes;
}
private static bool VerifyHashedPasswordV3(byte[] hashedPassword, string password, out int iterCount)
{
iterCount = default(int);
try
{
// Read header information
KeyDerivationPrf prf = (KeyDerivationPrf)ReadNetworkByteOrder(hashedPassword, 1);
iterCount = (int)ReadNetworkByteOrder(hashedPassword, 5);
int saltLength = (int)ReadNetworkByteOrder(hashedPassword, 9);
// Read the salt: must be >= 128 bits
if (saltLength < 128 / 8)
{
return false;
}
byte[] salt = new byte[saltLength];
Buffer.BlockCopy(hashedPassword, 13, salt, 0, salt.Length);
// Read the subkey (the rest of the payload): must be >= 128 bits
int subkeyLength = hashedPassword.Length - 13 - salt.Length;
if (subkeyLength < 128 / 8)
{
return false;
}
byte[] expectedSubkey = new byte[subkeyLength];
Buffer.BlockCopy(hashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);
// Hash the incoming password and verify it
byte[] actualSubkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, subkeyLength);
return ByteArraysEqual(actualSubkey, expectedSubkey);
}
catch
{
// This should never occur except in the case of a malformed payload, where
// we might go off the end of the array. Regardless, a malformed payload
// implies verification failed.
return false;
}
}
答案 1 :(得分:0)
密码是纯文本的,因此您只需从当前数据库加载每个用户,并使用Identity中的UserManager
类将它们添加到新数据库。
UserManager
类有CreateAsync
方法,它接受密码并为您处理散列。
示例:
var user = new IdentityUser // or whatever your user class is
{
UserName = userName,
Email = email,
// set other required properties
};
var result = await userManager.CreateAsync(user, password);
我建议在单独的程序中手动运行它作为一次性任务。您不希望此过程存在于新应用中。