2011-04-13 59 views
4

我正在寻找允许我的身份验证库中的bcrypt支持。现在的问题之一是我认为哈希将是HashAlgorithm。 Bcrypt.net不会实现这个类。此外,它是密封的,所以我将不得不使自己的分支,并自己修改它。是否有更好的替代方案已经实现HashAlgorithm?。bcrypt的实现,实现HashAlgorithm?

回答

6

试试这个:

public class BCryptHasher : HashAlgorithm 
{ 
    private MemoryStream passwordStream = null; 

    protected override void HashCore(byte[] array, int ibStart, int cbSize) 
    { 
     if (passwordStream == null || Salt == null) 
      Initialize(); 

     passwordStream.Write(array, ibStart, cbSize); 
    } 

    protected override byte[] HashFinal() 
    { 
     passwordStream.Flush(); 

     // Get the hash 
     return Encoding.UTF8.GetBytes(BCrypt.Net.BCrypt.HashPassword(Encoding.UTF8.GetString(passwordStream.ToArray()), Salt));    
    } 

    public override void Initialize() 
    { 
     passwordStream = new MemoryStream(); 

     // Set up salt 
     if (Salt == null) 
     { 
      if (WorkFactor == 0) 
       Salt = BCrypt.Net.BCrypt.GenerateSalt(); 
      else 
       Salt = BCrypt.Net.BCrypt.GenerateSalt(WorkFactor); 
     } 
    } 

    public int WorkFactor { get; set; } 

    public string Salt { get; set; } 

    public bool Verify(string plain, string hash) 
    { 
     return BCrypt.Net.BCrypt.Verify(plain, hash); 
    } 
} 

用法:

BCryptHasher hasher = new BCryptHasher(); 
string pw = "abc"; 
string hash = Encoding.UTF8.GetString(hasher.ComputeHash(Encoding.UTF8.GetBytes(pw))); 

另外,我增加了一个辅助检查方法,这样你就可以验证密码和散列匹配,但如果你只是你能消除这种调用默认的BCrypt.Verify。

bool matches = hasher.Verify(pw, hash); 

我增加了一些额外的属性,所以你可以在预先计算的盐或产生新的盐工作因子通过你做的哈希前:

string pw = "abc"; 
hasher.Salt = "$2a$06$If6bvum7DFjUnE9p2uDeDu"; 
string hash = Encoding.UTF8.GetString(hasher.ComputeHash(Encoding.UTF8.GetBytes(pw))); 

我与BCrypt试了一下用“$ 2a $ 06 $ If6bvum7DFjUnE9p2uDeDu”的盐测试用例“abc”并得到正确的散列。

+0

这看起来很完美。今晚我会试试,如果一切正常,那么你真的对我非常感兴趣 – Earlz 2011-06-27 19:06:19

+2

对未来的观众:请注意,这不是“传统”与HashAlgorithm兼容。由于BCrypt的工作原理,它具有我所称的“盐跟踪”。你不能只将salt加入到散列密码或类似的东西中,你必须明确地将salt存储在明文(或加密)的地方,以便获得相同的密码散列。 – Earlz 2011-08-31 04:47:21