2011-04-13 168 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