西电大数据安全与隐私(现代密码学基础技能)

ops/2024/9/23 2:54:04/

西电大数据安全隐私(现代密码学基础技能)

大数据安全隐私这门课的lab1,要求如下图:

请添加图片描述

采用的方案是RSA和AES相结合, 利用RSA来加密传输AES的密钥, 用AES的密钥来加密数据. 如果使用RSA加密数据, 虽然安全性会更高, 但效率低. AES加解密效率高, 但安全性会差一些, 所以采用RSA加密AES的密钥, 然后用AES加密数据, 这样既保证了效率也保证了安全性.

为了保证相同文件每次发送的加密文件不同, 将随机生成的秘钥与当前时间戳结合为随机AES秘钥. 注释写得很详细了, 有些细节的东西我就不解释了.

运行结果如下:

请添加图片描述

请添加图片描述

服务端代码
import sys
import threading
import socket
import struct
from Crypto.Cipher import AES
import rsa
import timeiv = '1425374853627180'  # 初始向量
BUFF = 1024# 去除末尾填充字符
def unpadding(text):length = len(text)print(text[length - 1])return text[0:length - text[length - 1]]def socket_service():try:s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#  设置socket可以重用已绑定地址s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)s.bind(('localhost', 9001))  # 绑定端口为9001s.listen(10)  # 设置监听数,最多允许10个客户端连接except socket.error as msg:print(msg)sys.exit(1)print('等待连接...')while 1:# 调用accept阻塞: 等待请求并接受(程序会停留在这一旦收到连接请求即开启接受数据的线程)conn, addr = s.accept()# 接收数据t = threading.Thread(target=deal_data, args=(conn, addr))t.start()def deal_data(conn, addr):print('接收到来自 {0}的连接'.format(addr))# 收到请求后的回复conn.send('welcome!'.encode('utf-8'))key = ""while 1:if not key:s1_recv_data = conn.recv(BUFF)if s1_recv_data.decode('utf-8') == 'changekey':print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + ' 开始交换秘钥!')# 使用RSA产生一对公钥和私钥(pubkey, privkey) = rsa.newkeys(512, poolsize=8)print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + ' 创建RSA秘钥对!')# 将公钥模数和指数发送给客户端modulus = pubkey.nexponent = pubkey.econn.send(str(modulus).encode('utf-8'))conn.send(str(exponent).encode('utf-8'))print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + ' 发送RSA公钥')# 服务端收到消息key = conn.recv(BUFF)print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) + ' 接收加密后的AES秘钥:' + key.decode('utf8','ignore'))# 服务端用私钥进行解密,得到AES密钥key = rsa.decrypt(key, privkey)print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + ' 解密AES秘钥中')key = key.decode()print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + ' AES秘钥:' + key)# 申请相同大小的空间存放发送过来的文件名与文件大小信息fileinfo_size = struct.calcsize('128sl')# 接收文件名与文件大小信息buf = conn.recv(fileinfo_size)# 判断是否接收到文件头信息if buf:# 获取文件名和文件大小filename, filesize = struct.unpack('128sl', buf)fn = filename.strip(b'\00')fn = fn.decode()print('文件名是 {0}, 文件大小是 {1}'.format(str(fn), filesize))recvd_size = 0  # 定义已接收文件的大小# 存储在该脚本所在目录下面fp = open('./' + str(fn), 'wb')print('开始接收...')if not filesize % 16 == 0:filesize += 16 - filesize % 16# 将分批次传输的二进制流依次写入到文件while not recvd_size == filesize:if filesize - recvd_size > 1024:data = conn.recv(1024)recvd_size += len(data)else:data = conn.recv(filesize - recvd_size)recvd_size = filesizeprint(len(data))print(data)# 将加密数据转换位bytes类型数据cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, iv.encode('utf8'))text_decrypted = cipher.decrypt(data)print(len(text_decrypted))print(text_decrypted)if len(text_decrypted) < 1024:text_decrypted = unpadding(text_decrypted)print(text_decrypted)fp.write(text_decrypted)fp.close()print('结束接收...')# 传输结束断开连接conn.close()breakif __name__ == "__main__":socket_service()
客户端代码
import socket
import os
import sys
import struct
from Crypto.Cipher import AES
import time
import rsakey0 = os.urandom(16).hex()  # 随机生成秘钥,16位字符串
iv = '1425374853627180'  # 初始向量
BUFF = 1024def padding(text):bs = AES.block_size  # 16字节length = len(text)   # 获取明文长度,字符bytes_length = len(bytes(text, encoding='utf-8'))padding = length if (bytes_length == length) else bytes_lengthpadding_size = bs - padding % bspadding_text = chr(padding_size) * padding_size   # 按照PKCS7填充方式生成填充文本return text + padding_text# 函数功能:对明文进行PKCS7填充
# 参数text:需要填充的明文
# 返回值:填充后的明文def socket_client():try:# 创建socket,ipv4+流s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect(('localhost', 9001))except socket.error as msg:print(msg)sys.exit(1)print(s.recv(1024))# 加上给密钥加上时间戳,保证相同的明文,每次发送的密文不同t = time.time()t_str = str(int(t))key = key0[0:8] + t_str[2:10]  # 取key0前八位和时间戳中的后八位生成新keyprint(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + ' 开始交换秘钥!')s.send('changekey'.encode('utf-8'))modulus = int(s.recv(BUFF).decode('utf-8'))  # 接收公钥模数exponent = int(s.recv(BUFF).decode('utf-8'))  # 接收公钥指数print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + ' 开始构建RSA公钥')pubkey = rsa.PublicKey(modulus, exponent)  # 构建公钥print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + ' 加密AES秘钥')crypto = rsa.encrypt(key.encode('utf-8'), pubkey)  # 用RSA公钥对AES密钥进行加密print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + ' 发送加密后的AES秘钥:' + crypto.decode('utf8', 'ignore'))s.send(crypto)  # 发送加密后的AES密钥# 需要传输的文件路径filepath = 'C:/XingYan/1.png'# 判断是否为文件if os.path.isfile(filepath):# 定义定义文件信息。128s表示文件名为128bytes长,l表示一个int或long,在此为文件大小fileinfo_size = struct.calcsize('128sl')# 打包文件名和大小filehead = struct.pack('128sl', os.path.basename(filepath).encode('utf-8'), os.stat(filepath).st_size)s.send(filehead)# 将传输文件以二进制的形式分多次上传至服务器fp = open(filepath, 'rb')while 1:data = fp.read(1024)print(data)if not data:print('{0} 发送结束...'.format(os.path.basename(filepath)))breakif len(data) < 1024:newdata = data.decode('utf8', 'ignore')print(len(newdata))newdata = padding(newdata)print(len(newdata))data = newdata.encode('utf8')cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, iv.encode('utf8'))  # AES加密对象encryptedbytes = cipher.encrypt(data)s.send(encryptedbytes)print(encryptedbytes)print(len(encryptedbytes))s.close()if __name__ == '__main__':socket_client()

