基于CRC64 LSB的反向实现

Posted

技术标签:

【中文标题】基于CRC64 LSB的反向实现【英文标题】:Crc64 LSB based reverse implementation 【发布时间】:2020-01-15 13:41:38 【问题描述】:

我尝试实现基于 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;
        

    

【问题讨论】:

不清楚你在问什么。下面,您写了“我想将校验和反转为原始的 8 字节值”。请澄清你的意思。如果您打算恢复原始数据的实际 8 个字节,这通常是不可能的。如果您知道原始数据总是正好是 8 个字节,那么首先计算 64 位校验和就没有意义了。只需存储实际字节。如果输入可能是可变长度的,那么就不可能从校验和中恢复输入。 CRC计算只能单向成功。 【参考方案1】:

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

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

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

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

请注意,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"));
        
    

【讨论】:

感谢您的回答。我是新的。我尝试通过对基于 LSB 设计的反转的修改来重新实现 MSB 设计反转代码。我不知道需要纠正什么。 我正在试验代码。我的目标是成功创建一个反向表和函数。我有一个 MSB 转发表和函数,它计算校验和。我想将校验和反转为原始的 8 字节值。我不知道应该实施或纠正什么。缺少 MSB 计算校验和功能,所以我正在更新文章。 上面显示的文章中的源代码不正确。我已经用正确的源代码更新了它。您提供的代码没有帮助。我将您的代码插入到这两个函数中都没有成功。 我正在使用 Compute_MSB 前向 CRC 函数和 MSB 表,并试图通过基于 LSB 的反向方法和表来反转它。它在我上面显示的源代码中。 我使用作为 MSB 的 generateCrcTableConstants() 方法来创建转发表。然后我使用 LSB 的 generateRevCrcTableConstants() 方法来创建反向表。

以上是关于基于CRC64 LSB的反向实现的主要内容,如果未能解决你的问题,请参考以下文章

基于Qt的CRC16校验实现(查表法)

基于Verilog的CRC-CCITT校验

实践出真知——基于squid实现反向代理实践

图像隐写基于matlab LSB数字水印嵌入提取含Matlab源码 2412期

语音隐写基于 LSB语音隐藏matlab源码

多种隐写基于matlab GUI LSB+DCT文本图片嵌入+提取含Matlab源码 1851期