DES分组密码算法_加解密任意长度文件

参考来源:https://blog.csdn.net/lisonglisonglisong/article/details/41777413


  1. 调用DES分组密码源程序中的相关函数,设计一个文件加密器,可以加密任意长度的文件,并且密文文件可解密还原回原明文文件。
  2. DES分组密码算法流程:

1)以下程序加密从桌面上的des_message.txt读入8个字符长度的明文,然后输出到桌面上的des_password.txt文件中,解密从后者输出到桌面上的des_p2m.txt文件中(由于加密后或解密失败后输出的字符为中文乱码,在Mac系统中无法正常打开,因此显示图标不一样)。


代码如下:/*提醒:代码很长*/

#include

#include

#include "memory.h"

#include "time.h"

#include "stdlib.h"

using namespace std;


#define PLAIN_FILE_OPEN_ERROR -1

#define CIPHER_FILE_OPEN_ERROR -2

#define OK 1 


typedef char ElemType;


/* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *//* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */

 /*初始置换IP*////第一步

int IP_Table[64] = {  57,49,41,33,25,17,9,1,

                      59,51,43,35,27,19,11,3,

                      61,53,45,37,29,21,13,5,

                      63,55,47,39,31,23,15,7,

                      56,48,40,32,24,16,8,0,

                      58,50,42,34,26,18,10,2,

                      60,52,44,36,28,20,12,4,

                      62,54,46,38,30,22,14,6}; 

/*逆初始置换IP^-1*////最后一步

int IP_1_Table[64] = {39,7,47,15,55,23,63,31,

                      38,6,46,14,54,22,62,30,

                      37,5,45,13,53,21,61,29,

                      36,4,44,12,52,20,60,28,

                      35,3,43,11,51,19,59,27,

                      34,2,42,10,50,18,58,26,

                      33,1,41,9,49,17,57,25,

                      32,0,40,8,48,16,56,24};

  

/* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *//* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */


/* ***** ***** ***** ***** ***** 密码函数f所用到的表 ***** ***** ***** ***** ***** *//* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */


/*选择运算E*///扩展置换表,将32位扩展位48

int E_Table[48] = {31, 0, 1, 2, 3, 4,

                   34, 5, 6, 7, 8,

                   78, 9,10,11,12,

                   11,12,13,14,15,16,

                   15,16,17,18,19,20,

                   19,20,21,22,23,24,

                   23,24,25,26,27,28,

                   27,28,29,30,31, 0};

  

/*置换运算P*///P置换,将32位变成32//S盒输出的8*4=32位的置换//f函数的输出

int P_Table[32] = {15,6,19,20,

                   28,11,27,16,

                   0,14,22,25,

                  4,17,30,9,

                  1,7,23,13,

                  31,26,2,8,

                  18,12,29,5,

                  21,10,3,24};

  

/*S*///8S盒,均为4*16的置换表,将6位转换为4//1位和第6位作为行,中间四位作为列,对应的数作为4位二进制数输出

