客戶端和伺服器之間的套接字和訊息加密解密
使用的語言: Python 2.7(下載連結: https : //www.python.org/downloads/ )
使用的庫:
* PyCrypto (下載連結: https : //pypi.python.org/pypi/pycrypto )
* PyCryptoPlus (下載連結: https : //github.com/doegox/python-cryptoplus )
庫安裝:
PyCrypto: 解壓縮檔案。轉到目錄並開啟 linux 終端(alt + ctrl + t)和 CMD(shift +右鍵單擊+在此處選擇命令提示符)以獲取 Windows。之後編寫 python setup.py install(在 Windows 作業系統中正確設定了 Sure Python 環境)
PyCryptoPlus: 與最後一個庫相同。
任務實施: 任務分為兩部分。一個是握手過程,另一個是通訊過程。套接字設定:
-
在建立公鑰和私鑰以及雜湊公鑰時,我們需要立即設定套接字。為了設定套接字,我們需要匯入另一個帶有
import socket
的模組並連線(用於客戶端)或繫結(用於伺服器)IP 地址和埠以及來自使用者的套接字。- - - - - 客戶端 - - - - -
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) host = raw_input("Server Address To Be Connected -> ") port = int(input("Port of The Server -> ")) server.connect((host, port))
- - - - - 伺服器端 - - - - -
try: #setting up socket server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((host,port)) server.listen(5) except BaseException: print "-----Check Server Address or Port-----"
“socket.AF_INET,socket.SOCK_STREAM”將允許我們使用
accept()
函式和訊息傳遞基礎。而不是它,我們也可以使用“socket.AF_INET,socket.SOCK_DGRAM”,但那時我們將不得不使用setblocking(value)
。
握手過程:
- (CLIENT)第一項任務是建立公鑰和私鑰。要建立私鑰和公鑰,我們必須匯入一些模組。它們是:從 Crypto 匯入 Random 和從 Crypto.PublicKey 匯入 RSA。要建立金鑰,我們必須編寫幾行簡單的程式碼:
random_generator = Random.new().read
key = RSA.generate(1024,random_generator)
public = key.publickey().exportKey()
random_generator 派生自來自加密匯入隨機模組。金鑰源自來自 Crypto.PublicKey 匯入 RSA,它將通過生成隨機字元來建立大小為 1024 的私鑰。Public 從先前生成的私鑰匯出公鑰。
-
(CLIENT)建立公鑰和私鑰後,我們必須使用 SHA-1 雜湊對公鑰進行雜湊處理以傳送到伺服器。要使用 SHA-1 雜湊,我們需要通過編寫
import hashlib
來匯入另一個模組。要雜湊公鑰,我們寫了兩行程式碼:hash_object = hashlib.sha1(public) hex_digest = hash_object.hexdigest()
這裡 hash_object 和 hex_digest 是我們的變數。在此之後,客戶端將傳送 hex_digest 和 public 到伺服器,Server 將通過比較從客戶端獲得的雜湊和公鑰的新雜湊來驗證它們。如果新雜湊和來自客戶端的雜湊匹配,它將轉移到下一個過程。由於從客戶端傳送的公共字串形式,它將無法用作伺服器端的金鑰。為了防止這種情況並將字串公鑰轉換為 rsa 公鑰,我們需要編寫 server_public_key = RSA.importKey(getpbk)
,這裡 getpbk 是來自客戶端的公鑰。
-
(伺服器)下一步是建立會話金鑰。在這裡,我使用
os
模組建立一個隨機金鑰“key =os.urandom(16)
”,這將給我們一個 16 位長的金鑰,之後我在“AES.MODE_CTR”中加密了該金鑰並再次雜湊使用 SHA-1:#encrypt CTR MODE session key en = AES.new(key_128,AES.MODE_CTR,counter = lambda:key_128) encrypto = en.encrypt(key_128) #hashing sha1 en_object = hashlib.sha1(encrypto) en_digest = en_object.hexdigest()
所以 en_digest 將是我們的會話金鑰。
-
(SERVER)握手過程的最後一部分是加密從客戶端獲得的公鑰和在伺服器端建立的會話金鑰。
#encrypting session key and public key E = server_public_key.encrypt(encrypto,16)
加密後,伺服器將金鑰作為字串傳送給客戶端。
-
(CLIENT)從伺服器獲取(公共金鑰和會話金鑰)的加密字串後,客戶端將使用先前與公鑰一起建立的私鑰對它們進行解密。由於加密(公共和會話金鑰)是字串形式,現在我們必須使用
eval()
將其作為金鑰取回。如果解密完成,則握手過程也完成,因為雙方都確認他們正在使用相同的金鑰。要解密:en = eval(msg) decrypt = key.decrypt(en) # hashing sha1 en_object = hashlib.sha1(decrypt) en_digest = en_object.hexdigest()
我在這裡使用了 SHA-1,以便在輸出中可讀。
溝通過程:
對於通訊過程,我們必須使用來自兩側的會話金鑰作為 IDEA 加密 MODE_CTR 的 KEY。雙方將使用會話金鑰使用 IDEA.MODE_CTR 加密和解密訊息。
-
(加密)對於 IDEA 加密,我們需要大小為 16bit 的金鑰和必須可呼叫的計數器。計數器在 MODE_CTR 中是必需的。我們加密和雜湊的會話金鑰現在大小為 40,它將超過 IDEA 加密的限制金鑰。因此,我們需要減小會話金鑰的大小。為了減少,我們可以使用普通的 python 內建函式 string [value:value]。其中值可以是根據使用者選擇的任何值。在我們的例子中,我已經完成了“key [:16]”,它將從鍵中獲取 0 到 16 個值。這種轉換可以通過金鑰[1:17]或金鑰[16:]等多種方式完成。接下來的部分是通過編寫
IDEA.new()
來建立新的 IDEA 加密函式,它將需要 3 個引數進行處理。第一個引數將是 KEY,第二個引數將是 IDEA 加密的模式(在我們的例子中,IDEA。MODE_CTR)和第三個引數將是 counter =,它是必須可呼叫的函式。counter =將保持函式返回的字串大小。要定義 counter =,我們必須使用合理的值。在這種情況下,我通過定義 lambda 使用了 KEY 的大小。我們可以使用 Counter.Util 而不是使用 lambda,它為 counter =生成隨機值。要使用 Counter.Util,我們需要從 crypto 匯入計數器模組。因此,程式碼將是: 要使用 Counter.Util,我們需要從 crypto 匯入計數器模組。因此,程式碼將是: 要使用 Counter.Util,我們需要從 crypto 匯入計數器模組。因此,程式碼將是:ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
一旦將 ideaEncrypt
定義為我們的 IDEA 加密變數,我們就可以使用內建的加密函式來加密任何訊息。
eMsg = ideaEncrypt.encrypt(whole)
#converting the encrypted message to HEXADECIMAL to readable eMsg =
eMsg.encode("hex").upper()
在此程式碼段中,whole 是要加密的訊息,eMsg 是加密訊息。加密訊息後,我將其轉換為 HEXADECIMAL 以使其可讀,而 upper()
是內建函式,使字元變為大寫。之後,該加密訊息將被髮送到對方站進行解密。
- (解密)
要解密加密的訊息,我們需要使用相同的引數和相同的金鑰建立另一個加密變數,但這次變數將解密加密的訊息。與上次相同的程式碼。但是,在解密訊息之前,我們需要解碼來自十六進位制的訊息,因為在我們的加密部分中,我們用十六進位制編碼加密訊息以使其可讀。因此,整個程式碼將是:
decoded = newmess.decode("hex")
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
這些過程將在伺服器端和客戶端完成,以進行加密和解密。