RSA+AES混合加密机制

基于python,可以实现任意文件的加解密,源码放在资料区

  • 实验的目的与要求

1.目的:设计实现一种实现消息认证的通信方案

2.要求:

2.1基本功能:设计实现一种实现消息认证的通信(基于对称密钥的、基于数字签

名的、基于仲裁方的等,任选)方案,至少实现对消息来源认证、完整性检查功能,

考虑抗抵赖、抗合谋攻击等功能。

2.2扩展功能:要求有图形界面、可对多种文件类型进行通信认证(可选择文件路

径)、对认证的消息进行正确性验证。

二、实验正文

  1. 通信方案基本结构
    1. 实验原理

首先给发送方A和接收方B分配两者的公私钥,A将文件转化成二进制流,然后产生随机的32字节AES密钥。A先用hash256产生定长为32字节的消息摘要,通过RSA算法用A的私钥对消息摘要进行签名,将明文,消息摘要和数字签名拼接用AES密钥加密产生初始化向量iv和密文ct,再用B的公钥对AES密钥进行加密,最后把初始化向量iv,密文ct加密后后的AES密钥拼接发送给B。

B接收后先别拆出iv,ct和加密后的AES密钥,用B的私钥先解出原始的AES密钥,再解出明文,消息摘要和数字签名,对消息摘要和数字签名进行验证。

    1. 逻辑图

2.代码实现

    2.1生成AB的公私钥,并保存为pem文件,防止私钥泄露

    from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend

Aprivate_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)
Apublic_key = Aprivate_key.public_key()
Bprivate_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)
Bpublic_key = Bprivate_key.public_key()
# Apublic_key, Aprivate_key = rsa.newkeys(2048)
# Bpublic_key, Bprivate_key = rsa.newkeys(2048)
with open('Aprivate_key.pem', 'wb') as file:
    private_key_pem = Aprivate_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption()
    )
    file.write(private_key_pem)

# 将公钥保存到文件
with open('Apublic_key.pem', 'wb') as file:
    public_key_pem = Apublic_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
    )
    file.write(public_key_pem)

with open('Bprivate_key.pem', 'wb') as file:
    private_key_pem = Bprivate_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption()
    )
    file.write(private_key_pem)

# 将公钥保存到文件
with open('Bpublic_key.pem', 'wb') as file:
    public_key_pem = Bpublic_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
    )
    file.write(public_key_pem)

def load_rsa_public_key(public_key_path):
    with open(public_key_path, 'rb') as key_file:
        public_key = serialization.load_pem_public_key(
            key_file.read(),
            backend=default_backend()
        )
    return public_key


def loader_Aprivate_key():
    with open('Aprivate_key.pem', 'rb') as file:
        Aprivate_key = serialization.load_pem_private_key(
            file.read(),
            password=None
        )
    return Aprivate_key

2.2读取pem文件

def read_pem_key(file_path):
    with open(file_path, 'r') as f:
        key = RSA.import_key(f.read())
    return key

2.3AES密钥的加解密

def read_pem_key(file_path):
    with open(file_path, 'r') as f:
        key = RSA.import_key(f.read())
    return key

def decrypt_aes_key_with_rsa(private_key_file, encrypted_aes_key):
    private_key = read_pem_key(private_key_file)
    cipher_rsa = PKCS1_OAEP.new(private_key)
    decrypted_aes_key = cipher_rsa.decrypt(encrypted_aes_key)
    return decrypted_aes_key

2.3用AES加解密明文

def encrypt_message_with_aes(message, aes_key):
    cipher_aes = AES.new(aes_key, AES.MODE_CBC)
    ct_bytes = cipher_aes.encrypt(pad(message, AES.block_size))
    iv = b64encode(cipher_aes.iv).decode('utf-8')
    ct = b64encode(ct_bytes).decode('utf-8')
    return iv, ct

def decrypt_message_with_aes(iv, ct, aes_key):
    iv = b64decode(iv)
    ct = b64decode(ct)
    cipher_aes = AES.new(aes_key, AES.MODE_CBC, iv)
    pt_bytes = unpad(cipher_aes.decrypt(ct), AES.block_size)
    return pt_bytes

