第3章
DES和RSA 加密算法的
程序实现 
3.1 实验目的 
. 掌握密码学的基本概念、对称密钥加密和公钥加密技术。
. 掌握DES算法的原理,用程序实现。
. 掌握RSA 算法的原理,用程序实现。
. 比较DES和RSA 算法,理解这两种加密方式。 
3.2 实验环境 
实验主机操作系统为Windows7,安装VS编译器。 
3.3 实验工具 
. VisualStudio:MicrosoftVisualStudio是VS的全称。VS是美国微软公司的开
发工具包系列产品。VS是一个基本完整的开发工具集,它包括了整个软件生命
周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE) 
等。所写的目标代码适用于微软支持的所有平台。
. 也可以使用其他工具。 
3.4 实验内容 
3.4.1 实验原理
1. 密码学概述 
密码是实现秘密通信的主要手段,是隐蔽语言、文字、图像的特种符号。用特种符号

第3章 DES和RSA加密算法的程序实现 
按照通信双方约定的方法把电文的原形隐蔽起来,不为第三者所识别的通信方式称为密
码通信。在计算机通信中,采用密码技术将信息隐蔽起来,再将隐蔽后的信息传输出去, 
信息在传输过程中即使被窃取或截获,窃取者也不能了解信息的内容,从而保证信息传输
的安全。
任何一个加密系统至少包括下面4个组成部分。
① 未加密的报文,也称明文。
② 加密后的报文,也称密文。
③ 加密解密设备或算法。
④ 加密解密的密钥。
发送方用加密密钥,通过加密设备或算法,将信息加密后发送出去。接收方在收到密
文后,用解密密钥将密文解密,恢复成明文。如果传输中有人窃取,他只能得到无法理解
的密文,从而对信息起到保密作用。
2. DES 对称加密技术
基于密钥的算法通常有两类:对称算法和公开密钥算法。在大多数对称算法中,加
解密的密钥是相同的。对称算法要求发送者和接收者在安全通信之前协商一个密钥。对
称算法的安全性依赖于密钥,泄露密钥就意味着任何人都能对消息进行加密。
DES是DataEncryptionStandard(数据加密标准)的缩写。它是由IBM 公司研制的
一种对称密码算法,美国国家标准局于1977年公布把它作为非机要部门使用的数据加密
标准。DES一直活跃在国际保密通信的舞台上,扮演了十分重要的角色。
DES是一个分组加密算法,典型的DES以64位为分组对数据加密,加密和解密用的
是同一个算法。它的密钥长度是56位(因为每个第8位都用作奇偶校验),密钥可以是任
意的56位的数,而且可以随时改变。其中有极少数被认为是易破解的弱密钥,但是很容
易避开它们不用,所以保密性依赖于密钥。
(1)DES加密算法的框架
首先要生成一套加密密钥,从用户处取得一个64位长的密码口令,然后通过等分、移
位、选取和迭代形成一套16个加密密钥,分别供每一轮运算中使用。
DES对64位(bit)的明文分组M 进行操作,M 经过一个初始置换IP,置换成m0。将
m0 明文分成左半部分和右半部分m0= (L0,R0),各32位长。然后进行16轮完全相同
的运算(迭代),这些运算被称为函数f,在每一轮运算过程中数据与相应的密钥结合。
在每一轮中,密钥位移位,然后再从密钥的56位中选出48位。通过一个扩展置换将
数据的右半部分扩展成48位,并通过一个异或操作替代成新的48位数据,再将其压缩置
换成32位。这4步运算构成了函数f。然后,通过另一个异或运算,函数f 的输出与左
半部分结合,其结果成为新的右半部分,原来的右半部分成为新的左半部分。将该操作重
复16次。
经过16轮迭代后,左、右两半部分合在一起经过一个末置换(数据整理),这样就完成
了加密过程。
加密流程如图3-1所示。
23

