📄 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 + -