DES密码算法

// 此算法,输入是键盘上任意字符,利用字符的ASCII值进行计算,输出是字符型。


#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
int IP[9][9]={0},Yuan[9][9]={0},Miwen[9][9]={0},Key[8][8]={0};  // IP --->初始置换的值  Yuan --->明文  Miwen --->密文 Key --->密钥
int Right[8][4]={0},Left[8][4]={0};	   // Right ---右部分  Left ---左部分
int R_0[8][4]={0};                     // 存放Right上一次的值
int E[8][6]={0};                       // 存放E扩展后的值    存放与子密钥异或的值
int S_R[8][4]={0};                     // 存放S盒置换后的值
int P_R[8][4]={0};                     // 存放P置换后的值
int C[28],D[28],kz2[8][6],kz[8][7];    // kz2 为子密钥
char ZI[8];                            // 存放密文的字符型
int P_Box[8][4]={ 
				  16,  7, 20, 21,      // P置换表
				  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 };
int pc1[8][7]={  
              57, 49, 41, 33, 25, 17,  9,  // PC-1置换表
              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 };
int pc2[8][6]={
                14, 17, 11, 24,  1,  5,    // PC-2置换表
                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 };
int S_Box[8][4][16]=					   // S盒置换表
			//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}; 

// 明文的ASCII值 转换为二进制
void B_change(int i,int temp)
{
	int j,k;
	for(j=8;j>=1&&temp;j--)
	{
		k=temp%2;
		Yuan[i][j]=k;
		temp=temp/2;
	}
}
// 密钥的ASCII值 转换为二进制
void B_B(int i,int temp)
{
	int j,k;
	for(j=7;j>=0&&temp;j--)
	{
		k=temp%2;
		Key[i][j]=k;
		temp=temp/2;
	}
}
// 初始置换IP
void Zhuanhuan( )
{
	int i,j,k;
	for(i=1;i<=8;i++)
	{	
		if(i<5) k=i*2;
	    else k=2*(i-5)+1;

		for(j=1;j<=8;j++)
			IP[i][j]=Yuan[8-j+1][k];
	}
}
//将初始置换IP分左右两部分
void Left_Right( )
{
	int i,j,k=1,n=1;
	for(i=0;i<8;i++)
	{
		if(k>=9) { n++; k=1;  }
		for(j=0;j<4;j++)
		{
			Left[i][j]=IP[n][k];
			Right[i][j]=IP[n+4][k];
			k++;
		}
	}
}
//E 扩展
void E_Table( )
{
	int i,j;
	for(i=0;i<8;i++)
	{
		for(j=0;j<6;j++)
		{
			if(j==0)
			{
				if(i==0)	E[i][j]=Right[7][3];
				else		E[i][0]=Right[i-1][3];
			}
			else     		E[i][j]=Right[i][j-1];

			if(j==5)
			{
				if(i==7)	E[7][5]=Right[0][0];
				else		E[i][5]=Right[i+1][0];
			}
		}
	}
	/*   // 验证是否正确
	cout<<"E扩展:";
	for(i=0;i<8;i++)
		for(j=0;j<6;j++)
			cout<<E[i][j]<<" ";
		cout<<endl;
    */
}

// 与子密钥异或
void Key_XOR( )
{
	int i,j;
	for(i=0;i<8;i++)
		for(j=0;j<6;j++)
			E[i][j]=E[i][j]^kz2[i][j];

	/* // 验证是否正确
    cout<<"E扩展与子密钥异或:";
	for(i=0;i<8;i++)
		for(j=0;j<6;j++)
		   cout<<E[i][j]<<" ";
	cout<<endl;
	*/
}
//  S盒中的值 转换为二进制
void B_Dexchange(int i,int temp)
{
	int j=0,k=0;
	for(j=3;j>=0;j--)
	{  
		k=temp%2;
		S_R[i][j]=k;
		temp=temp/2;
	}
}
// S 盒置换
void S_Table()
{
	int i,right,left,temp,j;
	for(i=0;i<8;i++)
	{	
		// left 为s盒中第i个s表的行,right 为s盒中第i个s表的列
		// temp 为s表中置换后的数,十进制
		left=E[i][0]*2+E[i][5];
		right=E[i][1]*8+E[i][2]*4+E[i][3]*2+E[i][4];
		temp=S_Box[i][left][right];

		B_Dexchange(i,temp);  // 将S盒中的十进制数化为二进制数
	}
	/*  // 验证是否正确
	cout<<"S盒压缩:";
	for(i=0;i<8;i++)
		for(j=0;j<4;j++)
			cout<<S_R[i][j]<<" ";
	cout<<endl;
	*/
}