网络空间安全综合实验教程
图3-1 加密流程
(2)DES解密过程
了解加密过程中所有的代替、置换、异或和循环
迭代之后,读者也许会认为,解密算法应该是加密的
逆运算,与加密算法完全不同。恰恰相反,经过密码
学家精心设计选择的各种操作,DES获得了一个非
常有用的性质:加密和解密使用相同的算法。
DES加密和解密唯一的不同是密钥的次序相
反。如果各轮加密密钥分别是K1,K2,K3,…,K16, 
那么解密密钥就是K16,K15,K14,…,K1。
3. RSA 公钥加密技术
公开密钥密码体制就是使用不同的加密密钥与
解密密钥,RSA 公开加密密钥体制是一种基于大数
不可能质因数分解假设的公钥体系,在公开密钥密码
体制中,加密密钥PK是公开信息,而解密密钥SK是
需要保密的。加密算法E 和解密算法D 也是公开
的。虽然秘密密钥SK 是由公开密钥PK 决定的,但
却不能根据PK计算出SK。
RSA 体制可以简单描述如下。
① 生成两个大素数p 和q。
② 计算这两个素数的乘积n=pq。
③ 计算小于n 并且与n 互质的整数的个数,即φ(n)=(p-1)(q-1)。
④ 选择一个随机数b 满足1<b<φ(n),并且b 和φ(n)互质,即gcd(b,φ(n))=1。
⑤ 计算ab=1modφ(n)。
⑥ 保密a、p 和q,公开n 和b。
利用RSA 加密时,明文以分组的方式加密:每一组的比特数应该小于log2n 比特。
加密明文x 时,利用公钥(b,n)来计算c=xb modn 就可以得到相应的密文c。解密时, 
通过计算ca modn 就可以恢复出明文x。
3.4.2 实验步骤
1. 实验1———DES 算法的程序实现 
#include"memory.h" 
#include"stdio.h" 
enum{ENCRYPT,DECRYPT}; //ENCRYPT:加密,DECRYPT:解密
void Des_Run(char Out[8], char In[8], bool Type =ENCRYPT); 
//设置密钥
void Des_SetKey(const char Key[8]); 
static void F_func(bool In[32], const bool Ki[48]); //f 函数
24

