I have tried to implement LSB based reversal function. The code is in C#. There's a bug in reversal of the checksum. The function can only reverse the Crc64 checksum when it was computed with only 8 bytes original data. When I try to reverse the checksum through FixChecksum method, the middle 6 bytes are reversed, but the first & the last byte are reversed corrupted. Please inform what is wrong, what's needed to be implemented or fixed. I will appreciate any solution.
[UPDATED]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MYC;
using primaryMethodsCS_2;
using System.Globalization;
using UnitsFramework.Numerics;
using UnitsFramework;
namespace MYC
{
public class Crc64_LSB_Reverse
{
public const UInt64 POLY64REV = 0xD800000000000000; //0xffffffffffffff00;
public static ulong TOPBIT_MASK = 0x8000000000000000;
public static ulong LOWBIT_MASK = 0x0000000000000001;
public const ulong startxor = 0; //0xffffffffffffffff;
public const ulong FinalXor = 0; // 0xffffffffffffffff;
public UInt64[] CRCTable;
public UInt64[] revCRCTable;
public UInt64 crc = 0;
public Crc64_LSB_Reverse(UInt64 POLY = POLY64REV)
{
List<ulong> listforward = new List<ulong>();
List<ulong> listreverse = new List<ulong>();
for (int i = 0; i <= 255; i++)
{
List<ulong> forward = generateCrcTableConstants(new List<ulong>() { (UInt64)i }, POLY);
List<ulong> reverse = generateRevCrcTableConstants(new List<ulong>() { (UInt64)i }, POLY);
listforward.AddRange(forward);
listreverse.AddRange(reverse);
}
this.CRCTable = listforward.ToArray();
this.revCRCTable = listreverse.ToArray();
return;
}
public static List<UInt64> generateCrcTableConstants(List<UInt64> initialValues, UInt64 POLY)
{
List<UInt64> list = new List<ulong>();
for (int thisValue = 0; thisValue < initialValues.Count; thisValue++)
{
UInt64 currentValue = initialValues[thisValue];
UInt64 initialValue = currentValue;
currentValue <<= 56; // is valid for MSB forward table creation
// MSB based forward table implementation.
for (byte bit = 0; bit < 8; bit++)
{
if ((currentValue & TOPBIT_MASK) != 0)
{
//currentValue <<= 1;
//currentValue ^= CrcFramework.Reflect64(POLY);
currentValue = (currentValue << 1) ^ ((0 - (currentValue >> 63)) & POLY); // fwd
}
else
{
currentValue <<= 1;
}
}
list.Add(currentValue);
}
return list;
}
public static List<UInt64> generateRevCrcTableConstants(List<UInt64> initialValues, UInt64 POLY)
{
List<UInt64> list = new List<ulong>();
for (int thisValue = 0; thisValue < initialValues.Count; thisValue++)
{
UInt64 initialValue = initialValues[thisValue];
UInt64 currentValue = initialValues[thisValue];
// LSB based reverse table implementation for MSB based forward table function.
for (byte bit = 0; bit < 8; bit++)
{
if ((currentValue & LOWBIT_MASK) != 0)
{
//currentValue ^= POLY; // CrcFramework.Reflect64(POLY); //POLY;
currentValue = (currentValue >> 1) ^ ((0 - (currentValue & 1)) & POLY); // rvs
//currentValue >>= 1;
//currentValue |= 1; // TOPBIT_MASK;
}
else
{
currentValue >>= 1;
}
}
list.Add(currentValue);
}
return list;
}
public ulong Compute_LSB(byte[] bytes, bool reset = true)
{
if (reset) this.crc = startxor;
foreach (byte b in bytes)
{
byte curByte = b;
/* update the LSB of crc value with next input byte */
crc = (ulong)(crc ^ (ulong)(curByte));
/* this byte value is the index into the lookup table */
byte pos = (byte)(crc & 0xFF); // tushar: original 12-September-2019-1: & 0xFF);
/* shift out this index */
crc = (ulong)(crc >> 8);
/* XOR-in remainder from lookup table using the calculated index */
crc = (ulong)(crc ^ (ulong)CRCTable[pos]);
/* shorter:
byte pos = (byte)((crc ^ curByte) & 0xFF);
crc = (ulong)((crc >> 8) ^ (ulong)(crcTable[pos]));
*/
}
return (ulong)(crc ^ FinalXor);
}
public ulong Compute_MSB(byte[] bytes, bool reset = true)
{
if (reset) this.crc = startxor;
foreach (byte b in bytes)
{
byte curByte = b;
/* update the MSB of crc value with next input byte */
crc = (ulong)(crc ^ (ulong)((ulong)curByte << 56));
/* this MSB byte value is the index into the lookup table */
byte pos = (byte)(crc >> 56);
/* shift out this index */
crc = (ulong)(crc << 8);
/* XOR-in remainder from lookup table using the calculated index */
crc = (ulong)(crc ^ (ulong)CRCTable[pos]);
/* shorter:
byte pos = (byte)((crc ^ (curByte << 56)) >> 56);
crc = (uint)((crc << 8) ^ (ulong)(crcTable[pos]));
*/
}
return (ulong)(crc ^ FinalXor);
}
public UInt64 FixChecksum(byte[] bytes, Int64 length, Int64 fixpos, UInt64 wantcrc)
{
if (fixpos + 8 > length) return 0;
UInt64 crc = startxor;
for (Int64 i = 0; i < fixpos; i++)
{
crc = (crc >> 8) ^ CRCTable[(crc ^ bytes[i]) & 0xff];
}
Array.Copy(BitConverter.GetBytes(crc), 0, bytes, fixpos, 8);
List<UInt64> list = new List<UInt64>();
crc = wantcrc ^ startxor;
for (Int64 i = length - 1; i >= fixpos; i--)
{
UInt64 param0 = (UInt64)(crc >> 56);
list.Add(param0);
crc = (crc << 8) ^ revCRCTable[param0] ^ bytes[i]; //
}
Array.Copy(BitConverter.GetBytes(crc), 0, bytes, fixpos, 8);
return crc;
}
}
}
The solution to this problem involves reverse cycling a CRC.
If using tables, for CRC generation (forward cycling), a left shifting CRC uses the left byte of the CRC to index a table, and a right shifting CRC uses the right byte of the CRC to index a table. For CRC reverse cycling, a left shifting CRC uses the right byte of the CRC to index a table, and a right shifting CRC uses the left byte of the CRC to index a table.
Example code below for both left shifting and right shifting CRCs. Two additional tables are used for reverse cycling CRCs. The CRC functions take in a data length parameter, in case the buffer has additional space to store the CRC after generating it.
To simplify the reverse cycling functions, a CRC is generated and xor'ed with the wanted CRC, that can be used with an imaginary buffer of zeroes, to generate the 8 bytes of data needed to produce the xor'ed CRC. The 8 bytes of data are then xor'ed to the original buffer. The xor's cancel out the CRC initial and xor out values, so the reverse cycling functions don't have to take those values into account.
Note that the CRC bytes can go anywhere in a message (although they are usually at the end of a message). For example a 24 byte message consisting of 8 bytes of data, 8 bytes of CRC, 8 bytes of data, which can be created using crc64fw(0ul, bfr, 24, 8); or crc64rw(0ul, bfr, 24, 8);.
namespace crc64
{
public class crc64
{
public const ulong poly64f = 0x000000000000001bul;
public const ulong poly64r = 0xd800000000000000ul;
public const ulong crcin = 0x0000000000000000ul; // initial value
public const ulong xorot = 0x0000000000000000ul; // xorout
public static ulong[] crctblf; // fwd tbl
public static ulong[] crctblg; // fwd tbl reverse cycle
public static ulong[] crctblr; // ref tbl
public static ulong[] crctbls; // ref tbl reverse cycle
// generate tables
public static void gentbls()
{
ulong crc;
byte b;
b = 0;
do
{
crc = ((ulong)b)<<56;
for(int i = 0; i < 8; i++)
crc = (crc<<1)^((0-(crc>>63))&poly64f);
crctblf[b] = crc;
b++;
}while (b != 0);
do
{
crc = ((ulong)b) << 0;
for (int i = 0; i < 8; i++)
crc = (crc<<63)^((crc^((0-(crc&1))&poly64f))>>1);
crctblg[b] = crc;
b++;
} while (b != 0);
do
{
crc = ((ulong)b)<<0;
for(int i = 0; i < 8; i++)
crc = (crc>>1)^((0-(crc&1))&poly64r);
crctblr[b] = crc;
b++;
}while (b != 0);
do
{
crc = ((ulong)b) << 56;
for (int i = 0; i < 8; i++)
crc = (crc>>63)^((crc^((0-(crc>>63))&poly64r))<<1);
crctbls[b] = crc;
b++;
} while (b != 0);
}
// generate forward crc
public static ulong crc64f(byte[] bfr, int len)
{
ulong crc = crcin;
for(int i = 0; i < len; i++)
crc = (crc<<8)^(crctblf[(crc>>56)^bfr[i]]);
return (crc^xorot);
}
// append forward crc
public static void crc64fa(ulong crc, byte[] bfr, int pos)
{
bfr[pos+0] = (byte)(crc>>56);
bfr[pos+1] = (byte)(crc>>48);
bfr[pos+2] = (byte)(crc>>40);
bfr[pos+3] = (byte)(crc>>32);
bfr[pos+4] = (byte)(crc>>24);
bfr[pos+5] = (byte)(crc>>16);
bfr[pos+6] = (byte)(crc>> 8);
bfr[pos+7] = (byte)(crc>> 0);
}
// "fix" bfr to generate wanted forward crc
public static void crc64fw(ulong crc, byte[] bfr, int len, int pos)
{
crc ^= crc64f(bfr, len);
for(int i = pos; i < len; i++)
crc = (crc>>8)^(crctblg[crc&0xff]);
bfr[pos+0] ^= (byte)(crc>>56);
bfr[pos+1] ^= (byte)(crc>>48);
bfr[pos+2] ^= (byte)(crc>>40);
bfr[pos+3] ^= (byte)(crc>>32);
bfr[pos+4] ^= (byte)(crc>>24);
bfr[pos+5] ^= (byte)(crc>>16);
bfr[pos+6] ^= (byte)(crc>> 8);
bfr[pos+7] ^= (byte)(crc>> 0);
}
// generate reflected crc
public static ulong crc64r(byte[] bfr, int len)
{
ulong crc = crcin;
for(int i = 0; i < len; i++)
crc = (crc>>8)^(crctblr[(crc&0xff)^bfr[i]]);
return (crc^xorot);
}
// append reflected crc
public static void crc64ra(ulong crc, byte[] bfr, int pos)
{
bfr[pos+0] = (byte)(crc>> 0);
bfr[pos+1] = (byte)(crc>> 8);
bfr[pos+2] = (byte)(crc>>16);
bfr[pos+3] = (byte)(crc>>24);
bfr[pos+4] = (byte)(crc>>32);
bfr[pos+5] = (byte)(crc>>40);
bfr[pos+6] = (byte)(crc>>48);
bfr[pos+7] = (byte)(crc>>56);
}
// "fix" bfr to generate wanted reflected crc
public static void crc64rw(ulong crc, byte[] bfr, int len, int pos)
{
crc ^= crc64r(bfr, len);
for (int i = pos; i < len; i++)
crc = (crc<<8)^(crctbls[crc>>56]);
bfr[pos+0] ^= (byte)(crc>> 0);
bfr[pos+1] ^= (byte)(crc>> 8);
bfr[pos+2] ^= (byte)(crc>>16);
bfr[pos+3] ^= (byte)(crc>>24);
bfr[pos+4] ^= (byte)(crc>>32);
bfr[pos+5] ^= (byte)(crc>>40);
bfr[pos+6] ^= (byte)(crc>>48);
bfr[pos+7] ^= (byte)(crc>>56);
}
static void Main(string[] args)
{
crctblf = new ulong[256];
crctblg = new ulong[256];
crctblr = new ulong[256];
crctbls = new ulong[256];
byte[] bfr = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, // data (16 bytes)
0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x66,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // space for crc
ulong crcf, crcr, crcw, crcg, crcs;
int dl = bfr.Length-8; // length of data
int bl = bfr.Length; // length of bfr
gentbls();
crcf = crc64f(bfr, dl); // forward crc
crc64fa(crcf, bfr, dl); // append crc
crcw = crc64f(bfr, bl); // crcw == 0
crcr = crc64r(bfr, dl); // reflected crc
crc64ra(crcr, bfr, dl); // append crc
crcw = crc64r(bfr, bl); // crcw == 0
Console.WriteLine(crcf.ToString("x16") + " " + crcr.ToString("x16"));
crcw = 0x0001020304050607ul; // wanted crc
crc64fw(crcw, bfr, dl, 8); // "fix" for forward
crcg = crc64f(bfr, dl); // crcg == crcw
crc64fw(crcf, bfr, dl, 8); // undo "fix" for forward (restore bfr)
crc64rw(crcw, bfr, dl, 8); // "fix" for reflected
crcs = crc64r(bfr, dl); // crcs == crcw
Console.WriteLine(crcg.ToString("x16") + " " + crcs.ToString("x16"));
}
}
}
I am having trouble getting a CRC function to work in C#. Below is the example C code given, below is the C# code I use. I suspect the culprit is the big endian, but when I switch the byte order of the checksum it still gives different values.
Any ideas where I am going wrong?
Many thanks
Matt
CRC is calculated using CRC-CCITT (Kermit) algorithm (http://www.lammertbies.nl/comm/info/crccalculation.html).
Parameter length – 2 bytes. Format is big endian. That is why bytes 0 and 1 are “switched”.
CRC calculation algorithm is shown below (C programming language).
/*----------------------------------------------------------------------------
* FUNCTION: CRC16
*---------------------------------------------------------------------------
*/
unsigned short crc_16_rec (unsigned char *pucData, unsigned short ucLen) {
//--------------------------------------------------------------------
unsigned int i;
unsigned char ucBit, ucCarry;
//--------------------------------------------------------------------
unsigned short usPoly = 0x8408;//reversed 0x1021
unsigned short usCRC = 0;
//--------------------------------------------------------------------
for (i = 0; i < ucLen; i++) {
usCRC ^= pucData[i];
for (ucBit = 0; ucBit < 8; ucBit++) {
ucCarry = usCRC & 1;
usCRC >>= 1;
if (ucCarry) {
usCRC ^= usPoly;
}
}
}
//--------------------------------------------------------------------
return usCRC;
//--------------------------------------------------------------------
}
The code I use
public enum Crc16Mode : ushort { Standard = 0xA001, CcittKermit = 0x8408 }
Crc16 CRC = new Crc16(Crc16Mode.CcittKermit);
public class Crc16
{
readonly ushort[] table = new ushort[256];
public ushort ComputeChecksum(params byte[] bytes)
{
ushort crc = 0;
for (int i = 0; i < bytes.Length - 2; ++i)
{
byte index = (byte)(crc ^ bytes[i]);
crc = (ushort)((crc >> 8) ^ table[index]);
}
return crc;
}
public bool ChecksumValid(ref byte[] bytes)
{
ushort checksum = (ushort)((bytes[bytes.Length - 2] << 8) | bytes[bytes.Length - 1]);
ushort checksum_received = CRC16(bytes);
if (checksum == checksum_received)
{
return true;
}
else
{
return false;
}
}
public ushort CRC16(byte[] bytes)
{
ushort crc = 0; //(ushort.maxvalue, 65535)
for (int j = 0; j < bytes.Length; j++)
{
crc = (ushort)(crc ^ bytes[j]);
for (int i = 0; i < 8; i++)
{
if ((crc & 0x0001) == 1)
crc = (ushort)((crc >> 1) ^ 0x8408);
else
crc >>= 1;
}
}
return (ushort)~(uint)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;
}
}
}
These C# codes are for CRC(CyclicRedundancyCheck),run correctly.
public static void ByteCRC(ref int CRC, char Ch)
{
int genPoly = 0x18005;
CRC ^= (Ch << 8);
for (int i = 0; i < 8; i++)
if ((CRC & 0x8000) != 0)
CRC = (CRC << 1) ^ genPoly;
else
CRC <<= 1;
CRC &= 0xffff;
}
public static int BlockCRC(String Block)
{
int BlockLen = Block.Length;
int CRC = 0;
for (int i = 0; i < BlockLen; i++)
ByteCRC(ref CRC, Block[i]);
return CRC;
}
//Invoking the function
String data="test"; //testing string
Console.WriteLine(BlockCRC(data).ToString("X4"));
I want to convert it to java codes.First to solve the “ref”(in C#) question,I use a global variable and make some other grammar changes.Here are the Java codes.
public static int CRC;
public static void ByteCRC(int CRC, char Ch)
{
int genPoly = 0x18005;
CRC ^= (Ch << 8);
for (int i = 0; i < 8; i++)
if ((CRC & 0x8000) != 0)
CRC = (CRC << 1) ^ genPoly;
else
CRC <<= 1;
CRC &= 0xffff;
}
public static int BlockCRC(String Block)
{
int BlockLen = Block.length();
CRC = 0;
for (int i = 0; i < BlockLen; i++)
ByteCRC(CRC, Block.charAt(i));
return CRC;
}
//Invoking the function
String data="test"; //testing string
System.out.println(BlockCRC(data));
I know the answer won't be hexadecimal, but it's even not the right decimal number,the result is 0.What's wrong? Another question, does java have some function the same as "ToString('X4')" in C#?
does Java have some function the same as "ToString('X4')" in C#?
Java has Format class, descendant of this class NumberFormat, DecimalFormat, DateFormat etc.
In server side (C#.NET,Windows 2003) I have a web service with a method and in client side (Visual C++ v6, WinINet, POST) I want to call that method and pass binary data as a parameter to it.
when I send Binary data an error rise and when I send ASCII data it called successful.
How can I send binary data as parameter of a method?
To send binary data to a web method you can base64 encode it and then decode it in the web service. If your variable is a byte array called data then you would do the following.
In C++ you need to create a base64 header and cpp file. The following example is from http://www.adp-gmbh.ch/cpp/common/base64.html
base64.h
#include <string>
std::string base64_encode(unsigned char const* , unsigned int len);
std::string base64_decode(std::string const& s);
base64.cpp
#include "base64.h"
#include <iostream>
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;
}
After you have your base64 implementation you can create the string to pass.
std::string encoded = base64_encode(data, sizeof(data));
You have to be mindful however of the fact that your data will expand by encoding it to Base64 so your uploads will take longer as the data will be larger. It will be approximately 37% larger (see the MIME section of http://en.wikipedia.org/wiki/Base64)
To decode the data on the other end you would simply do the following.
byte[] data = System.Convert.FromBase64String(yourParameterName);
I have decompiled an vb.net application with reflector
All string are encrypted with this method:
Public Shared Function smethod_0(ByVal string_0 As String) As String
Dim length As Integer = string_0.Length
Dim chArray As Char() = New Char(length - 1) {}
Dim i As Integer
For i = 0 To chArray.Length - 1
Dim ch As Char = string_0.Chars(i)
Dim num3 As Byte = CByte((ch Xor (length - i)))
Dim num4 As Byte = CByte(((ch >> 8) Xor i))
chArray(i) = DirectCast(((num4 << 8) Or num3), Char)
Next i
Return String.Intern(New String(chArray))
End Function
This method receives an input string like this:
"j" & ChrW(354) & ChrW(623) & ChrW(868)
and returns a readable string.
How can I convert this code in vb.net or c#?
The Vb.net compiler complains that this code is not correcte because xor is not defined for a char/int combination.
C# version (only for educational reasons - keeping similar code as possible):
public static string encrypt(string s)
{
int length = s.Length, i = 0;
char[] chArray = new char[length];
byte b1, b2;
char ch;
for (i = 0; i <= chArray.Length - 1; i++)
{
ch = s[i];
b1 = Convert.ToByte((ch ^ (length - i)));
b2 = Convert.ToByte(((ch >> 8) ^ i));
chArray[i] = (char)((b2 << 8) | b1);
}
return string.Intern(new string(chArray));
}
I have resolved in this way:
public static string encrypt(string string_0)
{
int length = string_0.Length;
char[] chArray = new char[length];
for (int i = 0; i < chArray.Length; i++)
{
char ch = string_0[i];
byte num3 = (byte)(ch ^ (length - i));
byte num4 = (byte)((ch >> 8) ^ i);
chArray[i] = (char)((num4 << 8) | num3);
}
File.AppendAllText("decript.txt", Environment.NewLine + string_0 + " = " + string.Intern(new string(chArray)));
return string.Intern(new string(chArray));
}
Thanks for help