0

我试图实现基于 LSB 的反转功能。代码在 C# 中。校验和的反转存在错误。该函数只能在仅使用 8 字节原始数据计算时反转 Crc64 校验和。当我尝试通过 FixChecksum 方法反转校验和时,中间 6 个字节被反转,但第一个和最后一个字节被反转损坏。请告知有什么问题,需要实施或修复什么。我将不胜感激任何解决方案。

[更新]

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;
        }

    }
}
4

1 回答 1

0

该问题的解决方案涉及反向循环 CRC。

如果使用表,对于 CRC 生成(前向循环),左移 CRC 使用 CRC 的左字节来索引表,右移 CRC 使用 CRC 的右字节来索引表。对于 CRC 反向循环,左移 CRC 使用 CRC 的右字节来索引表,而右移 CRC 使用 CRC 的左字节来索引表。

下面的示例代码用于左移和右移 CRC。两个附加表用于反向循环 CRC。CRC 函数采用数据长度参数,以防缓冲区在生成 CRC 后有额外的空间来存储它。

为了简化反向循环功能,生成一个 CRC 并与所需的 CRC 进行异或运算,该 CRC 可与一个虚构的零缓冲区一起使用,以生成产生异或 CRC 所需的 8 字节数据。然后将 8 个字节的数据异或到原始缓冲区。异或抵消了 CRC 初始值和异或输出值,因此反向循环函数不必考虑这些值。

请注意,CRC 字节可以放在消息中的任何位置(尽管它们通常位于消息的末尾)。例如一个 24 字节的消息,由 8 个字节的数据、8 个字节的 CRC、8 个字节的数据组成,可以使用 crc64fw(0ul, bfr, 24, 8) 创建;或 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"));
        }
    }
}
于 2019-09-13T21:28:23.680 回答