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

📄 yingying.cpp

📁 加密解密现代密码学的内容c语言编写uoto
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    unsigned long work[2];      /*存放轮函数迭代中当前轮的左右分组各32bit*/
    long tmp;

    permute(block,iperm,(char *)work);   /* 初始置换 */

    /*先将左右各32bit交换*/
    tmp=work[0];
    work[0]=work[1];
    work[1]=tmp;

    /* 作16轮迭代,注意密钥使用的顺序与加密时正好相反 */
    /* 16轮迭代的子密钥还是存在二维数组kn[16][8]中,使用哪一轮的密钥由i来控制*/
    printf("分别解密的16轮每轮所得结果为:\n");
    for(i=15;i>=0;i--)  
         round(i,work);    /*轮数从0-15*/

    permute((char *)work,fperm,block);   /* 逆初始置换 */
    printf("\n\n");
}


static int permute(char *inblock,char perm[16][16][8],char *outblock){
    /*此函数的作用是: 1 对输入的64bit明文利用ip[64]进行初始置换*/
    /*                2 对经过16轮迭代并左右交换后的64bit利用fp[64]进行逆初始置换*/
    register int i,j;
    register char *ib,*ob;   
    register char *p,*q;

    /*这是此函数的一个附属功能,把inblock(含义见函数endes/dedes)拷贝给outblock*/
    /*函数endes和dedes将会使用outblock*/   
    if(perm==NULL){     
        for(i=8;i!=0;i--)
            *outblock++=*inblock++;
        return 0;
    }
   
    /*按照调用位置的不同,以下完成上述功能1或2*/
    for(i=8,ob=outblock;i!=0;i--)
        *ob++=0;
         ib=inblock;
         for(j=0;j<16;j+=2,ib++){            
             ob=outblock;
             p=perm[j][(*ib>>4)&017];
             q=perm[j+1][*ib&017];
             for(i=8;i!=0;i--)               
                 *ob++ |=*p++ | *q++;        
         }
    return 0;
}



static void round(int num,unsigned long *block){       
    /*此函数完成一轮DES迭代,轮数从0-15轮*/
    
    /*抓住Feistel结构的规律:L(i)=R(i-1),R(i)=L(i-1)^f(R(i-1),K(i-1))*/
    /*由上规律可知:若当前轮轮数i是奇数,则经过当前轮迭代后,输出中的L(i)是一开始明文经初始置换后*/
    /*传入轮迭代的左32bit经过一系列变换的结果,R(i)是右32bit经过一系列变换的结果. 若当前轮 */
    /*轮数i是偶数,结论正好与上述相反*/

    /*由上述规律可得:若当前轮轮数i是奇数,则经过当前轮迭代后,block[0]中实际存放的是L(i),*/
    /*(block[1]实际存放的是R(i).若当前轮轮数i是偶数,则经过当前轮迭代后,block[0]中实际存放的是R(i),*/
    /*(block[1]实际存放的是L(i),与i是奇数时正好相反.*/

    if(num&1)  {block[1]^=f(block[0],kn[num]);
                printf("%d   %02x",num+1,((unsigned long) block[0])&0x00ffffffff);
                printf(" %04x\n",((unsigned long) block[1])&0x00ffffffff);}
    /*当前轮数i是奇数时,由上述知,只需改变block[1]*/ 
    else        {block[0]^=f(block[1],kn[num]);
                printf("%d   %02x",num+1,((unsigned long) block[1])&0x00ffffffff);
                printf(" %04x\n",((unsigned long) block[0])&0x00ffffffff);}
    /*当前轮数i是偶数时,由上述知,只需改变block[0]*/
}

