本项目是python实现的基于密钥分发过程的简易信息管理系统,实现了加密交流,信息录入,信息查看等功能,重点在于密钥分发的流程展示,以体现密钥分发的原理。

密钥分发流程如下

发送:

  1. 服务器生成共享密钥和随机对称密钥
  2. 用客户端公钥经sm2算法加密随机对称密钥得到E(对称密钥)
  3. 用随机对称密钥经sm4算法加密共享密钥得到E(共享密钥)
  4. 共享密钥经sm3生成摘要,用服务器私钥经sm2算法签名得到 数字签名
  5. 封装{E(对称密钥)+E(共享密钥)+数字签名}形成数字签名
  6. 发送至客户端

接收:

  1. 客户端接收数字信封
  2. 用客户端私钥经sm2算法解密E(对称密钥)得到随机对称密钥
  3. 用随机对称密钥经sm4算法解密E(共享密钥)得到共享密钥
  4. 用发送方公钥解密数字签名得到信息摘要
  5. 共享密钥经sm3生成信息摘要
  6. 生成的信息摘要和接受的进行对比相同,则保存共享密钥

工程目录如下:

----客户端

|______userlist.txt

|______client.py

----服务器

|______keylist.txt

|______studentlist.txt

|______server.py

客户端目录下需要有userlist.txt

服务器目录下需要有keylist.txt 和 studentlist.txt

需要国密库,下载命令行:pip install gmssl

server.py

