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

📄 des_ecbmode.cpp

📁 利用DES算法(包括ECB和CBC模式)加解密BMP图像
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                }
                return nobj;
        }
}

void DES::writeBMP(FILE *bmp, char *str, int nobj)
//将64个元素的数组转化成nobj字节信息写到BMP文件中
{
        char strBuf[8];       //储存转换后的字节信息

        //转换
        for(int i=0; i<nobj; i++){
                strBuf[i] = 0;
                for(int j=0; j<8; j++)
                        strBuf[i] += str[i*8 + j] * (128 / int(pow(2,j)));
        }


        //写入
        fwrite(strBuf, sizeof(char), nobj, bmp);
}

void DES::cryptography(FILE* fin, FILE* fout, int mode)
//DES加解密函数,bmp为位图图像文件名
{
        char strBuf[8];                 //初始输入的8字节明文
        char plain[64],                 //变换成64位之后的数组
                M_IP[64],               //经过初始置换的明文
                L[17][32], R[17][32],
                E_R[17][32],            //扩展后的Rn
                XOR_kR[17][32],         //与密钥异或后的Rn
                B[8][6], S_B[8][4],     //8个S盒的输入 输出
                S[32],                  //S盒的完整输出
                f[32],                  //f函数经过P置换的结果
                RL[32],                 //交换左右部分的结果
                cipher[64];             //最后的密文输出

        //加密文件 ECB模式
        int nobj = readBMP(fin, strBuf);
        while(nobj > 0){

                //8字节明文strBuf转化为64位的数组plain
                int i = 0;
                for(int j=0; j<8; j++)
                        //每1个字节都转化为8位数组
                        for(int d=128, s=7; s>=0; d=d/2, s--)
                                plain[i++] = (strBuf[j] & d) >> s;

                //明文初始置换IP
                for(i=0; i<64; i++)
                        M_IP[i] = plain[IP[i]];

                //分成左右两部分 得到L0 R0
                for(i=0; i<32; i++){
                        L[0][i] = M_IP[i];
                        R[0][i] = M_IP[i+32];
                }

                //循环16次,用密钥加\解密数据
                for(i=1; i<=16; i++){
                        //Li = Ri-1
                        for(int j=0; j<32; j++)
                                L[i][j] = R[i-1][j];

                        //32位的Ri通过E函数扩展成48位的E_Ri
                        for(int j=0; j<48; j++){
                                E_R[i][j] = R[i-1][E[j]];
                                //cout << int(E_R[i][j]) <<" ";
                        }

                        //用ki(加密时)或k(n-i+1)(解密时)和E_Ri异或得到XOR_kRi
                        if(mode == 0){  //加密
                                for(int j=0; j<48; j++)
                                        XOR_kR[i][j] = subKeys[i][j] ^ E_R[i][j];
                        }
                        else{           //解密
                                for(int j=0; j<48; j++)
                                        XOR_kR[i][j] = subKeys[17-i][j] ^ E_R[i][j];
                        }

                        //8个S盒的变换 每个XOR_kRi分成8快 分别对应8个S盒进行变换 输出到S
                        //----分成8块 B0, B1, ..., B7
                        for(int j=0; j<8; j++){
                                for(int k=0; k<6; k++)
                                        B[j][k] = XOR_kR[i][j*6 + k];
                        }
                        //----S盒变换 循环8次 完成8块的代换
                        for(int j=0; j<8; j++){
                                int Sx, Sy, Sc; //S盒列坐标、行坐标及对应位置的数
                                Sx = B[j][0]*2 + B[j][5];
                                Sy = B[j][1]*8 + B[j][2]*4 + B[j][3]*2 + B[j][4];
                                //确定代换后的数字
                                switch(j)
                                {
                                        case 0: Sc = S1[Sx][Sy]; break;
                                        case 1: Sc = S2[Sx][Sy]; break;
                                        case 2: Sc = S3[Sx][Sy]; break;
                                        case 3: Sc = S4[Sx][Sy]; break;
                                        case 4: Sc = S5[Sx][Sy]; break;
                                        case 5: Sc = S6[Sx][Sy]; break;
                                        case 6: Sc = S7[Sx][Sy]; break;
                                        case 7: Sc = S8[Sx][Sy]; break;
                                }
                                //将S盒中的数字转化为4位16进制数 以数组形式存放于S_B中
                                for(int d=0; d<4; d++){
                                        S_B[j][d] = (Sc & (8 / int(pow(2, d)))) >> (3-d);  //这个式子太过诡异 记得检查......
                                }
                        }
                        //----组合起来
                        for(int j=0; j<8; j++)
                                for(int k=0; k<4; k++)
                                        S[j*4 + k] = S_B[j][k];

                        //P置换
                        for(int j=0; j<32; j++)
                                f[j] = S[P[j]];

                        //终于可以把32位的Ri计算出来了.....
                        for(int j=0; j<32; j++)
                                R[i][j] = L[i-1][j] ^ f[j];

                }//endfor( 16次循环 )

                //将R16和L16组合起来 得到64位的RL
                for(int i=0; i<32; i++){
                        RL[i] = R[16][i];
                        RL[i+32] = L[16][i];
                }

                //下面进行IP的逆置换
                for(int i=0; i<64; i++)
                        cipher[i] = RL[IP_inverse[i]];

                //加密完成,写入文件
                writeBMP(fout, cipher, nobj);

                //读下一段明文
                nobj = readBMP(fin, strBuf);
        }
}

