How about this approach ( using System.Security.Cryptography):
To store user passwords in a database in a way that cannot be retrieved, passwords must be hashed using a one-way hash algorithm such as SHA1
To do this, use RNGCryptoServiceProvider to create a random salt, add the salt to the password, hash it using the SHA1 CryptoServiceProvider class and save the resulting row in the database along with the salt
, , , .
:
private byte [] CreateDbPassword(byte[] unsaltedPassword)
{
byte[] saltValue = new byte[saltLength];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(saltValue);
return CreateSaltedPassword(saltValue, unsaltedPassword);
}
private byte[] CreateSaltedPassword(byte[] saltValue, byte[] unsaltedPassword)
{
byte[] rawSalted = new byte[unsaltedPassword.Length + saltValue.Length];
unsaltedPassword.CopyTo(rawSalted,0);
saltValue.CopyTo(rawSalted,unsaltedPassword.Length);
SHA1 sha1 = SHA1.Create();
byte[] saltedPassword = sha1.ComputeHash(rawSalted);
byte[] dbPassword = new byte[saltedPassword.Length + saltValue.Length];
saltedPassword.CopyTo(dbPassword,0);
saltValue.CopyTo(dbPassword,saltedPassword.Length);
return dbPassword;
}
private bool ComparePasswords(byte[] storedPassword, byte[] hashedPassword)
{
if (storedPassword == null || hashedPassword == null || hashedPassword.Length != storedPassword.Length - saltLength)
return false;
byte[] saltValue = new byte[saltLength];
int saltOffset = storedPassword.Length - saltLength;
for (int i = 0; i < saltLength; i++)
saltValue[i] = storedPassword[saltOffset + i];
byte[] saltedPassword = CreateSaltedPassword(saltValue, hashedPassword);
return CompareByteArray(storedPassword, saltedPassword);
}
private bool CompareByteArray(byte[] array1, byte[] array2)
{
if (array1.Length != array2.Length)
return false;
int mismatch = 0;
for (int i = 0; i < array1.Length; i++)
{
mismatch |= array1[i] ^ array2[i];
}
return mismatch == 0;
}
UPDATE
UWP Windows.Security.Cryptography.Core:
public String SampleDeriveFromPbkdf(
String strAlgName,
UInt32 targetSize)
{
KeyDerivationAlgorithmProvider objKdfProv = KeyDerivationAlgorithmProvider.OpenAlgorithm(strAlgName);
String strSecret = "MyPassword";
IBuffer buffSecret = CryptographicBuffer.ConvertStringToBinary(strSecret, BinaryStringEncoding.Utf8);
IBuffer buffSalt = CryptographicBuffer.GenerateRandom(32);
UInt32 iterationCount = 10000;
KeyDerivationParameters pbkdf2Params = KeyDerivationParameters.BuildForPbkdf2(buffSalt, iterationCount);
CryptographicKey keyOriginal = objKdfProv.CreateKey(buffSecret);
IBuffer keyDerived = CryptographicEngine.DeriveKeyMaterial(
keyOriginal,
pbkdf2Params,
targetSize);
String strKeyHex = CryptographicBuffer.EncodeToHexString(keyDerived);
return strKeyHex;
}