# 导入socket库 和 国密库
from socket import *
from random import SystemRandom
import base64
import binascii
from gmssl import sm2, func
from gmssl import sm3
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import os.path
import os
import jsonfilename = 'keylist.txt'
studentfile = 'studentlist.txt'
server_priKey = b'feb8f2803dd43e1754d22f7e761a8bb47da5197220aafdc534c05565d0e7adbe'
server_pubKey = b'd053f19eb5b2fcd94714f8c4f6d4c64c5dc3b2fd4c061896ffb512261f2a6c53b64e67dcc6e66a55db78200900e77563568d0d9990496f5ecd81eba3582f85be'def show():name_encode = dataSocket.recv(BUFLEN)name = name_encode.decode()gethubkey = []with open(filename, 'r', encoding='utf-8') as rfile:date = rfile.readlines()for item in date:d = dict(eval(item))if name != '':if d['用户名'] == name:gethubkey.append(d)for getkey in gethubkey:hubkey = getkey.get('会话共享密钥')student_lst = []if os.path.exists(studentfile):with open(studentfile, 'r', encoding='utf-8') as rfile:students = rfile.readlines()for item in students:student_lst.append(eval(item))# 初始化sm4crypt_sm4 = CryptSM4()crypt_sm4.set_key(hubkey.encode(), SM4_ENCRYPT)encrypt_tosend = crypt_sm4.crypt_ecb(str(student_lst).encode())print('加密后学生信息:', encrypt_tosend)dataSocket.send(encrypt_tosend)def insert():name_encode = dataSocket.recv(BUFLEN)name = name_encode.decode()gethubkey = []with open(filename, 'r', encoding='utf-8') as rfile:date = rfile.readlines()for item in date:d = dict(eval(item))if name != '':if d['用户名'] == name:gethubkey.append(d)for getkey in gethubkey:hubkey = getkey.get('会话共享密钥')student_list = []recved = dataSocket.recv(BUFLEN)print('收到加密后学生信息',recved)# 初始化crypt_sm4 = CryptSM4()crypt_sm4.set_key(hubkey.encode(), SM4_DECRYPT)decrypt_date = crypt_sm4.crypt_ecb(recved)recv_json = decrypt_date.decode('utf-8')student = json.loads(recv_json)print('解密得到学生信息:',student)student_list.append(student)savedate(student_list)send = '信息录入完毕'dataSocket.send(send.encode())def savedate(lst):  # 保存用户信息try:student_txt = open(studentfile, 'a', encoding='utf-8')except:student_txt = open(studentfile, 'w', encoding='utf-8')for item in lst:student_txt.write(str(item) + '\n')  # 将内容写入文件中def community():name_encode  = dataSocket.recv(BUFLEN)name = name_encode.decode()gethubkey = []while True:# 尝试读取对方发送的消息# BUFLEN 指定从接收缓冲里最多读取多少字节recved = dataSocket.recv(BUFLEN)# 如果返回空bytes,表示对方关闭了连接# 退出循环,结束消息收发if not recved:breakwith open(filename, 'r', encoding='utf-8') as rfile:date = rfile.readlines()for item in date:d = dict(eval(item))if name != '':if d['用户名'] == name:gethubkey.append(d)for getkey in gethubkey:hubkey = getkey.get('会话共享密钥')# 初始化sm4crypt_sm4 = CryptSM4()crypt_sm4.set_key(hubkey.encode(), SM4_DECRYPT)decrypt_date = crypt_sm4.crypt_ecb(recved)info = decrypt_date.decode()print(f'收到对方信息密文: {recved}')print(f'解密后明文为: {info}')# 从终端读入用户输入的字符串toSend = input('>>> ')# 加密后发送crypt_sm4.set_key(hubkey.encode(), SM4_ENCRYPT)encrypt_date = crypt_sm4.crypt_ecb(toSend.encode())dataSocket.send(encrypt_date)# 登记
def register():Key = PrivateKey()hubkey = Key.toString()print('收到用户信息')recved = dataSocket.recv(BUFLEN)# 将二进制数据流转换成字符串dec_date_json = recved.decode('utf-8')# 将json格式字符串转换成字典dec_date = json.loads(dec_date_json)print(dec_date)print('生成共享密钥', hubkey)list = {'用户名':dec_date.get('用户名') , '用户公钥':dec_date.get('用户公钥') ,'会话共享密钥':hubkey}user_list = []# 将学生信息添加到列表中user_list.append(list)# 调用save()函数save(user_list)# 回复客户端send='登记完成'dataSocket.send(send.encode())print('用户登记完毕!!!')recved = dataSocket.recv(BUFLEN)dec_recved = recved.decode()if dec_recved == 'get_hubkey':print('收到共享密钥获取请求')# 初始化sm2算法,公钥加密为对方公钥,私钥签名为己方私钥usr_public_key = dec_date.get('用户公钥')sm2_crypt = sm2.CryptSM2(public_key=usr_public_key, private_key=server_priKey.decode())# 共享密钥输入sm3,生成信息摘要data = hubkey.encode()  # bytes类型summary = sm3.sm3_hash(func.bytes_to_list(data))# sm2为摘要签名,生成数字签名sign = sm2_crypt.sign(summary.encode(), server_priKey)# 生成随机对称密钥random_key = func.random_hex(sm2_crypt.para_len)# sm2加密随机密钥enc_random_key = sm2_crypt.encrypt(random_key.encode())# sm4加密共享密钥key = random_key.encode()crypt_sm4 = CryptSM4()crypt_sm4.set_key(key, SM4_ENCRYPT)encrypt_hubkey = crypt_sm4.crypt_ecb(data)# 生成数字信封,写入字典digital = {'E(随机密钥)': base64.b64encode(enc_random_key).decode(), 'E(共享密钥)': base64.b64encode(encrypt_hubkey).decode(), '数字签名':sign}print('以生成数字信封')print(digital)# 将字典转换成json格式的字符串digital_json = json.dumps(digital)# 将字符串转换成二进制数据流send_digital = digital_json.encode('utf-8')# 发送至客户端dataSocket.send(send_digital)print('发送完毕')def save(lst):  # 保存用户信息try:user_txt = open(filename, 'a', encoding='utf-8')except:user_txt = open(filename, 'w', encoding='utf-8')for item in lst:user_txt.write(str(item) + '\n')  # 将内容写入文件中# 生成密钥对模块
class CurveFp:def __init__(self, A, B, P, N, Gx, Gy, name):self.A = Aself.B = Bself.P = Pself.N = Nself.Gx = Gxself.Gy = Gyself.name = namesm2p256v1 = CurveFp(name="sm2p256v1",A=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC,B=0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93,P=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF,N=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123,Gx=0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7,Gy=0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0
)def multiply(a, n, N, A, P):return fromJacobian(jacobianMultiply(toJacobian(a), n, N, A, P), P)def add(a, b, A, P):return fromJacobian(jacobianAdd(toJacobian(a), toJacobian(b), A, P), P)def inv(a, n):if a == 0:return 0lm, hm = 1, 0low, high = a % n, nwhile low > 1:r = high // lownm, new = hm - lm * r, high - low * rlm, low, hm, high = nm, new, lm, lowreturn lm % ndef toJacobian(Xp_Yp):Xp, Yp = Xp_Ypreturn (Xp, Yp, 1)def fromJacobian(Xp_Yp_Zp, P):Xp, Yp, Zp = Xp_Yp_Zpz = inv(Zp, P)return ((Xp * z ** 2) % P, (Yp * z ** 3) % P)def jacobianDouble(Xp_Yp_Zp, A, P):Xp, Yp, Zp = Xp_Yp_Zpif not Yp:return (0, 0, 0)ysq = (Yp ** 2) % PS = (4 * Xp * ysq) % PM = (3 * Xp ** 2 + A * Zp ** 4) % Pnx = (M ** 2 - 2 * S) % Pny = (M * (S - nx) - 8 * ysq ** 2) % Pnz = (2 * Yp * Zp) % Preturn (nx, ny, nz)def jacobianAdd(Xp_Yp_Zp, Xq_Yq_Zq, A, P):Xp, Yp, Zp = Xp_Yp_ZpXq, Yq, Zq = Xq_Yq_Zqif not Yp:return (Xq, Yq, Zq)if not Yq:return (Xp, Yp, Zp)U1 = (Xp * Zq ** 2) % PU2 = (Xq * Zp ** 2) % PS1 = (Yp * Zq ** 3) % PS2 = (Yq * Zp ** 3) % Pif U1 == U2:if S1 != S2:return (0, 0, 1)return jacobianDouble((Xp, Yp, Zp), A, P)H = U2 - U1R = S2 - S1H2 = (H * H) % PH3 = (H * H2) % PU1H2 = (U1 * H2) % Pnx = (R ** 2 - H3 - 2 * U1H2) % Pny = (R * (U1H2 - nx) - S1 * H3) % Pnz = (H * Zp * Zq) % Preturn (nx, ny, nz)def jacobianMultiply(Xp_Yp_Zp, n, N, A, P):Xp, Yp, Zp = Xp_Yp_Zpif Yp == 0 or n == 0:return (0, 0, 1)if n == 1:return (Xp, Yp, Zp)if n < 0 or n >= N:return jacobianMultiply((Xp, Yp, Zp), n % N, N, A, P)if (n % 2) == 0:return jacobianDouble(jacobianMultiply((Xp, Yp, Zp), n // 2, N, A, P), A, P)if (n % 2) == 1:return jacobianAdd(jacobianDouble(jacobianMultiply((Xp, Yp, Zp), n // 2, N, A, P), A, P), (Xp, Yp, Zp), A, P)class PrivateKey:def __init__(self, curve=sm2p256v1, secret=None):self.curve = curveself.secret = secret or SystemRandom().randrange(1, curve.N)def publicKey(self):curve = self.curvexPublicKey, yPublicKey = multiply((curve.Gx, curve.Gy), self.secret, A=curve.A, P=curve.P, N=curve.N)return PublicKey(xPublicKey, yPublicKey, curve)def toString(self):return "{}".format(str(hex(self.secret))[2:].zfill(64))class PublicKey:def __init__(self, x, y, curve):self.x = xself.y = yself.curve = curvedef toString(self, compressed=True):return {True: str(hex(self.x))[2:],False: "{}{}".format(str(hex(self.x))[2:].zfill(64), str(hex(self.y))[2:].zfill(64))}.get(compressed)def create_key_pair():priKey = PrivateKey()pubKey = priKey.publicKey()return priKey.toString(), pubKey.toString(compressed=False)# 主机地址为空字符串,表示绑定本机所有网络接口ip地址
# 等待客户端来连接
IP = '127.0.0.1'
# 端口号
PORT = 4000
# 定义一次从socket缓冲区最多读入512个字节数据
BUFLEN = 2048# 实例化一个socket对象
# 参数 AF_INET 表示该socket网络层使用IP协议
# 参数 SOCK_STREAM 表示该socket传输层使用TCP协议
listenSocket = socket(AF_INET, SOCK_STREAM)# socket绑定地址和端口
listenSocket.bind((IP, PORT))# 使socket处于监听状态,等待客户端的连接请求
# 参数 5 表示 最多接受多少个等待连接的客户端
listenSocket.listen(5)
print(f'服务端启动成功,在{PORT}端口等待客户端连接...')dataSocket, addr = listenSocket.accept()
print('接受一个客户端连接:', addr)while True:# 尝试读取对方发送的消息# BUFLEN 指定从接收缓冲里最多读取多少字节recved = dataSocket.recv(BUFLEN)# 如果返回空bytes,表示对方关闭了连接# 退出循环,结束消息收发if not recved:break# 读取的字节数据是bytes类型,需要解码为字符串info = recved.decode()if info == 'user_reg':print('收到用户登记请求')print('准备登记')# 回复客户端send = '登记中'dataSocket.send(send.encode())# 登记用户register()continueif info == 'community':community()if info == 'insert':insert()if info == 'show':show()dataSocket.close()
listenSocket.close()

