So machen Sie den Klassenfaden der CRC -Berechnung sicherC#

Ein Treffpunkt für C#-Programmierer
Anonymous
 So machen Sie den Klassenfaden der CRC -Berechnung sicher

Post by Anonymous »

Als wir unsere Anwendung (einen DOTNE -Dienst) parallelistisch ausgestattet haben, fanden wir ein unerwartetes Verhalten bei der CRC -Berechnung gegenüber Textdokumenten. < /p>
Um das Problem zu isolieren, habe ich einen Testfall erstellt. Die CRC -Berechnung schlägt fehl, wenn er aus der parallelen Schleife aufgerufen wird. In diesem Testfall ersetzt das Parallele foreach durch den Standard foreach gut. Ich denke, ich habe eine Änderung der CRC32 -Klassen -Implementierung vorgenommen. Ist das die richtige Richtung?

Code: Select all

[TestMethod()]
public void Test_Crc_TestoDoc()
{
string query = @"select top 100 docId from sometable";
///key is document's id
///value is a couple, crc and text
Dictionary docs = new Dictionary();
using (SqlDataReader oSqlDataReader = Utility.ExecuteSP_Reader(query))
{
while (oSqlDataReader.Read())
{
int docId = oSqlDataReader.GetInt32(0);
///retrive the text by docId
string docText = Utility.GetDocText(docId);
///calculate and add crc in dic
int CRC = CRC32.Compute(docText);
docs.Add(docId, new Tuple(CRC, docText));
}
oSqlDataReader.Close();
}
///calculate crc 100 times to check if the value
///is always the same for same text
for (int i = 0; i < 100; i++)
{
Parallel.ForEach(docs.Keys,(int docId) =>
{
///crc saved in dictionary
int CRC1 = docs[docId].Item1;
///text saved in dictionary
string docText = docs[docId].Item2;
///calculate crc again, crc2 must be equal to crc1 stored in dictionary
int CRC2 = CRC32.Compute(docText);
Assert.AreEqual(CRC1, CRC2, $"crc not equal, why? docId->{docId} CRC1->{CRC1} CRC2->{CRC2}");
});
}
}
< /code>
CRC32 Klasse: < /p>
public class CRC32 : HashAlgorithm
{

#region CONSTRUCTORS
/// Creates a CRC32 object using the .
public CRC32()
: this(DefaultPolynomial)
{
}

/// Creates a CRC32 object using the specified polynomial.
/// The polynomical should be supplied in its bit-reflected form.  .
[CLSCompliant(false)]
public CRC32(uint polynomial)
{
HashSizeValue = 32;
_crc32Table = (uint[])_crc32TablesCache[polynomial];
if (_crc32Table == null)
{
_crc32Table = CRC32._buildCRC32Table(polynomial);
_crc32TablesCache.Add(polynomial, _crc32Table);
}
Initialize();
}

// static constructor
static CRC32()
{
_crc32TablesCache = Hashtable.Synchronized(new Hashtable());
_defaultCRC = new CRC32();
}
#endregion

#region PROPERTIES
/// Gets the default polynomial (used in WinZip, Ethernet, etc.)
/// The default polynomial is a bit-reflected version of the standard polynomial 0x04C11DB7 used by WinZip, Ethernet, etc.
[CLSCompliant(false)]
public static readonly uint DefaultPolynomial = 0xEDB88320; // Bitwise reflection of 0x04C11DB7;
#endregion

#region METHODS
/// Initializes an implementation of HashAlgorithm.
public override void Initialize()
{
_crc = _allOnes;
}

/// Routes data written to the object into the hash algorithm for computing the hash.
protected override void HashCore(byte[] buffer, int offset, int count)
{
for (int i = offset; i < count; i++)
{
ulong ptr = (_crc & 0xFF) ^ buffer[i];
_crc >>= 8;
_crc ^= _crc32Table[ptr];
}
}

/// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
protected override byte[] HashFinal()
{
byte[] finalHash = new byte[4];
ulong finalCRC = _crc ^ _allOnes;

finalHash[0] = (byte)((finalCRC >> 0) & 0xFF);
finalHash[1] = (byte)((finalCRC >> 8) & 0xFF);
finalHash[2] = (byte)((finalCRC >> 16) & 0xFF);
finalHash[3] = (byte)((finalCRC >> 24) & 0xFF);

return finalHash;
}

/// Computes the CRC32 value for the given ASCII string using the .
public static int Compute(string asciiString)
{
_defaultCRC.Initialize();
return ToInt32(_defaultCRC.ComputeHash(asciiString));
}

/// Computes the CRC32 value for the given input stream using the .
public static int Compute(Stream inputStream)
{
_defaultCRC.Initialize();
return ToInt32(_defaultCRC.ComputeHash(inputStream));
}

/// Computes the CRC32 value for the input data using the .
public static int Compute(byte[] buffer)
{
_defaultCRC.Initialize();
return ToInt32(_defaultCRC.ComputeHash(buffer));
}

/// Computes the hash value for the input data using the .
public static int Compute(byte[] buffer, int offset, int count)
{
_defaultCRC.Initialize();
return ToInt32(_defaultCRC.ComputeHash(buffer, offset, count));
}

/// Computes the hash value for the given ASCII string.
/// The computation preserves the internal state between the calls, so it can be used for computation of a stream data.
public byte[] ComputeHash(string asciiString)
{
byte[] rawBytes = ASCIIEncoding.ASCII.GetBytes(asciiString);
return ComputeHash(rawBytes);
}

/// Computes the hash value for the given input stream.
/// The computation preserves the internal state between the calls, so it can be used for computation of a stream data.
new public byte[] ComputeHash(Stream inputStream)
{
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.Read(buffer, 0, 4096)) >  0)
{
HashCore(buffer, 0, bytesRead);
}
return HashFinal();
}

/// Computes the hash value for the input data.
/// The computation preserves the internal state between the calls, so it can be used for computation of a stream data.
new public byte[] ComputeHash(byte[] buffer)
{
return ComputeHash(buffer, 0, buffer.Length);
}

/// Computes the hash value for the input data.
/// The computation preserves the internal state between the calls, so it can be used for computation of a stream data.
new public byte[] ComputeHash(byte[] buffer, int offset, int count)
{
HashCore(buffer, offset, count);
return HashFinal();
}
#endregion

#region PRIVATE SECTION
private static uint _allOnes = 0xffffffff;
private static CRC32 _defaultCRC;
private static Hashtable _crc32TablesCache;
private uint[] _crc32Table;
private uint _crc;

// Builds a crc32 table given a polynomial
private static uint[] _buildCRC32Table(uint polynomial)
{
uint crc;
uint[] table = new uint[256];

// 256 values representing ASCII character codes.
for (int i = 0; i < 256; i++)
{
crc = (uint)i;
for (int j = 8; j > 0; j--)
{
if ((crc & 1) == 1)
crc = (crc >> 1) ^ polynomial;
else
crc >>= 1;
}
table[i] = crc;
}

return table;
}

private static int ToInt32(byte[] buffer)
{
return BitConverter.ToInt32(buffer, 0);
}
#endregion

}

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post