2.4消息摘要的生成和验证,验证数据的完整性

def generate_digest(message):
    hasher = hashlib.sha256()
    hasher.update(message)
    digest = hasher.hexdigest()
    return digest

def verify_digest(message, digest):
    expected_digest = generate_digest(message)
    return digest == expected_digest

2.5数字签名的生成和验证,验证消息来源的正确性

def sign_message_with_rsa(private_key_file, message):
    with open(private_key_file, "rb") as key_file:
        key = RSA.import_key(key_file.read())

    # 将消息转换为字节类对象
    message_bytes = message.encode('utf-8')

    # 使用 SHA256 哈希算法处理消息
    hash_obj = SHA256.new(message_bytes)

    # 使用 RSA 私钥对哈希值进行签名
    signer = pkcs1_15.new(key)
    signature = signer.sign(hash_obj)

    return signature

def verify_signature_with_rsa(public_key_file, message, signature):
    with open(public_key_file, "rb") as key_file:
        key = RSA.import_key(key_file.read())

    # 将消息转换为字节类对象
    message_bytes = message

    # 使用 SHA256 哈希算法处理消息
    hash_obj = SHA256.new(message_bytes)

    # 使用 RSA 公钥验证签名
    verifier = pkcs1_15.new(key)
    try:
        verifier.verify(hash_obj, signature)
        return True
    except (ValueError, TypeError):
        return False

2.6图形界面实现代码,采用place()方法

root=tk.Tk()
root.title('测试窗口')
root.geometry('500x300+500+250')

frame1=tk.Frame(root)
tk.Label(frame1,text='选择你的身份',font=("Simsun",16),pady=10).place(relx=0.37,rely=0.15,anchor='w')
button_sender=tk.Button(frame1, text="发送方",font=("SimSun", 14),command=open_frame2)
button_sender.place(relx=0.42,rely=0.31,anchor='w')
button_receiver=tk.Button(frame1, text="接受方",font=("SimSun", 14),command=open_frame4)
button_receiver.place(relx=0.42,rely=0.5,anchor='w')
frame1.pack(fill=tk.BOTH, expand=True)

frame2=tk.Frame(root)
tk.Label(frame2,text='根据标签中的内容提供相应的文件',font=("Simsun",16),pady=10).place(relx=0.05,rely=0.15,anchor='w')
tk.Label(frame2, text="源文件:",font=("SimSun", 14),pady=10).place(relx=0.05,rely=0.31,anchor='w')
entry_message=tk.Entry(frame2, width=23,font=("SimSun", 14))
entry_message.place(relx=0.3,rely=0.31,anchor='w')
button_message= tk.Button(frame2, text="选择路径",font=("SimSun", 14), command=select_message_file)
button_message.place(relx=0.8,rely=0.31,anchor="w")
tk.Label(frame2,text='A私钥pem文件:',font=("SimSun", 14),padx=0,pady=9).place(relx=0.05,rely=0.43,anchor='w')
entry_Aprivate_send = tk.Entry(frame2, width=23,font=("SimSun", 14))
entry_Aprivate_send.place(relx=0.3,rely=0.43,anchor="w")
button_Aprivate= tk.Button(frame2, text="选择路径",font=("SimSun", 14), command=select_Aprivate_key_file)
button_Aprivate.place(relx=0.8,rely=0.43,anchor="w")
tk.Label(frame2,text='B公钥pem文件:',font=("SimSun", 14),padx=0,pady=0).place(relx=0.05,rely=0.55,anchor="w")
entry_Bpublic_send= tk.Entry(frame2, width=23,font=("SimSun", 14))
entry_Bpublic_send.place(relx=0.3,rely=0.55,anchor="w")
button_Bpubic= tk.Button(frame2, text="选择路径",font=("SimSun", 14), command=select_Bpublic_key_file)
button_Bpubic.place(relx=0.8,rely=0.55,anchor="w")
button_encrypt= tk.Button(frame2, text="加密文件",font=18,command=sender)
button_encrypt.place(relx=0.4,rely=0.7,anchor='w')
#frame2.pack(fill=tk.BOTH, expand=True)