int main()
{
        char bmp[100], outFileName[100]={0};
        int mode;
        FILE *fin, *fout;               //输入、输出文件
        int colorCount;                 //颜色深度
        BITMAPFILEHEADER bfile;         //BMP文件头
        BITMAPINFOHEADER binfo;         //BMP信息头
        RGBQUAD *bquad;                 //索引信息

        //指定要处理的文件 及操作
        cout << "输入待处理的文件名:";
        scanf("%s", bmp);
        cout << "要进行什么操作:\n1.加密\n2.解密\n";
        cin >> mode;
        mode--;

        //产生输出文件名
        if(mode == 0){
                strcat(outFileName, "cipher_");
                strcat(outFileName, bmp);
        }
        else{
                strcat(outFileName, "plain_");
                strcat(outFileName, bmp);
        }

        //处理bmp图像头部信息  读出原始文件中的BMP头部信息,写入待处理的文件中
        fin = fopen(bmp, "rb");         //读写二进制文件
        if( fin ){
                fread(&bfile, sizeof(bfile), 1, fin);   //读取BMP文件头
                fread(&binfo, sizeof(binfo), 1, fin);   //读取BMP信息头
                colorCount = (1 << binfo.biBitCount);   //计算颜色数
                //颜色索引信息
                bquad = (RGBQUAD*)malloc(sizeof(RGBQUAD)*colorCount);
                fread(bquad, sizeof(RGBQUAD), colorCount, fin);

                fout = fopen(outFileName, "wb");        //输出二进制BMP文件
                fwrite(&bfile, sizeof(bfile), 1, fout); //输出BMP文件头
                fwrite(&binfo, sizeof(binfo), 1, fout); //输出BMP文件信息头
                fwrite(bquad, sizeof(RGBQUAD), colorCount, fout);
        }
        else{
                cout << "文件未找到\n" ;
                return -1;
        }

        //产生DES密钥
        char key[10];
        cout << "输入密钥:";
        scanf("%s", key);
        DES picture = DES(key);

        //加密
        cout << "处理中...\n";
        picture.cryptography(fin, fout, mode);
        cout << "处理完成!\n";

        fclose(fin);
        fclose(fout);
        system("pause");
        return 0;
}
//---------------------------------------------------------------------------


⌨️ 快捷键说明

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