当前位置: 首页 > 工具软件 > sms4j > 使用案例 >

SMS4(中国商用加密算法)

仲法
2023-12-01
/*******************************************************************************
密码学实验-----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);
}   
}


 类似资料: