密码程序之DES

通过编程实现des加密,更加深入的了解其原理,掌握des算法。

(1)      建立初始的明密文置换表单和各个加密模块的数组。

(2)      输入密钥

(3)      把输入的字符的ascii码转换成二进制

(4)      密钥经过PC1_Table和 PC2_Table变为48位

(5)      输入明文

(6)      把输入的字符的ascii码转换成二进制

(7)      明文经过IP_Table初始置换

(8)      明文右32位经过E-box变为48位

(9)      与48位的密钥异或

(10)  48位经过S-box变为32位

(11)  与左侧32位明文异或

(12)  原明文右32位变为左32位

(13)  进行16轮

(14)  最后一次经过IPR_Table置换

(15)  输出密文

#include<stdio.h>
#include<string.h>
#define N 8

//明文初始换位表 IP
const static int IP_Table[64] = {
     58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
     62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
     57, 49, 41, 33, 25, 17,  9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
    61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
};
//明文第16次换位表 
const static int IPR_Table[64] = {
     40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
     38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
    36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
     34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41,  9, 49, 17, 57, 25
};
//E-boxes
static const int E_Table[48] = {
     32,  1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,
      8,  9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
     16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
     24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32,  1
};
//32-bit permutation function P used on the output of the S-boxes 
const static int P_Table[32] = {
     16, 7, 20, 21, 29, 12, 28, 17, 1,  15, 23, 26, 5,  18, 31, 10,
     2,  8, 24, 14, 32, 27, 3,  9,  19, 13, 30, 6,  22, 11, 4,  25
};
//密钥PC-1块 
const static int PC1_Table[56] = {
     57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
     10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
     63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
     14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
};
//密钥PC-2块
const static int PC2_Table[48] = {
     14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
     23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
     41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
     44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
};
//密钥每阶段左移位数列表数组 
const static int LOOP_Table[16] = {
     1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};
//S-boxes 
const static int S_Box[8][4][16] = {
     // S1 
     14, 4,     13, 1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
      0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
      4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
    15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
     // S2 
    15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
      3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
      0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
    13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
     // S3 
    10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
     13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
     13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
     1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
     // S4 
     7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
     13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
     10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
     3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
     // S5 
     2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
     14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
      4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
    11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
     // S6 
    12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
     10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
      9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
     4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
     // S7 
     4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
     13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
    1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
     6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
     // S8 
    13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
      1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
      7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
     2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
};
//P-boxes
static const int PBox[32] =
  {
  16, 7, 20, 21, 29, 12, 28, 17,
1, 15, 23, 26, 5, 18, 31, 10, 
2, 8, 24, 14, 32, 27, 3, 9,
19, 13, 30, 6, 22, 11, 4, 25 
  };
