对称密码算法DES的讲解:

1. 《信息安全原理与实践》 Matk Stamp  第三章  DES 

2. http://www.docin.com/p-23162685.html

 

      网上这两篇文章算还是讲得不错的。不过我刚开始看的时候,感觉书上和网上的资料都讲的太含糊,很多转换的知识点都是不清不楚,自己看得是不明不白,后来请教一位同学才把这个问题搞明白(当然他也是想了很久才想明白的)。

      整个DES算法太繁琐了,我只是挑选其中子密钥的生成这个知识点来写

 

了解相关专业名词:

1. 移位和循环移位:

移位就是将一段数码按照规定的位数整体性地左移或右移。循环右移就是当右移时,把数码的最后的位移到数码的最前头,循环左移正相反。例如,对十进制数码12345678循环右移1位(十进制位)的结果为81234567,而循环左移1位的结果则为23456781。

这里的循环移位,指的是前后28位密码的位置循环左移,比如

     49 42  35  28  21  14   7                                       42  35  28 21  14  7   0

     0   50  43  36  29  22  15        循环左移一位            50  43  36 29  22 15  8

     8    1   51  44  37  30  23         ————————>   1    51  44 37  30 23 16

     16  9    2   52  45  38  31                                      9    2    52  45  38 31 49

2. 置换:
就是将数码中的某一位的值根据置换表的规定,用另一位代替。它不像移位操作那样整齐有序,看上去杂乱无章。这正是加密所需,被经常应用。

 

DES密钥扩展算法:

for each round i = 1,2,3....n
         LK = cyclically left shift LK by ri bits
        RK = cyclically left shift RK by ri bits
        The left half of subkey Ki consists of bits of LP of LK
        The right half of subkey Ki consits of bits of RP of RK
     next i

 

具体的操作:

      特别注意:这里讲的数字都是指密钥的具体位置,而不是密钥的内容

     1. 我们将DES的56位密钥从左到右从0开始编号。首先扩展DES密钥的前28位,并进行置换,结果称为LK,DES密钥的LK是原始密钥的下列各位:

     49 42  35  28  21  14   7                                       

     0   50  43  36  29  22  15            

     8    1   51  44  37  30  23        

     16  9    2   52  45  38  31 

  通俗讲,就是说第一位前面的28位密钥中,第一位放的元素就是原先56中的第49位,第二位就是原先的42位

 

     2. 类似的,DES密钥的剩余28位称为RK,由原始密钥的下列各位构成

     55 48  41 34  27 20 13

     6   54  47 40  33 26 19

     12  5   53 46  39 32 25

     18 11  4   24  17  10 3

 

    3. 在进行密钥扩张算法之前,还需要定义LP置换:

    13  16  10  23  0  4  2   27  14  5    20  9

    22  18  11  3   25 7  15  6   26  19  12  1

这也是我刚开始百思不得其解的地方,其实也很简单,就是将经过移位之后的左边的28位密钥重现编号,再按下标放好

缺少8,17,21,24

 

    4.RP置换

     12  23  2   8   18  26  1   11   22  16  4  19

     15  20  10  27 5   24  17  13  21  7    0  3

缺少了6,9,14,25

 

 

具体实现的代码:

