2

パスワードのデータをハッシュ/保存/取得するための以下のコードがありますが、最初の単体テストで失敗します。

GetBytes が呼び出されたときに が返されるため、Encoding が問題の原因であるbyte[38]byte[36]考えています。

データベースに保存しているので、文字列に変換する必要があります。

何か案は?ありがとう

[Fact]
public void EncryptDecryptPasswordShouldMatch()
{
    string password = "password";
    string passwordKey = string.Empty;
    string passwordSalt = string.Empty;

    Helpers.CreatePasswordHash(password, out passwordSalt, out passwordKey);

    Assert.True(Helpers.PasswordsMatch(passwordSalt, passwordKey, password));

}


public static bool PasswordsMatch(string passwordSalt, string passwordKey, string password)
{
    byte[] salt = Encoding.UTF8.GetBytes(passwordSalt);
    byte[] key = Encoding.UTF8.GetBytes(passwordKey);

    using (var deriveBytes = new Rfc2898DeriveBytes(password, salt))
    {
        byte[] newKey = deriveBytes.GetBytes(20);  // derive a 20-byte key

        if (!newKey.SequenceEqual(key))
            return false;
    }

    return true;
}

public static void CreatePasswordHash(string password, out string passwordSalt, out string passwordKey)
{
    // specify that we want to randomly generate a 20-byte salt
    using (var deriveBytes = new Rfc2898DeriveBytes(password, 20))
    {
        byte[] salt = deriveBytes.Salt;
        byte[] key = deriveBytes.GetBytes(20);  // derive a 20-byte key

        passwordSalt = Encoding.UTF8.GetString(salt);
        passwordKey = Encoding.UTF8.GetString(key);
    }
}
4

3 に答える 3

4

Base64 を使用してバイナリ値を文字列にエンコードすると、任意のバイト シーケンスを処理できます。UTF-8 は Unicode テキストとバイト間の変換用であり、すべての有効なバイト シーケンスが UTF-8 に対して有効であるとは限りません。Utf-8 を使用してパスワード (テキスト) をバイトに変換しますが、ソルトとハッシュには Base64 を使用します。

Convert.ToBase64StringConvert.FromBase64Stringトリックを行う必要があります。


いくつかの追加メモ:

  • あなたの用語は本当に奇妙です。ハッシュkeyを呼び出さないで、それを呼び出してhashください。
  • 関数でハッシュとソルトを連結するCreatePasswordHashので、呼び出し元は 2 つの個別の値を気にする必要がありません。

    検証機能でreturn Base64Encode(salt)+"$"+Base64Encode(hash)使用するようなもの。string.Split

  • 一定の時間比較を使用して確認することをお勧めしますが、タイミング サイドチャネルが実際に悪用される可能性は低いようです。

  • あなたの反復回数はかなり少ないです。10000に増やすことをお勧めします。
于 2013-05-02T15:54:07.580 に答える
3

Convert.FromBase64Stringメソッドを使用するようにコードを変更します。

byte[] salt = Convert.FromBase64String(passwordSalt);
byte[] key = Convert.FromBase64String(passwordKey);

Convert.ToBase64Stringメソッドを使用するようにコードを変更します。

passwordSalt = Convert.ToBase64String(salt);
passwordKey = Convert.ToBase64String(key);
于 2013-05-02T15:56:34.933 に答える
1

UTF8は、ランダムなバイトを文字列に変換する方法ではありません。テキストをエンコードするためのものです。すべてのバイトが有効な UTF8 エンコード値であるだけではありません。Base64変換を使用できます。base64 でエンコードされた文字列は、生バイトの最大 4/3 倍の文字を使用することに注意してください。次に例を示します。

byte[] salt = deriveBytes.Salt;
byte[] key = deriveBytes.GetBytes(20);  // derive a 20-byte key

passwordSalt = Convert.ToBase64String(salt);
passwordKey = Convert.ToBase64String(key);

以降:

byte[] salt = Convert.FromBase64String(passwordSalt);
byte[] key = Convert.FromBase64String(passwordKey);
于 2013-05-02T15:58:25.893 に答える