用python实现一个简单的加密认证通信系统

**

用python实现一个简单的加密认证通信系统

**

要求:设计实现一个通信系统,双方可以通过消息通信,用户可选择一种加密算法和认证算法,对消息进行加密通信和完整性验证。

实现方案:
客户端与服务器端建立连接,发送的消息在客户端程序进行加密,经过服务器转发给其他客户端,由客户端解密后显示。
首先,在客户端1对要发送的明文使用MD5算法得到消息摘要,然后用客户端1的RSA私钥对摘要进行签名。把得到的签名和明文合在一起生成消息,再对消息使用RC4流秘钥进行加密成密文,通过服务器来进行消息传输。
客户端2接收到密文后使用RC4解密算法进行解密,得到由明文合签名组成的消息,此时对明文再使用一次MD5算法生成消息摘要,使用得到的摘要和客户端1的RSA公钥对签名进行验证,如果签名的认证结果为True,则证明消息确实是有客户端1发送的,且消息为被篡改。如果签名认证的结果为False,则此消息的来源可能不真确,消息的可靠信丧失。
其中,客户端1和客户端2都要生成自己的RSA公私钥对,对于私钥自己保存,对于公钥则可以公布。RC4算法是一种对称加密算法,加密和解密用的都是一个秘钥,这个秘钥由需要进行通信的不同的客户端自行保存。由于RC4算法是一种流加密算法不同于对称分组加密算法,所以我设计了一个函数来拆分解密后得到的消息,最终分别得到明文和签名。

流程图如下:
用python实现一个简单的加密认证通信系统_第1张图片
用python实现一个简单的加密认证通信系统_第2张图片
服务器代码:

import tkinter
import socket,threading


win=tkinter.Tk()#创建主窗口
win.title('服务器')
win.geometry("300x200")
users={}#用户字典

def run(ck,ca):
    userName=ck.recv(1024)
    users[userName.decode("utf-8")]=ck#解码并存储用户信息
    printStr=""+userName.decode("utf-8")+"连接\n" #在显示框中显示是否连接成功
    text.insert(tkinter.INSERT,printStr)

    while True:
        buffer=[]
        rData=ck.recv(1024) #接受客户端发送的消息
        dataStr=rData.decode("utf-8")
        buffer.append(dataStr)
        infolist=dataStr.split(":")
        #要发送信息的客户端向目标客户端发送消息
        #users[infolist[0]].send((userName.decode("utf-8")+": "+infolist[1]).encode("utf"))
        users[infolist[0]].send((infolist[1]).encode("utf"))

def start():
    ipStr=eip.get()#从输入端中获取ip
    portStr=eport.get()

    server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.bind((ipStr,int(portStr))) #绑定ip和端口号
    server.listen(10)
    printStr="服务器启动成功\n"
    text.insert(tkinter.INSERT,printStr)

    while True:
        ck,ca=server.accept() #接受所连接的客户端的信息
        t=threading.Thread(target=run,args=(ck,ca))#每连接一个客户端就开启一个线程
        t.start()

def startSever():
    s=threading.Thread(target=start)
    s.start()#开启线程

labelIp = tkinter.Label(win, text='ip').grid(row=0, column=0)
labelPort = tkinter.Label(win, text='port').grid(row=1, column=0)
eip = tkinter.Variable()
eport = tkinter.Variable()
entryIp = tkinter.Entry(win, textvariable=eip).grid(row=0, column=1)
entryPort = tkinter.Entry(win, textvariable=eport).grid(row=1, column=1)
button = tkinter.Button(win, text="启动", command=startSever).grid(row=8, column=0)
text = tkinter.Text(win, height=5, width=30)
labeltext = tkinter.Label(win, text='连接消息:').grid(row=3, column=1)
text.grid(row=4, column=1)
win.mainloop()

客户端代码:

import tkinter
import socket
import threading
import MD5
import RC4
import RSA

win=tkinter.Tk()
win.title("客户端1")
win.geometry("300x300+200+20")

ck=None #用来存储客户端的信息

def chaifen(message):   #用于拆分明文与签名
    plain = " "
    signal = " "
    for i in range(0,len(message)):
        if message[i]=='@':
            plain=message[0:i]
            signal=message[i+1:len(message)]

    return plain,signal


def getInfo():  # 接受消息
    while True:
        data = ck.recv(1024)  # 用于接受服务器发送的信息

        key = "569716548"
        box = RC4.init_box(key)
        mingwen = RC4.ex_decrypt(data, box)  # 解密消息

        p = chaifen(mingwen)  # 返回一个包含明文和签名的元组
        print("拆分出的签名:")
        print(p[1])
        s = p[1]
        s = s[2:len(s) - 1]
        s = s.encode(encoding="utf-8")

        m = MD5.md5(p[0])  # 对明文部分使用md5算法生成摘要
        # signal2=KEY.sign(m)
        v = RSA.Verify(m, s)  # 验证签名
        judge(v)  # 判断安全性
        text.insert(tkinter.INSERT, p[0])


def judge(v):
    if v == "SHA-1":
        print("消息未被篡改,且由本人发送。")
    else:
        print("本次通信存在安全隐患!")

def connectServer():
    global ck
    ipStr=eip.get()
    portStr=eport.get()
    userStr=euser.get()
    client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    client.connect((ipStr,int(portStr)))
    client.send(userStr.encode("utf-8"))
    ck=client

    t=threading.Thread(target=getInfo)
    t.start()

