⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crijndael.cpp

📁 1、更正了原来的1.0版本的所有内存泄漏问题。 2、使用了文件读写的缓冲技术
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	SubBytes();
	ShiftRows();
	AddRoundKey();
}

void CRijndael::Decryption()//解密
{
	int j,k=0;
	round=Nr;
	AddRoundKey();
	round=round-1;
	for(j=Nr-1;j>0;j--)
	{
		InvShiftRows();
		InvSubBytes();
		AddRoundKey();
		round=round-1;
		InvMixColumns();
	}
	InvShiftRows();
	InvSubBytes();
	AddRoundKey();
}

bool CRijndael::EncrypFile()
{
	long i,j,k,len,count,size;
	int remain;
	byte *temp,(*in_stream)[4][4];
	State=NULL;
	Cur_Round=0;
	/////////////获取文件名//////////////
	len=Source.GetLength();//取得文件长度(字节)
	if(len%16==0)//计算总的加密轮数
		Total_Round=len/16;
	else
		Total_Round=len/16+1;
	
	remain=len;//计算不够用于加密的字节数
	while(remain>=16)
	{
		if(remain>=MaxSize)
			size=MaxSize;
		else
			size=remain-remain%16;
		len=size/16;
		in_stream=new byte[len][4][4];//设置读入缓冲区
		count=remain/size;//计算读取文件的次数
		while((in_stream==NULL)&&(size>16))//循环计算可得到的最大缓冲区
		{
			size=size/2;
			if(size%16!=0)
				size=size+(16-size%16);	
			if(size<16)//若可得的最大缓冲区小于16个字节时,为错误情形
			{
				ErrorMessage=ErrorMessage+"\n内存空间不足!";
				Source.Close();
				Target.Close();
				return false;
			}
			len=size/16;
			count=remain/size;//计算读取文件的次数
			in_stream=new byte[len][4][4];//设置读入缓冲区
		}
		for(i=0;i<count;i++)
		{
			try
			{
				Source.Read(in_stream,size);//从明文文件中读入size个字节内容到缓冲区
			}
			catch(...)//读入文件失败
			{
				ErrorMessage=ErrorMessage+"\n读入文件失败!";
				delete []in_stream;
				Source.Close();
				Target.Close();
				return false;
			}
			for(j=0;j<len;j++)
			{
				State=&(in_stream[j][0]);
				Encryption();//调用加密函数
				Cur_Round++;//当前轮数加1
			}
			try
			{
				Target.Write(in_stream,size);//将缓冲区的size个字节内容写入到密文文件中
			}
			catch(...)//写入文件失败
			{
				ErrorMessage=ErrorMessage+"\n写入文件失败!";
				delete []in_stream;
				Source.Close();
				Target.Close();
				return false;
			}
		}			
		remain=remain-size*count;//计算未处理的文件大小
		if(remain<16&&remain>0)
		{
			Target.Seek(-(16-remain),CFile::current);//当前指针后移(相对于当前位置)remain=2
			temp=new byte[remain];
			if(temp==NULL)
			{
				ErrorMessage=ErrorMessage+"\n读入文件失败!";
				delete []in_stream;
				Source.Close();
				Target.Close();
				return false;
			}
			byte *p=NULL;
			p=&(State[0][0]);
			try
			{
				Source.Read(temp,remain);
			}
			catch(...)//读入文件失败
			{
				ErrorMessage=ErrorMessage+"\n读入文件失败!";
				delete []temp;
				delete []in_stream;
				Source.Close();
				Target.Close();
				return false;
			}
			k=0;
			for(j=remain;j<16;j++,k++)
				*(p+k)=*(p+j);//k=16-remain
			for(j=0;j<remain;j++,k++)
				*(p+k)=temp[j];
			Encryption();//调用加密函数
			Cur_Round++;//当前轮数加1
			try
			{
				Target.Write(State,16);
			}
			catch(...)//写入文件失败
			{
				ErrorMessage=ErrorMessage+"\n写入文件失败!";					
				delete []temp;
				delete []in_stream;
				Source.Close();
				Target.Close();
				return false;
			}
			delete []temp;
			remain=0;
		}
		delete []in_stream;
		}
	Source.Close();
	Target.Close();
	for(i=0;i<4;i++)//释放密钥的内存并置空
	{
		delete key[i];
		key[i]=NULL;
		delete w[i];
		w[i]=NULL;
	}
	return true;
}