#include<stdio.h>
int secretKey[56];//密钥
int subSecretKey[17][48];//16轮的子密钥1-16
int leftSecretKey[28]; 
int rightSecretKey[28];
int subLeftSecretKey[24];
int subRightSecretKey[24];
int sumOfk[56];
int LK[28] = {
	49,42,35,28,21,14,7,
	0,50,43,36,29,22,15,
	8,1,51,44,37,30,23,
	16,9,2,52,45,38,31
};
int RK[28] = {
	55,48,41,34,27,20,13,
	6,54,47,40,33,26,19,
	12,5,53,46,39,32,25,
	18,11,4,24,17,10,3
};
int LP[24] = {	//缺少8,17,21,24
	13,16,10,23,0,4,2,27,14,5,20,9,
	22,18,11,3,25,7,15,6,26,19,12,1
};
int RP[24] = {	//缺少6,9,14,25
	12,23,2,8,18,26,1,11,22,16,4,19,
	15,20,10,27,5,24,17,13,21,7,0,3
};
void leftshiftby1(); //循环左移一位
void leftshiftby2(); //循环左移两位
void leftLK();		 //映射,形成leftSecretKey[28]
void rightRK();		 //映射,形成rightSecretKey[28]
void leftLP();		 //置换,形成subLeftSecretKey[24]
void rightRP();		 //置换,形成subRightSecretKey[24];
void printSubSecretKey(); //将16轮的子密钥全部打印出来
void computeSumOfk();     //计算机每个密钥位的使用次数
void printSumOfk();		  //将每个密钥位的使用次数打印出来
int main(){
	int i;
	//密钥的初始化
	for(i=0;i<56;i++){
		secretKey[i] = i;
	}
	//16轮的子密钥生成
	for(i=1;i<=16;i++){
		if(i==1 || i==2 ||i==9 ||i==16){//循环左移一位
			leftshiftby1();
		}
		else{//循环左移两位
			leftshiftby2();
		}
		//映射,形成leftSecretKey[28],rightSecretKey[28]
		leftLK();
		rightRK();
		//置换,形成subLeftSecretKey[24],subRightSecretKey[24];
		leftLP();
		rightRP();
		//生成第i轮的子密钥
		for(int s=0;s<48;s++){
			if(s<24){
				subSecretKey[i][s] = subLeftSecretKey[s];
			}
			else{
				subSecretKey[i][s] = subRightSecretKey[s-24];
			}
		}	
	}
	//输出16轮的子密钥
	printSubSecretKey();
	computeSumOfk();
	printSumOfk();
	
	return 0;
}

void leftshiftby1(){
	int tempLeft = LK[0];
	int tempRight = RK[0];
	for(int i=0;i<27;i++){
		LK[i] = LK[i+1];
		RK[i] = RK[i+1];
	}
	LK[27] = tempLeft;
	RK[27] = tempRight;
}
void leftshiftby2(){
	int tempLeft1 = LK[0],tempLeft2 = LK[1];
	int tempRight1 = RK[0],tempRight2 = RK[1];
	for(int i=0;i<26;i++){
		LK[i] = LK[i+2];
		RK[i] = RK[i+2];
	}
	LK[26] = tempLeft1;
	LK[27] = tempLeft2;
	RK[26] = tempRight1;
	RK[27] = tempRight2;
}
void leftLK(){
	for(int i=0;i<28;i++){
		leftSecretKey[i] = secretKey[LK[i]];
	}
}
void rightRK(){
	for(int i=0;i<28;i++){
		rightSecretKey[i] = secretKey[RK[i]];
	}
}
void leftLP(){
	for(int i=0;i<24;i++){
		subLeftSecretKey[i] = leftSecretKey[LP[i]];
	}
}
void rightRP(){
	for(int i=0;i<24;i++){
		subRightSecretKey[i] = rightSecretKey[RP[i]];
	}
}
void printSubSecretKey(){
	int i,j;
	for(i=1;i<=16;i++){
		for(j=0;j<48;j++){
			printf("%3d",subSecretKey[i][j]);
			if(23==j)
				printf("/n");
		}
		printf("/n/n");
	}
}
void computeSumOfk(){
	int i,j;
	//对SumOfk清零
	for(i=0;i<56;i++){
		sumOfk[i] = 0;
	}
	for(i=1;i<=16;i++){
		for(j=0;j<48;j++){
			sumOfk[subSecretKey[i][j]]++;
		}	
	}
}
void printSumOfk(){
	int i;
	for(i=0;i<56;i++){
		printf("%3d: %3d/n",i,sumOfk[i]);
	}
}