Switch to using DataProtection for Crypto

This commit is contained in:
Hao Kung 2014-03-07 12:23:20 -08:00
parent 56c67d5ef0
commit d845ef0b7c
4 changed files with 22 additions and 45 deletions

View File

@ -1,15 +1,14 @@
#if NET45
using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNet.Security.DataProtection;
namespace Microsoft.AspNet.Identity
{
internal static class Crypto
{
private const int PBKDF2IterCount = 1000; // default for Rfc2898DeriveBytes
private const int PBKDF2SubkeyLength = 256/8; // 256 bits
private const int Pbkdf2IterCount = 1000; // default for Rfc2898DeriveBytes
private const int Pbkdf2SubkeyLength = 256/8; // 256 bits
private const int SaltSize = 128/8; // 128 bits
/* =======================
@ -30,17 +29,13 @@ namespace Microsoft.AspNet.Identity
}
// Produce a version 0 (see comment above) text hash.
byte[] salt;
byte[] subkey;
using (var deriveBytes = new Rfc2898DeriveBytes(password, SaltSize, PBKDF2IterCount))
{
salt = deriveBytes.Salt;
subkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
}
var outputBytes = new byte[1 + SaltSize + PBKDF2SubkeyLength];
var salt = new byte[SaltSize];
CryptRand.FillBuffer(new ArraySegment<byte>(salt));
var passwordBytes = Encoding.UTF8.GetBytes(password);
var subkey = PBKDF2.DeriveKey("SHA1", passwordBytes, salt, Pbkdf2IterCount, Pbkdf2SubkeyLength);
var outputBytes = new byte[1 + SaltSize + Pbkdf2SubkeyLength];
Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize);
Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, PBKDF2SubkeyLength);
Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, Pbkdf2SubkeyLength);
return Convert.ToBase64String(outputBytes);
}
@ -56,26 +51,19 @@ namespace Microsoft.AspNet.Identity
throw new ArgumentNullException("password");
}
var hashedPasswordBytes = Convert.FromBase64String(hashedPassword);
// Verify a version 0 (see comment above) text hash.
if (hashedPasswordBytes.Length != (1 + SaltSize + PBKDF2SubkeyLength) || hashedPasswordBytes[0] != 0x00)
var hashedPasswordBytes = Convert.FromBase64String(hashedPassword);
if (hashedPasswordBytes.Length != (1 + SaltSize + Pbkdf2SubkeyLength) || hashedPasswordBytes[0] != 0x00)
{
// Wrong length or version header.
return false;
}
var salt = new byte[SaltSize];
Buffer.BlockCopy(hashedPasswordBytes, 1, salt, 0, SaltSize);
var storedSubkey = new byte[PBKDF2SubkeyLength];
Buffer.BlockCopy(hashedPasswordBytes, 1 + SaltSize, storedSubkey, 0, PBKDF2SubkeyLength);
byte[] generatedSubkey;
using (var deriveBytes = new Rfc2898DeriveBytes(password, salt, PBKDF2IterCount))
{
generatedSubkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
}
var storedSubkey = new byte[Pbkdf2SubkeyLength];
Buffer.BlockCopy(hashedPasswordBytes, 1 + SaltSize, storedSubkey, 0, Pbkdf2SubkeyLength);
var passwordBytes = Encoding.UTF8.GetBytes(password);
var generatedSubkey = PBKDF2.DeriveKey("SHA1", passwordBytes, salt, Pbkdf2IterCount, Pbkdf2SubkeyLength);
return ByteArraysEqual(storedSubkey, generatedSubkey);
}
@ -87,12 +75,10 @@ namespace Microsoft.AspNet.Identity
{
return true;
}
if (a == null || b == null || a.Length != b.Length)
{
return false;
}
var areSame = true;
for (var i = 0; i < a.Length; i++)
{
@ -102,4 +88,3 @@ namespace Microsoft.AspNet.Identity
}
}
}
#endif

View File

@ -12,11 +12,7 @@ namespace Microsoft.AspNet.Identity
/// <returns></returns>
public virtual string HashPassword(string password)
{
#if NET45
return Crypto.HashPassword(password);
#else
return password;
#endif
}
/// <summary>
@ -27,11 +23,7 @@ namespace Microsoft.AspNet.Identity
/// <returns></returns>
public virtual PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
{
#if NET45
return Crypto.VerifyHashedPassword(hashedPassword, providedPassword) ? PasswordVerificationResult.Success : PasswordVerificationResult.Failed;
#else
return hashedPassword == providedPassword ? PasswordVerificationResult.Success : PasswordVerificationResult.Failed;
#endif
}
}
}

View File

@ -2,10 +2,10 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.AspNet.DependencyInjection;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.DependencyInjection;
namespace Microsoft.AspNet.Identity
{
@ -41,7 +41,7 @@ namespace Microsoft.AspNet.Identity
PasswordHasher = serviceProvider.GetService<IPasswordHasher>();
UserValidator = serviceProvider.GetService<IUserValidator<TUser>>();
PasswordValidator = serviceProvider.GetService<IPasswordValidator>();
// TODO: validator interfaces, and maybe each optional store as well? Email and SMS services?
// TODO: maybe each optional store as well? Email and SMS services?
}
/// <summary>
@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Identity
Store = store;
UserValidator = new UserValidator<TUser, TKey>(this);
PasswordHasher = new PasswordHasher();
//ClaimsIdentityFactory = new ClaimsIdentityFactory<TUser, TKey>();
//TODO: ClaimsIdentityFactory = new ClaimsIdentityFactory<TUser, TKey>();
}
/// <summary>
@ -243,8 +243,7 @@ namespace Microsoft.AspNet.Identity
get
{
ThrowIfDisposed();
return false;
//return Store is IUserClaimStore<TUser, TKey>;
return Store is IUserClaimStore<TUser, TKey>;
}
}

View File

@ -2,7 +2,8 @@
"version" : "0.1-alpha-*",
"dependencies": {
"Microsoft.AspNet.DependencyInjection" : "0.1-alpha-*",
"System.Security.Claims" : "0.1-alpha-*"
"System.Security.Claims" : "0.1-alpha-*",
"Microsoft.AspNet.Security.DataProtection" : "0.1-alpha-*"
},
"configurations": {
"net45": {},