is there any equivalient php hash crc32b method in c#? - c#
In PHP
echo hash("crc32b","hello world");
//it print : 0d4a1185
Is there any equivalent method in c#?
bellow the class used in one of my c# projects :
class CRC32B
{
public static int Main(String INPUT)
{
// first convert string to byte-array
String input = INPUT;
byte[] bytes = new byte[input.Length * sizeof(char)];
System.Buffer.BlockCopy(input.ToCharArray(), 0, bytes, 0, bytes.Length);
// then calculate the value
int crcVal = (int)crc32(input);
if (crcVal < 0)
{
crcVal = crcVal * (-1);
}
//Console.WriteLine((int)crcVal);
return (int)crcVal;
}
public static uint crc32(string input)
{
var table = new uint[]{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
unchecked
{
uint crc = (uint)(((uint)0) ^ (1));
var len = input.Length;
for (var i = 0; i < len; i++)
{
crc = (crc >> 8) ^ table[
(crc ^ (byte)input[i]) & 0xFF
];
}
//crc = (uint)(crc ^ (-1));
if (crc < 0)
{
crc += (uint)4294967296;
crc = (uint)(crc ^ (-1));
}
return crc;
}
}
}
Related
My symmetric encryption adds data to my rsa key I want to save and load encrypted
Currently I am trying to implement a save function for my RSA key with the help of bouncycastle. I am running into problems if I try to save my public or private key encrypted and load it afterwards. As a little example here the original public key: 305C300D06092A864886F70D0101010500034B00304802410096B4751049165D1E046063EA22E8FFA0F90AE1DD997A3876DA5F79C7DE97951F009AC9ACA3EB91114F8A32C04F48293B6665CD6DD5C406C81CD13270A2AB61130203010001 What I get after loading it (it adds 4 zeroes, bigger key means more zeroes added): 305C300D06092A864886F70D0101010500034B00304802410096B4751049165D1E046063EA22E8FFA0F90AE1DD997A3876DA5F79C7DE97951F009AC9ACA3EB91114F8A32C04F48293B6665CD6DD5C406C81CD13270A2AB611302030100010000 I found out it has something to do with my implementation of the symmetric encryption and the padding used there. Normal text no matter how long it is just works fine without extra data getting added. This is the code I am using for my AES encryption: Encryption byte[] outputBytes = new byte[0]; AesEngine aesengine = new AesEngine(); CbcBlockCipher aesblockCipher = new CbcBlockCipher(aesengine); PaddedBufferedBlockCipher aescipher = new PaddedBufferedBlockCipher(aesblockCipher); KeyParameter aeskeyParameter = new KeyParameter(Hash.HashDataBlock(password, Hash.HashAlgorithm.SHA3).Bytes); aescipher.Init(true, aeskeyParameter); outputBytes = new byte[aescipher.GetOutputSize(inputBytes.Bytes.Length)]; int aeslength = aescipher.ProcessBytes(inputBytes.Bytes, outputBytes, 0); aescipher.DoFinal(outputBytes, aeslength); Decryption byte[] inputBytes = input.Bytes; byte[] outputBytes = new byte[0]; AesEngine aesengine = new AesEngine(); CbcBlockCipher aesblockCipher = new CbcBlockCipher(aesengine); PaddedBufferedBlockCipher aescipher = new PaddedBufferedBlockCipher(aesblockCipher); KeyParameter aeskeyParameter = new KeyParameter(Hash.HashDataBlock(password, Hash.HashAlgorithm.SHA3).Bytes); aescipher.Init(false, aeskeyParameter); outputBytes = new byte[aescipher.GetOutputSize(inputBytes.Length)]; int aeslength = aescipher.ProcessBytes(inputBytes, outputBytes, 0); aescipher.DoFinal(outputBytes, aeslength); My Functions to save and load the keys. The DataBlock class just converts data to needed formats like UTF8, Base64 or just byte arrays: public static void SaveKeyEncrypted(DataBlock key, string path, DataBlock password) { StreamWriter sw = new StreamWriter(path); DataBlock encrypted = SymmetricEncryption.Encrypt(key, password, SymmetricEncryption.SymmetricAlgorithms.AES); sw.Write(encrypted.Base64); sw.Close(); } public static DataBlock ReadKeyEncrypted(string path, DataBlock password) { StreamReader sr = new StreamReader(path); DataBlock readData = new DataBlock(sr.ReadLine(), DataBlock.DataType.Base64); sr.Close(); return SymmetricEncryption.Decrypt(readData, password, SymmetricEncryption.SymmetricAlgorithms.AES); } For reproduction my other code that has to do with this problem: public class DataBlock { private byte[] _data; public DataBlock() { this._data = new byte[0]; } public enum DataType { UTF8, UTF7, UTF32, ASCII, Unicode, Hex, Base64, Base32 } public DataBlock(string data, DataType dataType) : this() { switch (dataType) { case DataType.UTF8: this._data = Encoding.UTF8.GetBytes(data); break; case DataType.UTF7: this._data = Encoding.UTF7.GetBytes(data); break; case DataType.UTF32: this._data = Encoding.UTF32.GetBytes(data); break; case DataType.ASCII: this._data = Encoding.ASCII.GetBytes(data); break; case DataType.Unicode: this._data = Encoding.Unicode.GetBytes(data); break; case DataType.Hex: this._data = new byte[data.Length / 2]; for (int i = 0; i < data.Length; i += 2) { this._data[i / 2] = Convert.ToByte(data.Substring(i, 2), 16); } break; case DataType.Base64: this._data = Convert.FromBase64String(data); break; case DataType.Base32: this._data = this.FromBase32String(data); break; } } public DataBlock(byte[] data) { this._data = data; } public string UTF8 { get { return Encoding.UTF8.GetString(this._data); } } public string UTF7 { get { return Encoding.UTF7.GetString(this._data); } } public string UTF32 { get { return Encoding.UTF32.GetString(this._data); } } public string ASCII { get { return Encoding.ASCII.GetString(this._data); } } public string Unicode { get { return Encoding.Unicode.GetString(this._data); } } public string Hex { get { return BitConverter.ToString(this._data).Replace("-", ""); } } public string Base64 { get { return Convert.ToBase64String(this._data); } } public string Base32 { get { return this.ToBase32String(this._data); } } public byte[] Bytes { get { return this._data; } } private string ValidChars = "QAZ2WSX3" + "EDC4RFV5" + "TGB6YHN7" + "UJM8K9LP"; private string ToBase32String(byte[] bytes) { StringBuilder sb = new StringBuilder(); byte index; int hi = 5; int currentByte = 0; while (currentByte < bytes.Length) { if (hi > 8) { index = (byte)(bytes[currentByte++] >> (hi - 5)); if (currentByte != bytes.Length) { index = (byte)(((byte)(bytes[currentByte] << (16 - hi)) >> 3) | index); } hi -= 3; } else if (hi == 8) { index = (byte)(bytes[currentByte++] >> 3); hi -= 3; } else { index = (byte)((byte)(bytes[currentByte] << (8 - hi)) >> 3); hi += 5; } sb.Append(ValidChars[index]); } return sb.ToString(); } public byte[] FromBase32String(string str) { int numBytes = str.Length * 5 / 8; byte[] bytes = new Byte[numBytes]; str = str.ToUpper(); int bit_buffer; int currentCharIndex; int bits_in_buffer; if (str.Length < 3) { bytes[0] = (byte)(ValidChars.IndexOf(str[0]) | ValidChars.IndexOf(str[1]) << 5); return bytes; } bit_buffer = (ValidChars.IndexOf(str[0]) | ValidChars.IndexOf(str[1]) << 5); bits_in_buffer = 10; currentCharIndex = 2; for (int i = 0; i < bytes.Length; i++) { bytes[i] = (byte)bit_buffer; bit_buffer >>= 8; bits_in_buffer -= 8; while (bits_in_buffer < 8 && currentCharIndex < str.Length) { bit_buffer |= ValidChars.IndexOf(str[currentCharIndex++]) << bits_in_buffer; bits_in_buffer += 5; } } return bytes; } } Function to generate a keypair public static DataBlock[] GenerateKeyPair(KeyPairSize keyPairSize) { RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), (int) keyPairSize)); AsymmetricCipherKeyPair keyPair = keyPairGenerator.GenerateKeyPair(); PrivateKeyInfo pkInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private); SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public); DataBlock[] keyPairData = new DataBlock[2]; keyPairData[0] = new DataBlock(pkInfo.GetDerEncoded()); keyPairData[1] = new DataBlock(info.GetDerEncoded()); return keyPairData; } Code to reproduce the error: DataBlock[] keyPair = AsymmetricEncryption.GenerateKeyPair(AsymmetricEncryption.KeyPairSize.Bits512); DataBlock pass = new DataBlock("1234", DataBlock.DataType.UTF8); DataBlock orig = new DataBlock("Hello World", DataBlock.DataType.UTF8); DataBlock encrypted = AsymmetricEncryption.Encrypt(orig, keyPair[1]); AsymmetricEncryption.SaveKeyEncrypted(keyPair[0], "D:\\privateenc", pass); AsymmetricEncryption.SaveKeyEncrypted(keyPair[1], "D:\\publicenc", pass); DataBlock privateKey = AsymmetricEncryption.ReadKeyEncrypted("D:\\privateenc", pass); DataBlock publicKey = AsymmetricEncryption.ReadKeyEncrypted("D:\\publicenc", pass); DataBlock decrypted = AsymmetricEncryption.Decrypt(encrypted, privateKey); Console.WriteLine(decrypted.UTF8); The encryption/decryption method is not needed because the error already happens after reading the encrypted key on my harddrive. Why/where is the extra data added and how can I fix it?
I was able to fix it by adding the initial byte array length of the key to the encrypted text and read it later on. In the read function I cut everything after the original size of the key. The main problem is still present and this is just a workaround.
Add number of characters and extend time of Rfc6238AuthenticationService
I am using Rfc6238AuthenticationService at https://github.com/aspnet/Identity/blob/85012bd0ac83548f7eab31f0585dae3836935d9d/src/Microsoft.AspNet.Identity/Rfc6238AuthenticationService.cs which uses rfc6238 https://www.rfc-editor.org/rfc/rfc6238 internal static class Rfc6238AuthenticationService { private static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); private static readonly TimeSpan _timestep = TimeSpan.FromMinutes(3); private static readonly Encoding _encoding = new UTF8Encoding(false, true); private static int ComputeTotp(HashAlgorithm hashAlgorithm, ulong timestepNumber, string modifier) { // # of 0's = length of pin const int Mod = 1000000; // See https://www.rfc-editor.org/rfc/rfc4226 // We can add an optional modifier var timestepAsBytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((long)timestepNumber)); var hash = hashAlgorithm.ComputeHash(ApplyModifier(timestepAsBytes, modifier)); // Generate DT string var offset = hash[hash.Length - 1] & 0xf; Debug.Assert(offset + 4 < hash.Length); var binaryCode = (hash[offset] & 0x7f) << 24 | (hash[offset + 1] & 0xff) << 16 | (hash[offset + 2] & 0xff) << 8 | (hash[offset + 3] & 0xff); return binaryCode % Mod; } private static byte[] ApplyModifier(byte[] input, string modifier) { if (String.IsNullOrEmpty(modifier)) { return input; } var modifierBytes = _encoding.GetBytes(modifier); var combined = new byte[checked(input.Length + modifierBytes.Length)]; Buffer.BlockCopy(input, 0, combined, 0, input.Length); Buffer.BlockCopy(modifierBytes, 0, combined, input.Length, modifierBytes.Length); return combined; } // More info: https://www.rfc-editor.org/rfc/rfc6238#section-4 private static ulong GetCurrentTimeStepNumber() { var delta = DateTime.UtcNow - _unixEpoch; return (ulong)(delta.Ticks / _timestep.Ticks); } public static int GenerateCode(byte[] securityToken, string modifier = null) { if (securityToken == null) { throw new ArgumentNullException(nameof(securityToken)); } // Allow a variance of no greater than 90 seconds in either direction var currentTimeStep = GetCurrentTimeStepNumber(); using (var hashAlgorithm = new HMACSHA1(securityToken)) { return ComputeTotp(hashAlgorithm, currentTimeStep, modifier); } } public static bool ValidateCode(byte[] securityToken, int code, string modifier = null) { if (securityToken == null) { throw new ArgumentNullException(nameof(securityToken)); } // Allow a variance of no greater than 90 seconds in either direction var currentTimeStep = GetCurrentTimeStepNumber(); using (var hashAlgorithm = new HMACSHA1(securityToken)) { for (var i = -2; i <= 2; i++) { var computedTotp = ComputeTotp(hashAlgorithm, (ulong)((long)currentTimeStep + i), modifier); if (computedTotp == code) { return true; } } } // No match return false; } } Is it possible to add character limit in this class and make it configurable(like 6 chars)? Also, is it possible to extend the time of token and make it configurable(like 120 seconds)?
Here is the place, where OTP is truncated to the defined length: return binaryCode % Mod; So, you just need to change the value of the Mod to 1000000 to get 6-digits code. A variable, responsible for time of token is timestepNumber. So change the logic in its calculation if needed.
C# equalent to perl `pack("v",value)` while packing some values into `byte[]`
I am trying to replicate behavior of a perl script in my c# code. When we convert any value into the Byte[] it should look same irrespective of the language used. SO I have this function call which looks like this in perl: $diag_cmd = pack("V", length($s_part)) . $s_part; where $s_par is defined in following function. It is taking the .pds file at the location C:\Users\c_desaik\Desktop\DIAG\PwrDB\offtarget\data\get_8084_gpio.pds $s_part = sub read_pds { my $bin_s; my $input_pds_file = $_[0]; open(my $fh, '<', $input_pds_file) or die "cannot open file $input_pds_file"; { local $/; $bin_s = <$fh>; } close($fh); return $bin_s; } My best guess is that this function is reading the .pds file and turning it into a Byte array. Now, I tried to replicate the behavior into c# code like following static byte[] ConstructPacket() { List<byte> retval = new List<byte>(); retval.AddRange(System.IO.File.ReadAllBytes(#"C:\Users\c_desaik\Desktop\DIAG\PwrDB\offtarget\data\get_8084_gpio.pds")); return retval.ToArray(); } But the resulting byte array does not look same. Is there any special mechanism that I have to follow to replicate the behavior of pack("V", length($s_part)) . $s_part ?
As Simon Whitehead mentioned the template character V tells pack to pack your values into unsigned long (32-bit) integers (in little endian order). So you need to convert your bytes to a list (or array) of unsigned integers. For example: static uint[] UnpackUint32(string filename) { var retval = new List<uint>(); using (var filestream = System.IO.File.Open(filename, System.IO.FileMode.Open)) { using (var binaryStream = new System.IO.BinaryReader(filestream)) { var pos = 0; while (pos < binaryStream.BaseStream.Length) { retval.Add(binaryStream.ReadUInt32()); pos += 4; } } } return retval.ToArray(); } And call this function: var list = UnpackUint32(#"C:\Users\c_desaik\Desktop\DIAG\PwrDB\offtarget\data\get_8084_gpio.pds"); Update If you wanna read one length-prefixed string or a list of them, you can use this function: private string[] UnpackStrings(string filename) { var retval = new List<string>(); using (var filestream = System.IO.File.Open(filename, System.IO.FileMode.Open)) { using (var binaryStream = new System.IO.BinaryReader(filestream)) { var pos = 0; while ((pos + 4) <= binaryStream.BaseStream.Length) { // read the length of the string var len = binaryStream.ReadUInt32(); // read the bytes of the string var byteArr = binaryStream.ReadBytes((int) len); // cast this bytes to a char and append them to a stringbuilder var sb = new StringBuilder(); foreach (var b in byteArr) sb.Append((char)b); // add the new string to our collection of strings retval.Add(sb.ToString()); // calculate start position of next value pos += 4 + (int) len; } } } return retval.ToArray(); }
pack("V", length($s_part)) . $s_part which can also be written as pack("V/a*", $s_part) creates a length-prefixed string. The length is stored as a 32-bit unsigned little-endian number. +----------+----------+----------+----------+-------- ... | Length | Length | Length | Length | Bytes | ( 7.. 0) | (15.. 8) | (23..16) | (31..24) | +----------+----------+----------+----------+-------- ... This is how you recreate the original string from the bytes: Read 4 bytes If using a machine other than a little-endian machine, Rearrange the bytes into the native order. Cast those bytes into an 32-bit unsigned integer. Read a number of bytes equal to that number. Convert that sequences of bytes into a string. Some languages provide tools that perform more than one of these steps. I don't know C#, so I can't write the code for you, but I can give you an example in two other languages. In Perl, this would be written as follows: sub read_bytes { my ($fh, $num_bytes_to_read) = #_; my $buf = ''; while ($num_bytes_to_read) { my $num_bytes_read = read($fh, $buf, $num_bytes_to_read, length($buf)); if (!$num_bytes_read) { die "$!\n" if !defined($num_bytes_read); die "Premature EOF\n"; } $num_bytes_to_read -= $num_bytes_read; } return $buf; } sub read_uint32le { unpack('V', read_bytes($_[0], 4)) } sub read_pstr { read_bytes($_[0], read_uint32le($_[0])) } my $str = read_pstr($fh); In C, int read_bytes(FILE* fh, void* buf, size_t num_bytes_to_read) { while (num_bytes_to_read) { size_t num_bytes_read = fread(buf, 1, num_bytes_to_read, fh); if (!num_bytes_read) return 0; num_bytes_to_read -= num_bytes_read; buf += num_bytes_read; } return 1; } int read_uint32le(FILE* fh, uint32_t* p_i) { int ok = read_bytes(fh, p_i, sizeof(*p_i)); if (!ok) return 0; { /* Rearrange bytes on non-LE machines */ const char* p = (char*)p_i; *p_i = ((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0]; } return 1; } char* read_pstr(FILE* fh) { uint32_t len; char* buf = NULL; int ok; ok = read_uint32le(fh, &len); if (!ok) goto ERROR; buf = malloc(len+1); if (!buf) goto ERROR; ok = read_bytes(fh, buf, len); if (!ok) goto ERROR; buf[len] = '\0'; return buf; ERROR: if (p) free(p); return NULL; } char* str = read_pstr(fh);
CRC16 ISO 13239 Implementation
i'm trying to implement Crc16 in C#. I already tried many different implementations, but most of them gives me different values. Here are some of the codes that i already used. private static int POLYNOMIAL = 0x8408; private static int PRESET_VALUE = 0xFFFF; public static int crc16(byte[] data) { int current_crc_value = PRESET_VALUE; for (int i = 0; i < data.Length; i++) { current_crc_value ^= data[i] & 0xFF; for (int j = 0; j < 8; j++) { if ((current_crc_value & 1) != 0) { current_crc_value = (current_crc_value >> 1) ^ POLYNOMIAL; } else { current_crc_value = current_crc_value >> 1; } } } current_crc_value = ~current_crc_value; return current_crc_value & 0xFFFF; } this is the another implementation that i used but both gives different values const ushort polynomial = 0xA001; ushort[] table = new ushort[256]; public ushort ComputeChecksum(byte[] bytes) { ushort crc = 0; for (int i = 0; i < bytes.Length; ++i) { byte index = (byte)(crc ^ bytes[i]); crc = (ushort)((crc >> 8) ^ table[index]); } return crc; } public byte[] ComputeChecksumBytes(byte[] bytes) { ushort crc = ComputeChecksum(bytes); return BitConverter.GetBytes(crc); } public Crc16() { ushort value; ushort temp; for (ushort i = 0; i < table.Length; ++i) { value = 0; temp = i; for (byte j = 0; j < 8; ++j) { if (((value ^ temp) & 0x0001) != 0) { value = (ushort)((value >> 1) ^ polynomial); } else { value >>= 1; } temp >>= 1; } table[i] = value; } } The value I`m using is an Octet String "[jp3]TEST [fl]Flashing[/fl]" and its expected value is 95F9 in hex. This is an example on the guide of NTCIP protocol Thanks
This: static readonly ushort[] fcstab = new ushort[] { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; static ushort compute_fcs(byte[] data) { return compute_fcs(data, 0, data.Length); } static ushort compute_fcs(byte[] data, int start, int length) { ushort fcs = 0xFFFF; int end = start + length; for (int i = start; i < end; i++) { fcs = (ushort)(((ushort)(fcs >> 8)) ^ fcstab[(fcs ^ data[i]) & 0xFF]); } return (ushort)(~fcs); } static void Main(string[] args) { byte[] pattern = new byte[] { 0x02, 0x07, 0x01, 0x03, 0x01, 0x02, 0x00, 0x34, 0x07, 0x07, 0x1C, 0x59, 0x34, 0x6F, 0xE1, 0x83, 0x00, 0x00, 0x41, 0x06, 0x06, 0x7B, 0x3C, 0xFF, 0xCF, 0x3C, 0xC0 }; // http://www.ite.org/standards/1203v03-04%20Part%201%20dms2011.pdf // Page 158, CRC = 0x52ED ushort fcs = compute_fcs(pattern); // 0x52ED } will work for the only test given here http://www.ite.org/standards/1203v03-04%20Part%201%20dms2011.pdf (around page 158, CRC = 0x52ED). For the string example of the PDF, as written some pages later: " Indicates the CRC-16 (polynomial defined in ISO/IEC 3309) value created using the values of the dmsMessageMultiString (MULTI-Message), the dmsMessageBeacon, and the dmsMessagePixelService objects in the order listed, not including the OER type or length fields. Note that the calculation shall assume a value of zero (0) for the dmsMessageBeacon object and/or for the dmsMessagePixelService object if they are not supported (emphasis added) so: string str = "[jp3]TEST [fl]Flashing[/fl]"; var bytes = Encoding.ASCII.GetBytes(str); Array.Resize(ref bytes, bytes.Length + 2); // Note that these two rows are useless, because the Array.Resize will have already filled with 0 bytes[bytes.Length - 2] = 0; // dmsMessageBeacon bytes[bytes.Length - 1] = 0; // dmsMessagePixelService ushort fcs2 = compute_fcs(bytes); // 0xF995 var bytes2 = BitConverter.GetBytes(fcs2); // 0x95 0xF9 This shows that the protocol is little endian (as my PC, that is an Intel). In fact the CRC-16 of the string is 0xF995, but these 16 bits in memory appear as 0x95 0xF9 (as in the example, that shows the single bytes).
There are many algorithms of CRC-16 calculation. For instance: CRC-16-IBM which used in Modbus protocol, USB etc. is most popular. CRC-16-CCITT used in Bluetooth. I use CRC-16-IBM in my applications which work with industrial controllers. public static UInt16 FastCRC16(byte[] Buffer, UInt16 ui_length) { UInt16[] crc_table = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040}; UInt16 Crc = 65535; UInt16 x; for (UInt16 i = 0; i < ui_length; i++) { x = (UInt16)(Crc ^ Buffer[i]); Crc = (UInt16)((Crc >> 8) ^ crc_table[x & 0x00FF]); } return Crc; }
how to calculate CRC value for a file in C#.net?
i want to calculate the CRC value for a file using 32-bit algorithm in C#.net....
Algorithm is straightforward (rewritten from c++) class Crc32 { public static uint CountCrc(byte[] pBuf) { // Table of CRC-32's of all single byte values uint[] crctab = new uint[] { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; uint c = 0xffffffff; // begin at shift register contents int i, n = pBuf.Length; for (i = 0; i < n; i++) { c = crctab[((int)c ^ pBuf[i]) & 0xff] ^ (c >> 8); } return c ^ 0xffffffff; } }
I used Crc32.NET in BackgroundWorker: private void Crc_DoWork(object sender, DoWorkEventArgs e) { FileInfo file = e.Argument as FileInfo; uint r = 0; using (var s = file.OpenRead()) { byte[] buff = new byte[1024]; int len = s.Read(buff, 0, buff.Length); r = Crc32Algorithm.Compute(buff, 0, len); while ((len = s.Read(buff, 0, buff.Length)) > 0) r = Crc32Algorithm.Append(r, buff, 0, len); } e.Result = Convert.ToString(r, 16).ToUpper(); }