How to generate a CRC-16 from C# - c#

I am trying to generate a CRC-16 using C#. The hardware I am using for RS232 requires the input string to be HEX. The screenshot below shows the correct conversion, For a test, I need 8000 to be 0xC061, however the C# method that generates CRC-16 must be able to convert any given HEX string.
I have tried using Nito.KitchenSink.CRC
I have also tried the below which generates 8009 when 8000 is inputted -
public string CalcCRC16(string strInput)
{
ushort crc = 0x0000;
byte[] data = GetBytesFromHexString(strInput);
for (int i = 0; i < data.Length; i++)
{
crc ^= (ushort)(data[i] << 8);
for (int j = 0; j < 8; j++)
{
if ((crc & 0x8000) > 0)
crc = (ushort)((crc << 1) ^ 0x8005);
else
crc <<= 1;
}
}
return crc.ToString("X4");
}
public Byte[] GetBytesFromHexString(string strInput)
{
Byte[] bytArOutput = new Byte[] { };
if (!string.IsNullOrEmpty(strInput) && strInput.Length % 2 == 0)
{
SoapHexBinary hexBinary = null;
try
{
hexBinary = SoapHexBinary.Parse(strInput);
if (hexBinary != null)
{
bytArOutput = hexBinary.Value;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
return bytArOutput;
}

Here we go; note that this is a specific flavor of CRC-16 - it is confusing to say just "CRC-16". This borrows some implementation specifics from http://www.sanity-free.com/ - note I have made it static rather than instance-based.
using System;
static class Program
{
static void Main()
{
string input = "8000";
var bytes = HexToBytes(input);
string hex = Crc16.ComputeChecksum(bytes).ToString("x2");
Console.WriteLine(hex); //c061
}
static byte[] HexToBytes(string input)
{
byte[] result = new byte[input.Length / 2];
for(int i = 0; i < result.Length; i++)
{
result[i] = Convert.ToByte(input.Substring(2 * i, 2), 16);
}
return result;
}
public static class Crc16
{
const ushort polynomial = 0xA001;
static readonly ushort[] table = new ushort[256];
public static 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;
}
static 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;
}
}
}
}

In Addition, If you want CRC16-CCITT.
private ushort Crc16Ccitt(byte[] bytes)
{
const ushort poly = 4129;
ushort[] table = new ushort[256];
ushort initialValue = 0xffff;
ushort temp, a;
ushort crc = initialValue;
for (int i = 0; i < table.Length; ++i)
{
temp = 0;
a = (ushort)(i << 8);
for (int j = 0; j < 8; ++j)
{
if (((temp ^ a) & 0x8000) != 0)
temp = (ushort)((temp << 1) ^ poly);
else
temp <<= 1;
a <<= 1;
}
table[i] = temp;
}
for (int i = 0; i < bytes.Length; ++i)
{
crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
}
return crc;
}

Related

Diffie Hellman key exchange between C# and C++ on Windows