第3章 DES和RSA加密算法的程序实现 
static void S_func(bool Out[32], const bool In[48]); //S 盒代替
//变换
static void Transform(bool *Out, bool *In, const char *Table, int len); 
static void Xor(bool *InA, const bool *InB, int len); //异或
static void RotateL(bool *In, int len, int lool); //循环左移
//字节组转换为位组
static void ByteToBit(bool *Out, const char * In, int bits); 
//位组转换成字节组
static void BitToByte(char*Out, const bool *In, int bits); 
//置换IP 表
const static char IP_Table[64] ={ 
58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4, 
62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8, 
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 
}; 
//逆置换IP 表
const static char IPR_Table[64] ={ 
40,8,48,16,5624,64,32,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 
}; 
//E 位选择表
const static char E_Table[48] ={ 
32,1,2,3,4,5,4,5,6,7,8,9, 
8,9,10,11,12,13,12,13,14,15,16,17, 
16,17,18,19,20,21,20,21,22,23,24,25, 
24,25,26,27,28,29,28,29,30,31,32,1 
}; 
//P 换位表
const static char P_Table[32] ={ 
16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10, 
2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25 
}; 
//PC1 选位表
const static char PC1_Table[56] ={ 
57,49,41,33,25,17,9,1,58,50,42,34,26,18, 
10,2,59,51,43,35,27,19,11,3,60,52,44,36, 
63,55,47,39,31,23,15,7,62,54,46,38,30,22, 
14,6,61,53,45,37,29,21,13,5,28,20,12,4 
}; 
//PC2 选位表
const static char PC2_Table[48] ={ 
25

网络空间安全综合实验教程 
14,17,11,24,1,5,3,28,15,6,21,10, 
23,19,12,4,26,8,16,7,27,20,13,2, 
41,52,31,37,47,55,30,40,51,45,33,48, 
44,49,39,56,34,53,46,42,50,36,29,32 
}; 
//左移位数表
const static char LOOP_Table[16] ={ 
1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 
}; 
//S 盒
const static char S_Box[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, 
26

第3章 DES和RSA加密算法的程序实现 
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 
}; 
static bool SubKey[16][48]; 
void Des_Run(char Out[8], char In[8], bool Type) { 
static bool M[64], Tmp[32], *Li =&M[0], *Ri =&M[32]; 
ByteToBit(M, In, 64); 
Transform(M, M, IP_Table, 64); 
if (Type ==ENCRYPT) { 
for (int i =0; i <16; i++) { 
memcpy(Tmp, Ri, 32); 
F_func(Ri, SubKey[i]); 
Xor(Ri, Li, 32); 
memcpy(Li, Tmp, 32); 
} 
} 
else { 
for (int i =15; i >=0; i--) { 
memcpy(Tmp, Li, 32); 
F_func(Li, SubKey[i]); 
Xor(Li, Ri, 32); 
memcpy(Ri, Tmp, 32); 
} 
} 
Transform(M, M, IPR_Table, 64); 
BitToByte(Out, M, 64); 
}v
oid Des_SetKey(const char Key[8]) { 
static bool K[64], *KL =&K[0], *KR =&K[28]; 
ByteToBit(K, Key, 64); 
Transform(K, K, PC1_Table, 56); 
for (int i =0; i <16; i++) { 
RotateL(KL, 28, LOOP_Table[i]); 
RotateL(KR, 28, LOOP_Table[i]); 
} 
}v
oid F_func(bool In[32], const bool Ki[48]) { 
static bool MR[48]; 
Transform(MR, In, E_Table, 48); 
27

网络空间安全综合实验教程 
Xor(MR, Ki, 48); 
S_func(In, MR); 
Transform(In, In, P_Table, 32); 
}v
oid S_func(bool Out[32], const bool In[48]) { 
for (char i =0, j, k; i <8; i++, In +=6, Out +=4) { 
j =(In[0] <<1) +In[5]; 
k =(In[1] <<3) +(In[2] <<2) +(In[3] <<1) +In[4]; 
ByteToBit(Out, &S_Box[i][j][k], 4); 
} 
}v
oid Transform(bool *Out, bool *In, const char *Table, int len) { 
static bool Tmp[256]; 
for (int i =0; i <len; i++) 
Tmp[i] =In[Table[i] -1]; 
memcpy(Out, Tmp, len); 
}v
oid Xor(bool *InA, const bool *InB, int len) { 
for (int i =0; i <len; i++) { 
InA[i] ^=InB[i]; 
} 
}v
oid RotateL(bool *In, int len, int loop) 
{ 
static bool Tmp[256]; 
memcpy(Tmp, In, loop); 
memcpy(In, In +loop, len -loop); 
memcpy(In +len -loop, Tmp, loop); 
}v
oid ByteToBit(bool *Out, const char *In, int bits) { 
for (int i =0; i <bits; i++) 
Out[i] =(In[i / 8] >>(i %8)) & 1; 
}v
oid BitToByte(char *Out, const bool *In, int bits) { 
memset(Out, 0, (bits +7) / 8); 
for (int i =0; i <bits; i++) 
Out[i / 8] |=In[i] <<(i %8); 
}
int main() 
{ 
char key[8] ={ 1,9,8,0,9,1,7,2 }, str[] ="test"; 
puts("Before encrypting"); 
puts(str); 
28

第3章 DES和RSA加密算法的程序实现 
Des_SetKey(key); 
Des_Run(str, str, ENCRYPT); 
puts("After encrypting"); 
puts(str); 
puts("After decrypting"); 
Des_Run(str, str, DECRYPT); 
puts(str); 
return 0; 
}
运行结果如图3-2所示。
图3-2 第3章实验1运行结果
2. 实验2———RSA 算法的程序实现 
#include<iostream> 
#include<cmath> 
#include<cstring> 
#include<ctime> 
#include<cstdlib> 
using namespace std; 
int Plaintext[100]; //明文
long long Ciphertext[100]; //密文
int n, e =0, d; 
//二进制转换
int BianaryTransform(int num, int bin_num[]) 
{ 
int i =0, mod =0; 
//转换为二进制,逆向暂存temp[]数组中 
while(num !=0) 
{ 
mod =num%2; 
bin_num[i] =mod; 
num =num/2; 
i++; 
} 
29

网络空间安全综合实验教程 
//返回二进制数的位数 
return i; 
} //反复平方求幂
long long Modular_Exonentiation(long long a, int b, int n) 
{ 
int c =0, bin_num[1000]; 
long long d =1; 
int k =BianaryTransform(b, bin_num)-1; 
for(int i =k; i >=0; i--) 
{ 
c =2*c; 
d =(d*d)%n; 
if(bin_num[i] ==1) 
{ 
c =c +1; 
d =(d*a)%n; 
} 
} 
return d; 
}
//生成1000 以内的素数
int ProducePrimeNumber(int prime[]) 
{ 
int c =0, vis[1001]; 
memset(vis, 0, sizeof(vis)); 
for(int i =2; i <=1000; i++)if(!vis[i]) 
{ 
prime[c++] =i; 
for(int j =i*i; j <=1000; j+=i) 
vis[j] =1; 
} 
return c; 
}
//欧几里得扩展算法
int Exgcd(int m,int n,int &x) 
{ 
int x1,y1,x0,y0, y; 
x0=1; y0=0; 
x1=0; y1=1; 
x=0; y=1; 
int r=m%n; 
30

第3章 DES和RSA加密算法的程序实现 
int q=(m-r)/n; 
while(r) 
{ 
x=x0-q*x1; y=y0-q*y1; 
x0=x1; y0=y1; 
x1=x; y1=y; 
m=n; n=r; r=m%n; 
q=(m-r)/n; 
} 
return n; 
}
//RSA 初始化
void RSA_Initialize() 
{ 
//取出1000 内素数保存在prime[]数组中 
int prime[5000]; 
int count_Prime =ProducePrimeNumber(prime); 
//随机取两个素数p,q 
srand((unsigned)time(NULL)); 
int ranNum1 =rand()%count_Prime; 
int ranNum2 =rand()%count_Prime; 
int p =prime[ranNum1], q =prime[ranNum2]; 
n =p*q; 
int On =(p-1)*(q-1); 
//用欧几里得扩展算法求e,d 
for(int j =3; j <On; j+=1331) 
{ 
int gcd =Exgcd(j, On, d); 
if( gcd ==1 && d >0) 
{ 
e =j; 
break; 
} 
} 
}
//RSA 加密
void RSA_Encrypt() 
{ 
cout<<"Public Key (e, n) : e ="<<e<<" n ="<<n<<'\n'; 
cout<<"Private Key (d, n) : d ="<<d<<" n ="<<n<<'\n'<<'\n'; 
int i =0; 
31

网络空间安全综合实验教程 
for(i =0; i <100; i++) 
Ciphertext[i] =Modular_Exonentiation(Plaintext[i], e, n); 
cout<<"Use the public key (e, n) to encrypt:"<<'\n'; 
for(i =0; i <100; i++) 
cout<<Ciphertext[i]<<" "; 
cout<<'\n'<<'\n'; 
}
//RSA 解密
void RSA_Decrypt() 
{ 
int i =0; 
for(i =0; i <100; i++) 
Ciphertext[i] =Modular_Exonentiation(Ciphertext[i], d, n); 
cout<<"Use private key (d, n) to decrypt:"<<'\n'; 
for(i =0; i <100; i++) 
cout<<Ciphertext[i]<<" "; 
cout<<'\n'<<'\n'; 
}
//算法初始化
void Initialize() 
{ 
int i; 
srand((unsigned)time(NULL)); 
for(i =0; i <100; i++) 
Plaintext[i] =rand()%1000; 
cout<<"Generate 100 random numbers:"<<'\n'; 
for(i =0; i <100; i++) 
cout<<Plaintext[i]<<" "; 
cout<<'\n'<<'\n'; 
}
int main() 
{ 
Initialize(); 
while(!e) 
RSA_Initialize(); 
RSA_Encrypt(); 
RSA_Decrypt(); 
return 0; 
}
运行结果如图3-3所示。
32

