📄 des_ecbmode.cpp
字号:
}
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 + -