基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业


前言:由于今年疫情影响,保研夏令营都改为了线上模式,我有幸参加了西工大网安学院的夏令营,并拿到了优秀营员,考核形式为一周时间内编程实现大作业(无面试),因此分享一下当时写的大作业,希望对大家有所帮助。

一、设计内容

编写一段程序,实现两个主机之间的**分发和加密传输。
要求:
(1)用RSA算法实现两个主机之间的**分发,分发的**是“12345678”;(2)用分发的**和AES加密算法,实现两个主机之间的加密数据传输,传输的数据是“NPU”;
(3)两个步骤在程序中自动执行完,无手动参与;程序可以在同一台主机上完成,但数据必须经过网络传输(可以本地发送,本地接收);
(4)RSA和AES算法必须是源码编译得到,不能用编译过的库文件;RSA和AES算法的源码可以来自于网络或其他任意渠道;
(5)用python或C/C++语言实现程序,写出实现技术文档。

二、基本思路实现

(1)通过编写客户端程序和服务器程序,利用windows下的socket套接字来实现同一台主机上客户端与服务器进程之间数据的网络传输,用来实现**的分发和数据的加密传输。
(2)**的传输基于RSA算法实现,由服务器根据RSA算法生成公钥和私钥,然后将公钥传输给客户端,由客户端根据公钥负责将AES加密算法的**进行加密传给服务器,服务器根据自己的私钥和RSA算法进行解密处理,得到AES的**。由于RSA是非对称加密算法,因此即使攻击者截取到了加密的数据和公钥,也会因为没有私钥而无法解密,保证了**的安全传输。
(3)数据之间的传输基于AES算法实现,由客户端根据先前的**和AES算法对数据实现加密传输,再在服务器端根据计算得到的AES**对数据进行解密处理,从而得到最终的数据。

三、设计原理与流程

**分发和加密传输总体流程图如下:
基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业

3.1. 建立socket套接字连接

3.1.1建立socket连接原理:

在网络中,要全局的标识一个参与通信的进程,需要三元组:协议,IP地址以及端口号。要描述两个应用进程之间的端到端的通信关联需要五元组:协议,信源主机IP,信源应用进程端口,信宿主机IP,信宿应用进程端口。为了实现两个应用进程的通信连接,提出了套接字的概念。套接字可以理解为通信连接的一端,将两个套接字连接在一起,可以实现不同进程之间的通信。
在本程序中,首先通过socket函数分别为客户端和服务器创建套接字,然后定义家族协议、主机地址和主机端口等,得到socket嵌套字,通过bind函数在服务器端将套接字地址与所创建的套接字号连接起来,设定套接字为监听状态,准备接收由客户端进程发出的连接请求。客户端提出与服务器建立连接的请求,如果服务器进程接受请求,则服务器进程与客户机进城之间便建立了一条通信连接,之后便可以通过recv函数和send函数分别实现在已建立的套接字上接收和发送数据,实现同一台主机下数据之间的网络传输。

3.1.2建立socket连接的流程图如下:

基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业

3.2. RSA算法实现**加密分发

3.2.1 RSA算法加密原理:

在对称加密体系中,由于对称加密的加密和解密使用的是同一个**,所以对称加密的安全性就不仅仅取决于加密算法本身的强度,更取决于**是否被安全的保管,因此加密者如何把**安全的传递到解密者手里,就成了对称加密面临的关键问题。比如,我们客户端肯定不能直接存储对称加密的**,因为被反编译之后,**就泄露了,数据安全性就得不到保障,所以实际中我们一般都是客户端向服务端请求对称加密的**,而且**还得用非对称加密算法加密后再传输。由于RSA算法是非对称加密算法,因此RSA算法便可以解决**的分发传输问题。
在RSA算法中,先由服务器生成一对RSA**,其中之一是保***,由用户保存,另一个则为公开**,可对外公开。当客户端想向服务器发送消息时,便通过公开的**对数据进行加密传输,在服务器端根据私钥便可以实现对加密数据的解密。
在本程序中,RSA算法的步骤如下:
1.由服务器端先随机选择两个不相等的质数p和q,选择的质数越大,则越难**;然后计算p和q的乘积n,n的长度即为**长度,在实际应用中,RSA的**一般为1024位;
2.计算n的欧拉函数φ(n)=(p-1)*(q-1),随机选择一个整数e,条件是1< e < φ(n),且e与φ(n)互质;
3. 计算e对于φ(n)的模反元素d,所谓“模反元素”就是指有一个整数d,可以使得ed被φ(n)除的余数为1。
ed ≡ 1 (mod φ(n)),即 ed – 1 = k φ(n)
通过扩展欧几里得算法求解得到d的值作为私钥的一部分。
4.将n和e封装成公钥,n和d封装成私钥,将公钥通过网络传输给客户端,实现RSA**的分发,客户端得到RSA公钥后,对AES的**进行加密传输给服务器端,即用公钥(n,e)算出m^e≡c (mod n)中c的值;服务器利用私钥解密得到AES的**,同样也是利用m^e≡c (mod n)算出c的值即为AES的**。

