2015-10-26 51 views
12

我一直在閱讀本文,內容來自MSDN,Rfc2898DeriveBytes。以下是他們提供的示例加密代碼。如何在本地正確存儲密碼

string pwd1 = passwordargs[0]; 
// Create a byte array to hold the random value. 
byte[] salt1 = new byte[8]; 
using (RNGCryptoServiceProvider rngCsp = ne RNGCryptoServiceProvider()) 
{ 
    // Fill the array with a random value. 
    rngCsp.GetBytes(salt1); 
} 

//data1 can be a string or contents of a file. 
string data1 = "Some test data"; 
//The default iteration count is 1000 so the two methods use the same iteration count. 
int myIterations = 1000; 
try 
{ 
    Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(pwd1,salt1,myIterations); 
    Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(pwd1, salt1); 
    // Encrypt the data. 
    TripleDES encAlg = TripleDES.Create(); 
    encAlg.Key = k1.GetBytes(16); 
    MemoryStream encryptionStream = new MemoryStream(); 
    CryptoStream encrypt = newCryptoStream(encryptionStream, encAlg.CreateEncryptor(), CryptoStreamMode.Write); 
    byte[] utfD1 = new System.Text.UTF8Encoding(false).GetBytes(data1); 

    encrypt.Write(utfD1, 0, utfD1.Length); 
    encrypt.FlushFinalBlock(); 
    encrypt.Close(); 
    byte[] edata1 = encryptionStream.ToArray(); 
    k1.Reset(); 

我的問題是,我將如何正確讀/寫散列數據/從文本文件?

我的主要目標是做這個developer正在做的事情。我需要在本地存儲密碼。當我的應用程序提示用戶輸入密碼時,用戶將輸入密碼,然後我的應用程序將從文本文件中讀取並驗證用戶輸入的密碼是否確實正確。我該怎麼去做呢?

+1

它只是文本。散列用戶的pw,從文件讀取存儲的散列,比較兩個散列。如果他們是平等的,那麼這是正確的指數。 –

+0

@MarcB - 你能舉一個密碼哈希的例子嗎? –

+5

你爲什麼要加密密碼?密碼通常是散列的,而不是加密的。散列和加密不是一回事。 – Tim

回答

4

您通常存儲密碼的哈希值,那麼當用戶輸入密碼時,計算散列在輸入的密碼,並將其與儲存了哈希比較 - 這麼說,只是散列通常是不夠的(從安全角度查看),您應該使用一個函數,如PKBDF2(基於密碼的密鑰推導函數2)。這裏是更詳細的方式以及示例代碼(頁面底部)覆蓋所有信息的文章:http://www.codeproject.com/Articles/704865/Salted-Password-Hashing-Doing-it-Right

這裏是一個codereview的鏈接,我猜是指與上述文章相同的實現。

+0

謝謝你的例子。 –

+0

快速問題,我將如何以及在哪裏存儲要檢索和散列的密碼?我不想硬編碼到我的應用程序。 –

+0

@MrRobot:你不存儲密碼,您存儲PKBDF2的結果,這是安全的存儲 –

4

如何妥善保存密碼在本地

只是不去做。 No really don't do it

...但是如果你真的需要,不要自己實施。我會建議審查如何ASP.NET Identity hashes passwords。版本3目前非常穩定:

請注意,以下內容取自github.com,並可能隨時更改。有關最新信息,請參閱上一個鏈接。

private static byte[] HashPasswordV3(string password, RandomNumberGenerator rng, KeyDerivationPrf prf, int iterCount, int saltSize, int numBytesRequested) 
    { 
     // Produce a version 3 (see comment above) text hash. 
     byte[] salt = new byte[saltSize]; 
     rng.GetBytes(salt); 
     byte[] subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested); 

     var outputBytes = new byte[13 + salt.Length + subkey.Length]; 
     outputBytes[0] = 0x01; // format marker 
     WriteNetworkByteOrder(outputBytes, 1, (uint)prf); 
     WriteNetworkByteOrder(outputBytes, 5, (uint)iterCount); 
     WriteNetworkByteOrder(outputBytes, 9, (uint)saltSize); 
     Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length); 
     Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length); 
     return outputBytes; 
    } 
+1

感謝您的這一點。我的應用程序將從其他員工的特定計算機發送電子郵件,所以我需要找到一種方法在本地存儲帳戶密碼。否則,如你所述,我不會這樣做。 –

+0

爲什麼會要求你存儲密碼? –

+0

我正在使用Hotmail帳戶以及我的應用程序。在發送電子郵件時,它會要求輸入電子郵件帳戶的用戶名/密碼。我不想將密碼存儲在純文本文件中。我需要一種散列方式,並正確讀入應用程序。 –

2

你應該存儲密碼的單向散列和用於創建密碼的鹽。通過這種方式,您可以絕對確保用戶的密碼永遠不會被解密。切勿爲此特定任務使用任何雙向加密,因爲您可能會將用戶信息暴露給潛在的攻擊者。

void Main() 
{ 
    string phrase, salt, result; 
    phrase = "test"; 
    result = Sha256Hash(phrase, out salt); 

    Sha256Compare(phrase, result, salt); 
} 

public string Sha256Hash(string phrase, out string salt) 
{ 
    salt = Create256BitSalt(); 
    string saltAndPwd = String.Concat(phrase, salt); 
    Encoding encoder = Encoding.Default; 
    SHA256Managed sha256hasher = new SHA256Managed(); 
    byte[] hashedDataBytes = sha256hasher.ComputeHash(encoder.GetBytes(saltAndPwd)); 
    string hashedPwd = Encoding.Default.GetString(hashedDataBytes); 
    return hashedPwd; 
} 

public bool Sha256Compare(string phrase, string hash, string salt) 
{ 
    string saltAndPwd = String.Concat(phrase, salt); 
    Encoding encoder = Encoding.Default; 
    SHA256Managed sha256hasher = new SHA256Managed(); 
    byte[] hashedDataBytes = sha256hasher.ComputeHash(encoder.GetBytes(saltAndPwd)); 
    string hashedPwd = Encoding.Default.GetString(hashedDataBytes); 
    return string.Compare(hash, hashedPwd, false) == 0; 
} 

public string Create256BitSalt() 
{ 
    int _saltSize = 32; 
    byte[] ba = new byte[_saltSize]; 
    RNGCryptoServiceProvider.Create().GetBytes(ba); 
    return Encoding.Default.GetString(ba); 
} 

你也可以找出另一種獲得鹽的方法,但是我已經做了它,它計算了2048位價值的隨機數據。你可以只使用一個隨機生成的長度,但是這樣會很不安全。您將無法使用SecureString,因爲SecureString不是可序列化的。其中DPAPI的全部重點。有許多方法可以將數據提取出來,但最終不得不跳過一些障礙來完成。

FWIW,PBKDF2(基於密碼的密鑰推導函數2)與SHA256基本相同,只是速度較慢(好東西)。它本身都非常安全。如果您將PBKDF2與SHA256結合爲鹽,那麼您將擁有一個非常安全的系統。

+0

在這種情況下,短語將是我的密碼? –

+0

是的。短語=「密碼」 –

+0

快速的問題,比方說,我有一個WinForm,它涉及到密碼框。我接受密碼作爲字符串並將其傳遞給短語變量? –