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

📄 spn.h

📁 spn算法加密和解密
💻 H
字号:
#ifndef _SPN_H_
#define _SPN_H_

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

//按二进制输出整数x
void Binary(unsigned int x){
	for(unsigned int t=32768;t>0;t>>=1)
		if(x&t) cout<<1;
		else cout<<0;
}

//把无符合整数y拆分成俩个字符从c1、c2
void Char(unsigned int y,unsigned char &c1,unsigned char &c2){
	c1=(unsigned char)(y>>8);
	c2=(unsigned char)y;
}

//把俩个字符拼凑成无符合整数
unsigned int Int(unsigned char c1,unsigned char c2){
	return ((unsigned int)c1<<8)|((unsigned int)c2);
}

//取整数x的第n位(顺序从左到右)
unsigned int GetBit(unsigned int x,int n){
	unsigned int t=0x8000;
	if(x&(t>>(n-1))) 
		return 1;
	return 0;
}

/*permutation(置换)
查询P盒(或P逆盒)中x对应的值*/
unsigned int Per(unsigned int x,unsigned int *Pbox){
	unsigned int y=0, t=32768, k=32768;
	for(int i=0;i<16;i++,t>>=1)
		if(x&t) y|=(k>>Pbox[i]);
	return y;
}

/*substitution(代换)
查询S盒中x(一个分组)对应的值
当Sbox为S逆盒时返回x对应的S盒逆变换值*/
unsigned int Sub(unsigned int x,unsigned int *Sbox){
	unsigned int y=Sbox[(x>>12)&15];
	for(int t=8;t>=0;t-=4){	
		y<<=4;
		y|=Sbox[(x>>t)&15];
	}
	return y;
}

/*由盒Box生成它的逆盒iBox
可用于生成S或P逆盒*/
void GeniBox(unsigned int *Box,unsigned int *iBox){
	for(int i=0;i<16;i++)
		iBox[Box[i]]=i;
}

//轮密钥生成函数
void GenKey(unsigned int *Key,int Nr,unsigned int InitKey){
	unsigned int Kbox[16]={7,4,3,11,2,15,1,8,13,0,6,12,5,9,10,14};
	for(int i=0;i<Nr+1;i++){
		Key[i]=Per(InitKey,Kbox);
		InitKey=Key[i];
	}
}

/*生成解密所需的轮密钥
因为加\解密用同一个函数,所以解密轮密钥应满足如下要求:
Key为加密的轮密钥,iKey为解密的轮密钥,iPbox为P逆盒,iKey[0]、iKey[Nr]与加密密钥相同,
Key[1]~Key[Nr-1]为加密密钥经过P逆盒置换之后的值,Nr为迭代次数。*/
void GeniKey(unsigned int *Key,unsigned int *iKey,unsigned int *iPbox,int Nr){
	iKey[Nr]=Key[0];
	iKey[0]=Key[Nr];
	for(int i=1;i<Nr;i++)
		iKey[Nr-i]=Per(Key[i],iPbox); 
}

//随机产生包含m个整数元素的数组,用于产生S或P盒
void GenBox(unsigned int *box,int m=16){
	time_t t;
    srand((unsigned)time(&t));
	for(int i=0;i<m;){	
		box[i]=rand()%16;
		for(int j=0;j<i;j++)
			if(box[i]==box[j])
				break;
		if(i==j) i++;
	}
}

/*代换-置换网络
加密:w为明文,Sbox为S盒,Pbox为P盒,K为轮密钥,Nr为迭代次数,返回密文。
解密:w为密文,Sbox为S逆盒,Pbox为P逆盒,K[0]、K[Nr]与加密密钥相同,
K[1]~K[Nr-1]为加密密钥经过P逆盒置换之后的值,Nr为迭代次数,返回明文。*/
unsigned int SPN(unsigned int w,unsigned int *Sbox,unsigned int *Pbox,
				 unsigned int *K,int Nr){
	unsigned int v;
	for(int r=0;r<Nr-1;r++){	
		v=Sub(w^K[r],Sbox);
		w=Per(v,Pbox);
	}	
	v=Sub(w^K[r],Sbox);
	return v^K[Nr];
}

/*加-解密文件系统
加密:FileName1为明文文件,Sbox为S盒,Pbox为P盒,Key为轮密钥,
      Nr为迭代次数,密文存放在文件FileName2中。
解密:FileName1为密文文件,Sbox为S逆盒,Pbox为P逆盒,Key[0]、Key[Nr]与加密密钥相同,
      Key[1]~Key[Nr-1]为加密密钥经过P逆盒置换之后的值,Nr为迭代次数,返回明文。*/
void SPNS(char *FileName1,char *FileName2,unsigned int *Key,
		  int Nr,unsigned int *Sbox,unsigned int *Pbox){
	ifstream fin(FileName1,ios::nocreate|ios::binary);
	ofstream fout(FileName2,ios::binary);
	if(fin==NULL||fout==NULL){
		cout<<"Open File Erro!\n";
		exit(0);
	}
	int flag=1;
	while(fin.peek()!=EOF){		
		unsigned char c1, c2;
		fin.get(c1); 
		if(fin.peek()==EOF){
			c2=255; flag=0;
		}
		else fin.get(c2); 
		unsigned int x, y;
		x=Int(c1,c2); 
		y=SPN(x,Sbox,Pbox,Key,Nr);
		Char(y,c1,c2);
		fout.put(c1); 
		if(flag) fout.put(c2); 
	}
	fin.close();
	fout.close();
}

#endif

⌨️ 快捷键说明

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