bool CRijndael::DecrypFile()
{
	long i,j,k=0,len,count,size;
	int remain;
	byte *temp=NULL,*s=NULL,(*in_stream)[4][4];
	State=NULL;
	Cur_Round=0;
	/////////////获取文件名//////////////
	len=Source.GetLength();//取得文件长度(字节)		
	if(len%16==0)//计算总的解密轮数
		Total_Round=len/16;
	else
		Total_Round=len/16+1;
	
	remain=len;
	if(remain%16!=0)
	{
		k=16+remain%16;
		remain=remain-k;
	}
	while(remain>=16)
	{
		if(remain>=MaxSize)
			size=MaxSize;
		else
			size=remain;
		len=size/16;
		in_stream=new byte[len][4][4];//设置读入缓冲区
		count=remain/size;//计算读取文件的次数
		while((in_stream==NULL)&&(size>16))//循环计算可得到的最大缓冲区
		{
			size=size/2;
			if(size%16!=0)
				size=size+(16-size%16);	
			if(size<16)//若可得的最大缓冲区小于16个字节时,为错误情形
			{
				ErrorMessage=ErrorMessage+"\n内存空间不足!";
				Source.Close();
				Target.Close();
				return false;
			}
			len=size/16;
			count=remain/size;//计算读取文件的次数
			in_stream=new byte[len][4][4];//设置读入缓冲区
		}
		for(i=0;i<count;i++)
		{
			try
			{
				Source.Read(in_stream,size);//从明文文件中读入size个字节内容到缓冲区
			}
			catch(...)//读入文件失败
			{
				ErrorMessage=ErrorMessage+"\n读入文件失败!";
				delete []in_stream;
				Source.Close();
				Target.Close();
				return false;
			}
			for(j=0;j<len;j++)
			{
				State=&(in_stream[j][0]);
				Decryption();//调用解密函数
				Cur_Round++;//当前轮数加1
			}
			try
			{
				Target.Write(in_stream,size);//将缓冲区的size个字节内容写入到密文文件中
			}
			catch(...)//写入文件失败
			{
				ErrorMessage=ErrorMessage+"\n写入文件失败!";
				delete []in_stream;
				Source.Close();
				Target.Close();
				return false;
			}
		}			
		remain=remain-size*count;//计算未处理的文件大小
		delete []in_stream;
	}
	if(k!=0)
	{
		remain=k-16;
		s=new byte[remain];//取出remain个字节
		if(s==NULL)//分配内存失败
		{
			ErrorMessage=ErrorMessage+"\n内存空间不足!";
			Source.Close();
			Target.Close();
			return false;
		}
		temp=new byte[remain];//取出remain个字节
		if(temp==NULL)//分配内存失败
		{
			ErrorMessage=ErrorMessage+"\n内存空间不足!";
			Source.Close();
			Target.Close();
			return false;			
		}
		byte in[4][4];
		try
		{
			Source.Read(s,remain);//跳过remain个字节
			Source.Read(in,16);//做最后一轮解密
		}
		catch(...)//读入文件失败
		{
			ErrorMessage=ErrorMessage+"\n读入文件失败!";
			Source.Close();
			Target.Close();
			delete []s;
			delete []temp;
			return false;
		}
		State=in;
		Decryption();//调用解密函数	
		
		Cur_Round++;//当前轮数加1
		
		byte *p=NULL;
		p=&(State[0][0]);			
		for(i=0,j=16-remain;j<16;j++)
			temp[i++]=*(p+j);
		for(i=15-remain,j=15;i>=0;i--,j--)
			*(p+j)=*(p+i);				
		for(j=0;j<remain;j++)
			*(p+j)=s[j];	
		Decryption();//调用解密函数
		
		Cur_Round++;//当前轮数加1
		try
		{
			Target.Write(State,16);
			Target.Write(temp,remain);
		}
		catch(...)//写入文件失败
		{
			ErrorMessage=ErrorMessage+"\n写入文件失败!";
			delete []s;
			delete []temp;
			Source.Close();
			Target.Close();
			return false;
		}
		delete []s;
		delete []temp;
	}
	Source.Close();
	Target.Close();
	for(i=0;i<4;i++)//释放密钥的内存并置空
	{
		delete key[i];
		key[i]=NULL;
		delete w[i];
		w[i]=NULL;
	}
	return true;
}