static long f(unsigned long r, unsigned char subkey[8]){
    /*此函数实现DES轮迭代中的非线性f函数,这是DES加解密过程的核心*/
    
    /*r是每轮迭代中左右各32bit中需要改动的32bit,或为左32bit,或为右32bit.详见函数round*/
    /*subkey[8]中,存有每轮所需的48bit子密钥(事先已求好).sunkey[8]中的一个值代表6bit*/

    register unsigned long rval,rt;
   
     #ifdef TRACE
        unsigned char *cp;
        int i;
        printf("f(%081x,%02x %02x %02x %02x %02x %02x %02x %02x)= " ,r,
               subkey[0],subkey[1],subkey[2],
               subkey[3],subkey[4],subkey[5],
               subkey[6],subkey[7]);
     #endif
     
     /*虽然宏定义中定义了选择扩展运算表ei[48],但在此函数中并没有使用这一运算表,而是利用*/
     /*其他方式代替了ei[64]的作用,下文有解释*/
      
      rt=(r>>1) | ((r&1)?0x80000000:0);
      /*r为32bit,若设r=a1,a2,a3------a32(从高位到低位),则rt=a32,a1,a2,a3,a4-----a31*/
      /*即将r比特表示的最低位(a32)移动到最高位*/
      
      rval=0;  /*rval中将存放一轮f函数作用后的结果*/
      
      rval |=sp[0][((rt>>26) ^*subkey++) & 0x3f];
      /*rt>>26=0,0,0,0,0,-----a32,a1,a2,a3,a4,a5(高位共26个0)*/
      /*"a32,a1,a2,a3,a4,a5"这正是选择扩展运算表ei[48]的第1行的值,因此不用扩展运算表ei[48]*/
      /*"&0x3f"即00111111是为了取得异或结果的后6bit(这6bit是1个S盒的输入)*/
      /*sp[8][64]的说明详见函数spinit*/

      rval |=sp[1][((rt>>22) ^*subkey++) & 0x3f];
      /*rt>>22=0,0,0,0-----a32,a1,a2,a3,a4,a5,a6,a7,a8,a9(高位共22个0)*/
      /*subkey只有6bit,所以只会和a4,a5,a6,a7,a8,a9做异或."a4,a5,a6,a7,a8,a9"正是*/
      /*选择扩展运算表ei[48]的第2行的值*/
      /*以下几步同理于此*/
       
      rval |=sp[2][((rt>>18) ^*subkey++) & 0x3f];
      rval |=sp[3][((rt>>14) ^*subkey++) & 0x3f];
      rval |=sp[4][((rt>>10) ^*subkey++) & 0x3f];
      rval |=sp[5][((rt>>6) ^*subkey++) & 0x3f];
      rval |=sp[6][((rt>>2) ^*subkey++) & 0x3f];
      
      rt=(r<<1) | ((r&0x80000000) ?1 :0);
      /*rt=a2,a3,a4-----a32,a1.(高位到低位)  即将r的最高位a1移动到最低位*/
      rval |=sp[7][(rt ^*subkey) &0x3f];
      /*subkey只有6bit,所以只会和a28,a29,a30,a31,a32,a1做异或."a28,a29,a30,a31,a32,a1"正是*/
      /*选择扩展运算表ei[48]的最后一行的值*/

      #ifdef TRACE
           printf(" %081x\n",rval);
      #endif
      return rval;
}


static void perminit(char perm[16][16][8],char p[64]){   
    /*此函数的功能是初始化perm[16][16][8](即iperm[16][16][8]和fperm[16][16][8])并赋值*/
    register int l,j,k;
    int i,m;
      /*将perm[16][16][8]初始化 */
      for(i=0;i<16;i++)
        for(j=0;j<16;j++)
           for(k=0;k<8;k++)
             perm[i][j][k]=0;
      
    /*对perm[16][16][8]赋值 */  
    for(i=0;i<16;i++)                   
        for(j=0;j<16;j++)               
            for(k=0;k<64;k++){           
              l=p[k]-1 ;                 
              if((l>>2)!=i)              
                  continue;               
              if(!(j&nibblebit[l&3]))
                  continue;                
              m=k&07;                     
              perm[i][j][k>>3] |=bytebit[m];
            }
}


static void spinit(){

    /*此函数先于DES加密过程(函数endes)进行.由于每个S盒输入为6bit,因此最多有64种*/
    /*(2的6次方)输入.此函数对每个S盒穷举出所有可能的64种输入,由此得到所对的64种输*/
    /*出(由S盒可以看到,每个S盒对应的输出为16*4=64种,与输入一一对应).再将各种输出经*/
    /*置换表p32i[32]变换后的结果存放于二维数组sp[8][64]中.(共8个S盒,有8*64种输出,*/
    /*因此经置换运算后也有8*64种.将每种情况的32bit存放在sp[8][64]的一个空间)*/

    /*注:一个S盒输入为6比特,输出为4比特.8个S盒输入共48比特,输出共32bit,经置换*/
    /*表p32i[32]变换后依旧为32bit*/

    char pbox[32];
    int p,i,s,j,rowcol;
    long val;

     for(p=0;p<32;p++)
        for(i=0;i<32;i++)
           if(p32i[i]-1==p){
                pbox[p]=i;
                break;
           }

     /*对8个S盒的输出比特依次编号为0-31.pbox[32]将依次存储这32bit经p32i[i]置换*/
     /*后的位置.如S-2输出的第2个比特,编号应为5,按照p32i[32]应被置换到第13个*/
     /*比特的位置,则pbox[5]中存放12(数组下标从0开始)*/

     for(s=0;s<8;s++)          /*依次对每个S盒穷举*/
        for(i=0;i<64;i++){     /* 对64种输入穷举 */
            val=0;

            /*设S盒中输入为a6,a5,a4,a3,a2,a1(从高到低位),a6,a1构成的十进制数*/
            /*决定行,a5,a4,a3,a2构成的十进制数决定列*/

            rowcol=(i&32)|((i&1)?16:0)|((i>>1)&0xf);
            /*rowcol等于a6,a1,a5,a4,a3,a2构成的十进制数,经数学证明,rowcol为*/
            /*当前输入所对应的S盒中输出的下标*/

            /*例如S-1输入为011001,按照定义应输出9."9"对应*/
            /*si[0][28].按上述算法rowcol=011100即28,可见si[0][rowcol]就是9*/

            for(j=0;j<4;j++)      /*对每一个输出比特处理 */
                if(si[s][rowcol]&(8>>j))
                    val |=1L<<(31-pbox[4*s+j]);


            sp[s][i]=val;

            /*sp[a][b]中只处理了第a+1个S盒中的4比特,其他比特位置为0(val每次进循环初始化为0)*/

            #ifdef DEBUG
                   printf("sp[%d][%2d]=%081x\n",s,i,sp[s][i]);
            #endif
        }
}