client.py

# 导入socket库 和 国密库
from socket import *
from random import SystemRandom
import base64
import binascii
from gmssl import sm2, func
from gmssl import sm3
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import os.path
import os
import json
# 生成密钥对模块
class CurveFp:def __init__(self, A, B, P, N, Gx, Gy, name):self.A = Aself.B = Bself.P = Pself.N = Nself.Gx = Gxself.Gy = Gyself.name = namesm2p256v1 = CurveFp(name="sm2p256v1",A=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC,B=0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93,P=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF,N=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123,Gx=0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7,Gy=0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0
)def multiply(a, n, N, A, P):return fromJacobian(jacobianMultiply(toJacobian(a), n, N, A, P), P)def add(a, b, A, P):return fromJacobian(jacobianAdd(toJacobian(a), toJacobian(b), A, P), P)def inv(a, n):if a == 0:return 0lm, hm = 1, 0low, high = a % n, nwhile low > 1:r = high // lownm, new = hm - lm * r, high - low * rlm, low, hm, high = nm, new, lm, lowreturn lm % ndef toJacobian(Xp_Yp):Xp, Yp = Xp_Ypreturn (Xp, Yp, 1)def fromJacobian(Xp_Yp_Zp, P):Xp, Yp, Zp = Xp_Yp_Zpz = inv(Zp, P)return ((Xp * z ** 2) % P, (Yp * z ** 3) % P)def jacobianDouble(Xp_Yp_Zp, A, P):Xp, Yp, Zp = Xp_Yp_Zpif not Yp:return (0, 0, 0)ysq = (Yp ** 2) % PS = (4 * Xp * ysq) % PM = (3 * Xp ** 2 + A * Zp ** 4) % Pnx = (M ** 2 - 2 * S) % Pny = (M * (S - nx) - 8 * ysq ** 2) % Pnz = (2 * Yp * Zp) % Preturn (nx, ny, nz)def jacobianAdd(Xp_Yp_Zp, Xq_Yq_Zq, A, P):Xp, Yp, Zp = Xp_Yp_ZpXq, Yq, Zq = Xq_Yq_Zqif not Yp:return (Xq, Yq, Zq)if not Yq:return (Xp, Yp, Zp)U1 = (Xp * Zq ** 2) % PU2 = (Xq * Zp ** 2) % PS1 = (Yp * Zq ** 3) % PS2 = (Yq * Zp ** 3) % Pif U1 == U2:if S1 != S2:return (0, 0, 1)return jacobianDouble((Xp, Yp, Zp), A, P)H = U2 - U1R = S2 - S1H2 = (H * H) % PH3 = (H * H2) % PU1H2 = (U1 * H2) % Pnx = (R ** 2 - H3 - 2 * U1H2) % Pny = (R * (U1H2 - nx) - S1 * H3) % Pnz = (H * Zp * Zq) % Preturn (nx, ny, nz)def jacobianMultiply(Xp_Yp_Zp, n, N, A, P):Xp, Yp, Zp = Xp_Yp_Zpif Yp == 0 or n == 0:return (0, 0, 1)if n == 1:return (Xp, Yp, Zp)if n < 0 or n >= N:return jacobianMultiply((Xp, Yp, Zp), n % N, N, A, P)if (n % 2) == 0:return jacobianDouble(jacobianMultiply((Xp, Yp, Zp), n // 2, N, A, P), A, P)if (n % 2) == 1:return jacobianAdd(jacobianDouble(jacobianMultiply((Xp, Yp, Zp), n // 2, N, A, P), A, P), (Xp, Yp, Zp), A, P)class PrivateKey:def __init__(self, curve=sm2p256v1, secret=None):self.curve = curveself.secret = secret or SystemRandom().randrange(1, curve.N)def publicKey(self):curve = self.curvexPublicKey, yPublicKey = multiply((curve.Gx, curve.Gy), self.secret, A=curve.A, P=curve.P, N=curve.N)return PublicKey(xPublicKey, yPublicKey, curve)def toString(self):return "{}".format(str(hex(self.secret))[2:].zfill(64))class PublicKey:def __init__(self, x, y, curve):self.x = xself.y = yself.curve = curvedef toString(self, compressed=True):return {True: str(hex(self.x))[2:],False: "{}{}".format(str(hex(self.x))[2:].zfill(64), str(hex(self.y))[2:].zfill(64))}.get(compressed)def create_key_pair():priKey = PrivateKey()pubKey = priKey.publicKey()return priKey.toString(), pubKey.toString(compressed=False)# 用户界面def loginmenm(): #登录print('==========================加密通信系统==========================')print('---------------------------登录界面----------------------------')print('\t\t\t   1.登录')print('\t\t\t   2.注册')print('\t\t\t   0.退出系统')print('-------------------------------------------------------------------')def menm():  # 菜单print('==========================加密通信系统==========================')print('---------------------------功能选项----------------------------')print('\t\t\t   1.与服务器通信')print('\t\t\t   2.录入学生信息')print('\t\t\t   3.查看学生信息')print('\t\t\t   0.退出登录')print('-------------------------------------------------------------------')# 文件名
filename = 'userlist.txt'# 服务器公钥
server_pubKey = b'd053f19eb5b2fcd94714f8c4f6d4c64c5dc3b2fd4c061896ffb512261f2a6c53b64e67dcc6e66a55db78200900e77563568d0d9990496f5ecd81eba3582f85be'IP = '127.0.0.1'
SERVER_PORT = 4000
BUFLEN = 2048# 实例化一个socket对象,指明协议
dataSocket = socket(AF_INET, SOCK_STREAM)# 连接服务端socket
dataSocket.connect((IP, SERVER_PORT))def main():  # 主程序while True:global numnum = '0'loginmenm()choice = int(input('请选择>>>'))if choice in [0, 1, 2]:if choice == 0:answer = input('您确定要退出系统吗?y/n>>>')if answer == 'y' or answer == 'Y':print('谢谢您的使用!!!')break  # 退出系统else:continueelif choice == 2:register()elif choice == 1:login()while num != '0':menm()choice = int(input('请选择>>>'))if choice in [0, 1, 2, 3]:if choice == 0:answer = input('您确定要退出登录吗?y/n>>>')if answer == 'y' or answer == 'Y':print('谢谢您的使用!!!')break  # 退出系统else:continueelif choice == 1:community(num) # 与服务器通信elif choice == 2:insert(num)elif choice == 3:show(num)
def insert(num):  # 插入信息send = 'insert'dataSocket.send(send.encode())sendname = numdataSocket.send(sendname.encode())name = numgethubkey = []with open(filename, 'r', encoding='utf-8') as rfile:date = rfile.readlines()for item in date:d = dict(eval(item))if name != '':if d['用户名'] == num:gethubkey.append(d)for getkey in gethubkey:hubkey = getkey.get('会话共享密钥')while True:  # 循环输入id = input('请输入ID(如1001):')if not id:  # 防止手滑breakname = input('请输入姓名:')if not name:breaktry:english = int(input('请输入英语成绩:'))python = int(input('请输入python成绩:'))java = int(input('请输入Java成绩:'))except:print('输入无效,不是整数类型,请重新输入')continue# 将录入的学生信息保存到字典当中student = {'id': id, 'name': name, 'english': english, 'python': python, 'java': java}answer = input('是否继续添加?y/n\n')if answer == 'y':continueelse:break# 将字典转换成json格式的字符串student_json = json.dumps(student)# 将字符串转换成二进制数据流send_data = student_json.encode('utf-8')# 初始化sm4crypt_sm4 = CryptSM4()crypt_sm4.set_key(hubkey.encode(), SM4_ENCRYPT)encrypt_tosend = crypt_sm4.crypt_ecb(send_data)print('发送加密后学生信息:', encrypt_tosend)# 发送数据dataSocket.send(encrypt_tosend)recved = dataSocket.recv(BUFLEN)print('收到浏览器回复:', recved.decode())def show(num):send = 'show'dataSocket.send(send.encode())sendname = numdataSocket.send(sendname.encode())name = numgethubkey = []with open(filename, 'r', encoding='utf-8') as rfile:date = rfile.readlines()for item in date:d = dict(eval(item))if name != '':if d['用户名'] == num:gethubkey.append(d)for getkey in gethubkey:hubkey = getkey.get('会话共享密钥')student_recv = dataSocket.recv(BUFLEN)print('收到加密学生信息:', student_recv)print('解密结果为')# 初始化crypt_sm4 = CryptSM4()crypt_sm4.set_key(hubkey.encode(), SM4_DECRYPT)decrypt_date = crypt_sm4.crypt_ecb(student_recv)students = decrypt_date.decode()if students:show_student(eval(students))def show_student(lst):if len(lst) == 0:print('没有查询到学生信息,无数据显示!!!')return# 定义标题显示格式format_title = '{:^6}\t{:^12}\t{:^8}\t{:^10}\t{:^10}\t{:^8}'print(format_title.format('ID', '姓名', '英语成绩', 'python成绩', 'java成绩', '总成绩'))# 定义内容的显示格式format_data = '{:^6}\t{:^12}\t{:^8}\t{:^10}\t{:^10}\t{:^8}'for item in lst:print(format_data.format(item.get('id'),item.get('name'),item.get('english'),item.get('python'),item.get('java'),int(item.get('english')) + int(item.get('python')) + int(item.get('java'))))def community(num):send = 'community'dataSocket.send(send.encode())sendname = numdataSocket.send(sendname.encode())name = numgethubkey = []while True:# 从终端读入用户输入的字符串toSend = input('>>> ')if toSend == 'exit':break# 获取共享密钥with open(filename, 'r', encoding='utf-8') as rfile:date = rfile.readlines()for item in date:d = dict(eval(item))if name != '':if d['用户名'] == num:gethubkey.append(d)for getkey in gethubkey:hubkey = getkey.get('会话共享密钥')# 初始化sm4crypt_sm4 = CryptSM4()crypt_sm4.set_key(hubkey.encode(), SM4_ENCRYPT)encrypt_tosend = crypt_sm4.crypt_ecb(toSend.encode())dataSocket.send(encrypt_tosend)# 等待接收服务端的消息recved = dataSocket.recv(BUFLEN)# 如果返回空bytes,表示对方关闭了连接if not recved:break# 打印读取的信息crypt_sm4.set_key(hubkey.encode(), SM4_DECRYPT)decrypt_date = crypt_sm4.crypt_ecb(recved)info = decrypt_date.decode()print(f'收到对方信息密文: {recved}')print(f'解密后明文为: {info}')def login(): # 登录password_query = []global numwhile True:if os.path.exists(filename):  # 如果可以打开文件name = input('请输入用户名:')psd = input('请输入密码:')gethubkey = []with open(filename, 'r', encoding='utf-8') as rfile:date = rfile.readlines()for item in date:d = dict(eval(item))if name != '':if d['用户名'] == name:gethubkey.append(d)for getkey in gethubkey:hubkey = getkey.get('会话共享密钥')with open(filename, 'r', encoding='utf-8') as rfile:date = rfile.readlines()for item in date:d = dict(eval(item))if name != '':if d['用户名'] == name:password_query.append(d)for getpassword in password_query:getpd = getpassword.get('密码')crypt_sm4 = CryptSM4()crypt_sm4.set_key(hubkey.encode(), SM4_DECRYPT)decrypt_value = crypt_sm4.crypt_ecb(getpd)if psd == decrypt_value.decode():print('密码正确')num = namereturn numelse:print('输入错误')num = '0'return numdef register(): # 注册user_list = []# 为新用户生成密钥对priKey = PrivateKey()pubKey = priKey.publicKey()while True:  # 循环输入username = input('请输入用户名:')if not username:  # 防止手滑breakpassword = input('请输入密码:')if not password:  # 防止手滑break# 发送用户信息至服务器登记print('发送用户登记请求')send_register = 'user_reg'dataSocket.send(send_register.encode())recved = dataSocket.recv(BUFLEN)print('收到服务器回复:',recved.decode())  #登记中# 发送用户信息print('发送用户信息')# 写入字典send_list=  {'用户名': username,'用户公钥':pubKey.toString(compressed=False)}# 将字典转换成json格式的字符串send_list_json= json.dumps(send_list)# 将字符串转换成二进制数据流enc_send_list= send_list_json.encode('utf-8')# 发送用户数据流dataSocket.send(enc_send_list)recved = dataSocket.recv(BUFLEN)print('收到服务器回复:',recved.decode()) #登记完成# 发送共享密钥请求print('发送共享密钥获取请求')toSend = 'get_hubkey'enc_toSend = toSend.encode()dataSocket.send(enc_toSend)# 获取服务器回复recved = dataSocket.recv(BUFLEN)# 将二进制数据流转换成字符串dec_date_json = recved.decode('utf-8')# 将json格式字符串转换成字典digital = json.loads(dec_date_json)print('收到服务器回复:', digital)# 初始化sm2算法,己方私钥解密,对方公钥验签sm2_crypt = sm2.CryptSM2(public_key=server_pubKey.decode(), private_key=priKey.toString())# 获得随机密钥enc_random_key = digital.get('E(随机密钥)')dec_random_key = sm2_crypt.decrypt(base64.b64decode(enc_random_key.encode()))  # byte# 获得共享密钥encrypt_hubkey = digital.get('E(共享密钥)')key = dec_random_keycrypt_sm4 = CryptSM4()crypt_sm4.set_key(key, SM4_DECRYPT)decrypt_hubkey = crypt_sm4.crypt_ecb(base64.b64decode(encrypt_hubkey.encode())) # byte# 生成共享密钥的信息摘要summary = sm3.sm3_hash(func.bytes_to_list(decrypt_hubkey))# 验证签名sign = digital.get('数字签名')result = sm2_crypt.verify(sign, summary.encode())if result:print('验证成功,收到共享密钥为:',decrypt_hubkey.decode())else:print('验证失败')# 用共享密钥加密密码crypt_sm4 = CryptSM4()crypt_sm4.set_key(decrypt_hubkey, SM4_ENCRYPT)encrypt_password = crypt_sm4.crypt_ecb(password.encode())# 将录入的学生信息保存到字典当中list = {'用户名': username, '密码': encrypt_password,'用户公钥':pubKey.toString(compressed=False) , '用户私钥':priKey.toString() , '会话共享密钥':decrypt_hubkey.decode()}# 将学生信息添加到列表中user_list.append(list)answer = input('是否继续添加?y/n\n')if answer == 'y':continueelse:break# 调用save()函数save(user_list)print('用户注册完毕!!!''')def save(lst):  # 保存信息try:user_txt = open(filename, 'a', encoding='utf-8')except:user_txt = open(filename, 'w', encoding='utf-8')for item in lst:user_txt.write(str(item) + '\n')  # 将内容写入文件中if __name__ == '__main__':main()dataSocket.close()