第3章 DES和RSA加密算法的程序实现 
图3-3 第3章实验2运行结果 
3.5 实验结果分析与总结 
1. 实验1———DES 算法的程序实现
设置一个密钥为数组charkey[8]= {1,9,8,0,9,1,7,2},要加密的字符串数组为
“test”,利用Des_SetKey(key)设置加密的密钥,调用Des_Run()对输入的明文进行加密, 
其中,第一个参数str是输出的密文,第二个参数str是输入的明文,枚举值ENCRYPT 
设置进行加密运算。
2. 实验2———RSA 算法的程序实现
RSA 是一种非对称加密算法,在公开密钥和电子商业中被广泛使用。它基于一个很
简单的数论事实,两个素数相乘很容易,对两素数乘积因式分解很困难。 
3.6 思考题 
假设需要加密的明文信息为m =85,选择:e=7,p=11,q=13,说明使用RSA 算法
的加密和解密过程。
解析: 
n=pq=11×13=143, 
φ(n)=(p-1)(q-1)=(11-1)×(13-1)=120, 
根据ed≡1modφ(n), 
又有7d mod120=1, 
33

网络空间安全综合实验教程
得出d=103, 
公钥为(e,n)=(7,143), 
加密公式为c=m^e modn, 
根据公钥加密明文m 计算得出C=85^7mod143=123, 
私钥为(d,n)=(103,143), 
解密公式为m =c^d modn, 
根据私钥解密C 计算得出m =123^103mod143=85。
根据上述过程理解RSA 算法的流程。 
3.7 练习 
(1)就目前计算机设备的计算能力而言,数据加密标准(DES)不能抵抗对密钥的穷
举搜索攻击,其原因是( )。(答案:B) 
A . DE S 算 法 是 公 开 的 
B.DES的密钥较短
C.DES除了其中S盒是非线性变换外,其余变换均为线性变换
D.DES算法简单
解析:DES所使用的密钥是64位,实际用到了56位,第8、16、24、32、40、48、56、64 
位是校验位,使得每个密钥都有奇数个1。
(2)密码技术的分类有很多种,根据加密和解密所使用的密钥是否相同,可以将加密
算法分为对称密码体制和(非对称密码体制),其中,对称密码体制又可分为两类,按字符
逐位加密的(序列密码)和按固定数据块大小加密的(分组密码)。
(3)为了保障数据的存储和传输安全,需要对一些重要数据进行加密。由于对称密
码算法( ① ),所以特别适合对大量的数据进行加密。DES 实际的密钥长度是
( ② )位。(答案:①C ②A) 
① A.比非对称密码算法更安全
B.比非对称密码算法密钥长度更长
C.比非对称密码算法效率更高
D.还能同时用于身份认证
② A.56 B.64 C.128 D.256 
(4)以下不属于对称密码算法的是( )。(答案:D) 
A.IDEA B.RC C.DES D.RSA 
(5)密码系统的安全性取决于用户对于密钥的保护,实际应用中的密钥种类有很多, 
从密钥管理的角度可以分为(初始密钥)、(会话密钥)、密钥加密密钥和(主密钥)。
34