// P 置换
void P_Table()
{
	int i,j,x,a,b;
	for(i=0;i<8;i++)
	{
		for(j=0;j<4;j++)
		{
			x=P_Box[i][j];   // P_BOX ---> P置换表
			a=x/4;
			b=x%4;
			if(a==0)		// P_R ---> 存P置换的值   S_R ---> S盒置换的值
			{				
				if(b==0)	P_R[i][j]=S_R[0][0]; 
				else		P_R[i][j]=S_R[0][b-1];
			}
			else
			{
				if(b==0)	P_R[i][j]=S_R[a-1][3];
				else		P_R[i][j]=S_R[a][b-1];
			}
		}
	}
	/*   // 验证是否正确
	cout<<"P置换:";
	for(i=0;i<8;i++)
		for(j=0;j<4;j++)
			cout<<P_R[i][j]<<" ";
		cout<<endl;
	*/
}

// R1=L0与P扩展后的值异或
void Left_XOR( )
{
	int i,j;
	for(i=0;i<8;i++)
		for(j=0;j<4;j++)
		{
			R_0[i][j]=Right[i][j];           // 保存上一次Right的值
			Right[i][j]=Left[i][j]^P_R[i][j];
		}
	/*  // 验证是否正确
		cout<<"Right:";
		for(i=0;i<8;i++)
			for(j=0;j<4;j++)
				cout<<Right[i][j]<<" ";
			cout<<endl;
	*/
}
// L1=R0
void L_R()
{
	int i,j;
	for(i=0;i<8;i++)
		for(j=0;j<4;j++)
			Left[i][j]=R_0[i][j];

    /* // 验证是否正确
		cout<<"Left:";
		for(i=0;i<8;i++)
			for(j=0;j<4;j++)
				cout<<Left[i][j]<<" ";
			cout<<endl;
	*/
}
// 当最后一次循环时,左右两部分交换
void R_L_R()
{
	int i,j,t;
	for(i=0;i<8;i++)
		for(j=0;j<4;j++)
		{
			t=Right[i][j];
			Right[i][j]=Left[i][j];
			Left[i][j]=t;
		}
/*  // 输出结果,验证是否正确
	cout<<"第16次Left:";
	for(i=0;i<8;i++)
		for(j=0;j<4;j++)
			cout<<Left[i][j]<<" ";
	cout<<"\n第16次Right:";
	for(i=0;i<8;i++)
		for(j=0;j<4;j++)
			cout<<Right[i][j]<<" ";
	cout<<endl;
	*/
}
// 逆置换IP_1
void Nizhihuan()
{
	int i,j,k;
	for(i=0;i<8;i++)		 //  Miwen ---> 密文   
	{
		if(i<4)// 第2 4 6 8 列
		{
			k=i*2+2;
			for(j=0;j<4;j++)
			{
				Miwen[8-j][k]=Left[k-2][j];
				Miwen[4-j][k]=Left[k-1][j];
			}
		}
		else  // 第1 3 5 7 列
		{
			k=2*(i-4)+1;
			for(j=0;j<4;j++)
			{
				Miwen[8-j][k]=Right[k-1][j];
				Miwen[4-j][k]=Right[k][j];
			}
		}
	}
}