主要功能的流程图

用户注册流程图:

  1. 用户选择注册功能,输入用户名和密码
  2. 为新用户生成密钥对,并向服务器发送登记请求
  3. 服务器接收登记请求,调用登记函数,并回复客户端
  4. 客户端接收回复,并将用户名和公钥,发送至服务器
  5. 服务器接收用户信息,并生成共享密钥
  6. 将用户信息和共享密钥写入密钥列表文件,回复客户端登记完成
  7. 客户端收到回复,并发送获取共享密钥请求
  8. 服务器接收请求,走密钥分发的发送流程
  9. 客户端走密钥分发的接收流程,获取共享密钥
  10. 客户端将用户所有信息和共享密钥写入用户列表文件

登录和查看信息流程图:

(1)客户端用户登录,输入用户名和密码,读取用户列表文件,获取加密的密码,解密对比验证密码

(2)登录成功,选择学生信息查看功能,向服务器发送查看请求

(3)服务器接收请求运行查看函数

(4)读取学生信息文件,并用共享密钥加密,发送至客户端

(5)客户端用共享密钥解密信息,并打印

登录和加密交流流程图: 

  1. 客户端用户登录,输入用户名和密码,读取用户列表文件,获取加密的密码,解密对比验证密码
  2. 登录成功,选择加密交流功能,向服务器发送交流请求
  3. 服务器接收交流请求运行交流函数
  4. 客户端输入信息,并用共享密钥加密,发送至服务器
  5. 服务器根据用户名,读取密钥列表文件,获取共享密钥,解密得到信息
  6. 服务器用对应的共享密钥加密信息进行回复
  7. 循环交流
  8. 客户端输入exit可退出交流功能

