2018-2019-2 20165221课程设计学习-week3
2018-2019-2 20165221课程设计学习-week3
目录
一 . 深入了解Openssl
#### 概念理解: > 在计算机网络上,OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。二 . 拷贝虚拟机搭建环境
- 完全克隆网络对抗实验用到的kali机,新建```课程设计的kali``` ![](https://img2018.cnblogs.com/blog/1322987/201905/1322987-20190524203051376-284688748.png)- 参考链接 , 下载并安装
pyOpenSSL
, 选择安装的版本为pyOpenSSL-0.11.winxp32-py2.7.msi
- 将其放到桌面上,使用openssl命令生成私钥
openssl genrsa -out private.pem -f4 1024
来生成私钥,指数值为10001
三 . 测试基于RSA的加解密
1 . 先完成相关配置,确定对Hello,20165221!
进行加解密:
-
从私钥
private.pem
导出公钥public.pem
-
将字符串”Hello 20165221!”存放到文件
msg.bin
作为测试数据:
2 . 进行加密:
- 输入指令
openssl rsautl -in msg.bin -out 20165221.enc -inkey public.pem -pubin -encrypt -pkcs
,使用前面生成的公钥public.pem
对测试数据msg.bin
进行加密,得到加密后的数据20165221.enc
:
- 查看加密后的数据:
3 . 进行解密:
- 使用私钥
private.pem
对加密后的数据20165221.enc
进行解密,并将结果存放到20165221.dec
文件中:
openssl rsautl -in 20165221.enc -out 20165221.dec -inkey private.pem -decrypt -pkcs
-
查看解密后的内容:
-
即成功完成一次加解密!!
4 . 指令详解:
in
选项指定待解密的数据文件msg.bin.enc
out
选项指定解密后的输出文件msg.bin.dec
inkey
选项指定用于解密的私钥Key.pem
,由于输入是私钥,所以不再需要使用选项-pubindecrypt
选项表明这里是进行解密操作pkcs
选项指定解密处理过程中数据的填充方式,对于填充,可选项有:-pkcs
,-oaep
,-ssl
, -raw
,默认是-pkcs
,即按照PKCS#1 v1.5规范进行填充
四 . python实现非对称加解密
- 因为加解密是基于Python下的cryptograhpy库,先安装该库```sudo pip3 install cryptography```: - 查看验证呢过环境是否完整,```python --version```: ![](https://img2018.cnblogs.com/blog/1322987/201905/1322987-20190525092030145-28419986.png)- 还是之前的
Hello,20165221!
进行加解密,这次将加解密的文件放到一起,是为rsa-加解密.py
:
#!/usr/bin/env python3
# 导入cryptography库的相关模块和函数
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
# 定义辅助函数,用于打印16进制数据
def dump_hex(buffer, sep=' ', indent=0, line_size=16):
"""
辅助函数,将bytes数组以如下格式打印输出:
0000: 40 71 37 d0 80 32 7f 04 d9 6d fb fc f7 6a 7d d4
0010: 48 ad 75 79 7a 0d 6c 55 01 ed 45 d5 1e 75 33 a6
:param buffer: 待打印数据
:param sep: 各16进制数据之间的分隔符,默认用空格' '分隔
:param indent: 打印输出前是否需要缩进,默认不缩进
:param line_size: 每行输出16进制的数量,默认1行输出16个
:return: 无返回值
"""
# 计算缩进空格数
leading = '%s' % ' '*indent
# 循环打印每行16进制数据
for x in range(0, len(buffer), line_size):
# 打印缩进字符和当前行数据的起始地址
print('%s%04X: ' % (leading, x), end='')
# 将当前行数据制作成列表list,并打印
line = ['%02x' % i for i in buffer[x:x+line_size]]
print(*line, sep=sep, end='\n')
# 加密函数
def encrypt(src_file_name, dst_file_name, public_key_file_name):
"""
对原始数据文件使用指定的公钥进行加密,并将加密输出到目标文件中
:param src_file_name: 原始数据文件
:param dst_file_name: 加密输出文件
:param public_key_file_name: 用于加密的公钥
:return: 加密结果的bytes数组
"""
# 读取原始数据
data_file = open(src_file_name, 'rb')
data = data_file.read()
data_file.close()
# 读取公钥数据
key_file = open(public_key_file_name, 'rb')
key_data = key_file.read()
key_file.close()
# 从公钥数据中加载公钥
public_key = serialization.load_pem_public_key(
key_data,
backend=default_backend()
)
# 使用公钥对原始数据进行加密,使用PKCS#1 v1.5的填充方式
out_data = public_key.encrypt(
data,
padding.PKCS1v15()
)
# 将加密结果输出到目标文件中
# write encrypted data
out_data_file = open(dst_file_name, 'wb')
out_data_file.write(out_data)
out_data_file.close()
# 返回加密结果
return out_data
# 解密函数
def decrypt(src_file_name, dst_file_name, private_key_file_name):
"""
对原始数据文件使用指定的私钥进行解密,并将结果输出到目标文件中
:param src_file_name: 原始数据文件
:param dst_file_name: 解密输出文件
:param private_key_file_name: 用于解密的私钥
:return: 解密结果的bytes数组
"""
# 读取原始数据
data_file = open(src_file_name, 'rb')
data = data_file.read()
data_file.close()
# 读取私钥数据
key_file = open(private_key_file_name, 'rb')
key_data = key_file.read()
key_file.close()
# 从私钥数据中加载私钥
private_key = serialization.load_pem_private_key(
key_data,
password=None,
backend=default_backend()
)
# 使用私钥对数据进行解密,使用PKCS#1 v1.5的填充方式
out_data = private_key.decrypt(
data,
padding.PKCS1v15()
)
# 将解密结果输出到目标文件中
out_data_file = open(dst_file_name, 'wb')
out_data_file.write(out_data)
out_data_file.close()
# 返回解密结果
return out_data
if __name__ == "__main__":
data_file_name = r'msg.bin'
encrypted_file_name = r'msg.bin.encrypted'
decrypted_file_name = r'msg.bin.decrypted'
private_key_file_name = r'Key.pem'
public_key_file_name = r'Key_pub.pem'
# 先对数据加密
data = encrypt(data_file_name, encrypted_file_name, public_key_file_name)
# 打印加密结果
print("encrypted data:")
dump_hex(data)
# 对数据进行解密
data = decrypt(encrypted_file_name, decrypted_file_name, private_key_file_name)
# 打印解密结果
print("decrypted data:")
dump_hex(data)
-
运行刚刚的
rsa-加解密.py
,使用指令python3 rsa-加解密.py
-
与源文件对比,发现解密成功:
-
对于解密后的数据
msg.bin.decrypted
和原始数据msg.bin
,二者的md5校验值是一样的,也证明了解密成功!
五 . 基于Python和OpenSSL实现的SSL网络通信
- 首先用openssl生成相关的证书: ```openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout key.pem``` ![](https://img2018.cnblogs.com/blog/1322987/201905/1322987-20190525104522462-1322684543.png) - 紧接着配置证书的相关信息: ![](https://img2018.cnblogs.com/blog/1322987/201905/1322987-20190525104554148-1034443295.png) - **对于客户端**:发送6次100byte的数据,显示客户端发送时长,以及客户端数据的时长,并显示平均时长: ![](https://img2018.cnblogs.com/blog/1322987/201905/1322987-20190525105057231-1190897776.png)- 对于服务端:接收客户端的数据,并向客户端发送1000byte的数据,显示服务端收到时间,发送时间,以及平均时间:
- 并且获取证书的具体信息:
六 . 代码链接
- [代码链接](https://gitee.com/tx0630/course_design_for_201810192) ![](https://img2018.cnblogs.com/blog/1322987/201905/1322987-20190524215620668-412103868.png) ![](https://img2018.cnblogs.com/blog/1322987/201905/1322987-20190525110528099-542687150.png)
七 . 本周学习总结
- 这周尝试了一下基于Python的rsa的加解密,还是挺有趣的,虽然学习的过程是波折的,但学到的喜悦也是真是的啦! - 尝试SSL通信的成功也很有意思,这次课设自己还是有收获的,就是有点后悔之前没有好好学,但是,现在还想也不算迟吧....- 附SSL网络通信的代码:
- 服务器端
import socket
import ssl,time
sock=socket.socket()
print("建立套接字成功")
sock.bind(("127.0.0.1", 443))
print("绑定成功")
sock.listen(1)
def input_pro(connstream,data):
print("接收到的客户端数据长度是",len(data))
return True
def doclient(connstream):
recvtime=0
sendtime=0
n=0
t1=time.clock()
data=connstream.recv(1024)
t2=time.clock()
print("服务端接收客户端数据的时间",t2-t1)
while data:
if not input_pro(connstream,data):
break
n=n+1
t3 = time.clock()
connstream.send(b'b' * 1000)
t4 = time.clock()
sendtime += t4 - t3
print("服务端发送数据时长", t4 - t3)
t3 = time.clock()
data = connstream.recv(1024)
t4 = time.clock()
recvtime += t4 - t3
print("服务端接收客户端数据时间", t4 - t3)
print("平均发送时间是",sendtime/n,"平均接收时间是",recvtime/n,)
return True
while True:
#接受连接并返回(conn,address),
# 其中conn是新的套接字对象,
# 可以用来接收和发送数据。
# address是连接客户端的地址。
conn,addr=sock.accept()
print("客户端的套接字数据接收到了")
connstream=ssl.wrap_socket(conn,"key.pem","cert.pem",server_side=True)
try:
doclient(connstream)
finally:
connstream.shutdown(socket.SHUT_RDWR)
connstream.close()
- 客户端:
import socket, ssl, pprint, time
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ssl_s=ssl.wrap_socket(s,cert_reqs=ssl.CERT_REQUIRED,ca_certs="cert.pem")
ssl_s.connect(("127.0.0.1", 443))
print("套接字连接成功")
n=0
sendtime=0
recvtime=0
while n<6:
n=n+1
t1=time.clock()
ssl_s.send(b'a'*100)
t2=time.clock()
sendtime+=t2-t1
print("发送时长",t2-t1)
t1=time.clock()
data=ssl_s.recv(1024)
t2=time.clock()
recvtime+=t2-t1
print("接收时长",t2-t1)
print(len(data))
print("平均接收时间",sendtime/n,"平均发送时间",recvtime/n)
print("生成的证书信息")
pprint.pprint(ssl_s.getpeercert())
ssl_s.close()