ソルトを生成し、(bcrypt などを使用して) パスワードをハッシュしたら、結果を文字列またはバイト配列としてデータベースに保存するのが最善でしょうか? どちらにしてもメリットはありますか?それとももっと主観的な判断ですか?
3 に答える
VARCHAR を使用する場合は、ハッシュとソルトを保存する前に、バイトが有効な文字であることを確認するか、バイトを強制的に ASCII にします。データの破損を防ぐために、バイトを VARCHAR フィールドに格納する前に Base64 または 16 進数でエンコードすることをお勧めします。
たとえば、MD5またはSHA1byte[]
からの出力を保存する場合、有効な UTF-8/Unicode ではないため、テキストに変換されるときに一部のバイト値が削除または置換されることがあります。ASCII を使用している場合、これはそれほど問題にはなりませんが、それでもデータが破損する可能性があります。byte[]
Hex を処理したくない場合は、フレームワークに組み込まれているこの base64 メソッドConvert.ToBase64Stringを使用できます。
VARBINARY を使用し、テキスト エンコーディング メソッドを使用しようとしない場合、この問題は存在しないはずですが、ハッシュの比較がより困難になる可能性があります。
...このデータを使用するとNVARCHAR
、データ破損が発生する可能性があることに注意してください...
static void Main(string[] args)
{
var salt = "MySalt";
var password = "MyPassword";
var saltedKey = CalculateHash(salt, password);
Console.WriteLine(saltedKey);
// MySalt$teGOpFi57nENIRifSW3m1RQndiU=
var checkHash = CheckHash(saltedKey, password);
Console.WriteLine(checkHash);
// True
}
private static string CalculateHash(string saltOrSaltedKey, string password)
{
var salt =
saltOrSaltedKey.Contains('$')
? saltOrSaltedKey.Substring(0, saltOrSaltedKey.IndexOf('$') + 1)
: saltOrSaltedKey + '$';
var newKey = Encoding.UTF8.GetBytes(salt + password);
var sha1 = SHA1.Create();
sha1.Initialize();
var result = sha1.ComputeHash(newKey);
// if you replace this base64 version with one of the encoding
// classes this will become corrupt due to nulls and other
// control character values in the byte[]
var outval = salt + Convert.ToBase64String(result);
return outval;
}
private static bool CheckHash(string saltedKey, string password)
{
var outval = CalculateHash(saltedKey, password);
return outval == saltedKey;
}
VARCHAR で十分です。私の意見では、VARCHAR データは、バイナリよりも簡単に使用および操作できます。
組み込みの ASP.NET メンバーシップ プロバイダーも、ハッシュ化されたパスワードを VARCHAR フィールドとして格納します。
ほとんどの md5/sha1 ライブラリは base64 でエンコードされたハッシュを返します。この場合、varchar で十分です。