1

私は実際に、組み込みデバイスの Visual C# .NET 2.0 で開発しているアプリに非常に単純なログイン メカニズムを実装しようとしています。いくつかの調査の後、msdn でパスワードハッシュを実行するコードサンプルを見つけました:

パスワードの保存方法

byte.Parse残念ながら、このコード サンプルを使用しようとすると、16 進数の文字列の部分文字列に対する呼び出しで FormatException が発生しますSaltValue。コードに変更を加えていないため、理由を理解するのに本当に苦労しています。

コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Globalization;

private const int SaltValueSize = 4;

private static string GenerateSaltValue()
{
UnicodeEncoding utf16 = new UnicodeEncoding();

if (utf16 != null)
{
    // Create a random number object seeded from the value
    // of the last random seed value. This is done
    // interlocked because it is a static value and we want
    // it to roll forward safely.

    Random random = new Random(unchecked((int)DateTime.Now.Ticks));

    if (random != null)
    {
        // Create an array of random values.

        byte[] saltValue = new byte[SaltValueSize];

        random.NextBytes(saltValue);

        // Convert the salt value to a string. Note that the resulting string
        // will still be an array of binary values and not a printable string. 
        // Also it does not convert each byte to a double byte.


        //Original line :
        //string saltValueString = utf16.GetString(saltValue);
        //Replaced by :
        string saltValueString = utf16.GetString(saltValue, 0, SaltValueSize);

        // Return the salt value as a string.

        return saltValueString;
    }
}

return null;
}

private static string HashPassword(string clearData, string saltValue, HashAlgorithm hash)
{
UnicodeEncoding encoding = new UnicodeEncoding();

if (clearData != null && hash != null && encoding != null)
{
    // If the salt string is null or the length is invalid then
    // create a new valid salt value.

    if (saltValue == null)
    {
        // Generate a salt string.
        saltValue = GenerateSaltValue();
    }

    // Convert the salt string and the password string to a single
    // array of bytes. Note that the password string is Unicode and
    // therefore may or may not have a zero in every other byte.

    byte[] binarySaltValue = new byte[SaltValueSize];

    //FormatException raised here
    binarySaltValue[0] = byte.Parse(saltValue.Substring(0, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
    binarySaltValue[1] = byte.Parse(saltValue.Substring(2, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
    binarySaltValue[2] = byte.Parse(saltValue.Substring(4, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
    binarySaltValue[3] = byte.Parse(saltValue.Substring(6, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);

//...
//Some more code
//...
}
}

私は1行だけを変更しました:

string saltValueString = utf16.GetString(saltValue);

string saltValueString = utf16.GetString(saltValue, 0, SaltValueSize);

メソッドの最初のバージョンは組み込み C# では使用できないように見えるためです。とにかく、この行を変更せずに (非埋め込み環境で) テストしましたが、それでも FormatException が発生していました。

SaltValueSize他の msdn コード サンプル (関連する) から値を コピーしました:パスワードを検証する方法

例外を発生させるテスト:

HashPassword("youpi", null, new SHA1CryptoServiceProvider());

4

1 に答える 1

2

問題は、GenerateSaltValueメソッドが 16 進数の文字列を返さないことにあります。

いくつかのランダムな記号の文字列を返しますが、これは有効な 16 進数記号である場合もあれば、通常はそうでない場合もあります

また、あなたの例はMicrosoft Commerce Serverに関するものです。それが何であるかはわかりません。

"解決:"

このすべての例が、この文字列から 16 進数への変換で何を達成したいのかわかりませんが、GenerateSaltValue を正常に実行するには、次のようにする必要があります。

public static string ByteArrayToString(byte[] byteArray)
{
    StringBuilder hex = new StringBuilder(byteArray.Length * 2);

    foreach (byte b in byteArray)
        hex.AppendFormat("{0:x2}", b);

    return hex.ToString();
}

// Renamed GenerateSaltValue method
private static string GenerateHexSaltString()
{
    Random random = new Random();

    // Create an array of random values.
    byte[] saltValue = new byte[SaltValueSize];

    random.NextBytes(saltValue);

    string saltValueString = ByteArrayToString(saltValue);

    // Return the salt value as a string.
    return saltValueString;
}

そして、バイト配列を16進文字列に変換する方法、およびその逆のおかげで、プログラムは「機能」します。

しかし:

  • Salt の作成に Random を使用するのは悪い考えです。
  • string-tohex-tobinary 変換はさらに悪いように見えます。
  • そして他の問題...

それで:

次のような、C# のパスワード ハッシュと暗号化に実際に関連する記事を読んでください。

C# でのハッシュ パスワードとソルト パスワード

また、コード例を検索するときは十分に注意してください。別のバージョン、プラットフォーム、さらには言語を使用している可能性もあります。幸運を。

于 2014-07-28T18:56:50.090 に答える