1、前言
项目经理来提需求了,直接丢了张图,以前是看图写作,现在是看图写代码……
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;
}