int S[8][4][16] =

    {

        /*S1*/

        {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},

         {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},

         {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},

         {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},


        /*S2*/

        {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},

         {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},

         {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},

         {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},


        /*S3*/

        {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},

         {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},

         {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},

         {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},


        /*S4*/

        {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},

         {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},

         {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},

         {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},


        /*S5*/

        {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},

         {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},

         {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},

         {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},


        /*S6*/

        {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},

         {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},

         {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},

         {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},


        /*S7*/

        {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},

         {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},

         {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},

         {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},


        /*S8*/

        {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},

         {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},

         {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},

         {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};


/* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *//* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */


/* ***** ***** ***** ***** ***** 生成密钥所用表 ***** ***** ***** ***** ***** *//* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */


/*置换选择1*///密钥置换表,将64位密钥变成56//去奇偶校验位

int PC_1[56] = {

                56, 48, 40, 32, 24, 16, 8,

                0, 57, 49, 41, 33, 25, 17,

                9, 1, 58, 50, 42, 34, 26,

                18, 10, 2, 59, 51, 43, 35,

                62, 54, 46, 38, 30, 22, 14,

                6, 61, 53, 45, 37, 29, 21,

                13, 5, 60, 52, 44, 36, 28,

                20, 12, 4, 27, 19, 11, 3};


/*置换选择2*///压缩置换,将56位密钥压缩成48

int PC_2[48] = {

                13, 16, 10, 23, 0, 4, 2, 27,

                14, 5, 20, 9, 22, 18, 11, 3,

                25, 7, 15, 6, 26, 19, 12, 1,

                40, 51, 30, 36, 46, 54, 29, 39,

                50, 44, 32, 46, 43, 48, 38, 55,

                33, 52, 45, 41, 49, 35, 28, 31};


/*循环左移位数表*///每轮左移的位数

int MOVE_TIMES[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};


/* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *//* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */


/* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *//* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */

/*函数声明(共19个)*/

int ByteToBit(ElemType ch,ElemType bit[8]);

int BitToByte(ElemType bit[8],ElemType *ch);


int Char8ToBit64(ElemType ch[8],ElemType bit[64]);

int Bit64ToChar8(ElemType bit[64],ElemType ch[8]);


int DES_MakeSubKeys(ElemType key[64],ElemType subKeys[16][48]);


int DES_PC1_Transform(ElemType key[64], ElemType tempbts[56]);

int DES_PC2_Transform(ElemType key[56], ElemType tempbts[48]);


int DES_ROL(ElemType data[56], int time);

int DES_IP_Transform(ElemType data[64]);

int DES_IP_1_Transform(ElemType data[64]);

int DES_E_Transform(ElemType data[48]);

int DES_P_Transform(ElemType data[32]);

int DES_SBOX(ElemType data[48]);

int DES_XOR(ElemType R[48], ElemType L[48],int count);

int DES_Swap(ElemType left[32],ElemType right[32]);

int DES_EncryptBlock(ElemType plainBlock[8], ElemType subKeys[16][48], ElemType cipherBlock[8]);

int DES_DecryptBlock(ElemType cipherBlock[8], ElemType subKeys[16][48], ElemType plainBlock[8]);

int DES_Encrypt(char *plainFile, char *keyStr,char *cipherFile);

int DES_Decrypt(char *cipherFile, char *keyStr,char *plainFile);  

/* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *//* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */


/*函数功能实现*/


/*字节转换成二进制*/

int ByteToBit(ElemType ch, ElemType bit[8]){

  int cnt;

  for(cnt = 0;cnt < 8; cnt++){

    *(bit+cnt) = (ch>>cnt)&1;

  }

  return 0;

}//倒序的

  

/*二进制转换成字节*/

int BitToByte(ElemType bit[8],ElemType *ch){

 int cnt;

 for(cnt = 0;cnt < 8; cnt++){

  *ch |= *(bit + cnt)<

 }

 return 0;

}

  

/*将长度为8的字符串转为二进制位串*/

int Char8ToBit64(ElemType ch[8],ElemType bit[64]){

 int cnt;

 for(cnt = 0; cnt < 8; cnt++){  

  ByteToBit(*(ch+cnt),bit+(cnt<<3));

 }

 return 0;

}

  

/*将二进制位串转为长度为8的字符串*/

int Bit64ToChar8(ElemType bit[64],ElemType ch[8]){

 int cnt;

 memset(ch,0,8);  //void *memset( void *dest, int c, size_t count );

 for(cnt = 0; cnt < 8; cnt++){

  BitToByte(bit+(cnt<<3),ch+cnt);

 }

 return 0;

}

  

/*生成子密钥*/

int DES_MakeSubKeys(ElemType key[64],ElemType subKeys[16][48]){

 ElemType temp[56];

 int cnt;

 DES_PC1_Transform(key,temp);    /*PC1置换*/

 for(cnt = 0; cnt < 16; cnt++){  /*16轮跌代,产生16个子密钥*/

  DES_ROL(temp,MOVE_TIMES[cnt]); /*循环左移*/

  DES_PC2_Transform(temp,subKeys[cnt]);  /*PC2置换,产生子密钥*/

 }

 return 0;

}

  

/*置换选择1*////去奇偶校验位

int DES_PC1_Transform(ElemType key[64], ElemType tempbts[56]){

 int cnt; 

 for(cnt = 0; cnt < 56; cnt++){

  tempbts[cnt] = key[PC_1[cnt]];//PC1的顺序将key数组的字符存入到tempbts

 }

 return 0;

}

  

/*置换选择2*/

int DES_PC2_Transform(ElemType key[56], ElemType tempbts[48]){

 int cnt;

 for(cnt = 0; cnt < 48; cnt++){

  tempbts[cnt] = key[PC_2[cnt]];

 }

 return 0;

}

  

/*循环左移*/

int DES_ROL(ElemType data[56], int time){

 ElemType temp[56];

  

 /*保存将要循环移动到右边的位*/

 memcpy(temp,data,time);   //void *memcpy( void *dest, const void *src, size_t count );

 memcpy(temp+time,data+28,time);

 

 /*28位移动*/

 memcpy(data,data+time,28-time);

 memcpy(data+28-time,temp,time);

  

 /*28位移动*/

 memcpy(data+28,data+28+time,28-time);

 memcpy(data+56-time,temp+time,time); 

  

 return 0;

}

  

/*IP置换*////第一步

int DES_IP_Transform(ElemType data[64]){

 int cnt;

 ElemType temp[64];

 for(cnt = 0; cnt < 64; cnt++){

  temp[cnt] = data[IP_Table[cnt]];//data中数据以IP_Table的顺序存储在temp

 }

 memcpy(data,temp,64);//更新data数组

 return 0;

}

  

/*IP逆置换*/

int DES_IP_1_Transform(ElemType data[64]){

 int cnt;

 ElemType temp[64];

 for(cnt = 0; cnt < 64; cnt++){

  temp[cnt] = data[IP_1_Table[cnt]];

 }

 memcpy(data,temp,64);

 return 0;

}

  

/*选择运算E*/

int DES_E_Transform(ElemType data[48]){

 int cnt;

 ElemType temp[48];

 for(cnt = 0; cnt < 48; cnt++){

  temp[cnt] = data[E_Table[cnt]];//data中数据以E_Table的顺序存储在temp

 }

 memcpy(data,temp,48);

 return 0;

}

  

/*P置换--S盒输出的32位数据打乱*/

int DES_P_Transform(ElemType data[32]){

 int cnt;

 ElemType temp[32];

 for(cnt = 0; cnt < 32; cnt++){

  temp[cnt] = data[P_Table[cnt]];//data中数据以P_Table的顺序存储在temp

 }

 memcpy(data,temp,32);

 return 0;

}

  

/*异或--2加运算*/

int DES_XOR(ElemType R[48], ElemType L[48] ,int count){

 int cnt;

 for(cnt = 0; cnt < count; cnt++){

  R[cnt] ^= L[cnt];

 }

 return 0;

}

  

/*S盒置换*/

int DES_SBOX(ElemType data[48]){

 int cnt;

 int line,row,output;

 int cur1,cur2;

 for(cnt = 0; cnt < 8; cnt++){

  cur1 = cnt*6;

  cur2 = cnt<<2/*cur2=cnt*4;*/

  

  /*计算在S盒中的行与列*/

  line = (data[cur1]<<1) + data[cur1+5];

  row = (data[cur1+1]<<3) + (data[cur1+2]<<2) + (data[cur1+3]<<1) + data[cur1+4];

  output = S[cnt][line][row];

    

  /*化为2进制*/

  data[cur2] = (output&0X08)>>3;

  data[cur2+1] = (output&0X04)>>2;

  data[cur2+2] = (output&0X02)>>1;

  data[cur2+3] = output&0x01;

 }

 return 0;

}

  

/*交换*/

int DES_Swap(ElemType left[32], ElemType right[32]){

 ElemType temp[32];

 memcpy(temp,left,32);

 memcpy(left,right,32);  

 memcpy(right,temp,32);

 return 0;

}

  

/*加密单个分组*/

int DES_EncryptBlock(ElemType plainBlock[8], ElemType subKeys[16][48], ElemType cipherBlock[8]){

 ElemType plainBits[64];

 ElemType copyRight[48];

 int cnt;

  

 Char8ToBit64(plainBlock,plainBits);  

 /*初始置换(IP置换)*/

 DES_IP_Transform(plainBits);

  

 /*16轮迭代*/

 for(cnt = 0; cnt < 16; cnt++){

    memcpy(copyRight,plainBits+32,32);//取右边32


    /*将右边32位进行扩展置换,从32位扩展到48*////原明文操作

    DES_E_Transform(copyRight);


    /*将右边32位与子密钥进行异或操作*/

    DES_XOR(copyRight,subKeys[cnt],48);


    /*异或结果进入S盒,输出32位结果*/

    DES_SBOX(copyRight);


    /*P置换*/

    DES_P_Transform(copyRight);


    /*将明文左边32位与右边32位进行异或*/

    DES_XOR(plainBits,copyRight,32);

    if(cnt != 15){

    /*最后完成左右两边的交换*/

        DES_Swap(plainBits,plainBits+32);

    }

 }

 /*逆初始置换(IP^1置换)*/

 DES_IP_1_Transform(plainBits);

 Bit64ToChar8(plainBits,cipherBlock);//cipherBlock是输出的密文

 return 0;

}

  

/*解密单个分组*/

int DES_DecryptBlock(ElemType cipherBlock[8], ElemType subKeys[16][48],ElemType plainBlock[8]){

    ElemType cipherBits[64];

    ElemType copyRight[48];

    int cnt;


    Char8ToBit64(cipherBlock,cipherBits); 

    /*初始置换(IP置换)*/

    DES_IP_Transform(cipherBits);


    /*16轮迭代*/

    for(cnt = 15; cnt >= 0; cnt--){

        memcpy(copyRight,cipherBits+32,32);

        /*将右边32位进行扩展置换,从32位扩展到48*/

        DES_E_Transform(copyRight);

        /*将右边32位与子密钥进行异或操作*/

        DES_XOR(copyRight,subKeys[cnt],48);  

        /*异或结果进入S盒,输出32位结果*/

        DES_SBOX(copyRight);

        /*P置换*/

        DES_P_Transform(copyRight);  

        /*将明文左边32位与右边32位进行异或*/

        DES_XOR(cipherBits,copyRight,32);

        if(cnt != 0){

            /*最后完成左右两边的交换*/

            DES_Swap(cipherBits,cipherBits+32);

        }

    }

    /*逆初始置换(IP^1置换)*/

    DES_IP_1_Transform(cipherBits);

    Bit64ToChar8(cipherBits,plainBlock);

    return 0;

}


int format(){

    fstream file;

    file.open("/Users/fenglunli/Desktop/des_message.txt",ios::in);

    int i = 0;

    ElemType m;

    while(file.peek()!=EOF){

        file >> m;

        i++;

    }

    file.close();

    return i;

}


void fun(ElemType* m1, ElemType* m2, ElemType* k, bool des){

    ElemType temp[64];//64位密钥

    Char8ToBit64(k,temp);//

    DES_IP_Transform(temp);//IP置换//temp已更新

    ElemType subkeys[16][48];//子密钥

    DES_MakeSubKeys(temp,subkeys);//16子密钥

    if(des)

        DES_EncryptBlock(m1,subkeys,m2);//cout<<"密文为:";

    else

        DES_DecryptBlock(m1,subkeys,m2);//cout<<"明文为:";

}


void fun2(ElemType* k, bool des, int n){

    fstream file_in("/Users/fenglunli/Desktop/des_message.txt", ios::in);//读入

    fstream file_out("/Users/fenglunli/Desktop/des_password.txt", ios::out | ios::app);//写出

    fstream file_in2("/Users/fenglunli/Desktop/des_password.txt", ios::in);

    fstream file_out2("/Users/fenglunli/Desktop/des_p2m.txt", ios::out | ios::app);

    ElemType message[8], password[8], p2m[8];

    int time = n/8, num = n%8;

    if(des){

        //while(file_in.peek() != EOF){

        for(int j=0;j<time;j++){

            for(int i=0;i<8;i++)

                file_in >> message[i];

            fun(message, password, k, true);

            for(int i=0;i<8;i++)

                file_out << password[i];

        }

        for(int i=0;i

            file_in >> message[i];

        fun(message, password, k, true);

        for(int i=0;i

            file_out << password[i];

    }else{

        //while(file_in2.peek() != EOF){

        for(int j=0;j<time;j++){

            for(int i=0;i<8;i++)

                file_in2 >> password[i];

            fun(password, p2m, k, false);

            /*if(file_in2.peek() == EOF)

                for(int i=0;i

                    file_out2 << p2m[i];

            else

                for(int i=0;i<8;i++)

                    file_out2 << p2m[i];*/

            for(int i=0;i<8;i++)

                file_out2 << p2m[i];

        }

        for(int i=0;i

            file_in2 >> password[i];

        fun(password, p2m, k, false);

        for(int i=0;i

            file_out2 << p2m[i];

    }

    file_in.close();

    file_out.close();

    file_in2.close();

    file_out2.close();

}


int main(){

    int n = format();

    //int time = n/8, num = n%8;

    fstream file_out("/Users/fenglunli/Desktop/des_password.txt",ios::out);

    file_out << "";

    fstream file_out2("/Users/fenglunli/Desktop/des_p2m.txt",ios::out);

    file_out2 << "";

    ElemType key[8];

    cout<<"请选择   1:加密; 其他:解密:";

    int c;

    while(cin>>c){

        cout<<"请输入密钥:";

        for(int i=0;i<8;i++){

            key[i] = getchar();

            if(key[i]<48 || key[i]>122)

                i--;

        }

        fun2(key, c==1, n);

        cout<<"请选择   1:加密; 其他:解密:";

    }

    return 0;

}



2)测试:

第一步:准备好测试文件,由于任意长度均可测试,此处取14个字符:

第二步:解密时先输入错误的密钥:

然后发现解密输出文件时乱码,无法打开:

第三步:输入正确的密钥:

这时再打开解密后的文件,与明文一致,实验成功!

/*好像传不了图片,有空再补吧*/

你可能感兴趣的:(DES分组密码算法_加解密任意长度文件)