CString CRijndael::EncrypStr()
{
	long i,j,k,len,count;
	int x;
	byte in[4][4],*p=NULL;
	p=&(in[0][0]);
	len=source.GetLength();//取得字符串长度(字节)
	count=len/16;//计算可直接加密的轮数
	x=len%16;//计算不够用于加密的字节数
	if(x==0)//刚好可以直接加密
		for(i=0;i<count;i++)
		{
			for(j=0;j<16;j++)//获得明文
				*(p+j)=source.GetAt(16*i+j);
			State=in;
			Encryption();//调用加密函数
			for(j=0;j<16;j++)//获得密文
				source.SetAt(16*i+j,*(p+j));
		}
		else//字符串末尾有不够16个字节的
		{
			for(i=0;i<count;i++)
			{
			for(j=0;j<16;j++)//获得明文
				*(p+j)=source.GetAt(16*i+j);
			State=in;
			Encryption();//调用加密函数
			for(j=0;j<16;j++)//获得密文
				source.SetAt(16*i+j,*(p+j));
			}
			byte *temp=new byte[x];
			j=16*count;
			for(len=0;len<x;len++)//获得明文
				temp[len]=source.GetAt(j+len);
			for(k=0,j=x;j<16;j++,k++)
				*(p+k)=*(p+j);//k=16-x
			for(j=0;j<x;j++,k++)
				*(p+k)=temp[j];
			State=in;
			Encryption();//调用加密函数
			k=16*count-(16-x);
			for(i=0;i<16;i++)
				source.SetAt(k++,*(p+i));
			delete []temp;
		}
	save=source;
	return *target=source;
}

CString CRijndael::DecrypStr()
{
	long i,j,len,count;
	int x;
	byte in[4][4],*p=NULL;
	p=&(in[0][0]);
	if(!save.IsEmpty())
		source=save;
	len=source.GetLength();//取得字符串长度(字节)
	count=len/16;//计算可直接解密的轮数
	x=len%16;//计算不够用于解密的字节数
	if(x==0)//刚好可以直接解密
		for(i=0;i<count;i++)
		{
			for(j=0;j<16;j++)//获得明文
				//*(p+j)=Plaintext[16*i+j];
				*(p+j)=source.GetAt(16*i+j);
			State=in;
			Decryption();//调用解密函数
			for(j=0;j<16;j++)//获得密文
			//	Ciphertext[16*i+j]=*(p+j);
				source.SetAt(16*i+j,*(p+j));
	}
		else//字符串末尾有不够16个字节的
		{
			for(i=0;i<count-1;i++)
			{
			for(j=0;j<16;j++)//获得明文
				*(p+j)=source.GetAt(16*i+j);
			State=in;
			Decryption();//调用解密函数
			for(j=0;j<16;j++)//获得密文
				source.SetAt(16*i+j,*(p+j));
			}
			byte *s=new byte[x];//取出x个字节
			byte *t=new byte[x];//取出x个字节
			memset(s,0,x);
			memset(t,0,x);
			for(len=0;len<x;len++)//获得明文,先跳过x个字符
				s[len]=source.GetAt(16*i+len);
			for(len=0;len<16;len++)//获得明文
				*(p+len)=source.GetAt(16*i+x+len);
			State=in;
			Decryption();//调用解密函数	
			for(j=16-x,i=0;j<16;j++)
				t[i++]=*(p+j);
			for(i=15-x,j=15;i>=0;i--,j--)
				*(p+j)=*(p+i);				
			for(j=0;j<x;j++)
				*(p+j)=s[j];
			State=in;
			Decryption();//调用解密函数
			for(len=0;len<16;len++)
				source.SetAt(16*(count-1)+len,*(p+len));//取得密文
			for(len=0;len<x;len++)
				source.SetAt(16*count+len,t[len]);//取得密文
			delete []s;
			delete []t;
		}
	return *target=source;
}

int CRijndael::GetCurPos()
{
	return Cur_Round*100/Total_Round;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -