5

序文:

検証コミット フェーズがあるデータ インポートを実行しています。アイデアは次のとおりです。最初のフェーズでは、さまざまなソースからデータを取得し、データベースに対してさまざまな挿入/更新/検証操作を実行できます。コミットはロールバックされますが、「検証ハッシュ/チェックサム」が生成されます。コミット フェーズは同じですが、「検証ハッシュ/チェックサム」が同じ場合、操作はコミットされます。(データベースは適切な分離レベルで実行されます。)

制限:

  • 入力の読み取りと操作は、前方読み取り 1 回のみです。
  • 大量のデータが存在する可能性があるため、ストリームを事前に作成しないでください (たとえば、MemoryStream への書き込みは望ましくありません) 。(サーバー/負荷で動作しますが、ふりをするメモリは限られています。)
  • 「自分で作成」したくない。( Damien による CRC-32 のような利用可能なコードを知っています。これは使用/変更できますが、「標準」を好むでしょう。)

そして、私が(私がいると思う)探しているもの:

入力 + 操作に基づいてハッシュ (SHA1 や MD5 など) またはチェックサム (CRC32 など) を生成する方法。(入力/操作自体をハッシュして、チェックサム生成に適した値にすることもできますが、「Steam に書き込む」ことができると便利です。)

したがって、質問は次のとおりです。

C#でランニングハッシュ(またはチェックサム)を生成するには?

また、Running オペレーション用に変更できる CRC32 実装がありますが、SHAx または MD5 ハッシュの実行についてはどうでしょうか?

アダプターとして使用できる便利な Stream アプローチが欠けていますか?

(批判は大歓迎ですが、該当する場合は上記にも回答してください。また、スレッドは扱いたくないです。;-)

4

4 に答える 4

9

HashAlgorithm.TransformBlockを複数回呼び出すとTransformFinalBlock、すべてのブロックの結果が得られます。

入力をチャンクアップし (ストリームから x バイト量を読み取ることによって)、TransformBlockチャンクごとに呼び出します。

編集(msdnの例から):

public static void PrintHashMultiBlock(byte[] input, int size)
{
    SHA256Managed sha = new SHA256Managed();
    int offset = 0;

    while (input.Length - offset >= size)
        offset += sha.TransformBlock(input, offset, size, input, offset);

    sha.TransformFinalBlock(input, offset, input.Length - offset);
    Console.WriteLine("MultiBlock {0:00}: {1}", size, BytesToStr(sha.Hash));
}

申し訳ありませんが、すぐに利用できる例はありませんが、基本的にinput独自のチャンクに置き換えている場合、sizeはそのチャンクのバイト数になります。オフセットを自分で追跡する必要があります。

于 2012-06-11T18:13:44.000 に答える
5

ハッシュには、ビルド フェーズとファイナライズ フェーズがあります。ビルド段階で、任意の量のデータを押し込むことができます。データは好きなように分割できます。最後に、ハッシュ操作を終了し、ハッシュを取得します。

書き込み可能なCryptoStreamを使用してデータを書き込むことができます。これが最も簡単な方法です。

于 2012-06-11T18:15:17.607 に答える
2

MD5CryptoServiceProviderComputeHashメソッドを使用して、MD5 ハッシュを生成できます。入力としてストリームを取ります。

メモリまたはファイル ストリームを作成し、それにハッシュ入力を書き込み、完了したら ComputeHash メソッドを呼び出します。

var myStream = new MemoryStream();

// Blah blah, write to the stream...

myStream.Position = 0;

using (var csp = new MD5CryptoServiceProvider()) {
    var myHash = csp.ComputeHash(myStream);
}

編集:大規模なストリームの構築を回避する1つの可能性は、これをループで何度も呼び出し、結果をXORすることです:

// Assuming we had this somewhere:
Byte[] myRunningHash = new Byte[16];

// Later on, from above:
for (var i = 0; i < 16; i++) // I believe MD5 are 16-byte arrays.  Edit accordingly.
    myRunningHash[i] = myRunningHash[i] ^ [myHash[i];

編集 #2: 最後に、以下の @usr の回答に基づいて構築すると、おそらく HashCore と HashFinal を使用できます。

using (var csp = new MD5CryptoServiceProvider()) {

    // My example here uses a foreach loop, but an 
    // event-driven stream-like approach is 
    // probably more what you are doing here.
    foreach (byte[] someData in myDataThings)
        csp.HashCore(someData, 0, someData.Length);

    var myHash = csp.HashFinal();
}
于 2012-06-11T18:14:39.170 に答える
0

これは標準的な方法です:

using System;
using System.Security.Cryptography;
using System.Text;

public void CreateHash(string sSourceData)
{
    byte[] sourceBytes;
    byte[] hashBytes;

    //create Bytearray from source data
    sourceBytes = ASCIIEncoding.ASCII.GetBytes(sSourceData);

    // calculate 16 Byte Hashcode
    hashBytes = new MD5CryptoServiceProvider().ComputeHash(sourceBytes);
    string sOutput = ByteArrayToHexString(hashBytes);
 }

static string ByteArrayToHexString(byte[] arrInput)
{
    int i;
    StringBuilder sOutput = new StringBuilder(arrInput.Length);
    for (i = 0; i < arrInput.Length - 1; i++)
    {
        sOutput.Append(arrInput[i].ToString("X2"));
    }
    return sOutput.ToString();
}
于 2012-06-11T18:21:23.007 に答える