循环队列在工作中的使用

204 阅读3分钟

1、前言

项目经理来提需求了,直接丢了张图,以前是看图写作,现在是看图写代码……

1666871793664.png

2、需求分析

分析图意:

输入:4字节种子(Seed)

算法处理

1、将4字节循环右移动3位

2、将每个字节的每两位进行互换

3、将4字节的数据合并为两个16位的数据,然后再进行循环左移3位

4、此时生成了新的4字节数据,将每个字节同下表数据进行异或XOR计算分别得到HB'、SB'、TB'、LB'

5、最后将其取反处理得到4字节的Key值

输出:4字节密钥(Key)

3、实现思路

由于工作中上位机是由C#开发的,而C#不存在C位域的操作,因此我的思路是首先将字节转换成二进制的字符串,后续只需要对二进制字符串进行操作即可。对于字符串进行操作,C#可是很方便的;为了实现图中的向左向右移动的操作,立马想到了数据结构中的循环队列。

4、代码实现

4.1 循环队列类实现

    class CircleQueue<T>
    {
        private int _index = -1;
        private int _count = 0;

        private List<T> _list = null;

        public CircleQueue(int k)
        {
            //构造器,设置队列长度为 k
            _count = k;
            _list = new List<T>();
        }

        public bool EnQueue(T value)
        {
            //向循环队列插入一个元素。如果成功插入则返回真
            if (_count == 0 || _index == _count - 1) return false;
            _index++;
            _list.Add(value);
            return true;
        }

        public bool DeQueue()
        {
            //从循环队列中删除一个元素。如果成功删除则返回真
            if (_count == 0 || _index == -1) return false;
            _index--;
            _list.RemoveAt(0);
            return true;
        }

        public T Front()
        {
            //从队首获取元素。如果队列为空,返回 -1
            //if (_count == 0 || _index == -1) return -1;
            return _list[0];
        }

        public T Rear()
        {
            //获取队尾元素。如果队列为空,返回 -1
            //if (_count == 0 || _index == -1) return;
            return _list[_index];
        }

        public bool IsEmpty()
        {
            //检查循环队列是否为空
            return _index == -1;
        }

        public bool IsFull()
        {
            //检查循环队列是否已满
            return _index == _count - 1;
        }
    }

4.2 循环移动操作和互换操作功能函数代码

        private enum MoveType
        {
            Left,
            Right
        }
        
        /// <summary>
        /// 实现循环右移功能
        /// </summary>
        /// <param name="circleQueue:循环队列"></param>
        /// <param name="strbin:二进制字符串"></param>
        /// <param name="capacity:循环队列的容量"></param>
        /// <param name="count:移动的位数"></param>
        /// 
        private string CircleMove(CircleQueue<char> circleQueue,string strbin,int capacity, MoveType type)
        {
            char[] cs = new char[capacity];

            if(type == MoveType.Right)
            {
                for (int j = capacity - 1; j >= 0; j--)
                {
                    circleQueue.EnQueue(strbin[j]);
                }
            }
            else
            {
                for (int j = 0; j < capacity - 1; j++)
                {
                    circleQueue.EnQueue(strbin[j]);
                }

            }
    
            //移动三位
            for (int k = 0; k < 3; k++)
            {
                //出循环队列
                char tmpchar = circleQueue.Front();
                circleQueue.DeQueue();
                //入循环队列
                circleQueue.EnQueue(tmpchar);
            }

            if (type == MoveType.Right)
            {
                for (int m = capacity - 1; m >= 0; m--)
                {
                    char tmpchar = circleQueue.Front();
                    circleQueue.DeQueue();
                    cs[m] = tmpchar;
                }
            }
            else
            {
                for (int m = 0; m < capacity - 1; m++)
                {
                    char tmpchar = circleQueue.Front();
                    circleQueue.DeQueue();
                    cs[m] = tmpchar;
                }

            }

            string str = new string(cs);

            return str;
        }
        
         /// <summary>
        /// 将8位二进制字符串每两位互换
        /// </summary>
        /// <param name="strbin"></param>
        /// <returns></returns>
        private string ExChange(string strbin)
        {
            char[] cs = new char[8];

            for (int j = 0; j < 8; j++)
            {
                cs[j] = strbin[j];
            }

            //3、两两交换
            for (int j = 0; j <= 6; j += 2)
            {
                char temp = cs[j];

                cs[j] = cs[j + 1];
                cs[j + 1] = temp;
            }

            string str = new string(cs);

            return str;
        }

4.3 需求实现

        /// 编程安全解密
        /// </summary>
        /// <param name="seed"></param>
        /// <returns></returns>
        public byte[] GetProgramSeedKey(byte[] seed)
        {         
            List<string> seedbinlst = new List<string>();
            List<string> tmpkeylstR = new List<string>();
            List<string> tmpkeylstChange = new List<string>();
            List<string> tmpkeylstMerge = new List<string>();
            List<string> tmpkeylstL = new List<string>();
            //1、将byte转换为2进制字符串
            for (int i = 0; i < seed.Length; i++)
            {
                string strTemp = Convert.ToString(seed[i], 2);
                strTemp = strTemp.Insert(0, new string('0', 8 - strTemp.Length));
                seedbinlst.Add(strTemp);
            }

            //2、循环右移三位 8位
            CircleQueue<char> circleQueue = new CircleQueue<char>(8);

            foreach (var item in seedbinlst)
            {
                string tmpstr = CircleMove(circleQueue, item, 8, MoveType.Right);
                tmpkeylstR.Add(tmpstr);
            }

            //3、两两交换
            foreach (var item in tmpkeylstR)
            {
                string tmpstr = ExChange(item);
                tmpkeylstChange.Add(tmpstr);
            }

            //4、循环左移三位 16位
            tmpkeylstMerge.Add(tmpkeylstChange[0] + tmpkeylstChange[1]);
            tmpkeylstMerge.Add(tmpkeylstChange[2] + tmpkeylstChange[3]);

            CircleQueue<char> circleQueue_16 = new CircleQueue<char>(16);

            foreach (var item in tmpkeylstMerge)
            {
                string tmpstr = CircleMove(circleQueue_16, item, 16, MoveType.Left);
                tmpkeylstL.Add(tmpstr);
            }

            string strkey = tmpkeylstL[0] + tmpkeylstL[1];

            //二进制字符串转化为byte[]
            byte[] keyout = new byte[strkey.Length / 8];
            for (int i = 0; i < keyout.Length; i++)
            {
                keyout[i] = Convert.ToByte(strkey.Substring(i * 8, 8), 2);
            }

            //5、取XOR值
            byte[] CofeArray = new byte[4]{ 0x27, 0x42, 0x3B, 0x6A };
            for (int i = 0; i < 4; i++)
            {
                keyout[i] ^= CofeArray[i];
            }

            //6、Reverse every bit
            for (int i = 0; i < 4; i++)
            {
                keyout[i] = (byte)~keyout[i];
            }
            return keyout;
        }

5 执行效果展示

企业微信截图_16669183207160.png