DES加密算法-C语言版

实验环境: DEV C++ 5.11

实验原理:

DES 算法使用的是 Feistel 框架,Feistel 框架的密码结构是用于分组密码 中的一种对称结构,Feistel 框架使用的是对同一处理流程进行多次循环的方式。 DES 算法就是采用的 16 轮循环的加密,当然循环次数越多加密的效果越好,同 时时间成本也会上去,设计者需要考虑这两方面的因素进行密码设计。因为这个 框架是用于处理分组密码的,我们就要了解一下什么是分组密码,分组密码是一 种加解密方案,将输入的明文分组当作一个整体处理,并输出一个等长的密文分组,典型的分组大小为 64 位和 128 位,随着对加密算法安全性能的要求不断提高,分组大小也就会越来越大。DES 算法所采用的分组大小为 64 位分组,所以输入的数据和密钥都是按照 64 位进行处理的,输出的密文也是 64 位一组

实验要求:

使用熟悉的高级语言,编写一段程序,实现凯撒密码

DES 加密算法过程

DES 属于分组密码,明文和密文为 64 位分组。密钥的长度为 64 位,但是密钥的每个第八位设置为奇偶校验位,因此密钥的实际长度为 56 位。

  1. 初始置换:

使用初始置换表对明文进行置换,这里的置换只是将数据的位置进行变化,得到一个新的数据。初始逆置换表和初始置换表是相互可逆的,就是将原来的数据的位置进行还原。

置换处理:在密码学中置换是指在保持数据不变的情况下,打乱数据的位置顺序的操作称作置换,在 DES 算法中每个置换处理都会按照 相应的置换表进行操作,置换处理在 DES 算法中得到了充分的运用,通过置换处理可以打乱输入数据的顺序,使输入的数据变得面目全非,当然也会造成雪崩效应,因为只要有一个数据位发生变化,就会影响到很多地方。

2.子秘钥生成:

        DES 算法子密钥输入长度为 64 位,但是只有 48 位是有效的,所以需要对密钥 K 进行变换得到每一轮所需的子密钥。16 轮迭代就需要 16 个 48位的子密钥来进行加密。

DES 算法子密钥生产比较简单,64 位密钥经过置换选择,只选择其中的 56位,对 56 位密钥同样分为左右 28 位,按照子密钥计算的逻辑表,每一轮进行循环左移运算分别得到新的 56 位,这 56 位再经过第二次置换选择就得到了本轮的子密钥。

然后对S盒的输出结果进行P盒置换

根据流程图可得,最后是左半部分和右半部分合并进行逆初始置换

DES源代码:

#include <stdio.h>
#include<string.h>
#include<math.h>
int get(int r);
void yihuo(int *a, int *b,int num);
void left_move(int s[56], int n);
void exchange(int *a, int *b, int *biao,int n);
void shizhuaner(int *a,int x,int i,int n);
void erzhuanshiliu(int *a,char *b, int n);
void s_box(int a[32],int b[48]);
void round(int r, int a[56], int b[48], int r_a[32], int r_b[48], int l[32], char mi_r[8], char mi_l[8]);

int get(int r)         //得到第r轮的移位数 
{
	int i;  	
	if (r==1||r==2||r==9||r==16) i=1;
	else i=2;
	return i;  
}

void yihuo(int *a, int *b,int num)      //异或 
{
	int i; 
	for (i=0;i<num;i++)
	{
		if (a[i]==b[i])  a[i]=0;
		else
			a[i]=1;
	}
}

void left_move(int s[56], int n)         //左移 
{
	int i;
	for (i=0;i<=28-n;i++) 
	{
		s[i]=s[(i+n)%28];
	}
	for(i=28;i<=56-n;i++)
	{
		s[i]=s[(i+n)%56];
	}
}

void exchange(int *a, int *b, int *biao,int n)    //置换 
{
	int i,loc;  
	for (i=0;i<n;i++)
	{
		loc=biao[i];	
		b[i]=a[loc-1];
	}
	return;
}


void shizhuaner(int *a,int x,int i,int n)
// a是存放二进制的数组,x是需要进行转换的十进制数,i是第i个十进制数,n是数组大小
{
	int j;n=n/8;j=n-1;
	do{
		a[i*n+j]=x%2;
		x=x/2;
		j--;
	} while(x!=0);
	while (j>=0)
	{
		a[i*n+j]=0;
		j--;
	}
	return;
}



void erzhuanshiliu(int *a,char *b, int n)
// a是二进制数组,b是存放十六进制的数组,n是二进制数组的大小
{
	int i,j; 
	n=n/4;
	for(i=0;i<n;i++)
	{
		j=8*a[4*i]+4*a[4*i+1]+2*a[4*i+2]+a[4*i+3];
		if(j>=10){
			if(j==10) b[i]='a';
			else if(j==11) b[i]='b';
			else if(j==12) b[i]='c';
			else if(j==13) b[i]='d';
			else if(j==14) b[i]='e';
			else if(j==15) b[i]='f';
		}
		else
		{
			j=j+48;
			b[i]=(char)j;
		}
	}
	return;
}


