模擬RSA雙向驗證,並且實現DES加密以及MD5校驗過程(python程式碼實現)
要求如下:
(1)A,B兩端各生成公鑰金鑰對(PA,SA), 金鑰對(PB,SB)。
(2)A端生成隨機數N1,用B的公鑰PB加密,併發送至B端,B端接受並用私鑰SB解密,將解密資料N1’,傳送回A端,A端驗證N1與N1’是否相等,若相等,A通過對B的身份認證。
(3)B端生成隨機數N2,用A的公鑰PA加密,併發送至A端,A端接受並用私鑰SA解密,將解密資料N2’,傳送回B端,B端驗證N2與N2’是否相等,若相等,B通過對A的身份認證。
(4)完成身份認證之後,用DES演算法傳送加一段兒隨機密資料,並用MD5演算法校驗檔案完整性。
實驗步驟:
。。。。執行過程中記得匯入所需要的包啊,黑屏終端會有提示資訊的。。。。。。
。。。。用pip install 包名 來匯入。。。。。。。。。。。。。。。。。。。。。
準備過程:
(1)在D盤下建立test目錄,test目錄下再建立A,B兩個目錄 ,如圖:
(2)然後執行檔案aaction.py生成公鑰和私鑰,然後把A目錄下的公鑰(public.pem)複製到B目錄下,名字改為yourpublic.pem
(3)執行baction.py檔案,將B下的公鑰(public.pem)複製到A目錄下並且把名字改為yourpublic.pem,這樣就讓A,B知道了對方的公鑰,接下來就能用對方的公鑰加密訊息傳送給對方,然後讓對方用自己的私鑰進行解密了。
上面步驟完成之後結果如下圖:
實驗過程:
(1)重新執行aaction.py檔案
(2)然後再執行baction.py檔案(一定要注意順序)
這時再看aaction.py這邊,如下圖:
如果出現上面兩張圖則說明模擬rsa演算法的雙向驗證完畢。
接下來在aaction.py的黑屏終端輸入需要用des演算法加密,並且讓MD5生成報文摘要的資料
baction.py終端下如下圖則說明收到的訊息用des演算法解密完成,並且經過MD5校驗之後沒有發現問題。有問題的話就會提示驗證失敗的訊息。
程式碼奉上:
(1)aaction.py的程式碼如下
import socket
import rsa
import os
import random
import threading
import multiprocessing
from time import ctime,sleep
import binascii
from pyDes import des, CBC, PAD_PKCS5
import hashlib
def myserver(mypubaddr,mypriaddr,mybind):
#判斷是否存在公鑰私鑰檔案,不存在的話就生成檔案
if os.path.exists(mypubaddr) == True:
print('File already exists')
else:
(pubkey, privkey) = rsa.newkeys(1024)
pub = pubkey.save_pkcs1()
pubfile = open(mypubaddr,'wb')
pubfile.write(pub)
pubfile.close()
pri = privkey.save_pkcs1()
prifile = open(mypriaddr,'wb')
prifile.write(pri)
prifile.close()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(mybind)
server.listen(5)
print("伺服器啟動成功。。。")
while True:
clientSocket, clientAddress = server.accept()
print("%s---%s連線成功"%(str(clientSocket), clientAddress))
with open(mypriaddr) as privatefile:
p = privatefile.read()
privkey = rsa.PrivateKey.load_pkcs1(p)
data = clientSocket.recv(1024)
message = rsa.decrypt(data, privkey)
#傳送給client的隨機數生成的密文
clientSocket.send(message)
data = clientSocket.recv(1024)
data = data.decode('utf-8')
if data == 'success':
print("驗證成功")
s1 = 'checksuccess'
return s1
else:
print("驗證失敗")
f1 = 'checkfail'
return f1
def myclient(conaddr,yourpubaddr):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(conaddr)
#生成隨機驗證數
message = str(random.randint(0,1000))
message = message.encode()
#讀取儲存的別人的公鑰
with open(yourpubaddr) as publickfile:
p = publickfile.read()
pubkey = rsa.PublicKey.load_pkcs1(p)
'''
with open(r'D:\text\private.pem') as privatefile:
p = privatefile.read()
privkey = rsa.PrivateKey.load_pkcs1(p)
'''
#對隨機驗證數進行公鑰加密
crypto = rsa.encrypt(message, pubkey)
#將公鑰加密過的資料傳送給接收方
data = crypto
client.send(data)
#接收對方發過來的資料並且與己方傳送的message進行對比校驗
while True:
info = client.recv(1024)
print(info.decode())
if message == info:
print("對server認證通過")
#client.send(data.encode("utf-8"))
check = str('success')
#print(check.encode("utf-8"))
client.send(check.encode('utf-8'))
print(check)
s1 = 'checksuccess'
return s1
else:
f1 = 'checkfail'
return f1
def clientagain(conaddr):
while True:
inputdata = input("請輸入需要傳送的資料:")
#用des演算法加密
desEncryptData = des_encrypt(inputdata)
#用MD5生成摘要
md5EncryptData = md5encrypt(inputdata)
md5EncryptData = bytes(md5EncryptData, 'utf-8')
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(conaddr)
#傳送拼接的資料
client.sendall(desEncryptData)
client.send(" ".encode('utf-8'))
client.sendall(md5EncryptData)
def des_encrypt(s):
secret_key = '20171117'
iv = secret_key
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
en = k.encrypt(s, padmode=PAD_PKCS5)
return binascii.b2a_hex(en)
def md5encrypt(str):
#str = input("請輸入需要用MD5加密的資料")
# 建立md5物件
hl = hashlib.md5()
# 此處必須宣告encode
# 若寫法為hl.update(str) 報錯為: Unicode-objects must be encoded before hashing
hl.update(str.encode(encoding='utf-8'))
#print('MD5加密前為 :' + str)
#print('MD5加密後為 :' + hl.hexdigest())
return hl.hexdigest()
if __name__ == '__main__':
print("--------------------------------雙向驗證開始---------------------------------")
mypubaddr = r'D:\test\A\public.pem'
mypriaddr = r'D:\test\A\private.pem'
mybind = ('127.0.0.1', 8083)
check1 = myserver(mypubaddr,mypriaddr,mybind)
sleep(1)
conaddr = ("127.0.0.1", 8082)
yourpubaddr = r'D:\test\A\yourpublic.pem'
check2 = myclient(conaddr,yourpubaddr)
if (check1 == 'checksuccess') and (check2 == 'checksuccess'):
print("--------------------------------雙向驗證成功---------------------------------")
print("--------------------------------雙向驗證結束---------------------------------")
print("---------------------準備正式傳送加密過的des和MD5資料---------------------------")
sleep(1)
clientagain(conaddr)
else:
print("--------------------------------雙向驗證失敗---------------------------------")
print("--------------------------------雙向驗證結束---------------------------------")
baction.py的程式碼如下:
import socket
import rsa
import os
import random
import threading
import multiprocessing
from time import ctime,sleep
import binascii
from pyDes import des, CBC, PAD_PKCS5
import hashlib
def myserver(mypubaddr,mypriaddr,mybind):
#判斷是否存在公鑰私鑰檔案,不存在的話就生成檔案
if os.path.exists(mypubaddr) == True:
print('File already exists')
else:
(pubkey, privkey) = rsa.newkeys(1024)
pub = pubkey.save_pkcs1()
pubfile = open(mypubaddr,'wb')
pubfile.write(pub)
pubfile.close()
pri = privkey.save_pkcs1()
prifile = open(mypriaddr,'wb')
prifile.write(pri)
prifile.close()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(mybind)
server.listen(5)
print("伺服器啟動成功。。。")
while True:
clientSocket, clientAddress = server.accept()
print("%s---%s連線成功"%(str(clientSocket), clientAddress))
with open(mypriaddr) as privatefile:
p = privatefile.read()
privkey = rsa.PrivateKey.load_pkcs1(p)
data = clientSocket.recv(1024)
message = rsa.decrypt(data, privkey)
#傳送給client的隨機數生成的密文
clientSocket.send(message)
data = clientSocket.recv(1024)
data = data.decode('utf-8')
if data == 'success':
print("驗證成功")
s1 = 'checksuccess'
return s1
else:
print("驗證失敗")
f1 = 'checkfail'
return f1
def myclient(conaddr,yourpubaddr):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(conaddr)
#生成隨機驗證數
message = str(random.randint(0,1000))
message = message.encode()
#讀取儲存的別人的公鑰
with open(yourpubaddr) as publickfile:
p = publickfile.read()
pubkey = rsa.PublicKey.load_pkcs1(p)
'''
with open(r'D:\text\private.pem') as privatefile:
p = privatefile.read()
privkey = rsa.PrivateKey.load_pkcs1(p)
'''
#對隨機驗證數進行公鑰加密
crypto = rsa.encrypt(message, pubkey)
#將公鑰加密過的資料傳送給接收方
data = crypto
client.send(data)
#接收對方發過來的資料並且與己方傳送的message進行對比校驗
while True:
info = client.recv(1024)
print(info.decode())
if message == info:
print("對server認證通過")
#client.send(data.encode("utf-8"))
check = str('success')
#print(check.encode("utf-8"))
client.send(check.encode('utf-8'))
print(check)
s1 = 'checksuccess'
return s1
else:
f1 = 'checkfail'
return f1
def serverAgain(mybind):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(mybind)
server.listen(5)
print("伺服器啟動成功。。。")
while True:
clientSocket, clientAddress = server.accept()
print("%s---%s連線成功"%(str(clientSocket), clientAddress))
'''
data = clientSocket.recv(1024)
clientSocket.send(message)
'''
data = clientSocket.recv(1024)
data = data.decode('utf-8')
#對資料進行res和md5校驗
check(data)
def des_descrypt(s):
secret_key = '20171117'
iv = secret_key
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
de = k.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)
return de
'''
str_de = des_descrypt(str_en)
print("解密後為:",str_de)
'''
def md5encrypt(de):
#str = input("請輸入需要加密的資料")
# 建立md5物件
hl = hashlib.md5()
# 此處必須宣告encode
# 若寫法為hl.update(str) 報錯為: Unicode-objects must be encoded before hashing
hl.update(de)
#print('MD5加密前為 :' + str)
#print('MD5加密後為 :' + hl.hexdigest())
return hl.hexdigest()
def check(data):
#分割字串,前為des加密的字串,後為md5報文摘要
list = data.split()
#des加密的字串
s1 = list[0]
#md5報文摘要
s2 = list[1]
#des解密
de = des_descrypt(s1)
#解密資料生成報文摘要
remd5 = md5encrypt(de)
if s2 == remd5:
print("XXXXXXXXXXXXXXXXXXX收到的訊息沒有被修改,驗證過程結束XXXXXXXXXXXXXXXXXXXXXXXX")
else:
print("XXXXXXXXXXXXXXXXXXXXXXXXXX傳輸資訊可能被修改XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
if __name__ == '__main__':
print("--------------------------------雙向驗證開始---------------------------------")
conaddr = ("127.0.0.1", 8083)
yourpubaddr = r'D:\test\B\yourpublic.pem'
check2 = myclient(conaddr,yourpubaddr)
mypubaddr = r'D:\test\B\public.pem'
mypriaddr = r'D:\test\B\private.pem'
mybind = ('127.0.0.1', 8082)
check1 = myserver(mypubaddr,mypriaddr,mybind)
if (check1 == 'checksuccess') and (check2 == 'checksuccess'):
print("--------------------------------雙向驗證成功---------------------------------")
print("--------------------------------雙向驗證結束---------------------------------")
print("------------------------準備正式接收rsa和MD5資料-----------------------------")
serverAgain(mybind)
else:
print("--------------------------------雙向驗證失敗---------------------------------")
print("--------------------------------雙向驗證結束---------------------------------")