登录和录入信息流程图:

(1)客户端用户登录,输入用户名和密码,读取用户列表文件,获取加密的密码,解密对比验证密码

(2)登录成功,选择学生信息录入功能,向服务器发送录入请求

(3)服务器接收录入请求,运行录入函数

(4)客户端输入学生信息,用共享密钥加密发送至服务器

(5)服务器接收加密信息,用共享密钥进行解密,将得到的学生信息写入,学生信息文件,并回复客户端录入完成

(5)客户端接收回复,提示用户是否继续录入

应用密码学课程设计 密钥分发相关推荐

  1. 密码学课程设计之DES对称加密

    前言 最近在进行密码学课程设计, 感觉拿python进行设计会显得比较简洁易懂,本人python比较渣渣,所以就拿出来练一练.用零零碎碎的时间写了五六天才把主干部分写完,真是菜哭我自己了.在此还需要感 ...

  2. 基于C++的文件加密解密(密码学课程设计)

    资源下载地址:https://download.csdn.net/download/sheziqiong/86882054 资源下载地址:https://download.csdn.net/downl ...

  3. 密码学课程设计——多人加密聊天系统

    实验设计要求: 模块: 用户认证:数字签名方案 信息加密:公钥加密方案 信息隐藏:LSB方案 要求: 实现登陆验证,信息发送和接收(文本和图片),信息加密解密,信息签名和签名验证 关键代码解释说明: ...

  4. 线性代数应用于计算机科学例子,线性代数课程设计_线性代数在密码学中的应用...

    科技展望 2015/24 线性代数课程设计 --线性代数在密码学中的应用 郑 欣 (沈阳理工大学,辽宁 沈阳 110168) [摘 要]线性代数是工科本科教育的基础学科,在教学过程中,经常注重理论学习 ...

  5. [密码学] 密钥分发

    文章目录 对称密码的密钥分发 安全性要求 物理亲自交付 用就密钥加密新密钥 依赖于第三方进行加密分发 大型网络的KDC层级体系 Needham-Schroeder协议 Denning-Sacco攻击 ...

  6. 实现两个主机之间的密钥分发和安全传输

    实现两个主机之间的密钥分发和安全传输 一.设计要求 编写一段程序,实现两个主机之间的密钥分发和安全传输. 要求: 用 RSA 算法实现两个主机之间的密钥分发,分发的密钥为 0x 01 23 45 67 ...

  7. 量子通信利用量子力学原理产生密钥对信息进行加密和解密,并采用量子纠缠效应进行密钥分发,被认为是当今最安全的通信系统.有两项特性,一个是不可分割,一个是不可复制...

    中国量子通信第一人详解量子通信技术 2016-08-16 半导体行业观察 尖端科技背后的故事 量子通信是基于量子力学基本原理的前沿技术.近年来,以潘建伟团队为代表的中国科学家在量子通信领域取得了举世瞩 ...

  8. 数据库课程设计测试部分_实用的数据库设计,第1部分

    数据库课程设计测试部分 在本系列文章中,我将讨论一些特别有用的常规最佳实践. 其中没有任何内容是特定于任何供应商的产品的,因此,无论使用哪种数据库实现,所有内容都应适用. 在本文的第一部分中,我想讨论 ...

  9. c语言课程设计宋军答案,C语言课程设计实习报告封面

    <C语言课程设计实习报告封面>由会员分享,可在线阅读,更多相关<C语言课程设计实习报告封面(27页珍藏版)>请在人人文库网上搜索. 1.信息安全基础课程设计姓 名: 范相地 学 ...

