123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- using System;
- using System.IO;
- namespace COSXML.Utils
- {
- public class Crc64
- {
- private static ulong[] _table;
- private static object _lock = new object();
- private const int GF2_DIM = 64;
- private static ulong _poly;
- private static void GenStdCrcTable(ulong poly)
- {
- _poly = poly;
- _table = new ulong[256];
- for (uint n = 0; n < 256; n++)
- {
- ulong crc = n;
- for (int k = 0; k < 8; k++)
- {
- if ((crc & 1) == 1)
- {
- crc = (crc >> 1) ^ poly;
- }
- else
- {
- crc = (crc >> 1);
- }
- }
- _table[n] = crc;
- }
- }
- private static ulong TableValue(ulong[] table, byte b, ulong crc)
- {
- unchecked
- {
- return (crc >> 8) ^ table[(crc ^ b) & 0xffUL];
- }
- }
- public static void Init(ulong poly)
- {
- if (_table == null)
- {
- lock (_lock)
- {
- if (_table == null)
- {
- GenStdCrcTable(poly);
- }
- }
- }
- }
- public static void InitECMA()
- {
- Init(0xC96C5795D7870F42);
- }
- public static ulong Compute(byte[] bytes, int start, int size, ulong crc = 0)
- {
- crc = ~crc;
- for (var i = start; i < start + size; i++)
- {
- crc = TableValue(_table, bytes[i], crc);
- }
- crc = ~crc;
- return crc;
- }
- private static ulong Gf2MatrixTimes(ulong[] mat, ulong vec)
- {
- ulong sum = 0;
- int idx = 0;
- while (vec != 0)
- {
- if ((vec & 1) == 1)
- {
- sum ^= mat[idx];
- }
- vec >>= 1;
- idx++;
- }
-
- return sum;
- }
- private static void Gf2MatrixSquare(ulong[] square, ulong[] mat)
- {
- for (int n = 0; n < GF2_DIM; n++)
- {
- square[n] = Gf2MatrixTimes(mat, mat[n]);
- }
- }
- static public ulong Combine(ulong crc1, ulong crc2, long len2)
- {
- // degenerate case.
- if (len2 == 0)
- {
- return crc1;
- }
- int n;
- ulong row;
- ulong[] even = new ulong[GF2_DIM];
- ulong[] odd = new ulong[GF2_DIM];
- // put operator for one zero bit in odd
- odd[0] = _poly;
- row = 1;
- for (n = 1; n < GF2_DIM; n++)
- {
- odd[n] = row;
- row <<= 1;
- }
- // put operator for two zero bits in even
- Gf2MatrixSquare(even, odd);
- // put operator for four zero bits in odd
- Gf2MatrixSquare(odd, even);
- // apply len2 zeros to crc1 (first square will put the operator for one
- // zero byte, eight zero bits, in even)
- do
- {
- // apply zeros operator for this bit of len2
- Gf2MatrixSquare(even, odd);
- if ((len2 & 1) == 1)
- {
- crc1 = Gf2MatrixTimes(even, crc1);
- }
-
- len2 >>= 1;
- // if no more bits set, then done
- if (len2 == 0)
- {
- break;
- }
- // another iteration of the loop with odd and even swapped
- Gf2MatrixSquare(odd, even);
- if ((len2 & 1) == 1)
- {
- crc1 = Gf2MatrixTimes(odd, crc1);
- }
- len2 >>= 1;
- // if no more bits set, then done
- } while (len2 != 0);
- // return combined crc.
- crc1 ^= crc2;
- return crc1;
- }
- public static bool CompareCrc64(string localFile, string crc64ecma)
- {
- Crc64.InitECMA();
- String hash = String.Empty;
- using (FileStream fs = File.Open(localFile, FileMode.Open))
- {
- byte[] buffer = new byte[2048];
- int bytesRead;
- ulong crc = 0;
- while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
- {
- ulong partCrc = Crc64.Compute(buffer, 0, bytesRead);
- if (crc == 0)
- {
- crc = partCrc;
- }
- else
- {
- crc = Crc64.Combine(crc, partCrc, bytesRead);
- }
- }
- string localFileCrc64 = crc.ToString();
- return localFileCrc64 == crc64ecma;
- }
- }
- }
- }
|