2014-05-12 27 views
0

歷史記錄用戶輸入和存儲的數據之間的不同:Password hashing used to work, now I can't get into my software字節值

自寫上面的問題(基本上,只是無法登錄,不知道爲什麼),我確定因爲當我在當我創建的用戶記錄我輸入密碼登錄我輸入的密碼字節數組,是完全不同的:

Here's the bytes from the database
Here's the bytes from the password when I failed to logged in

現在我知道該值被傳遞到數據庫(或存儲在中的值)數據庫)是錯誤的,我不知道該如何修復它...

我甚至不知道爲什麼這用於工作,但突然中斷。

在此先感謝您的任何建議!

EDIT

這裏的用戶登錄和註冊代碼

public User Login() // returns an instance of its own class 
    { 
     var auser = ie.users.FirstOrDefault(u => String.Compare(u.emailaddress, emailaddress, false) == 0); 

     if (auser == null) 
     { 
      throw new ValidationException("User not found"); 
     } 

     // get bytes for password in the database 
     byte[] passwordbytes = CryptUtility.GetBytes(auser.password); 

     HashGenerator h = new HashGenerator(password, auser.usersalt); 
     string hash = h.GetHash(); 

     var us = ie.users.FirstOrDefault(u => String.Compare(u.emailaddress, emailaddress, false) == 0 && String.Compare(u.password, password, false) == 0); 

     if (us == null) 
     { 
      throw new Exception("Invalid email address and/or password."); 
     } 
     User user = new User(); 

     user.userid = us.userid; 
     user.storeid = us.storeid; 
     user.role = us.role; 

     return user; 
    } 

    public void Add() // user registration 
    { 
     user newuser = new user(); 
     newuser.storeid = storeid; 
     newuser.emailaddress = emailaddress; 

     // Generate password hash 
     string usersalt = SaltGenerator.GetSaltString(); 
     HashGenerator hash = new HashGenerator(password, usersalt); 
     newuser.password = hash.GetHash(); 

     newuser.role = role; 
     newuser.usersalt = usersalt; 

     ie.users.Add(newuser); 
     ie.SaveChanges(); 
    } 

這裏的安全碼以生成散列和鹽值和它們的字節/字符串值以及

public class HashGenerator 
{ 
    public string pass { get; protected set; } 
    public string salt { get; protected set; } 

    public HashGenerator(string Password, string Salt) 
    { 
     pass = Password; 
     salt = Salt; 
    } 

    public string GetHash() 
    { 
     SHA512 sha = new SHA512CryptoServiceProvider(); 
     byte[] data = CryptUtility.GetBytes(String.Format("{0}{1}", pass, salt)); 
     byte[] hash = sha.ComputeHash(data); 

     return CryptUtility.GetString(hash); 
    } 
} 

public static class SaltGenerator 
{ 
    private static RNGCryptoServiceProvider provider = null; 
    private const int saltSize = 128; 

    static SaltGenerator() 
    { 
     provider = new RNGCryptoServiceProvider(); 
    } 

    public static string GetSaltString() 
    { 
     byte[] saltBytes = new byte[saltSize]; 

     provider.GetNonZeroBytes(saltBytes); 

     return CryptUtility.GetString(saltBytes); 
    } 
} 

class CryptUtility 
{ 
    public static byte[] GetBytes(string Str) 
    { 
     byte[] bytes = new byte[Str.Length * sizeof(char)]; 
     System.Buffer.BlockCopy(Str.ToCharArray(), 0, bytes, 0, bytes.Length); 
     return bytes; 
    } 

    public static string GetString(byte[] Bytes) 
    { 
     char[] chars = new char[Bytes.Length/sizeof(char)]; 
     System.Buffer.BlockCopy(Bytes, 0, chars, 0, Bytes.Length); 
     return new string(chars); 
    } 
} 
+1

我們需要更多的細節,添加您的代碼進行登錄和註冊。 –

+0

我猜想你用它的lib應該已經改變了!但是你需要支持更多關於你如何做的信息。 – prnjanuario

+0

@BertrandC。添加了代碼ya – Ortund

回答

2

我幾乎在評論中說了一切,但看着你的另一個問題,我覺得我必須發佈這是一個答案,因爲這絕對是解決您的問題的方法。

Unicode是一個複雜的字符集(http://www.joelonsoftware.com/articles/Unicode.html - 請閱讀它)。你必須認識到,unicode字符串和字節數組之間不存在1:1映射,這一點很重要。一個字符可以有一個字節,或者它可以有更多。更重要的是,有很多魔術字符,所以將一個普通的字節數組「鑄造」成一個字符串很容易導致一個無效的Unicode字符串,或者它可能會惡化你的數據!

這就是爲什麼當你的專欄是varchar時,它適合你。在varchar中,每個字符都有1:1映射到一個字節,就像那樣簡單。因此,將字節數組「鑄造」到varchar,並且不會導致數據更改或數據丟失。這不再適用於nvarchar,因爲nvarchar是一個Unicode字符串(就像.NET的string一樣)。

取而代之,將密碼散列保存爲字節數組(binaryvarbinary),或者將字節數組轉換爲Base-64字符串 - 例如,當您需要純文本和散列密碼時,常用的模式。所以你的GetBytes()會做Convert.FromBase64String,而GetString會做Convert.ToBase64String