void show(){
     /*此函数处理用户输入的明文和初始化密钥,因为DES一次只能处理64bit明文,同时使用64bit密钥*/
     /*要对用户输入的明文每64bit即8字节用一次DES*/
    int notation=0,i,j,m;
    char key[MAX_NUM],  plaintext[MAX_NUM], /*tempK[8],*/ tempP[8],ch;
    FILE *p,*q;
    p=fopen("D:\QQ.txt","r");

/*-----------------------------------------------------------------------------*/
   /* printf("请输入明文(以char型输入)\n以“#”结束输入\n");
    while(1){   
          scanf("%c",&plaintext[notation++]);
          if(plaintext[notation-1]=='#')  { notation--; break;}
    }  */
    /*notation记录下用户输入的明文长度*/

   /* printf("明文的16进制转换码\n");
    for(i=0;i<notation;i++)
          printf("%02x   ",((unsigned int) plaintext[i])&0x00ff);   printf("\n");
    */
/*-----------------------------------------------------------------------------*/

    while(ch!=EOF){/*从文件里读入明文*/
        ch=fgetc(p);
        plaintext[notation++]=ch;
        printf("%c",ch);}



   /* printf("请输入密钥(以char型输入,8位密钥)\n");*/
    printf("please input key (char)\n");
    for(i=0;i<8;i++)     
          scanf("%c",&key[i]);


/*-----------------------------------------------------------------------------*/
    /*printf("密钥的16进制转换码\n");
    for(i=0;i<8;i++)
          printf("%02x   ",((unsigned int) key[i])&0x00ff);  printf("\n\n");
    getchar(); */
/*-----------------------------------------------------------------------------*/


    desinit();   /*DES的一些初始化操作,详见desinit函数体说明*/
    setkey(key); /*算出16轮子密钥,详见setkey函数体说明*/
    
    for(i=0;i<(notation-1)/8+1;i++){
        for(j=i*8;j<(i+1)*8;j++){  /*DES一次只能处理64bit明文,对应char型就是8位char型*/
           /* tempK[j-i*8]=key[j];  因此本处循环将char型明文每8位存放在tempP[8]中,用于一次加密*/
           tempP[j-i*8]=plaintext[j];}
        /* setkey(tempK);   */
        endes(tempP);   /*DES加密,详见endes函数体说明*/
        for(j=i*8;j<(i+1)*8;j++)  
            plaintext[j]=tempP[j-i*8];
    }

    q=fopen("D:\ying.txt","w+");
    for(i=0;i<notation;i++)
        fputc(plaintext[i],q);


    printf("\n密文的16进制转换码:(02x output)\n");
    for(i=0;i<notation;i++){
        printf("%02x   ",((unsigned int) plaintext[i])&0x00ff);}
    printf("\n密文的char型输出:(char output)\n");
    for(i=0;i<notation;i++)
        printf("%c",plaintext[i]);  printf("\n\n");

   for(i=0;i<(notation-1)/8+1;i++){
        for(j=i*8;j<(i+1)*8;j++){ 
           /* tempK[j-i*8]=key[j];因此本处循环将char型明文每8位存放在tempP[8]中,用于一次解密*/
           tempP[j-i*8]=plaintext[j];}
        /* setkey(tempK);   */
        dedes(tempP);   /*DES解密,详见dedes函数体说明*/
        for(j=i*8;j<(i+1)*8;j++)   
           plaintext[j]=tempP[j-i*8];
    }/* */ 

    printf("\n解密恢复后明文的16进制转换码:\n");
    for(i=0;i<notation;i++)
        printf("%02x   ",((unsigned int) plaintext[i])&0x00ff);  
    printf("\n解密后明文的char型输出:\n");
    for(i=0;i<notation;i++)
        printf("%c",plaintext[i]); printf("\n");
    printf("\n");
    desdone();  /*回收使用的空间*/
}

void main(){
    show();   
    getchar();
}

⌨️ 快捷键说明

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