void s_box(int a[32],int b[48])         //S盒
{
	int i,r,c,s;  
	int s1[4][16] = { { 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[4][16] = { { 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[4][16] = { { 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[4][16] = { { 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, 3 },{ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } },
	    s5[4][16] = { { 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[4][16] = { { 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][16] = { { 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[4][16] = { { 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 } };
	for (i = 0; i < 8; i++)
	{
		r = 2*b[6*i]+b[6*i+5];  
		c = 8*b[6*i+1]+4*b[6*i+2]+2*b[6*i+3]+b[6*i+4]; 
		switch (i) 
		{
		case 0:s = s1[r][c]; break;
		case 1:s = s2[r][c]; break;
		case 2:s = s3[r][c]; break;
		case 3:s = s4[r][c]; break;
		case 4:s = s5[r][c]; break;
		case 5:s = s6[r][c]; break;
		case 6:s = s7[r][c]; break;
		case 7:s = s8[r][c]; break;
		}
		shizhuaner(a,s,i,32); 
	}
}


void round(int r, int a[56], int b[48], int r_a[32], int r_b[48], int l[32], char mi_r[8], char mi_l[8])
{
	int i, n, r1[32],r2[32]; //r1,r2为中间数组 
	int	zhihuan2[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 };  //置换2 
	int	e[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 };    //E盒 
	int	P[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 };     //P盒 
	printf("这是第%d轮密文:\n", r);
	n = get(r); left_move(a, n); exchange(a, b, zhihuan2, 48);  
	exchange(r_a,r_b,e,48); yihuo(r_b, b,48); s_box(r1,r_b); exchange(r1,r2,P,32);   
	for (i=0;i<32;i++)    r1[i] = r2[i];
	yihuo(r1,l,32);	
	for (i=0;i<32;i++)    l[i] = r_a[i];  //准备下次循环的L
    for (i=0;i<32;i++)    r_a[i] = r1[i];  //准备下次循环的R
	erzhuanshiliu(r_a,mi_r,32);	
	erzhuanshiliu(l,mi_l, 32);
	for (i=0;i<8;i++)     printf("%c ",mi_r[i]);  //第r轮R部分的密文
	for (i=0;i<8;i++)     printf("%c ",mi_l[i]);  //第r轮L部分的密文
	printf("\n\n");
	return;
}

int main()
{
	char a[8];        //初始明文 
	char b[8];        //初始密钥
	int m_a[64],m_b[64];          //IP置换前后的明文 
	int s_a[64],s_b[56];          //置换1前后的二进制密钥 
	int r;            //轮数
	int s_c[48];      //置换2后的数组
	int r_a[32],r_b[48];          //E扩展前后的m_b的右半部分明文
	int l[32];        //m_b的左半部分
	char mi_r[8],mi_l[8];         //存储密文的十六进制
	int mi1[16],mi2[16];          //IP_1置换前后的密文 
	char miwen[16];   //最终密文 
	int i;
	
	int zhihuan1[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 };      //置换1 
	int IP[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 };    //IP置换 
	int IP_1[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 };    //IP_1置换
	printf("*---------------DES加密--------------\n\n");
	printf("请输入需要加密的明文:\n");
	for (i=0;i<8;i++)  
	{
		scanf("%c",&a[i]);
		shizhuaner(m_a,(int)a[i],i,64);  
	}
	printf("\n请输入加密的密钥:\n");
	for (i=0;i<8;i++) 
	{
		scanf("%c", &b[i]);
		shizhuaner(s_a,(int)b[i],i,64);
	}
	exchange(m_a,m_b,IP, 64); 

	for(i=0;i<32;i++)
		l[i]=m_b[i];  
	for(i=32;i<64;i++)
		r_a[i-32]=m_b[i]; 

	
	exchange(s_a,s_b,zhihuan1,56);  
	for (r=1;r<=16;r++) 
		round(r,s_b,s_c,r_a,r_b,l,mi_r,mi_l);

	for(i=0;i<64;i++)  //将密文R的部分与密文L的部分合一起
	{
		mi1[i]=r_a[i];
		if(i>=32) mi1[i]=l[i-32];
	}

	exchange(mi1,mi2,IP_1,64);  
	erzhuanshiliu(mi2,miwen, 64);  //二进制转换成十六进制,得到最终密文
	printf("\n\n");
	printf("##########这是最终密文:##########\n");
	for (i=0;i<16;i++)
	 printf("%c ", miwen[i]);
	printf("\n\n\n\n");
	return 0;
}

运行结果:

  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是3DES加密算法的C语言源码实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define ENCRYPT 1 #define DECRYPT 0 typedef unsigned char BYTE; typedef unsigned long DWORD; /* 定义DES算法中使用的数据类型 */ typedef struct { BYTE key[8]; BYTE encrypt; BYTE iv[8]; } des_context; /* 定义3DES算法中使用的数据类型 */ typedef struct { des_context des1; des_context des2; des_context des3; } des3_context; /* 定义DES算法中使用的常量 */ static const BYTE odd_parity_table[256] = { 1, 2, 4, 7, 8, 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, 254, 1, 2, 4, 7, 8, 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, 254 }; static const BYTE bytebit[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; static const DWORD bigbyte[24] = { 0x800000L, 0x400000L, 0x200000L, 0x100000L, 0x080000L, 0x040000L, 0x020000L, 0x010000L, 0x008000L, 0x004000L, 0x002000L, 0x001000L, 0x000800L, 0x000400L, 0x000200L, 0x000100L, 0x000080L, 0x000040L, 0x000020L, 0x000010L, 0x000008L, 0x000004L, 0x000002L, 0x000001L }; static const BYTE pc1[56] = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; static const BYTE totrot[16] = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 }; static const BYTE pc2[48] = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; static const DWORD SP1[64] = { 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; static const DWORD SP2[64] = { 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; static const DWORD SP3[64] = { 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, 0x00000008L
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值