/*******************************************************************************
密码学实验-----SMS4算法演示
Wuhan University
Computer School
HonYi YanChao
*******************************************************************************/
/*头文件声明*/
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
/*数据结构定义*/
//S盒子
unsigned char S_box[256]=
{
0xd6 ,0x90 ,0xe9 ,0xfe ,0xcc ,0xe1 ,0x3d ,0xb7 ,0x16 ,0xb6 ,0x14 ,0xc2 ,0x28 ,0xfb ,0x2c ,0x05 ,
0x2b ,0x67 ,0x9a ,0x76 ,0x2a ,0xbe ,0x04 ,0xc3 ,0xaa ,0x44 ,0x13 ,0x26 ,0x49 ,0x86 ,0x06 ,0x99 ,
0x9c ,0x42 ,0x50 ,0xf4 ,0x91 ,0xef ,0x98 ,0x7a ,0x33 ,0x54 ,0x0b ,0x43 ,0xed ,0xcf ,0xac ,0x62 ,
0xe4 ,0xb3 ,0x1c ,0xa9 ,0xc9 ,0x08 ,0xe8 ,0x95 ,0x80 ,0xdf ,0x94 ,0xfa ,0x75 ,0x8f ,0x3f ,0xa6 ,
0x47 ,0x07 ,0xa7 ,0xfc ,0xf3 ,0x73 ,0x17 ,0xba ,0x83 ,0x59 ,0x3c ,0x19 ,0xe6 ,0x85 ,0x4f ,0xa8 ,
0x68 ,0x6b ,0x81 ,0xb2 ,0x71 ,0x64 ,0xda ,0x8b ,0xf8 ,0xeb ,0x0f ,0x4b ,0x70 ,0x56 ,0x9d ,0x35 ,
0x1e ,0x24 ,0x0e ,0x5e ,0x63 ,0x58 ,0xd1 ,0xa2 ,0x25 ,0x22 ,0x7c ,0x3b ,0x01 ,0x21 ,0x78 ,0x87 ,
0xd4 ,0x00 ,0x46 ,0x57 ,0x9f ,0xd3 ,0x27 ,0x52 ,0x4c ,0x36 ,0x02 ,0xe7 ,0xa0 ,0xc4 ,0xc8 ,0x9e ,
0xea ,0xbf ,0x8a ,0xd2 ,0x40 ,0xc7 ,0x38 ,0xb5 ,0xa3 ,0xf7 ,0xf2 ,0xce ,0xf9 ,0x61 ,0x15 ,0xa1 ,
0xe0 ,0xae ,0x5d ,0xa4 ,0x9b ,0x34 ,0x1a ,0x55 ,0xad ,0x93 ,0x32 ,0x30 ,0xf5 ,0x8c ,0xb1 ,0xe3 ,
0x1d ,0xf6 ,0xe2 ,0x2e ,0x82 ,0x66 ,0xca ,0x60 ,0xc0 ,0x29 ,0x23 ,0xab ,0x0d ,0x53 ,0x4e ,0x6f ,
0xd5 ,0xdb ,0x37 ,0x45 ,0xde ,0xfd ,0x8e ,0x2f ,0x03 ,0xff ,0x6a ,0x72 ,0x6d ,0x6c ,0x5b ,0x51 ,
0x8d ,0x1b ,0xaf ,0x92 ,0xbb ,0xdd ,0xbc ,0x7f ,0x11 ,0xd9 ,0x5c ,0x41 ,0x1f ,0x10 ,0x5a ,0xd8 ,
0x0a ,0xc1 ,0x31 ,0x88 ,0xa5 ,0xcd ,0x7b ,0xbd ,0x2d ,0x74 ,0xd0 ,0x12 ,0xb8 ,0xe5 ,0xb4 ,0xb0 ,
0x89 ,0x69 ,0x97 ,0x4a ,0x0c ,0x96 ,0x77 ,0x7e ,0x65 ,0xb9 ,0xf1 ,0x09 ,0xc5 ,0x6e ,0xc6 ,0x84 ,
0x18 ,0xf0 ,0x7d ,0xec ,0x3a ,0xdc ,0x4d ,0x20 ,0x79 ,0xee ,0x5f ,0x3e ,0xd7 ,0xcb ,0x39 ,0x48
};
//常数FK
unsigned int FK0=0xa3b1bac6 ,FK1=0x56aa3350 ,FK2=0x677d9197 ,FK3=0xb27022dc;
//固定参数CK
unsigned int CK[32]=
{
0x00070e15 ,0x1c232a31 ,0x383f464d ,0x545b6269 ,
0x70777e85 ,0x8c939aa1 ,0xa8afb6bd ,0xc4cbd2d9 ,
0xe0e7eef5 ,0xfc030a11 ,0x181f262d ,0x343b4249 ,
0x50575e65 ,0x6c737a81 ,0x888f969d ,0xa4abb2b9 ,
0xc0c7ced5 ,0xdce3eaf1 ,0xf8ff060d ,0x141b2229 ,
0x30373e45 ,0x4c535a61 ,0x686f767d ,0x848b9299 ,
0xa0a7aeb5 ,0xbcc3cad1 ,0xd8dfe6ed ,0xf4fb0209 ,
0x10171e25 ,0x2c333a41 ,0x484f565d ,0x646b7279
};
//循环移位 SHL(x,y)为32位的x循环左移y位
#define SHL(x,y) ((x<<y)|(x>>32-y))
//加解密 非线性τ函数B=τ(A)
#define unline_change(A) (S_box[(A)>>24&0xFF]<<24^S_box[(A)>>16&0xFF]<<16^S_box[(A)>>8&0xFF]<<8^S_box[(A)&0xFF])
//加解密中的L函数
#define L1(B) ((B)^SHL(B,2)^SHL(B,10)^SHL(B,18)^SHL(B,24))
//秘钥扩展中的L‘函数
#define L2(B) ((B)^SHL(B,13)^SHL(B,23))
/*子函数声明*/
void KeyExpasion(unsigned char *Key ,unsigned int *rk);//密钥扩展算法
void Encrypt (unsigned char * Input,unsigned char * Output,unsigned int * rk);//加密函数
void Dncrypt (unsigned char * Input,unsigned char * Output,unsigned int * rk);// 解密函数
/*主函数*/
//实验明文 :1 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
//正确密文:88 f9 a3 b1 7b 1d 9f 65 2c 17 d7 7 b2 ae e4 60
int main(void)
{
printf ("\n********************SMS4算法演示********************\n\n");
//待加密的明文
unsigned char m[16]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
//初始加密密钥
unsigned char key[16]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
unsigned char c[16];//用以存储密文的数组
unsigned int rk[32];//定义轮密钥rk
int i;//计数变量
KeyExpasion(key,rk); //密钥扩展算法
//加密过程
printf("**********加密过程**********\n");
printf("明文:\n");//显示加密前的明文
for (i=0;i<16;i++)
printf("%x ",m[i]);
printf ("\n\n");
printf("密钥\n");//显示密钥
for (i=0;i<16;i++)
printf("%x ",key[i]);
printf ("\n\n");
Encrypt(m,c,rk);//调用加密算法
printf ("加密后的密文:\n");//显示加密后的密文
for (i=0 ;i<16 ;i++ )
printf("%x ",c[i]);
printf("\n\n\n");
//解密过程
//先将轮密钥逆序
unsigned int temp;
int j;
for(j=0;j<16;j++)//将密钥逆序
temp=rk[j],rk[j]=rk[31-j],rk[31-j]=temp;
printf("**********解密过程**********\n");
printf("密文:\n");//显示解密前的密文
for (i=0;i<16;i++)
printf("%x ",c[i]);
printf ("\n\n");
printf("密钥:\n");//显示密钥
for (i=0;i<16;i++)
printf("%x ",key[i]);
printf ("\n\n");
Dncrypt(c,m,rk);//调用解密算法
printf ("解密后的明文:\n");//显示解密后的明文
for (i=0 ;i<16 ;i++ )
printf("%x ",m[i]);
printf("\n\n");
system("pause");
return 0;
}
/*加密函数*/
void Encrypt (unsigned char * Input,unsigned char * Output,unsigned int * rk)
// Input:输入已分组的明文,Output:输出的对应分组的密文,rk为轮密钥
{
unsigned int r,mid,x0,x1,x2,x3,*p;//需要用到的中间变量
p=(unsigned int *)Input;//此时p指针指向输入
x0=p[0];
x1=p[1];
x2=p[2];
x3=p[3];
for(r=0;r<32;r+=4)//开始32轮加密 ,一次进行4轮,共计八次
{
//F被分解为三步
mid=x1^x2^x3^rk[r+0]; //先计算 x1^x2^x3^rk
mid=unline_change(mid);//非线性τ函数
x0=x0^L1(mid);//与x0亦或
mid=x2^x3^x0^rk[r+1];
mid=unline_change(mid);
x1^=L1(mid);
mid=x3^x0^x1^rk[r+2];
mid=unline_change(mid);
x2^=L1(mid);
mid=x0^x1^x2^rk[r+3];
mid=unline_change(mid);
x3^=L1(mid);
}
p=(unsigned int *)Output;//此时p指针指向输出
p[0]=x3;
p[1]=x2;
p[2]=x1;
p[3]=x0;
}
/*解密函数,基本等同于于加密过程,只是密钥不同(被事先逆序)*/
void Dncrypt (unsigned char * Input,unsigned char * Output,unsigned int * rk)
// Input:输入分组的密文,Output:输出的对应的分组明文,rk为轮密钥
{
unsigned int r,mid,x0,x1,x2,x3,*p;//需要用到的中间变量
p=(unsigned int *)Input;//此时p指针指向输入
x0=p[0];
x1=p[1];
x2=p[2];
x3=p[3];
for(r=0;r<32;r+=4)//开始32轮解密 ,一次进行4轮,共计八次
{
//F被分解为三步
mid=x1^x2^x3^rk[r+0];//先计算 x1^x2^x3^rk
mid=unline_change(mid);//非线性τ函数
x0=x0^L1(mid);//与x0亦或
mid=x2^x3^x0^rk [r+1];
mid=unline_change(mid);
x1^=L1(mid);
mid=x3^x0^x1^rk[r+2];
mid=unline_change(mid);
x2^=L1(mid);
mid=x0^x1^x2^rk[r+3];
mid=unline_change(mid);
x3^=L1(mid);
}
p=(unsigned int *)Output;//此时p指针指向输出
p[0]=x3;
p[1]=x2;
p[2]=x1;
p[3]=x0;
}
/*密钥扩展算法*/
void KeyExpasion(unsigned char *Key ,unsigned int *rk)
//Key :为加密密钥,rk:为轮密钥
{
unsigned int r,mid,MK0,MK1,MK2,MK3,*p,k0,k1,k2,k3;//中间变量
p=(unsigned int *)Key ;//此时p指向密钥,以便将密钥Key分解为MK0~3
MK0=p[0];
MK1=p[1];
MK2=p[2];
MK3=p[3];
//初始计算K0~3
k0=MK0^FK0;
k1=MK1^FK1;
k2=MK2^FK2;
k3=MK3^FK3;
for(r=0;r<32;r+=4)//开始32轮密钥扩展 ,一次进行4轮,共计八次
{
mid=k1^k2^k3^CK[r+0];//先计算 x1^x2^x3^r
mid=unline_change(mid);//非线性τ函数
rk[r+0]=k0^L2(mid);//与k0亦或
mid=k2^k3^k0^CK[r+1];
mid=unline_change(mid);
rk[r+1]=k1^L2(mid);
mid=k3^k0^k1^CK[r+2];
mid=unline_change(mid);
rk[r+2]=k2^L2(mid);
mid=k0^k1^k2^CK[r+3];
mid=unline_change(mid);
rk[r+3]=k3^L2 (mid);
}
}