3.2.2 RSA算法加密流程图:

基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业

3.3. AES算法实现数据加密传输

3.3.1 AES算法加密原理:

AES算法(高级加密标准,Advanced Encryption Standard),即Rij-ndael 算法,是一个对称分组密码算法。数据分组长度必须是128 bits,使用的**长度为128,192或256 bits。对于三种不同**长度的 AES 算法,分别称为“AES-128”、“AES-192”、“AES-256”。
在本程序中采用的是AES-128标准,CBC加密模式。在该标准中,**长度必须为128位,也就是16字节;AES是分组密码,也就是将需要加密的明文分成组,每个分组的长度为128位,同样是16个字节,如果最后一段或者**长度不够16个字节,就需要用Padding来把这段数据填满16个字节,然后分别对每段数据进行加密,最后再把每段加密数据拼起来形成最终的密文。
Padding用来把不满16个字节的分组数据填满16个字节,有三种模式PKCS5、PKCS7和NOPADDING。PKCS5是指分组数据缺少几个字节,就在数据的末尾填充几个字节的几,比如缺少5个字节,就在末尾填充5个字节的5。PKCS7是指分组数据缺少几个字节,就在数据的末尾填充几个字节的0,比如缺少7个字节,就在末尾填充7个字节的0。NoPadding是指不需要填充,也就是说数据的发送方肯定会保证最后一段数据也正好是16个字节。解密端需要使用和加密端同样的Padding模式,才能准确的识别有效数据和填充数据。一般采用在末尾填充0的方式。
在AES加密过程的步骤如下:
1.首先AES加密会把明文按128位16字节切成一段一段的数据,如果数据的最后不够16个字节,则用Padding进行填充;
2.对**进行**扩展,所谓**扩展,就是根据初始**生成后面的10轮**的操作,在AES-128标准中,一共会对每一组明文进行11轮加密,所以AES会通过一个简单快速的混合操作,根据初始**依次生成后面10轮的**,每一轮的**都是依据上面一轮生成的,在这种模式下,每一轮的**都作为下一轮**的输入对明文进行异或运算,具体过程如下图所示:

基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业
3.初始轮:将128位的明文数据与128位的初始**进行异或操作;
4.重复轮:将字节混淆、行移位、列混轮、加轮**这四个操作重复执行九轮;
将初始轮得到的状态矩阵经过一个置换盒,会输出一个新的矩阵,我们这里叫它为字节混淆矩阵
对字节混淆矩阵进行行移位,每一行分别向左挪0、1、2、3个字节,然后重新放一下字节,这样行移位就算完成,得到的新矩阵称之为行移位矩阵
然后用模不可约多项式将每列混乱,得到一个新的矩阵,我们称之为列混乱矩阵
基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业
在每一轮结束的时候,我们需要把列混乱矩阵和下一轮的**做一下异或操作,得到一个新的矩阵,我们这里称之为加轮秘钥矩阵;
128位**重复轮重复执行9次:上一轮的加轮**矩阵就是下一轮的状态矩阵,拿着这个新的状态矩阵返回去,重复执行字节混淆、行移位、列混乱、加轮**这四个操作9次,就会进入加密的最终轮了。
5.最终轮:和重复轮的操作差不多,只是在最终轮我们丢弃了列混乱这个操作,因为我们不会再有下一轮了,所以没必要再进行列混乱,再进行的话也加强不了安全性了,只会白白的浪费时间、拖延加密效率。最终轮结束后,我们就算完成了一次AES加密,就会得到一块明文数据的密文。
因此,每执行一次AES加密,其实内部共进行了11轮加密,包括1个初始轮,9个拥有4个操作的重复轮,1个拥有3个操作的最终轮,才算得到密文。而AES的解密方法与加密方法类似,如下流程图所示。