frame3=tk.Frame(root)
tk.Label(frame3,text='选择加密文件另存为地址',font=("Simsun",16),pady=10).place(relx=0.26,rely=0.15,anchor='w')
button_choice= tk.Button(frame3, text="选择路径",font=("SimSun", 14), command=loader_sum_message_file)
button_choice.place(relx=0.4,rely=0.31,anchor='w')
button_back31= tk.Button(frame3, text="返回重新选择",font=("SimSun", 14), command=open_frame31)
button_back31.place(relx=0.36,rely=0.5,anchor='w')
#frame3.pack(fill=tk.BOTH, expand=True)

frame4=tk.Frame(root)
tk.Label(frame4,text='根据标签中的内容提供相应的文件',font=("Simsun",16),pady=10).place(relx=0.05,rely=0.15,anchor='w')
tk.Label(frame4, text="加密后的文件:",font=("SimSun", 14),pady=10).place(relx=0.05,rely=0.31,anchor='w')
entry_encrypted_message=tk.Entry(frame4, width=23,font=("SimSun", 14))
entry_encrypted_message.place(relx=0.3,rely=0.31,anchor='w')
button_encrypted_message= tk.Button(frame4, text="选择路径",font=("SimSun", 14), command=select_encrypted_message_file)
button_encrypted_message.place(relx=0.8,rely=0.31,anchor="w")
tk.Label(frame4,text='A公钥pem文件:',font=("SimSun", 14),padx=0,pady=9).place(relx=0.05,rely=0.43,anchor='w')
entry_Apublic_send = tk.Entry(frame4, width=23,font=("SimSun", 14))
entry_Apublic_send.place(relx=0.3,rely=0.43,anchor="w")
button_Apublic= tk.Button(frame4, text="选择路径",font=("SimSun", 14), command=select_Apublic_key_file)
button_Apublic.place(relx=0.8,rely=0.43,anchor="w")
tk.Label(frame4,text='B私钥pem文件:',font=("SimSun", 14),padx=0,pady=0).place(relx=0.05,rely=0.55,anchor="w")
entry_Bprivate_send= tk.Entry(frame4, width=23,font=("SimSun", 14))
entry_Bprivate_send.place(relx=0.3,rely=0.55,anchor="w")
button_Bprivate= tk.Button(frame4, text="选择路径",font=("SimSun", 14), command=select_Bprivate_key_file)
button_Bprivate.place(relx=0.8,rely=0.55,anchor="w")
button_decrypt= tk.Button(frame4, text="解密文件",font=18,command=receiver)
button_decrypt.place(relx=0.4,rely=0.7,anchor='w')
#frame4.pack(fill=tk.BOTH, expand=True)

frame5=tk.Frame(root)
tk.Label(frame5,text='选择解密文件另存为地址',font=("Simsun",16),pady=10).place(relx=0.26,rely=0.15,anchor='w')
button_choice= tk.Button(frame5, text="选择路径",font=("SimSun", 14), command=loader_decrypted_message_file)
button_choice.place(relx=0.4,rely=0.31,anchor='w')
button_back51= tk.Button(frame5, text="返回重新选择",font=("SimSun", 14), command=open_frame51)
button_back51.place(relx=0.36,rely=0.5,anchor='w')
#frame5.pack(fill=tk.BOTH, expand=True)

root.mainloop()

3.图形界面实现

3.1选择界面

3.2发送方界面

          3.3.1以txt为例

文件选择

保存路径

加密后的文件

接受方界面

文件选择

消息完整性和正确性验证

解密后的文件

3.3.2以png为例

加密前的文件

文件选择

加密后的文件

文件选择

消息完整性和正确性验证

解密后的文件

三、反思与总结

1.遇到的困难:一开始选择RSA加密文件,因为RSA公私钥位数的问题,会导致过大的文件无法加密,甚至只能加密短的txt文件,最后选择采用对称加密体制,用AES加密可以不限制文件大小,防止AES密钥泄露采用RSA对其加密

2.对纯txt文件加密后,原文以ASCII字符出现,AES密钥会以中文字符出现,导致会被人轻易看出

  • 21
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值