I want to use the Diffie Hellman algorithm to securely exchange keys between a C++ server an a C# client which both are running on Windows. I tried using ECDiffieHellmanCng in C# to generate a public key as follows:
ECDiffieHellmanCng diffieHellman = new ECDiffieHellmanCng
{
KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash,
HashAlgorithm = CngAlgorithm.Sha256
};
byte[] publicKey = diffieHellman.PublicKey.ToByteArray(); // 140 bytes
Furthermore, I'm deriving the AES key using the following code:
var cngKey = CngKey.Import(publicKey, CngKeyBlobFormat.EccPublicBlob);
var aesKey = diffieHellman.DeriveKeyMaterial(cngKey); // 32 bytes
This works well in a C# context, however I need it to interact with C++.
Is there any C++ library or code which is compatible with ECDiffieHellmanCng? I looked into Crypto++ but it wants me to generate a p, q, and g as well as the public key size being 128 bytes which looks like it's not compatible with my C# key exchange method.
Any other suggestions or code examples for performing the key exchange are welcome regardless.
Since I simply wanted an encrypted connection, going with OpenSSL was the way to go.
Maybe this will help you a bit?
#pragma warning(disable : 4996)
#include <stdio.h>
#include <iostream>
#include <string>
#include <sstream>
#include "openssl/dh.h"
#include "openssl/bn.h"
#include "openssl/pem.h";
using namespace std;
DH *dhp = NULL;
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i < 4); i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for (j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while ((i++ < 3))
ret += '=';
}
return ret;
}
std::string base64_decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i < 4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j < 4; j++)
char_array_4[j] = 0;
for (j = 0; j < 4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
int main(int argc, char *argv[])
{
BIGNUM* priv_key = NULL;
BIGNUM* apub_key = NULL;
BIGNUM* p = NULL;
BIGNUM* g = NULL;
std::string userPubKey;
std::string prime;
std::string generator;
if (argc < 6) {
printf("%s", "Missing parameters: -p, -key -g");
return -1;
}
//Process parameters
int count;
for (count = 1; count < argc; count+=2)
{
std::string param = (string)argv[count];
if (strcmpi(param.c_str(), "-p") == 0) {
prime = (string)argv[count+1];
}
else if (strcmpi(param.c_str(), "-key") == 0) {
userPubKey = (string)argv[count + 1];
}
else if (strcmpi(param.c_str(), "-g") == 0) {
generator = (string)argv[count+1];
}
}
//Set public key of remote User
BN_hex2bn(&apub_key, userPubKey.c_str());
DH *dhp = DH_new();
if (dhp == NULL) {
return -1;
}
//Set Prime and Generator
BN_hex2bn(&p, prime.c_str());
BN_dec2bn(&g, generator.c_str());
DH_set0_pqg(dhp, p, NULL, g);
if (DH_generate_key(dhp) != 1) {
printf("%s", "Error generating keys.");
return -1;
}
//Print Public Key as Hex
const BIGNUM* exportPublic = DH_get0_pub_key(dhp);
printf("Public Key: %s\r\n", BN_bn2hex(exportPublic));
//Calculate secret
char buf[256] = { 0 };
unsigned char* abuf = NULL;
int alen = DH_size(dhp);
abuf = (unsigned char*)OPENSSL_malloc(alen);
int aout = DH_compute_key(abuf, apub_key, dhp);
printf("\r\nThe shared secret is:\r\n");
std::string encoded = base64_encode(abuf, aout);
printf("%s\r\n", encoded.c_str());
DH_free(dhp);
p = NULL;
g = NULL;
abuf = NULL;
}

C#, Checksum CRC-16/MCRF4XX

Does anyone know the calculate of CRC-16/MCRF4XX with C#?
I tried with this code:
private static ushort Calc(byte[] x)
{
ushort wCRC = 0;
for (int i = 0; i < x.Length; i++)
{
wCRC ^= (ushort)(x[i] << 8);
for (int j = 0; j < 8; j++)
{
if ((wCRC & 0x8000) != 0)
wCRC = (ushort)((wCRC << 1) ^ 0x1021);
else
wCRC <<= 1;
}
}
return wCRC;
}
but the result doesn't match.

Incorrect CRC8 checksum computation

I got this class to compute the CRC8 checksum of a byte[]:
public static class Crc8
{
static byte[] table = new byte[256];
// x8 + x7 + x6 + x4 + x2 + 1
const byte poly = 0xd5;
public static byte ComputeChecksum(params byte[] bytes)
{
byte crc = 0;
if (bytes != null && bytes.Length > 0)
{
foreach (byte b in bytes)
{
crc = table[crc ^ b];
}
}
return crc;
}
static Crc8()
{
for (int i = 0; i < 256; ++i)
{
int temp = i;
for (int j = 0; j < 8; ++j)
{
if ((temp & 0x80) != 0)
{
temp = (temp << 1) ^ poly;
}
else
{
temp <<= 1;
}
}
table[i] = (byte)temp;
}
}
}
And in the Main I got:
static void Main(string[] args)
{
string number = "123456789";
Console.WriteLine(Convert.ToByte(Crc8.ComputeChecksum(StringToByteArray(number))).ToString("x2"));
Console.ReadLine();
}
private static byte[] StringToByteArray(string str)
{
ASCIIEncoding enc = new ASCIIEncoding();
return enc.GetBytes(str);
}
This results in 0xBC
However, according to: http://www.scadacore.com/field-tools/programming-calculators/online-checksum-calculator/
this is incorrect, because the checksum for the CheckSum8 Xor is 0x31.
What did I wrong there?
On the linked site only some 16 and 32 bit CRCs are listed, the
CheckSum8Xor is not a CRC. The 0xBC comes from a 8-bit CRC
called "CRC-8/DVB-S2", see http://reveng.sourceforge.net/crc-catalogue/1-15.htm
Ah, ok, so I've overiterpreted this checksum computation.
Well, in that case, it's easy:
public static byte Checksum8XOR(byte[] data)
{
byte checksum = 0x00;
for (int i = 0; i < data.Length; i++)
{
checksum ^= data[i];
}
return checksum;
}

Compare string using bitwise shift operation

So i am new to csharp and i cant seem to find a logical error here in this program.i am learning the bitwise shift operators as i am new to these operators. I need help tracing a fault in my code. the program encodes an input String and decodes the encoded String after.After that i compare the string to see if they are equal.They seem to be equal to me but i keep getting a false when i compare them. Here is my code:
class Program
{
static char[] transcode = new char[64];
private static void prep()
{
for (int i = 0; i < transcode.Length; i++)
{
transcode[i] = (char)((int)'A' + i);
if (i > 25 && i <= 51)
{
transcode[i] = (char)((int)transcode[i] + 6);
}
else if (i > 51)
{
transcode[i] = (char)((int)transcode[i] - 0x4b);
}
}
transcode[transcode.Length - 3] = '+';
transcode[transcode.Length - 2] = '/';
transcode[transcode.Length - 1] = '=';
}
static void Main(string[] args)
{
prep();
string test_string = "a";
if (Convert.ToBoolean(String.Compare(test_string, decode(encode(test_string)))))
{
Console.WriteLine("Test succeeded");
}
else
{
Console.WriteLine("Test failed");
}
}
private static string encode(string input)
{
int l = input.Length;
int cb = (l / 3 + (Convert.ToBoolean(l % 3) ? 1 : 0)) * 4;// (0 +(1))*4 =4
char[] output = new char[cb];
for (int i = 0; i < cb; i++)
{
output[i] = '=';
}
int c = 0;
int reflex = 0;
const int s = 0x3f;
for (int j = 0; j < l; j++)
{
reflex <<= 8;
reflex &= 0x00ffff00;
reflex += input[j];
int x = ((j % 3) + 1) * 2;
int mask = s << x;
while (mask >= s)
{
int pivot = (reflex & mask) >> x;
output[c++] = transcode[pivot];
char alpha = transcode[pivot];
int invert = ~mask;
reflex &= invert;
mask >>= 6;
x -= 6; //-4
}
}
switch (l % 3)
{
case 1:
reflex <<= 4; //16
output[c++] = transcode[reflex];
char at16 = transcode[16];
// Console.WriteLine("Character at 16 is: " + at16);
break;
case 2:
reflex <<= 2;
output[c++] = transcode[reflex];
break;
}
return new string(output);//final value is: YQ== (Encoded String.)
}
private static string decode(string input)//input is YQ== which has a length of 4
{
int l = input.Length;
int cb = (l / 4 + ((Convert.ToBoolean(l % 4)) ? 1 : 0)) * 3 + 1; // (1 + (0))*4
char[] output = new char[cb]; //4 in length
int c = 0;
int bits = 0;
int reflex = 0;
for (int j = 0; j < l; j++)
{
reflex <<= 6;
bits += 6;
bool fTerminate = ('=' == input[j]);
if (!fTerminate)
{
reflex += indexOf(input[j]);
while (bits >= 8)
{
int mask = 0x000000ff << (bits % 8);
output[c++] = (char)((reflex & mask) >> (bits % 8)); //convert issue cannot implicitly convert to proper data type.so will have to explicitly convert.
int invert = ~mask;
reflex &= invert;
bits -= 8;
}
}
else
{
break;
}
}
return new string(output);
}
private static int indexOf(char ch)
{
int index;
for (index = 0; index < transcode.Length; index++)
if (ch == transcode[index])
break;
return index;
}
}
Read the docs for String.Compare then read the docs for Convert.ToBoolean. Pay particular attention to the value returned by String.Compare when two strings are equal. Then compare with how that value gets converted to a boolean by ToBoolean
String.Compare is designed for sorting strings. It returns 0 when two strings are equal. ToBoolean will convert that 0 to false. So when you strings are equal, your if evaluates to false and not true.
A simple change would be:
if (String.Compare(test_string, decode(encode(test_string)))==0)
{
Console.WriteLine("Test succeeded");
}
else
{
Console.WriteLine("Test failed");
}
#Tom's comment about the trailing nulls also applies, but it seems that String.Compare just ignores them.

CRC_CCITT Kermit 16 in C#

I'm currently working on a hard way that requires the CRC_CCITT Kermit 16 protocol with the formula (X16 + X12 + X5 + 1). However some of the code I've found online both on this site or the web in general I don't seem to get my desired result. I saw this website (http://www.lammertbies.nl/comm/info/crc-calculation.html) that actually provides me with the exact match I want but it was written in C++. So can anyone help me with this?
I look forward to hearing from you.
Kind regards
Michael
if you need CRC CCITT 16 Kermit you'll need the following code (from my site):
var crc16Kermit = new Crc16( Crc16Mode.CcittKermit );
var checksum = crc16Kermit.ComputeChecksumBytes( 0x01, 0x23, 0x45 );
// checksum = 0x2e, 0x46
here's the source for the above code
using System;
public enum Crc16Mode : ushort { Standard = 0xA001, CcittKermit = 0x8408 }
public class Crc16 {
static ushort[] table = new ushort[256];
public ushort ComputeChecksum( params 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( params byte[] bytes ) {
ushort crc = ComputeChecksum( bytes );
return BitConverter.GetBytes( crc );
}
public Crc16( Crc16Mode mode ) {
ushort polynomial = (ushort)mode;
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;
}
}
}
link for the above code: http://sanity-free.org/147/standard_crc16_and_crc16_kermit_implementation_in_csharp.html
Seems you want CRC16 CCITT. Try this:
using System;
public enum InitialCrcValue { Zeros, NonZero1 = 0xffff, NonZero2 = 0x1D0F }
public class Crc16Ccitt {
const ushort poly = 4129;
ushort[] table = new ushort[256];
ushort initialValue = 0;
public ushort ComputeChecksum(byte[] bytes) {
ushort crc = this.initialValue;
for(int i = 0; i < bytes.Length; ++i) {
crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
}
return crc;
}
public byte[] ComputeChecksumBytes(byte[] bytes) {
ushort crc = ComputeChecksum(bytes);
return BitConverter.GetBytes(crc);
}
public Crc16Ccitt(InitialCrcValue initialValue) {
this.initialValue = (ushort)initialValue;
ushort temp, a;
for(int i = 0; i < table.Length; ++i) {
temp = 0;
a = (ushort)(i << 8);
for(int j = 0; j < 8; ++j) {
if(((temp ^ a) & 0x8000) != 0) {
temp = (ushort)((temp << 1) ^ poly);
} else {
temp <<= 1;
}
a <<= 1;
}
table[i] = temp;
}
}
}
Source:
http://sanity-free.org/133/crc_16_ccitt_in_csharp.html

Categories

Resources