📄 des.h
字号:
{//二进制显示字节
for(int i=0;i<8;i++)
printf("%d",GetBitFromSingleByte(uData,8-i));
printf("\n");
}
UCHAR GetBit(UCHAR uData[],UCHAR uBytes,UCHAR uBit)
{//uData为输入的字节型数组,uBytes为输入数组的字节数,uBit表示第几位(*从1开始),返回该位的值
UCHAR m,n;
if(uBit<1 || uBit>8*uBytes)
return ERROR_BITOUTOFRANGE; //有效性检查
if(uBit%8==0)
{//处理该位为每字节的最高位,其模8为0的特殊情况
m=uBit/8-1;//该位所在的字节
n=7;//该位所在字节中的位数
}
else
{
m=uBit/8;//该位所在的字节
n=uBit%8-1;//该位所在字节中的位数
}
if(uData[m] & (1<<n))//判断该位的值
return 1;
else
return 0;
}
UCHAR GetBitFromSingleByte(UCHAR uData,UCHAR uBit)
{//单字节版
UCHAR n;
if(uBit<1 || uBit>8)
return ERROR_BITOUTOFRANGE;
n=uBit-1;
if(uData & (1<<n))
return 1;
else
return 0;
}
UCHAR SetBit(UCHAR uData[],UCHAR uBytes,UCHAR uBit,UCHAR uValue)
{//设置一个数组某位的值,索引从1开始,uData为目标数组,uByte为数组字节数,uValue为设置的值
UCHAR m,n;
if(uBit<1 || uBit>8*uBytes)
return ERROR_BITOUTOFRANGE;
if(uBit%8==0)
{//处理该位为每字节的最高位,其模8为0的特殊情况
m=uBit/8-1;
n=7;
}
else
{
m=uBit/8;
n=uBit%8-1;
}
if(uValue)
uData[m]|=(1<<n);//如果uValut非0,置位该位
else
uData[m]&=(~(1<<n));//否则该位清0
return ERROR_SUCCESSED;
}
UCHAR SetBitOfSingleByte(UCHAR *uData,UCHAR uBit,UCHAR uValue)
{//置位单字节版
UCHAR n;
if(uBit<1 || uBit>8)
return ERROR_BITOUTOFRANGE;
n=uBit-1;
if(uValue)
*uData|=(1<<n);
else
*uData &=(~(1<<n));
return ERROR_SUCCESSED;
}
UCHAR PermuteSelectKey1(UCHAR uIn[],UCHAR uOut[])
{//密钥初始置换选择1,输入64位,有效输出56位,但输出还是8个字节,每4个字节高4位置0
UCHAR uIndex=1;
memset(uOut,0,8);//uOut数组的规模应该与PC_1表规模一致,清0
for(UCHAR i=0;i<8;i++)
for(UCHAR j=0;j<7;j++)
{//遍历PC_1表,填充uOut数组
if((i==3||i==7) && j==6)
{//如果到达第28或者第56个比特,先根据PC_1表中的值读输入数组中的指定位,用其值
//赋予当前位,然后再填充4个0
SetBit(uOut,8,uIndex++,GetBit(uIn,8,PC_1[i][j]));
for(UCHAR k=0;k<4;k++)
SetBit(uOut,8,uIndex++,0);
}
else//否则只赋值
SetBit(uOut,8,uIndex++,GetBit(uIn,8,PC_1[i][j]));
}
return ERROR_SUCCESSED;
}
UCHAR CycleLeftShift(UCHAR uData[],UCHAR uIndex)
{//根据轮数uIndex和uLeftShiftCount表对uData数组进行循环左移
UCHAR uCount=uLeftShiftCount[uIndex-1];//读移位位数
UCHAR uLeftOverflowBits;//左溢出的位
uData[3]=uData[3]<<uCount;//最高字节左移uCount位
uLeftOverflowBits=(uData[3] & 0xF0)>>4;//取高4位保存待最后放至数尾
uData[3]&=0x0F;//清最高字节高4位
for(UCHAR i=2;i>=0 && i<=2;i--) //加上&&符号防止计数器溢出
{
UCHAR uBuff=uData[i];//保存字节
uData[i]=(UCHAR)(uData[i]<<uCount);//左移uCount位
for(UCHAR j=7;j>7-uCount;j--)
{//用本字节左移溢出的高位填充高一字节左移后的低位
SetBitOfSingleByte(&uData[i+1],j+uCount-7,GetBitFromSingleByte(uBuff,j+1));
}
}
uData[0]|=uLeftOverflowBits;//最低位填充最高字节左移溢出的位
return ERROR_SUCCESSED;
}
void SubkeyfCycleLeftShift(UCHAR uLeft[],UCHAR uRight[],UCHAR uIndex)
{//子密钥左右两部分循环左移
CycleLeftShift(uLeft,uIndex);
CycleLeftShift(uRight,uIndex);
}
UCHAR PermuteSelectKey2(UCHAR uIn[],UCHAR uOut[])
{//uIn为输入的64bit数,其中有56bit位有效数据,每4个字节的高4位空0,先调整使之紧凑,
//变成56bit数7个字节,然后再查表进行置换选择2,输出uOut为48bit
UCHAR LowHalfByte;
LowHalfByte=uIn[4] & 0x0F;//获得输入第5个字节的低4位
uIn[3]|=(LowHalfByte<<4);//移入第4个字节高4位,低4字节除了第4个字节需要处理外其他不用处理
for(UCHAR i=5;i<8;i++)
{//处理高4字节
LowHalfByte=uIn[i] & 0x0F; //获得本字节低4bit
uIn[i-1]=uIn[i-1]>>4; //低一字节右移动4位
uIn[i-1]|=(LowHalfByte<<4);//填充低一字节的高4位
}
uIn[7]^=uIn[7];//最高字节清0
//====以上是去掉多余0的代码,以下是置换选择2的代码====//
UCHAR uIndex=1;
memset(uOut,0,6);
for(UCHAR j=0;j<6;j++)
for(UCHAR k=0;k<8;k++)
SetBit(uOut,6,uIndex++,GetBit(uIn,7,PC_2[j][k]));
return ERROR_SUCCESSED;
}
UCHAR ExtendPermute(UCHAR uIn[],UCHAR uOut[])
{//32bit明文的扩展置换,使用E盒
UCHAR uIndex=1;
memset(uOut,0,6);
for(UCHAR i=0;i<8;i++)
for(UCHAR j=0;j<6;j++)
SetBit(uOut,6,uIndex++,GetBit(uIn,4,E_BOX[i][j]));
return ERROR_SUCCESSED;
}
void XorBytes(UCHAR uPlainText[],UCHAR uSubKey[],UCHAR uBits)
{//数组异或,输出仍存在第一个参数中
for(UCHAR i=0;i<uBits;i++)
uPlainText[i]^=uSubKey[i];
}
UCHAR SubstituteSelect(UCHAR uIn[],UCHAR uOut[])
{//用S盒进行代换选择,输入48位,输出32位
UCHAR uBit=0,uTemp1=0,uTemp2=0,uRow=0,uColumn=0,uValue=0;
memset(uOut,0,4);//输出清0
for(UCHAR i=1;i<=48;i++)
{//遍历输入的48位
uBit=GetBit(uIn,6,i);//获得输入第i位值
if((i-1)%6==0)
{//如果是每6bit的开始
uTemp1=uBit;//保存当前位值做行值的低位
}
else if(i%6==0)
{//如果是每6bit的结束
uRow=(uBit<<1)|uTemp1;//当前位为行值的高位,左移一位或低位得行值
uValue=S_BOX[i/6-1][uRow][uColumn];//根据i可得S盒表的序号i/6-1,并根据行列值求S盒值
if(i%12==0)
{//如果是每12bit的结束
uOut[i/12-1]|=(uValue<<4);//uValue为输出每字节的高4位,故左移4位或低4位
}
else//如果不是12bit的结束
uOut[(i/6-1)/2]|=uValue;//uValue为输出每字节的低4位,保存的当前字节中
uTemp1=0;//中间变量清0
uTemp2=0;
uValue=0;
uRow=0;
uColumn=0;
}
else
{//如果是列值中的位
uColumn=(uBit<<(i%6-2))|uTemp2;//当前位左移i%6-2位后与上一位列值按位或得当前位列值
uTemp2=uColumn;//uTemp2存放遍历到上一位时的列值
}
}
return ERROR_SUCCESSED;
}
UCHAR Permute(UCHAR uData[])
{//对S盒输出进行置换,用P盒
UCHAR uIndex=1;
UCHAR uBuff[4];
memcpy(uBuff,uData,4);
for(UCHAR i=0;i<4;i++)
for(UCHAR j=0;j<8;j++)
SetBit(uData,4,uIndex++,GetBit(uBuff,4,P_BOX[i][j]));
return ERROR_SUCCESSED;
}
UCHAR GenerateSubkey(UCHAR uIn[],UCHAR uOut[][6])
{//生成子密钥表
UCHAR uSubkeyOut[6]={0},uTemp[8]={0};
memset(uOut,0,16*6);
//密钥置换选择1,输入uIn为64位,输出uTemp的56位有效,总64位,分左右32位,每32位高4位空0。
PermuteSelectKey1(uIn,uTemp);
for(UCHAR i=0;i<16;i++)
{
SubkeyfCycleLeftShift(uTemp,uTemp+4,i+1);//循环左移
PermuteSelectKey2(uTemp,uSubkeyOut);//置换紧缩56位(其实为64位)变48位子密钥
memcpy(uOut[i],uSubkeyOut,6);//保存至输出数组中
}
return ERROR_SUCCESSED;
}
UCHAR F_Function(UCHAR uRight[],UCHAR uSubkey[])
{//轮函数,输入为明文右32位和48位子密钥,输出为32位,仍存在uRight中
UCHAR uExtended[6];
memset(uExtended,0,6);
ExtendPermute(uRight,uExtended);//32位明文扩展置换,生成48位数
XorBytes(uExtended,uSubkey,6);//与48位子密钥异或
SubstituteSelect(uExtended,uRight);//用S盒代换选择48位数,输出32位数
Permute(uRight);//置换32位数,输出在uRight中
return ERROR_SUCCESSED;
}
UCHAR PlainTextPermute(UCHAR uData[],UCHAR uTable[][8])
{//明文初始置换和逆初始置换
UCHAR uIndex=1;
UCHAR uBuff[8];
memcpy(uBuff,uData,8);
for(UCHAR i=0;i<8;i++)
for(UCHAR j=0;j<8;j++)
SetBit(uData,8,uIndex++,GetBit(uBuff,8,uTable[i][j]));
return ERROR_SUCCESSED;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -