Я наткнулся на эту статью, в которой описывается опасность хранения "несоленых" хэшей паролей в базе данных, могут быть подвергнуты реинжинирингу с использованием так называемых "радужных таблиц.
Он также поставляется с этим примером кода C#, который в основном требует хранения двух хэш-столбцов в ваших пользовательских паролях. таблица базы данных (вместо традиционной - одна). Проблема такого подхода для меня в том, что у меня уже есть установленная таблица базы данных с несолеными хэшами паролей пользователей, и добавление новой колонки потребует реструктуризации базы данных. Поэтому, прежде чем я это сделаю, я искал другую альтернативу, и вот что я придумал.
Вот функция, которая вместо простого вычисления хэша SHA1 для пароля дополняет его длинной последовательностью псевдослучайных (но непротиворечивых) данных, а затем вычисляет хэш:
byte[] computeSecureHash(string strUserPassword)
{
//RETURN: = SHA1 byte array on the 'strUserPassword'
//Make simple junk array based on the password
ushort v = 117;
byte[] arrJunk = new byte[24];
for (int c = 0, i = 0; i < arrJunk.Length; i++)
{
v ^= strUserPassword[c++];
v *= 7;
arrJunk[i] = (byte)v;
if (c >= strUserPassword.Length)
c = 0;
}
//Make crypto byte array based on the password
Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(strUserPassword, arrJunk);
pbkdf2.IterationCount = 1000;
byte[] arrCrypto = pbkdf2.GetBytes(128);
//Pad actual password
string strUserPassword_Padded = "";
const string strChars2Use = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`-=[]\\;',./~!@#$%^&*()_+{}|:\"<>?";
int nHalfArrCrypto = arrCrypto.Length / 2;
//Left side
for (int i = 0; i < nHalfArrCrypto; i++)
{
strUserPassword_Padded += strChars2Use[arrCrypto[i] % strChars2Use.Length];
}
strUserPassword_Padded += strUserPassword;
//Right side
for (int i = nHalfArrCrypto; i < arrCrypto.Length; i++)
{
strUserPassword_Padded += strChars2Use[arrCrypto[i] % strChars2Use.Length];
}
//For user's password "123"
//the 'strUserPassword_Padded' becomes:
//"bwDR]_B>H5t-k:eIq?r_wGBWqWfs#tcAE~DQ5?(Pbj#<+Cw:9(r!B[f_.S<pCjn-123b9l3<Sz^D~>G}v)?NuHT4BZ-pI2$W[kW1e4KO\"`rTg3H`}&jmtrFh1J5c72:})tQ"
//And now compuse SHA1 on the padded password
SHA1 sha1 = new SHA1CryptoServiceProvider();
byte[] bytesInputData = System.Text.Encoding.UTF8.GetBytes(strUserPassword_Padded);
return sha1.ComputeHash(bytesInputData);
}
Итак, мой вопрос: может ли кто-нибудь просмотреть этот код и сказать мне, в чем опасность этого способа по сравнению с тем, что автор предложил в его код? В случае моего примера кода мне придется хранить в базе данных только один хеш вместо двух (хэш пароля + хэш соли.)