欢迎访问我的个人博客www.levitategu.cn


http://www.ppmy.cn/ops/30243.html

相关文章

SpringBoot使用git-commit-id-maven-plugin打包

简介 git-commit-id-maven-plugin 是一个maven 插件&#xff0c;用来在打包的时候将git-commit 信息打进jar中。 这样做的好处是可以将发布的某版本和对应的代码关联起来&#xff0c;方便查阅和线上项目的维护。至于它的作用&#xff0c;用官方说法&#xff0c;这个功能对于大…

《原则》生活和工作 - 三余书屋 3ysw.net

原则&#xff1a;生活和工作 您好&#xff0c;今天我们解读的书是《原则&#xff1a;生活和工作》。这本书和我们之前解读过的《原则&#xff1a;应对变化中的世界秩序》是同一个作者写的。那本书的主题非常宏大&#xff0c;它讨论的是世界运行的原则。而今天我们聊的《原则&a…

selenium 4.x 之验证码处理(python)

验证码处理 一般情况公司如果涉及web自动化测试需要对验证码进行处理的方式一般有一下几种&#xff1a; 关闭验证码功能&#xff08;开发处理&#xff09;设置万能验证码&#xff08;开发处理&#xff09;使用智能识别库进行验证 通过第三方打码平台识别验证码 1. 跳过验证功…

php使用Canal监听msyql

canal需要java8 去官网下载java8 安装JAVA #创建目录 mkdir -p /usr/local/java/ #解压到目录 tar zxvf jdk-8u411-linux-x64.tar.gz -C /usr/local/java/配置环境变量在 /etc/profile 最后加入 export JAVA_HOME/usr/local/java/jdk1.8.0_411 export CLASSPATH.:$JAVA_HOM…

C++ stack和queue的使用方法与模拟实现

文章目录 一、 stack的使用方法二、 queue的使用方法三、 容器适配器四、 stack的模拟实现五、 queue的模拟实现 一、 stack的使用方法 stack介绍文档 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的…

Python中覆盖类属性最好的方法

Python中有一个很独特的功能,类属性可为实例属性提供默认值。下面Person类中有一个名为current_year的类属性。compute_age方法中用到了这个属性,而且都故意使用self.current_year读取它的值。因为Person本身没有current_year这个实例属性,所以self.current_year默认获取的是…

学习100个Unity Shader (16) --- 程序纹理简述

文章目录 理解参考 理解 程序纹理顾名思义&#xff0c;就是通过代码生成的纹理&#xff0c;然后传入材质&#xff0c;生成图像。 假设&#xff0c;给一个模型添加了材质&#xff0c;并赋予了一个shader。shader中有一个纹理属性叫_MainTex。 程序纹理简单来说就是&#xff0c;…

spring源码分析之上下文构建

源码分析之上下文构建 以ClassPathXmlApplicationContext为例来说明 ApplicationContext context new ClassPathXmlApplicationContext("spring-lifecycle.xml"); 一个简单地创建ApplicationContext实例的方法&#xff0c;spring会做什么事呢&#xff1f; // this(n…