def sendMail():
    friend=efriend.get()#发给谁
    sendStr=esend.get()#发送的消息

    #用MD5生成消息摘要
    abstract=MD5.md5(sendStr)

    #用RSA算法对消息摘要进行签名
    signal1=RSA.sign(str(abstract))

    #生成消息
    message=sendStr+'@'+str(signal1)

    #用RC4算法对消息进行加密
    key="569716548"
    box = RC4.init_box(key)
    cipher=RC4.ex_encrypt(message, box)

    #发送消息
    sendStr=friend+":"+cipher
    ck.send(sendStr.encode("utf-8"))

#tkinter界面配置
labelUse = tkinter.Label(win, text="userName").grid(row=0, column=0)
euser = tkinter.Variable()
entryUser = tkinter.Entry(win, textvariable=euser).grid(row=0, column=1)

labelIp = tkinter.Label(win, text="ip").grid(row=1, column=0)
eip = tkinter.Variable()
entryIp = tkinter.Entry(win, textvariable=eip).grid(row=1, column=1)

labelPort = tkinter.Label(win, text="port").grid(row=2, column=0)
eport = tkinter.Variable()

entryPort = tkinter.Entry(win, textvariable=eport).grid(row=2, column=1)

button = tkinter.Button(win, text="启动", command=connectServer).grid(row=3, column=0)
text = tkinter.Text(win, height=5, width=25)
labeltext= tkinter.Label(win, text="显示消息").grid(row=4, column=0)
text.grid(row=4, column=1)

esend = tkinter.Variable()
labelesend = tkinter.Label(win, text="发送的消息").grid(row=5, column=0)
entrySend = tkinter.Entry(win, textvariable=esend).grid(row=5, column=1)

efriend = tkinter.Variable()
labelefriend= tkinter.Label(win, text="发给谁").grid(row=6, column=0)
entryFriend = tkinter.Entry(win, textvariable=efriend).grid(row=6, column=1)

button2 = tkinter.Button(win, text="发送", command=sendMail).grid(row=7, column=0)
win.mainloop()

调用RSA模块进行签名/验签:

import rsa
import base64

# 生成密钥
(pubkey, privkey) = rsa.newkeys(1024)

# 保存密钥
with open('public.pem', 'w+') as f:
    f.write(pubkey.save_pkcs1().decode())
with open('private.pem', 'w+') as f:
    f.write(privkey.save_pkcs1().decode())


# 私钥签名
def sign(message):
    with open('private.pem', 'r') as f:
        privkey = rsa.PrivateKey.load_pkcs1(f.read().encode())

        signature = rsa.sign(message.encode(), privkey, 'SHA-1')
        signature = base64.b64encode(signature)
        print("生成的签名:")
        print(signature)
        return signature


# 公钥验证
def Verify(message, signature):
    with open('public.pem', 'r') as f:
        pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())
        signature = base64.b64decode(signature)

        v = rsa.verify(message.encode(), signature, pubkey)
        print("验签结果:")
        print(v)
        return v
        

RC4算法进行加密:

import base64

def get_message():
    print("输入信息:")
    s = input()
    return s

def get_key():
    print("输入秘钥")
    key = input()
    return key

#初始化s盒
def init_box(key):
    s_box = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    return s_box

def ex_encrypt(plain, box):#加密

    res = []
    i = j = 0
    for s in plain:
        i = (i + 1) % 256
        j = (j + box[i]) % 256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j]) % 256
        k = box[t]
        res.append(chr(ord(s) ^ k))
    cipher = "".join(res)
    s=str(base64.b64encode(cipher.encode('utf-8')), 'utf-8')

     # base64的目的也是为了变成可见字符
    print("加密(解密)后经过base64编码后的输出:")
    print(s)

    return s

def ex_decrypt(plain, box):#解密

    plain = base64.b64decode(plain)
    plain = bytes.decode(plain)

    res = []
    i = j = 0
    for s in plain:
        i = (i + 1) % 256
        j = (j + box[i]) % 256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j]) % 256
        k = box[t]
        res.append(chr(ord(s) ^ k))
    cipher = "".join(res)

     # base64的目的也是为了变成可见字符
    print("加密(解密)后经过base64编码后的输出:")
    print(cipher)

    return cipher

def encrypt():
    message = get_message()
    key = get_key()
    box = init_box(key)
    ex_encrypt(message, box)

if __name__ == '__main__':
       while True:
           encrypt()

MD5摘要模块:

from hashlib import md5, sha1, sha224, sha256, sha384, sha512

hash_md5 = md5()  # MD5 hash对象
hash_sha1 = sha1()  # SHA1 hash对象
hash_sha224 = sha224()  # SHA224 hash对象
hash_sha256 = sha256()  # SHA256 hash对象
hash_sha384 = sha384()  # SHA384 hash对象
hash_sha512 = sha512()  # SHA512 hash对象



def md5(str):

    print('将要生成摘要的字符串:', str)

    # MD5 加密
    h_md5 = hash_md5.copy()  # 复制一个对象,避免频繁创建对象消耗性能
    h_md5.update(str.encode('utf-8'))  # 需要将字符串进行编码,编码成二进制数据
    md5_str = h_md5.hexdigest()  # 获取16进制的摘要
    print('MD5生成摘要结果:',md5_str)  # 输出结果
    return md5_str

你可能感兴趣的:(python,python,加密算法,通信系统)