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,由於輸入是私鑰,所以不再需要使用選項-pubin
  • decrypt 選項表明這里是進行解密操作
  • 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()

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM