📄 yingying.cpp
字号:
unsigned long work[2]; /*存放轮函数迭代中当前轮的左右分组各32bit*/
long tmp;
permute(block,iperm,(char *)work); /* 初始置换 */
/*先将左右各32bit交换*/
tmp=work[0];
work[0]=work[1];
work[1]=tmp;
/* 作16轮迭代,注意密钥使用的顺序与加密时正好相反 */
/* 16轮迭代的子密钥还是存在二维数组kn[16][8]中,使用哪一轮的密钥由i来控制*/
printf("分别解密的16轮每轮所得结果为:\n");
for(i=15;i>=0;i--)
round(i,work); /*轮数从0-15*/
permute((char *)work,fperm,block); /* 逆初始置换 */
printf("\n\n");
}
static int permute(char *inblock,char perm[16][16][8],char *outblock){
/*此函数的作用是: 1 对输入的64bit明文利用ip[64]进行初始置换*/
/* 2 对经过16轮迭代并左右交换后的64bit利用fp[64]进行逆初始置换*/
register int i,j;
register char *ib,*ob;
register char *p,*q;
/*这是此函数的一个附属功能,把inblock(含义见函数endes/dedes)拷贝给outblock*/
/*函数endes和dedes将会使用outblock*/
if(perm==NULL){
for(i=8;i!=0;i--)
*outblock++=*inblock++;
return 0;
}
/*按照调用位置的不同,以下完成上述功能1或2*/
for(i=8,ob=outblock;i!=0;i--)
*ob++=0;
ib=inblock;
for(j=0;j<16;j+=2,ib++){
ob=outblock;
p=perm[j][(*ib>>4)&017];
q=perm[j+1][*ib&017];
for(i=8;i!=0;i--)
*ob++ |=*p++ | *q++;
}
return 0;
}
static void round(int num,unsigned long *block){
/*此函数完成一轮DES迭代,轮数从0-15轮*/
/*抓住Feistel结构的规律:L(i)=R(i-1),R(i)=L(i-1)^f(R(i-1),K(i-1))*/
/*由上规律可知:若当前轮轮数i是奇数,则经过当前轮迭代后,输出中的L(i)是一开始明文经初始置换后*/
/*传入轮迭代的左32bit经过一系列变换的结果,R(i)是右32bit经过一系列变换的结果. 若当前轮 */
/*轮数i是偶数,结论正好与上述相反*/
/*由上述规律可得:若当前轮轮数i是奇数,则经过当前轮迭代后,block[0]中实际存放的是L(i),*/
/*(block[1]实际存放的是R(i).若当前轮轮数i是偶数,则经过当前轮迭代后,block[0]中实际存放的是R(i),*/
/*(block[1]实际存放的是L(i),与i是奇数时正好相反.*/
if(num&1) {block[1]^=f(block[0],kn[num]);
printf("%d %02x",num+1,((unsigned long) block[0])&0x00ffffffff);
printf(" %04x\n",((unsigned long) block[1])&0x00ffffffff);}
/*当前轮数i是奇数时,由上述知,只需改变block[1]*/
else {block[0]^=f(block[1],kn[num]);
printf("%d %02x",num+1,((unsigned long) block[1])&0x00ffffffff);
printf(" %04x\n",((unsigned long) block[0])&0x00ffffffff);}
/*当前轮数i是偶数时,由上述知,只需改变block[0]*/
}
static long f(unsigned long r, unsigned char subkey[8]){
/*此函数实现DES轮迭代中的非线性f函数,这是DES加解密过程的核心*/
/*r是每轮迭代中左右各32bit中需要改动的32bit,或为左32bit,或为右32bit.详见函数round*/
/*subkey[8]中,存有每轮所需的48bit子密钥(事先已求好).sunkey[8]中的一个值代表6bit*/
register unsigned long rval,rt;
#ifdef TRACE
unsigned char *cp;
int i;
printf("f(%081x,%02x %02x %02x %02x %02x %02x %02x %02x)= " ,r,
subkey[0],subkey[1],subkey[2],
subkey[3],subkey[4],subkey[5],
subkey[6],subkey[7]);
#endif
/*虽然宏定义中定义了选择扩展运算表ei[48],但在此函数中并没有使用这一运算表,而是利用*/
/*其他方式代替了ei[64]的作用,下文有解释*/
rt=(r>>1) | ((r&1)?0x80000000:0);
/*r为32bit,若设r=a1,a2,a3------a32(从高位到低位),则rt=a32,a1,a2,a3,a4-----a31*/
/*即将r比特表示的最低位(a32)移动到最高位*/
rval=0; /*rval中将存放一轮f函数作用后的结果*/
rval |=sp[0][((rt>>26) ^*subkey++) & 0x3f];
/*rt>>26=0,0,0,0,0,-----a32,a1,a2,a3,a4,a5(高位共26个0)*/
/*"a32,a1,a2,a3,a4,a5"这正是选择扩展运算表ei[48]的第1行的值,因此不用扩展运算表ei[48]*/
/*"&0x3f"即00111111是为了取得异或结果的后6bit(这6bit是1个S盒的输入)*/
/*sp[8][64]的说明详见函数spinit*/
rval |=sp[1][((rt>>22) ^*subkey++) & 0x3f];
/*rt>>22=0,0,0,0-----a32,a1,a2,a3,a4,a5,a6,a7,a8,a9(高位共22个0)*/
/*subkey只有6bit,所以只会和a4,a5,a6,a7,a8,a9做异或."a4,a5,a6,a7,a8,a9"正是*/
/*选择扩展运算表ei[48]的第2行的值*/
/*以下几步同理于此*/
rval |=sp[2][((rt>>18) ^*subkey++) & 0x3f];
rval |=sp[3][((rt>>14) ^*subkey++) & 0x3f];
rval |=sp[4][((rt>>10) ^*subkey++) & 0x3f];
rval |=sp[5][((rt>>6) ^*subkey++) & 0x3f];
rval |=sp[6][((rt>>2) ^*subkey++) & 0x3f];
rt=(r<<1) | ((r&0x80000000) ?1 :0);
/*rt=a2,a3,a4-----a32,a1.(高位到低位) 即将r的最高位a1移动到最低位*/
rval |=sp[7][(rt ^*subkey) &0x3f];
/*subkey只有6bit,所以只会和a28,a29,a30,a31,a32,a1做异或."a28,a29,a30,a31,a32,a1"正是*/
/*选择扩展运算表ei[48]的最后一行的值*/
#ifdef TRACE
printf(" %081x\n",rval);
#endif
return rval;
}
static void perminit(char perm[16][16][8],char p[64]){
/*此函数的功能是初始化perm[16][16][8](即iperm[16][16][8]和fperm[16][16][8])并赋值*/
register int l,j,k;
int i,m;
/*将perm[16][16][8]初始化 */
for(i=0;i<16;i++)
for(j=0;j<16;j++)
for(k=0;k<8;k++)
perm[i][j][k]=0;
/*对perm[16][16][8]赋值 */
for(i=0;i<16;i++)
for(j=0;j<16;j++)
for(k=0;k<64;k++){
l=p[k]-1 ;
if((l>>2)!=i)
continue;
if(!(j&nibblebit[l&3]))
continue;
m=k&07;
perm[i][j][k>>3] |=bytebit[m];
}
}
static void spinit(){
/*此函数先于DES加密过程(函数endes)进行.由于每个S盒输入为6bit,因此最多有64种*/
/*(2的6次方)输入.此函数对每个S盒穷举出所有可能的64种输入,由此得到所对的64种输*/
/*出(由S盒可以看到,每个S盒对应的输出为16*4=64种,与输入一一对应).再将各种输出经*/
/*置换表p32i[32]变换后的结果存放于二维数组sp[8][64]中.(共8个S盒,有8*64种输出,*/
/*因此经置换运算后也有8*64种.将每种情况的32bit存放在sp[8][64]的一个空间)*/
/*注:一个S盒输入为6比特,输出为4比特.8个S盒输入共48比特,输出共32bit,经置换*/
/*表p32i[32]变换后依旧为32bit*/
char pbox[32];
int p,i,s,j,rowcol;
long val;
for(p=0;p<32;p++)
for(i=0;i<32;i++)
if(p32i[i]-1==p){
pbox[p]=i;
break;
}
/*对8个S盒的输出比特依次编号为0-31.pbox[32]将依次存储这32bit经p32i[i]置换*/
/*后的位置.如S-2输出的第2个比特,编号应为5,按照p32i[32]应被置换到第13个*/
/*比特的位置,则pbox[5]中存放12(数组下标从0开始)*/
for(s=0;s<8;s++) /*依次对每个S盒穷举*/
for(i=0;i<64;i++){ /* 对64种输入穷举 */
val=0;
/*设S盒中输入为a6,a5,a4,a3,a2,a1(从高到低位),a6,a1构成的十进制数*/
/*决定行,a5,a4,a3,a2构成的十进制数决定列*/
rowcol=(i&32)|((i&1)?16:0)|((i>>1)&0xf);
/*rowcol等于a6,a1,a5,a4,a3,a2构成的十进制数,经数学证明,rowcol为*/
/*当前输入所对应的S盒中输出的下标*/
/*例如S-1输入为011001,按照定义应输出9."9"对应*/
/*si[0][28].按上述算法rowcol=011100即28,可见si[0][rowcol]就是9*/
for(j=0;j<4;j++) /*对每一个输出比特处理 */
if(si[s][rowcol]&(8>>j))
val |=1L<<(31-pbox[4*s+j]);
sp[s][i]=val;
/*sp[a][b]中只处理了第a+1个S盒中的4比特,其他比特位置为0(val每次进循环初始化为0)*/
#ifdef DEBUG
printf("sp[%d][%2d]=%081x\n",s,i,sp[s][i]);
#endif
}
}
void show(){
/*此函数处理用户输入的明文和初始化密钥,因为DES一次只能处理64bit明文,同时使用64bit密钥*/
/*要对用户输入的明文每64bit即8字节用一次DES*/
int notation=0,i,j,m;
char key[MAX_NUM], plaintext[MAX_NUM], /*tempK[8],*/ tempP[8],ch;
FILE *p,*q;
p=fopen("D:\QQ.txt","r");
/*-----------------------------------------------------------------------------*/
/* printf("请输入明文(以char型输入)\n以“#”结束输入\n");
while(1){
scanf("%c",&plaintext[notation++]);
if(plaintext[notation-1]=='#') { notation--; break;}
} */
/*notation记录下用户输入的明文长度*/
/* printf("明文的16进制转换码\n");
for(i=0;i<notation;i++)
printf("%02x ",((unsigned int) plaintext[i])&0x00ff); printf("\n");
*/
/*-----------------------------------------------------------------------------*/
while(ch!=EOF){/*从文件里读入明文*/
ch=fgetc(p);
plaintext[notation++]=ch;
printf("%c",ch);}
/* printf("请输入密钥(以char型输入,8位密钥)\n");*/
printf("please input key (char)\n");
for(i=0;i<8;i++)
scanf("%c",&key[i]);
/*-----------------------------------------------------------------------------*/
/*printf("密钥的16进制转换码\n");
for(i=0;i<8;i++)
printf("%02x ",((unsigned int) key[i])&0x00ff); printf("\n\n");
getchar(); */
/*-----------------------------------------------------------------------------*/
desinit(); /*DES的一些初始化操作,详见desinit函数体说明*/
setkey(key); /*算出16轮子密钥,详见setkey函数体说明*/
for(i=0;i<(notation-1)/8+1;i++){
for(j=i*8;j<(i+1)*8;j++){ /*DES一次只能处理64bit明文,对应char型就是8位char型*/
/* tempK[j-i*8]=key[j]; 因此本处循环将char型明文每8位存放在tempP[8]中,用于一次加密*/
tempP[j-i*8]=plaintext[j];}
/* setkey(tempK); */
endes(tempP); /*DES加密,详见endes函数体说明*/
for(j=i*8;j<(i+1)*8;j++)
plaintext[j]=tempP[j-i*8];
}
q=fopen("D:\ying.txt","w+");
for(i=0;i<notation;i++)
fputc(plaintext[i],q);
printf("\n密文的16进制转换码:(02x output)\n");
for(i=0;i<notation;i++){
printf("%02x ",((unsigned int) plaintext[i])&0x00ff);}
printf("\n密文的char型输出:(char output)\n");
for(i=0;i<notation;i++)
printf("%c",plaintext[i]); printf("\n\n");
for(i=0;i<(notation-1)/8+1;i++){
for(j=i*8;j<(i+1)*8;j++){
/* tempK[j-i*8]=key[j];因此本处循环将char型明文每8位存放在tempP[8]中,用于一次解密*/
tempP[j-i*8]=plaintext[j];}
/* setkey(tempK); */
dedes(tempP); /*DES解密,详见dedes函数体说明*/
for(j=i*8;j<(i+1)*8;j++)
plaintext[j]=tempP[j-i*8];
}/* */
printf("\n解密恢复后明文的16进制转换码:\n");
for(i=0;i<notation;i++)
printf("%02x ",((unsigned int) plaintext[i])&0x00ff);
printf("\n解密后明文的char型输出:\n");
for(i=0;i<notation;i++)
printf("%c",plaintext[i]); printf("\n");
printf("\n");
desdone(); /*回收使用的空间*/
}
void main(){
show();
getchar();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -