c简单实现Feistel加解密

关于上次数组越界的问题已经解决,内部定义的数组,函数结束时内存可能被回收。同一个函数定义的变量和数组之类,地址在方法栈中应该是连续的,如果字符串数组不定义结束符,%s输出会越界读取。
采取的方法是
1.尽量使用外部的数组或者指针,或者在函数内部手动分配空间(手动分配空间,系统并不会自动回收空间)!
因为外部指针(数组)在函数内进过修改,不用return,函数结束时影响也在,是直接修改对应地址的值。
2.数组尽量多分配几个空间,以便定义结束符号
3.可以采用数据断点来判断是否越界
以下是正确的feistel算法简单实现,还需留意的是明文加密最后,密文的组成是RiLi,而非LiRi,所以与前面加密分开理解。而解密时最后一步也是如此。


#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>


int main()
{
  int i=0,j=0;

  char key[50];        //key最大位数50位,但是还是只取16位

  char plaintext[100];   //明文

  char pGroup[10][10]; //明文组
 
  char keyGroup[16][17]; //密码组

  void encryption(char pGroup[10][10],char keyGroup[16][17]); 

  void decryption(char pGroup[10][10],char keyGroup[16][17]);
 
  void generateKey(char  key[50],char keyGroup[16][17]);

  void makeGroup(char plaintext[100],char pGroup[10][10]);
 
  memset(plaintext,0,sizeof(plaintext)/sizeof(char));

  memset(key,0,sizeof(key)/sizeof(char));

  memset(pGroup,0,sizeof(pGroup) / sizeof(char) );

  memset(keyGroup,0,sizeof(keyGroup) / sizeof(char) );

  printf("请输入明文\n");

  scanf("%s",plaintext);

  printf("请输入密码\n");

  scanf(" %s",key);

  generateKey(key,keyGroup);

  makeGroup(plaintext, pGroup);

   encryption(pGroup,keyGroup);

   printf("密文--》\n");

   for(i=0;i<10;i++)
   {
	   printf("%s",pGroup[i]);
   }

   printf("\n");

   decryption(pGroup,keyGroup);

	printf("明文--》\n");

   for(i=0;i<10;i++)
   {
	   printf("%s",pGroup[i]);
   }

   printf("\n");

  return 0;
}

void makeGroup(char plaintext[100],char pGroup[10][10])
{

    int i=0,j=0;

	int g_num=0;   //分组数
    
	int b_num=0;

	int n_num=0;

	int pLength=0;

	pLength = strlen(plaintext); 
    
	b_num = pLength % 8;

	n_num = 8 - b_num;

	g_num = pLength / 8 ;

	if(b_num != 0)
	{
		g_num += 1;

		for(i=0;i<n_num;i++)
		{
			plaintext[strlen(plaintext)] = n_num + '0';
		}
	}

	plaintext[strlen(plaintext)]='\0';
   
    for(i=0;i<g_num;i++)
	{
	   for(j=0;j<8;j++)
	   {
		  pGroup[i][j] = plaintext[i*8+j];

	   }

	  pGroup[i][8]='\0';

	}

}


void generateKey(char  key[50],char keyGroup[16][17])
{
	int i=0,j=0;  

	char keyadd[50]; //单个密码

	memset(keyadd,0,50);

	char last;

    while(strlen(key)<16)  //16*8=128bit
	{

		strcpy(keyadd,key);

		strcat (key,keyadd);
	}

   for(i=0;i<16;i++)    //获取不同的key,循环移位一bit
   {

	 last = key[15];   //最后一个
	  
	 for(j=15;j>0;j--)     //不用strlen获取长度了,因为是固定的
	 {
		   key[j]=key[j-1];
	 }
    
	 key[0] = last;     

	 memcpy(keyGroup[i],key,16*sizeof(char)); //一维数组叠加成为二维数组 
      
     keyGroup[i][16]='\0';     //密文矩阵
	  
   }
 
}

void f(char p[10],char key[17],int flag,int time)    //密钥固定16位
{

    int i=0,j=0;

	char LE[4];  //不用给多余空间,密码的大小是固定的

	char RE[4];

	char LE1[4];

	char RE1[4];
	
	strncpy(LE,p,4);

	strncpy(RE,p+4,4);

	strncpy(LE1,RE,4); 
    
	for(i=0;i<4;i++)
	{
		RE1[i] = RE[i]^key[4*i]^LE[i];  //按位异或
	}
   
	if(flag==0 && time == 15 || flag == 1 && time == 0)     //特殊处理(倒序)加密第16次和解密第16次
	{
		for(i=0;i<8;i++)
		{
		   if(i<4)
		   {
			 p[i]=RE1[i];
		   }
		   else
		   {
			 p[i]=LE1[i-4];
		   }
			
		}

	}
    else //正常处理
	{
		for(i=0;i<8;i++)
		{
		   if(i<4)
		   {
			 p[i]=LE1[i];
		   }
		   else
		   {

			 p[i]=RE1[i-4];

		   }
			
		}
	}
}


void loop(char pGroup[10],int flag,char keyGroup[16][17])         //flag=0为加密,flag=1为解密
{
	printf("loop开始\n");

	int i = 0;
	
   if(flag==0)
   {
 		 for(i=0;i<16;i++)
		 {
			f(pGroup,keyGroup[i],flag,i);  //循环16次,加密,密钥正向、
		 }

		 pGroup[8]='\0';
   }

  else	
  {

		for(i=15;i>-1;i--)
		{
			f(pGroup,keyGroup[i],flag,i);  //循环16次,解密,密钥倒过来
		}

		pGroup[8]='\0';

  }

}


void encryption(char pGroup[10][10],char keyGroup[16][17])    //加密
{   

     int i=0;

     int numP;

	numP = sizeof(pGroup) / sizeof(char);  //求组数,行数

	for(i=0;i<numP;i++)
	{ 	
		loop(pGroup[i],0,keyGroup); //分组加密	
	} 

}

void decryption(char pGroup[10][10],char keyGroup[16][17])  //解密
{
	
   int i=0;

   int numP = 0;

   printf("\n");


   numP = sizeof(pGroup) / sizeof(char);  //一维数组长度,以及知道列数是8
   
   for(i=0;i<numP;i++)
   {
	  loop(pGroup[i],1,keyGroup);
   }
}



  • 5
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值