3.3.2 AES算法加密解密流程图:

基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业

四、实验过程与运行结果

4.1. 网络传输连接的建立

通过socket套接字建立客户端与服务器之间的网络传输连接。在服务器端,先启动windows的socket服务,然后定义服务器、家族协议,并得到主机IP、端口和socket嵌套字,通过bind函数在服务器端将套接字地址与所创建的套接字号连接起来,然后利用accept()函数与客户端的connect()函数之间建立TCP连接,在这之后便可以通过recv()函数与send()函数建立与客户端的通信。
客户端与服务器端同理,当开启windows的socket后定义一系列参数,然后通过connect()函数建立与服务器之间的数据连接。
建立连接后的运行结果如下:
基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业
由运行结果可以发现,当客户端与服务器建立socket套接字连接后,便可以相互发送消息,且IP地址都为127.0.0.1,即本地环回地址。

4.2. RSA算法的实现与加密解密

在服务器端,随机产生两个10000以内的质数作为p和q的值,然后计算n=pq,φ(n)=(p-1)(q-1),随机产生一个e,通过通过扩展欧几里得方法计算d,然后通过send()函数将公钥(e,n)发送给客户端;
客户端在收到公钥后将AES的**按字节进行分组,对每一个分组进行RSA加密处理,然后发送到服务器端,在服务器端利用私钥对加密数据进行解密,得到AES的**。
发送公钥与对AES的加密解密运行结果如下:
基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业
根据运行结果可以发现,服务器产生了**对,其中公钥为(533,78109979),私钥为(17435273,78109979),将公钥发给客户端后,客户端对AES的**“12345678”进行RSA加密处理,将其分为了三块分别进行加密,加密后的AES**变为了6667911 76752624 45460071。服务器接收到AES加***后,使用私钥对加***进行RSA解密,解密后的会话**又变为了“12345678”,说明解密成功,AES**在网络中实现了加密传输。

4.3. AES的实现与加密解密

在AES加密模块,客户端首先对**进行**扩展,如果**不满16字节
则需要在后面补0凑够16个字节,然后进行**扩展,将**扩展为44个word,一个word占32位,四个word为一组**,然后将要加密的明文分段,转换为16进制数据,并凑够16个字节,如果不满16个字节则末尾补0。
然后不断地重复AES的加密流程,对每一段明文进行11轮加密操作,其中第一轮只是进行明文与**的异或运算,2-10轮则重复S盒变换、行变换、列变换、与扩展**进行异或运算四个步骤,第11轮为S盒变换、行变换还有与扩展**的异或运算,得到最后加密后的密文。运行结果如下所示:
基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业
由运行结果可以看出加密后的密文,然后通过send()函数将密文发送给服务器。服务器用之前解密得到的**进行解密,步骤与加密方法类似,先对**进行扩展,然后2-10轮不断重复反行变换、反S盒变换、与扩展**的异或运算与反列变换,第11轮进行反行变换、反列变换,最后与扩展**进行异或运算后便得到的明文,运行结果如下所示:
基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业
由运行结果可以看出,服务器端成功根据加密密文与**求出了明文,最终结果为“NPU”。

4.4. 运行总结果如下:

服务器端
基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业

客户端
基于RSA和AES的混合加密算法实现----2020年西北工业大学网络空间安全学院夏令营大作业

五、参考文献

[1] AES加密算法的实现

[2]对称加密及AES加密算法

[3]AES加密算法的详细介绍与实现

[4] RSA算法原理