最新文章

  1. /etc/rsyncd.conf
  2. Objective-C中对Url的参数进行编码
  3. 5G 网络接口与基础流程
  4. python 枚举相等判断_python中is和==的区别
  5. 寻找 ASP.NET 2.0 老师
  6. 拉普拉斯方程之美:万物的数学之匙
  7. mysql安装需要注意什么意思_mysql 安装过程及注意事项
  8. 理解Linux下的SELinux(MAC)
  9. cpan安装_生信平台搭建(五):安装perl模块
  10. Android官方多渠道方案详解
  11. springboot框架学习理解上
  12. jquery has 返回拥有匹配指定选择器的一个或多个元素在其内的所有元素
  13. pyqt5设置dialog的标题_PyQt5教程——对话框(6)
  14. RemCom.XFDTD.Bio-Pro.v6.3.8.4
  15. deglitch 技术_fdc2214中文资料-技术参考.pdf
  16. 二次型特征值的猜根法应用
  17. Python 简单的人名对话
  18. Java常用类字符串异常处理
  19. 代价函数,损失函数,目标函数区别
  20. 实战案例 :电信客户流失分析与预测

热门文章

  1. 罗技G29+Carla+实车twist三者互相控制以及三者联调
  2. 解决VS2013异常详细信息: System.ComponentModel.Composition.ImportCardinalityMismatchException: 未找到与约束
  3. 量化投资:一种可持续性的赚钱效应
  4. linux 运行msi文件是什么意思,linux msi文件怎么安装
  5. linux mint资源占用,linux mint使用感受
  6. JavaScript 新提案:array.groupBy()
  7. JS——Url 转码、获取Url上的参数
  8. Python3之hashlib
  9. vue3打包时提示 TS2322:Type ‘() => void‘ is not assignable to type ‘MouseEvent‘.
  10. 连接器信号完整性仿真教程 一