1. 程式人生 > >模擬RSA雙向驗證,並且實現DES加密以及MD5校驗過程(python程式碼實現)

模擬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("--------------------------------雙向驗證結束---------------------------------")