//此函数的作用是把密钥转换成ascii码,并加上奇偶校验位
int input_key(char key[8],int key1[7],int key64[64])
{
	int i,j;
	for(i=0;i<8;i++)
	{
		for(j=0;j<7;j++)
		{
			key1[j]=key[i]%2;
			key[i]=key[i]/2;
//			printf("%d",key1[j]);
		}
		
		for(j=0;j<7;j++)
		{
			
			key64[i*8+j]=key1[6-j];
//			printf("%d",key2[i*8+j]);
		
		}
//加奇偶校验为	
		int sum=0;
		for(j=0;j<7;j++)
		{
			
			sum+=key1[j];
		}
		if(sum%2==0)
		{
			key64[(i+1)*8-1]=1;
		}
		else
			key64[(i+1)*8-1]=0;

	}
	return 0;
}
//56位密钥经PC2_Table变为48位
int key_loop(int a,int key56[56],int key48[48])
{
	int temp,i,j;
	for(j=0;j<a;j++)
	{
		temp=key56[0];
		for(i=0;i<28;i++)
		{
			key56[i]=key56[i+1];
		}
		key56[i]=temp;
	}
	for(j=0;j<a;j++)
	{
		temp=key56[28];
		for(i=28;i<56;i++)
		{
			key56[i]=key56[i+1];
		}
		key56[i]=temp;
	}
	for(i=0;i<48;i++)
	{
		key48[i]=key56[PC2_Table[i]-1];
//		printf("%d",key48[i]);
	}
//	printf("\n");
	return 0;
}
//此函数的作用是把明文转换成ascii码,并加上奇偶校验位
int input_plantext(char plantext[200],int plantext2[200],int plantext3[7])
{
	int i,j;

	for(i=0;i<8;i++)
	{
		for(j=0;j<7;j++)
		{
			plantext3[j]=plantext[i]%2;
			plantext[i]=plantext[i]/2;
//			printf("%d",key1[j]);
		}
		
		for(j=0;j<7;j++)
		{
			
			plantext2[i*8+j]=plantext3[6-j];
//			printf("%d",key2[i*8+j]);
		
		}
	
		int sum=0;
		for(j=0;j<7;j++)
		{
			
			sum+=plantext3[j];
		}
		if(sum%2==0)
		{
			plantext2[(i+1)*8-1]=1;
		}
		else
			plantext2[(i+1)*8-1]=0;

	}
	return 0;
}
//e_box中把明文右32位转换为48位
int e_box(int plantext64[64],int plantext48[48])
{
	for(int i=0;i<48;i++)
	{
		plantext48[i]=plantext64[E_Table[i]+31];
	}
	return 0;
}
int main()
{
	int i,j,a,k,y;
	int key1[7],key64[64],key56[56],key48[48];
	int plantext2[200],plantext3[7],plantext64[64],plantext48[48],plantext_right32[32];
	int plantext_right[32],cipher[64];
	char key[8],plantext[200];
	printf("请输入密钥\n");
	scanf("%s",key);
	input_key(key,key1,key64);
	printf("64位密钥为\n");
	for(i=0;i<64;i++)						//显示64位密钥
	{
		printf("%d",key64[i]);
	}
	printf("\n");
/*
	for(i=0;i<56;i++)						//显示56位密钥
	{
		key56[i]=key64[PC1_Table[i]-1];
		printf("%d",key56[i]);
	}
	printf("\n");
	*/

	printf("请输入明文\n");
	scanf("%s",plantext);

	input_plantext(plantext,plantext2,plantext3);
	
	printf("初始明文为\n");
	for(i=0;i<64;i++)						//输出初始明文
	{
		printf("%d",plantext2[i]);
	}
	printf("\n");
//明文的初始置换
	for(i=0;i<64;i++)
	{
		plantext64[i]=plantext2[IP_Table[i]-1];
//		printf("%d",plantext64[i]);
	}

	for(i=0;i<16;i++)						//每一轮
	{
		a=LOOP_Table[i];
		key_loop(a,key56,key48);
		e_box(plantext64,plantext48);
		for(j=0;j<48;j++)					//每一轮的48位密钥加密E盒扩展后的明文				
		{
			plantext48[j]=(key48[j]+plantext48[j])%2;
		}
		for(k=0;k<8;k++)					//每一轮S盒
		{
			y=S_Box[k][plantext48[k*6]*2+plantext48[k*6+5]][plantext48[k*6+1]*8+plantext48[k*6+2]*4+plantext48[k*6+3]*2+plantext48[k*6+4]];
			plantext_right32[k*4]=y/8;		//把S盒中10进制转换成2进制
			y=y%8;
			plantext_right32[k*4+1]=y/4;
			y=y%4;
			plantext_right32[k*4+2]=y/2;
			y=y%2;
			plantext_right32[k*4+3]=y;
		}
		for(j=0;j<32;j++)					//每一轮p盒
		{
			plantext_right[j]=plantext_right32[P_Table[j]-1];
		}
		for(j=0;j<32;j++)					//最开始的左32位和右边异或
		{
			plantext_right[j]=(plantext64[j]+plantext_right[j])%2;
		}
		for(j=0;j<32;j++)					//最开始的右32位给左边
		{
			plantext64[j]=plantext64[j+32];
			plantext64[j+32]=plantext_right[j];
		}

	}
	for(i=0;i<64;i++)
	{
		cipher[i]=plantext64[IPR_Table[i]-1];
	}
	printf("密文为\n");
	for(i=0;i<64;i++)
	{
		printf("%d",cipher[i]);
	}

	printf("\n");
	return 0;

}

我承认这个代码比较糟糕,而且结果没经过测试,所以仅供娱乐。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值