DES加密算法实现

时间:2023-03-08 16:38:48
DES加密算法实现

  好久没写博客了,正好趁着实现网络工程与安全的DES算法的功夫,把代码发上来。

  DES的介绍可见:DES加密

  原理不赘述了。。实在太多,其实就是一个形式化算法,按部就班的实现就可以,只不过有些繁琐,我写了3个晚上 = =。

  主要实现了利用DES算法对一个文本文档加密,然后再将其内容解密。

程序截图

  明文和密钥

DES加密算法实现

  加密然后解密

DES加密算法实现

  密文和解密后文本

DES加密算法实现

代码

 //该程序实现了文本文档的DES加密和解密。

 #include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std; //IP置换表
char IP[] = {
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,}; //IP^-1 置换表
char IP_1[] = {
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,}; //扩展置换表E
int E[] = {, , , , , ,
, , , , , ,
, ,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,,,
,,,,, }; //置换函数P
int P[] = {,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,}; //S盒
int S[][][] ={
{{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}, {{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,},
{,,,,,,,,,,,,,,,}}};
//置换选择1
int PC_1[] = {,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,,
,,,,,,}; //置换选择2
int PC_2[] = {,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,}; //对左移次数的规定
int LS[] = {,,,,,,,,,,,,,,,,}; //存放子密钥
unsigned __int64 K[]; //将含64个二进制字符的字符串转换为二进制形式存储在long long int中
unsigned __int64 str2bit(unsigned char s[])
{
unsigned __int64 bin = ;
int i;
for(i=;i<;i++){
bin = bin<< | (s[i]-''); //s[i]>>j & 1 表示取s[i]的第j位
}
return bin;
} //将含8位字符串转换为二进制形式存储在long long int中,例ABCDEFGH转换为64位二进制数
unsigned __int64 bstr2bit(unsigned char s[])
{
unsigned __int64 bin = ;
int i,j;
for(i=;i<;i++){
for(j=;j<;j++){
bin = bin | ( (unsigned __int64)((s[i]>>j)%) << (j+*(-i)) ); //将s[i]的第j位(低位开始)取出放到bin的对应位置
}
}
return bin;
} //将 unsigned __int64 形式的按十六进制串输出(64位有效的二进制数串)
void DisplayHex64(unsigned __int64 bin)
{
int i,t=;
for(i=;i>=;i--){
t = t<< | ((bin>>i) & );
if(i%==){
if(<=t && t<=)
printf("%d",t);
else if(<=t && t<=)
printf("%c",+t-);
t=;
}
if(i%==)
printf(" ");
}
printf("\n");
}
//将 unsigned __int64 形式的按十六进制串输出(48位有效的二进制数串)
void DisplayHex48(unsigned __int64 bin)
{
int i,t=;
for(i=;i>=;i--){
t = t<< | ((bin>>i) & );
if(i%==){
if(<=t && t<=)
printf("%d",t);
else if(<=t && t<=)
printf("%c",+t-);
t=;
}
if(i%==)
printf(" ");
}
printf("\n");
}
//将 unsigned __int64 形式的按十六进制串输出(32位有效的二进制数串)
void DisplayHex32(unsigned __int64 bin)
{
int i,t=;
for(i=;i>=;i--){
t = t<< | ((bin>>i) & );
if(i%==){
if(<=t && t<=)
printf("%d",t);
else if(<=t && t<=)
printf("%c",+t-);
t=;
}
if(i%==)
printf(" ");
}
printf("\n");
}
//将 unsigned __int64 形式的按十六进制串输出(28位有效的二进制数串)
void DisplayHex28(unsigned __int64 bin)
{
int i,t=;
for(i=;i>=;i--){
t = t<< | ((bin>>i) & );
if(i%==){
if(<=t && t<=)
printf("%d",t);
else if(<=t && t<=)
printf("%c",+t-);
t=;
}
if(i%==)
printf(" ");
}
printf("\n");
} //将 unsigned __int64 形式的二进制串和十六进制输出(64位有效的二进制数串)
void DisplayBin64(unsigned __int64 bin)
{
int i;
for(i=;i>=;i--){
printf("%d",(bin>>i) %);
}
printf("\n");
DisplayHex64(bin);
} //将 unsigned __int64 形式的二进制串和十六进制输出(48位有效的二进制数串)
void DisplayBin48(unsigned __int64 bin)
{
int i;
for(i=;i>=;i--){
printf("%d",(bin>>i) %);
}
printf("\n");
DisplayHex48(bin);
} //将 unsigned __int64 形式的二进制串和十六进制输出(32位有效的二进制数串)
void DisplayBin32(unsigned __int64 bin)
{
int i;
for(i=;i>=;i--){
printf("%d",(bin>>i) %);
}
printf("\n");
DisplayHex32(bin);
} //将 unsigned __int64 形式的二进制串和十六进制输出(28位有效的二进制数串)
void DisplayBin28(unsigned __int64 bin)
{
int i;
for(i=;i>=;i--){
printf("%d",(bin>>i) %);
}
printf("\n");
DisplayHex28(bin);
} /* ------------------------------ 【1】初始置换IP ------------------------------
* 把明文顺序打乱重新排列,置换输出为64位,
* 数据置换后的第一位,第二位分别是原来的58、50位
*/ unsigned __int64 InitReplace(unsigned __int64 bin) //初始置换IP
{
unsigned __int64 t = ;
int i;
for(i=;i<;i++){
t = t | ( (bin>>(-IP[i])) %) << (-i);
}
return t;
} /* ------------------------------ 【2】将置换输出的64位数据分成左右两半 ------------------------------
* 左一半称为L0,右一半称为R0,各32位。
*/ void DivideLR(unsigned __int64 binip,unsigned __int64 &L0,unsigned __int64 &R0) //将置换输出的64位数据分为L0(32位),R0(32位)两部分
{
unsigned __int64 one = ;
L0 = binip >> ;
R0 = binip % (one<<);
} /* ------------------------------ 【3】计算函数的16轮迭代 ------------------------------
* 1~16轮加密迭代
*/ //置换选择1,64->56
unsigned __int64 FunPC_1(unsigned __int64 bink)
{
unsigned __int64 binpc_1 = ;
int i;
for(i=;i<;i++)
binpc_1 |= ( (bink>>(-PC_1[i])) %) << (-i);
return binpc_1;
} //获得第i轮C,D,即Ci-1,Di-1 ==> Ci,Di
void getNextCD(int i,unsigned __int64 &C,unsigned __int64 &D)
{
unsigned __int64 t=,one=;
t = C >> (-LS[i]);
C = (C<<LS[i])%(one<<);
C |= t;
t = D >> (-LS[i]);
D = (D<<LS[i])%(one<<);
D |= t;
} //置换选择2,56->48
unsigned __int64 FunPC_2(unsigned __int64 t)
{
//获得子密钥k
unsigned __int64 k=;
int i;
for(i=;i<;i++)
k |= ( (t>>(-PC_2[i])) %) << (-i);
return k;
} //子密钥生成
void ProduceK(unsigned __int64 bink)
{
unsigned __int64 binpc_1,one=,C=,D=;
binpc_1 = FunPC_1(bink); //置换选择1 //分成2个28位
C = binpc_1 >> ;
D = binpc_1 % (one << ); int i;
for(i=;i<=;i++){
//确定子密钥K[i]
getNextCD(i,C,D);
printf("第%d轮:\n",i);
printf("C[%d] = ",i);
DisplayBin28(C);
printf("D[%d] = ",i);
DisplayBin28(D);
printf("\n"); unsigned __int64 t=;
t = ((C<<) | D)%(one<<);
K[i] = FunPC_2(t); //进行置换选择2,将56位->48位子密钥
}
} //扩展置换E,32->48
unsigned __int64 FunE(unsigned __int64 R)
{
unsigned __int64 t = ;
int i;
for(i=;i<;i++)
t |= ( (R>>(-E[i])) %) << (-i);
return t;
} //S盒代换
unsigned __int64 FunS(unsigned __int64 RX)
{
int x,y,i;
unsigned __int64 one = ,t,RS = ;
for(i=;i<;i++){
t = ( RX >> (*(-i)) ) % (one<<);
x = t>>;
x = (x<<) | (t%);
y = (t<<)%(one<<)>>;
RS = RS<< | S[i][x][y];
}
return RS;
} //置换P运算
unsigned __int64 FunP(unsigned __int64 RS)
{
unsigned __int64 RP = ;
int i;
for(i=;i<;i++)
RP |= ( (RS>>(-P[i])) %) << (-i);
return RP;
} //轮函数f(R,K)
unsigned __int64 f(int i,unsigned __int64 R,unsigned __int64 k)
{
unsigned __int64 RE,RX,RS,RP;
RE = FunE(R); //将32位Ri-1扩展置换为48位
RX = RE ^ k; //将48位RE与子密钥k异或运算
RS = FunS(RX); //S盒代换
RP = FunP(RS); //置换P运算
return RP;
} unsigned __int64 Iteration16(unsigned __int64 L0,unsigned __int64 R0) //进行16次迭代计算
{
int i;
unsigned __int64 Ri = R0;
unsigned __int64 Li = L0;
printf("L0=");
DisplayBin32(L0);
printf("R0=");
DisplayBin32(R0);
printf("\n");
for(i=;i<=;i++){
printf("第%d轮加密:\n",i);
unsigned __int64 t = Ri; //轮函数
Ri = f(i,Ri,K[i]);
printf("f(R%d,K%d)=",i-,i);
DisplayBin32(Ri); //Li-1和轮函数结果异或运算得到Ri
Ri = Li ^ Ri;
//轮函数运算结果即是Li
Li = t; //输出Li和Ri
printf("L%d=",i);
DisplayBin32(Li);
printf("R%d=",i);
DisplayBin32(Ri);
printf("\n");
} return Ri<< | Li;
} unsigned __int64 InverseIteration16(unsigned __int64 L0,unsigned __int64 R0) //进行逆16次迭代计算,为解密过程
{
int i;
unsigned __int64 Ri = R0;
unsigned __int64 Li = L0;
printf("L0=");
DisplayBin32(L0);
printf("R0=");
DisplayBin32(R0);
printf("\n");
for(i=;i>=;i--){
printf("第%d轮加密:\n",-i);
unsigned __int64 t = Ri; //轮函数
Ri = f(i,Ri,K[i]);
printf("f(R%d,K%d)=",i-,i);
DisplayBin32(Ri); //Li-1和轮函数结果异或运算得到Ri
Ri = Li ^ Ri;
//轮函数运算结果即是Li
Li = t; //输出Li和Ri
printf("L%d=",i);
DisplayBin32(Li);
printf("R%d=",i);
DisplayBin32(Ri);
printf("\n");
} return Ri<< | Li;
} /* ------------------------------ 【4】逆初始置换IP^-1 ------------------------------
* 把数据打乱重排,产生64位密文。
*/ unsigned __int64 InverseInitReplace(unsigned __int64 bin) //进行逆初始置换IP^-1
{
unsigned __int64 t = ;
int i;
for(i=;i<;i++){
t = t | ( (bin>>(-IP_1[i])) %) << (-i);
}
return t;
} void printOut(FILE* fo,unsigned __int64 bin)
{
char ans[]={},t=;
int i,cnt=;
for(i=;i>=;i--){
t = t<< | ((bin>>i)%);
if(i%==){
ans[cnt++] = t;
t = ;
}
}
fwrite(ans,,,fo);
} //加密函数
void Encryption()
{
//文件读入
FILE* fm = fopen(".\\Plaintext.txt","rb"); //明文文件
FILE* fk = fopen(".\\key.txt","r"); //密钥文件
FILE* fo = fopen(".\\Ciphertext.txt","wb"); //密文文件 if(fm==NULL){
printf("明文文件input.txt打开失败\n");
}
if(fk==NULL){
printf("密钥文件key.txt打开失败\n");
}
if(fo==NULL){
printf("加密后文件output.txt打开失败\n");
} unsigned char s[]={},key[]={};
int i; fscanf(fk,"%s",key); //读取密钥 while(fread(s,,,fm)){
printf("----------------------------------------------------------------------------\n");
printf("\n");
printf("当前读取的明文串为:\n");
printf("%s\n",s);
unsigned __int64 bin = bstr2bit(s); //将加密串转换为2进制形式
printf("\n");
unsigned __int64 bink = str2bit(key); //将密钥串转换为2进制形式
printf("\n"); //输出
printf("\n");
printf("【输入】\n");
printf("输入的二进制明文串:\n");
DisplayBin64(bin);
printf("输入的二进制密钥串:\n");
DisplayBin64(bink);
printf("\n"); //IP置换
printf("明文初始化置换后:\n");
unsigned __int64 binip = InitReplace(bin);
DisplayBin64(binip);
printf("\n"); //获得L0,R0
printf("将明文分割为L0,R0两部分:\n");
unsigned __int64 L0,R0;
DivideLR(binip,L0,R0); //将binip分割为L0和R0
//输出L0,R0
printf("L0为:");
DisplayBin32(L0);
printf("R0为:");
DisplayBin32(R0);
printf("\n"); //生成16个子密钥,并输出
printf("--------------- 子密钥生成过程 ---------------\n");
memset(K,,sizeof(K));
ProduceK(bink);
printf("生成的16个子密钥:\n");
for(i=;i<=;i++){
printf("K[%d]为 ",i);
DisplayBin48(K[i]);
//printf("\n");
}
printf("\n"); //16次加密迭代
printf("--------------- 16轮加密迭代 --------------- \n");
unsigned __int64 binIter = Iteration16(L0,R0);
printf("迭代加密后的结果:\n");
DisplayBin64(binIter);
printf("\n"); //逆初始置换IP_1
unsigned __int64 binip_1 = InverseInitReplace(binIter);
printf("最后,逆初始置换:\n");
DisplayBin64(binip_1);
printf("\n"); //输出最终加密结果
printf("【加密结果】\n明文 \"%s\" 的DES加密的结果为:\n",s);
DisplayBin64(binip_1); printf("\n");
printf("----------------------------------------------------------------------------\n");
printf("\n"); //将加密结果写到加密文件中
printOut(fo,binip_1); memset(s,,sizeof(s));
}
//文件关闭
fclose(fm);
fclose(fk);
fclose(fo);
} //解密函数
void Decryption()
{
//文件读入
FILE* fm = fopen(".\\Ciphertext.txt","rb"); //密文文件
FILE* fk = fopen(".\\key.txt","r"); //密钥文件
FILE* fo = fopen(".\\DecrypPlaintext.txt","wb"); //解密后文件 if(fm==NULL){
printf("密文文件 Ciphertext.txt 打开失败\n");
}
if(fk==NULL){
printf("密钥文件 key.txt 打开失败\n");
}
if(fo==NULL){
printf("解密后文件 DecrypPlaintext.txt 打开失败\n");
} unsigned char s[]={},key[]={};
int i; fscanf(fk,"%s",key); //读取密钥 while(fread(s,,,fm)){
printf("----------------------------------------------------------------------------\n");
printf("\n");
printf("当前读取的密文串为:\n");
printf("%s\n",s);
unsigned __int64 bin = bstr2bit(s); //将密文串转换为2进制形式
printf("\n");
unsigned __int64 bink = str2bit(key); //将密钥串转换为2进制形式
printf("\n"); //输出
printf("----------------------------------------------------------------------------\n");
printf("\n");
printf("【输入】\n");
printf("输入的二进制密文串:\n");
DisplayBin64(bin);
printf("输入的二进制密钥串:\n");
DisplayBin64(bink);
printf("\n"); //IP置换
printf("密文初始化置换后:\n");
unsigned __int64 binip = InitReplace(bin);
DisplayBin64(binip);
printf("\n"); //获得L0,R0
printf("将密文分割为L0,R0两部分:\n");
unsigned __int64 L0,R0;
DivideLR(binip,L0,R0); //将binip分割为L0和R0
//输出L0,R0
printf("L0为:");
DisplayBin32(L0);
printf("R0为:");
DisplayBin32(R0);
printf("\n"); //生成16个子密钥,并输出
printf("--------------- 子密钥生成过程 ---------------\n");
memset(K,,sizeof(K));
ProduceK(bink);
printf("生成的16个子密钥:\n");
for(i=;i<=;i++){
printf("K[%d]为 ",i);
DisplayBin48(K[i]);
//printf("\n");
}
printf("\n"); //16次加密迭代
printf("--------------- 16轮加密迭代 --------------- \n");
unsigned __int64 binIter = InverseIteration16(L0,R0);
printf("迭代解密后的结果:\n");
DisplayBin64(binIter);
printf("\n"); //逆初始置换IP_1
unsigned __int64 binip_1 = InverseInitReplace(binIter);
printf("最后,逆初始置换:\n");
DisplayBin64(binip_1);
printf("\n"); //输出最终加密结果
printf("【解密结果】\n密文 \"%s\" 的DES解密的结果为:\n",s);
DisplayBin64(binip_1); printf("\n");
printf("----------------------------------------------------------------------------\n"); //将加密结果写到加密文件中
printOut(fo,binip_1); memset(s,,sizeof(s));
}
//文件关闭
fclose(fm);
fclose(fk);
fclose(fo);
} int Menu(int &Case)
{
int in; FILE* fk = fopen(".\\key.txt","r"); //密钥文件
if(fk==NULL){
printf("密钥文件key.txt打开失败\n");
} unsigned char key[];
fscanf(fk,"%s",key); //读取密钥
unsigned __int64 bink = str2bit(key); //将密钥串转换为2进制形式
printf("【%d】当前密钥(key)为:(二进制形式)\n",Case++);
DisplayBin64(bink);
printf("(密钥存储在 key.txt 中)\n");
printf("\n"); printf("请选择,是使用DES算法加密还是解密?\n");
printf("(加密过程:Plaintext.txt => Ciphertext.txt\n");
printf(" 解密过程:Ciphertext.txt => DecrypPlaintext.txt )\n");
printf("[1] 加密\n");
printf("[2] 解密\n");
printf("[0] 退出程序\n"); scanf("%d",&in);
getchar();
fflush(stdin); // 清空缓冲区 if(in== || in== || in==){
return in;
}
else{
printf("输入错误,请重新输入!\n");
printf("\n");
printf("----------------------------------------------------------------------------\n");
printf("\n");
return -;
}
} /*
* 主函数
*/
int main()
{
int Case=,in;
while(){
in = Menu(Case);
switch(in){
case -: //输入错误,进入下次循环
break;
case : //退出程序
printf("谢谢使用 :)\n");
return ;
case : //加密
Encryption();
break;
case : //解密
Decryption();
break;
}
}
return ;
}

Freecode : www.cnblogs.com/yym2013