2018-2019-2 20165221課程設計學習-week3
目錄
一 . 深入了解Openssl
#### 概念理解: > 在計算機網絡上,OpenSSL是一個開放源代碼的軟件庫包,應用程序可以使用這個包來進行安全通信,避免竊聽,同時確認另一端連接者的身份。這個包廣泛被應用在互聯網的網頁服務器上。二 . 拷貝虛擬機搭建環境
- 完全克隆網絡對抗實驗用到的kali機,新建```課程設計的kali``` - 參考鏈接 , 下載並安裝
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```: - 還是之前的
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```  - 緊接着配置證書的相關信息:  - **對於客戶端**:發送6次100byte的數據,顯示客戶端發送時長,以及客戶端數據的時長,並顯示平均時長: - 對於服務端:接收客戶端的數據,並向客戶端發送1000byte的數據,顯示服務端收到時間,發送時間,以及平均時間:
- 並且獲取證書的具體信息:
六 . 代碼鏈接
- [代碼鏈接](https://gitee.com/tx0630/course_design_for_201810192)  
七 . 本周學習總結
- 這周嘗試了一下基於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()