//第一次PC_1置换
void Key_PC1( )
{
   int i,j,x,y,tc=0,td=0;
   for(i=0;i<8;i++)
   {
       for(j=0;j<7;j++)
       {
           x=pc1[i][j]/8;
           y=pc1[i][j]%8;
            if(!y&&x)
            {
                 if(i<4)  C[tc++]=Key[x-1][y];
                 else     D[td++]=Key[x-1][y];
            }
            else
                {
                    if(y&&x)    y--;
                    if(!x&&y)   y--;
                    if(i<4)     C[tc++]=Key[x][y];
                    else        D[td++]=Key[x][y];
                }
       }
   }
}
// C D 左移
void zy(int x)
{
    int i,j,tc,td;
    tc=C[0]; td=D[0];
    for(i=0;i<27;i++)
    {
        C[i]=C[i+1];
        D[i]=D[i+1];
    }
    C[27]=tc;D[27]=td;
    if(!(x==1||x==2||x==9||x==16))
    {
        tc=C[0]; td=D[0];
        for(i=0;i<27;i++)
        {
            C[i]=C[i+1];
            D[i]=D[i+1];
        }
        C[27]=tc;D[27]=td;
    }
    for(i=0,tc=0;i<4;i++)
        for(j=0;j<7;j++)
			kz[i][j]=C[tc++];
    for(i=4,td=0;i<8;i++)
        for(j=0;j<7;j++)
            kz[i][j]=D[td++];
}
//PC_2置换
void PC_2()
{
   int i,j,x,y;
   for(i=0;i<8;i++)
   {
       for(j=0;j<6;j++)
       {
           x=pc2[i][j]/7;
           y=pc2[i][j]%7;
           if(!y&&x)      kz2[i][j]=kz[x-1][6];
           else
		   {
			   if(y&&x)    y--;
               if(!x&&y)   y--;
               kz2[i][j]=kz[x][y];
           }
       }
   }
   /*  // 输出子密钥,验证是否正确
   cout<<"子密钥:";
	   for(i=0;i<8;i++)
		   for(j=0;j<6;j++)
			   cout<<kz2[i][j]<<" ";
	cout<<endl;
	*/
}
// 求得子密钥函数
void Key_ki(int x)
{
 	 zy(x);   //左移
     memset(kz2,0,sizeof(kz2));
     PC_2();  //第二次置换
}
// 输出密文( 字符型 )			
void ZiFu()
{
	int i,temp;
	for(i=1;i<=8;i++)
	{ 
		temp=Miwen[i][1]*128+Miwen[i][2]*64+Miwen[i][3]*32+Miwen[i][4]*16+Miwen[i][5]*8+Miwen[i][6]*4+Miwen[i][7]*2+Miwen[i][8];
	    ZI[i]=temp;
	    cout<<ZI[i];
	}
}
int main()
{
	char a[9],b[9];
	int  i, temp,j;
	
	// 输入明文,密钥   这里是字符型
	cout<<"输入明文(最多8个字符):\n";
	gets(a);  
	cout<<"输入密钥(最多8个字符):\n";
	gets(b);

    // 得到明文字符的ASCII值,将ASCII值 转换为二进制
	for(i=0;a[i]!='\0';i++)
	{		
		temp=a[i];
		B_change(i+1,temp);
	}
	// 密钥转换为二进制值
	for(i=0;b[i]!='\0';i++)
	{
		temp=b[i];
		B_B(i,temp);
	}	
/*  // 这里是输入64位二进制
	cout<<"输入原文:\n";
	for(i=1;i<=8;i++)
		for(j=1;j<=8;j++)
			scanf("%d",&Yuan[i][j]);
	cout<<"输入密钥:\n";
	for(i=0;i<8;i++)
		for(j=0;j<8;j++)
			scanf("%d",&Key[i][j]);
*/	
/*	// 验证是否正确
	printf("\n输出明文(ASCII值,二进制):\n");
	for(i=1;i<=8;i++)
	{	for(j=1;j<=8;j++)
			printf("%d ",Yuan[i][j]);
	printf("\n");
	}
	printf("\n输出密钥(ASCII值,二进制):\n");
	for(i=0;i<8;i++)
	{	for(j=0;j<8;j++)
			printf("%d ",Key[i][j]);
	printf("\n");
	}
	printf("\n输出初始置换IP的值:\n");
	for(i=1;i<=8;i++)
	{	for(j=1;j<=8;j++)
			printf("%d ",IP[i][j]);
	printf("\n");
	}
*/
	Key_PC1( );			// 调用密钥函数,pc1置换
	Zhuanhuan( );		// 调用初始置换IP函数 
	Left_Right( );		// 将IP分左右两部分

    // 进行16轮迭代
	for(i=1;i<=16;i++)
	{	
	//	cout<<"\n----------------------第"<<i<<"次--------------------------\n";

		E_Table();  	// E 扩展函数
		Key_ki(i);      // 求得子密钥
		Key_XOR();      // 与子密钥异或
		S_Table();      // S 盒置换
		P_Table();		// P 置换
		
		// L1=R0   R1=L0与P扩展后的值异或
		Left_XOR(); 	
		L_R();      // L1=R0
		if(i==16)	R_L_R();    // 交换左右两部分的值
	}

	Nizhihuan( );  // 调用初始逆置换函数

/*	printf("\n输出密文(ASCII值,二进制):\n");
	for(i=1;i<=8;i++)
	{	for(j=1;j<=8;j++)
			printf("%d ",Miwen[i][j]);
	printf("\n");
	}
*/
	printf("\n输出密文(字符型):\n");
	ZiFu();

	cout<<endl;
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值