密码学~~~数字信封

#本文仅供参考有不足之处请指出

一、概括

        数字信封是公钥密码体制在实际中的一个应用,是用加密技术来保证只有规定的特定收信人才能阅读通信的内容。数字信封的功能类似于普通信封,普通信封在法律的约束下保证只有收信人才能阅读信的内容;数字信封则采用密码技术保证了只有规定的接收人才能阅读信息的内容。数字信封中采用了对称密码体制和公钥密码体制。信息发送者首先利用随机产生的对称密码加密信息,再利用接收方的公钥加密对称密码,被公钥加密后的对称密码被称之为数字信封。在传递信息时,信息接收方若要解密信息,必须先用自己的私钥解密数字信封,得到对称密码,才能利用对称密码解密所得到的信息。这样就保证了数据传输的真实性和完整性。

        在一些重要的电子商务交易中密钥必须经常更换,为了解决每次更换密钥的问题,结合对称加密技术和公开密钥技术的优点,它克服了私有密钥加密中私有密钥分发困难和公开密钥加密中加密时间长的问题,使用两个层次的加密来获得公开密钥技术的灵活性和私有密钥技术高效性。信息发送方使用密码对信息进行加密,从而保证只有规定的收信人才能阅读信的内容。采用数字信封技术后,即使加密文件被他人非法截获,因为截获者无法得到发送方的通信密钥,故不可能对文件进行解密。

二、原理

        实现发送方和接收方之间文件的加密传输,使之具有保密性、不可否认性和完整性。

1、发送方A操作

(1)与接收方B预先协商好通信过程中所使用到的对称加密算法、非对称加密算法和哈希函数;

(2)采用对称加密算法(密钥称之为会话密钥)对传输信息进行加密得到密文,确保传输信息的保密性;

(3)采用哈希函数(生成文件摘要)确保传输信息的完整性,并使用自己的私钥对文件摘要进行签名(得到数字签名),确保信息发送方的不可否认性;

(4)使用接受方B的公钥对会话密钥进行加密,确保传输信息的保密性以及信息接收方的不可否认性;

(5)将密文、加密后的会话密钥和数字签名打包封装(放到一起)后,通过网络传输给接收方B。

2、接收方B操作

(1)与发送方A预先已协商好的通信过程中使用到的对称加密算法、非对称加密算法和哈希函数;

(2)使用自己的私钥对发送方A加密的会话密钥进行解密,得到会话密钥;

(3)使用会话密钥对得到的密文进行解密,得到明文;

(4)使用发送方A的公钥对得到的数字签名进行解密,得到明文摘要;

(5)使用哈希函数计算得到的明文摘要,将计算得到的摘要与准明文摘要进行比较,若相同则表明文件安全传输成功。

        具体流程如图所示:

 三、设计内容

3.1设计环境

系统环境开发工具设计语言
windows10

PyCharm

Python3.8

3.2概要设计

        为了能够模拟出数字信封的发送和接受过程,这里基于python程序采用目录分类的形式来呈现,具体目录结构如图 所示:

        

         这里将目录文件主要分为了三类,分别是代表消息发送者的sender、消息接受者的receiver以及所传输的消息文件message,在初始状态下,sender目录下包含了所要发送的数据文件data.txt、消息发送的主要程序sender.py、主要加、解密算法和签名算法的类文件CryptoTest.py、对称算法AES的密钥文件aeskey.txt以及非对称算法RSA的公钥和私钥(这里指的是:发送者A的私钥文件Aprikey.bin和接受者B的公钥文件Bpubkey.bin),而接受者receiver目录下只包含了消息接受的主要程序receiver.py、主要加、解密算法和签名算法的类文件CryptoTest.py、以及非对称算法RSA的公钥和私钥(这里指的是:发送者A的公钥文件Apubkey.bin和接受者B的私钥文件Bprikey.bin),由于还未发送消息,所以message目录下为空,其中RSA的公钥和私钥是由produce_key.py程序生成,具体的发送运行流程如运行结果中所示。

3.3详细设计

3.3.1CryptoTest.py(包含AES、RSA加解密算法和哈希运算)

from Crypto.Cipher import AES
from binascii import b2a_hex,a2b_hex
import hashlib,base64
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
class aestest():#AES对称密码算法加解密
    def __init__(self, key):
        self.key = key
        self.mode = AES.MODE_CBC
    def encrypt(self, text):#AES加密
        cryptor = AES.new(self.key, self.mode, self.key)# 实例化加密套件,使用CBC模式
        text = text.encode("utf-8")
        length = 16
        count = len(text)
        add = length - (count % length)
        text = text + (b'\0'*add)#对明文进行编码转换,长度不够就补0
        self.ciphertext = cryptor.encrypt(text)#对明文进行aes加密
        entext = b2a_hex(self.ciphertext).decode("utf-8")#对加密后的文件进行编码转换
        with open('../message/ciphertext.bin', 'w') as f1:#eiphertext.bin密文文件
            f1.write(entext)
        return entext
    def decrypt(self, text):#AES解密
        cryptor = AES.new(self.key, self.mode, self.key)# 实例化加密套件,使用CBC模式
        plain_text = cryptor.decrypt(a2b_hex(text))#对密文进行解密
        plaintext = plain_text.rstrip(b'\0').decode("utf-8")#对删除补的0,编码转换得到明文
        with open('plaintext.bin', 'w') as f2:
            f2.write(plaintext)
        return plaintext
class rsatest():#RSA公钥算法加解密
    def encrypt(self,file,encryptedfile,pubk):
        with open(file,'rb') as f:
            recipient_key = RSA.import_key(open(pubk).read())#从文件中获取获取公钥
            cipher_rsa = PKCS1_OAEP.new(recipient_key)# 实例化加密套件
            c= cipher_rsa.encrypt(f.read())# 加密
            with open(encryptedfile,'wb') as out_file:#保存加密文件
                out_file.write(c)
    def decrypt(self,file,decryptedfile,prik):
        with open(file,'rb') as f:
            private_key = RSA.import_key(open(prik).read())#从文件中获取获取私钥
            cipher_rsa = PKCS1_OAEP.new(private_key)# 实例化加密套件
            m = cipher_rsa.decrypt(f.read())#解密
            with open (decryptedfile,'wb') as out_file:#保存解密文件
                out_file.write(m)
# hash类
class hashtest():#做哈希运算
    hash = hashlib.sha256()
    hash.update('admin'.encode('utf-8'))
class signverify:
    def sign(self, data, privkeyfile, sigfile):
        privkey = open(privkeyfile, "rb").read().decode("utf-8")# 读取私钥
        key = RSA.importKey(privkey)
        data1 = open(data, "rb").read()# 要签名的内容
        h = SHA256.new(data1)# 获取要签名的内容的HASH值。
        signer = PKCS1_v1_5.new(key)# 对HASH值使用私钥进行签名。
        signature = signer.sign(h)
        sig = base64.b64encode(signature)#对签名进行base64加密
        with open(sigfile, "wb") as f:
            f.write(sig)
    def verify(self, data, pubkeyfile, sigfile):
        publickey = open(pubkeyfile, "rb").read().decode("utf-8")# 读取公钥
        key = RSA.importKey(publickey)
        data1 = open(data, "rb").read()
        h = SHA256.new(data1)# 获取被签名的内容的HASH值。
        verifier = PKCS1_v1_5.new(key)
        signature = open(sigfile, "rb").read().decode('utf-8')
        if verifier.verify(h, base64.b64decode(signature)):
            return True
        return False

3.3.2produce_key.py(生成A、B公钥和私钥)

import rsa
f, e = rsa.newkeys(2048)  # 生成公钥、私钥
e = e.save_pkcs1()  # 保存
with open("./sender/Aprikey.bin", "wb") as x:  # 保存A私钥
    x.write(e)
f = f.save_pkcs1()  # 保存为格式
with open("./receiver/Apubkey.bin", "wb") as x:  # 保存A公钥
    x.write(f)
p,b = rsa.newkeys(2048)  # 生成公钥、私钥
b = b.save_pkcs1()  # 保存
with open("./receiver/Bprikey.bin", "wb") as x:  # 保存B私钥
    x.write(b)
p = p.save_pkcs1()  # 保存为 格式
with open("./sender/Bpubkey.bin", "wb") as x:  # 保存B公钥
    x.write(p)

3.3.3​​​​​​​sender.py(发送者)

import CryptoTest#发送方A的三步,发送方A已经获得接受方B的公钥Bpubkey.bin
#第一步用AES对称密钥加密明文文件
with open('aeskey.txt','rb') as f:
    aessymkey = f.read()
Aaestest = CryptoTest.aestest(aessymkey)#实例化对象
print('请输入要加密的明文文件')
fname = input()#请输入要加密的明文文件
with open(fname,'r') as f:
    m =f.read()
    Aaestest.encrypt(m)#AES的CBC模式加密
print('明文文件加密后的密文文件是ciphertext.bin')
#第二步用对方公钥Bpubkey.bin加密,对称文件aeeskey.txt
Arsa = CryptoTest.rsatest()
Arsa.encrypt('aeskey.txt','../message/keyencrypted.bin','Bpubkey.bin')
print('对称密钥文件aeskey.txt加密后的文件是keyencrypted.bin')
#第三步生成明文文件的摘要值,用自己的私钥Aprikey.bin对摘要进行数字签名
asgin = CryptoTest.signverify()
asgin.sign('data.txt','Aprikey.bin','../message/digitalsign.bin')
print('A签名后的文件是digitalsign.bin')
print('将三个文件ciphertext.bin,keyencrypted.bin,digitalsign.bin发送给B')

3.3.4​​​​​​​receiver.py(接受者)

import CryptoTest#接收方B的三步,接收方已经获得了发送方A的公钥Apubkey.bin
#第一步用自己的私钥解密得到对称密钥
Brsa = CryptoTest.rsatest()
Brsa.decrypt('../message/keyencrypted.bin','aeskey.txt','Bprikey.bin')
print('解密后的密钥文件是aeskey.txt')
with open('aeskey.txt','r',encoding = 'utf-8') as f:
p = f.read()
print('会话密钥是:'+p)
#第二步用对称密钥解密密文
with open('aeskey.txt','rb') as f:
    aessymkey = f.read()
Baestest2 = CryptoTest.aestest(aessymkey)
with open('../message/ciphertext.bin','r') as f:
    m = f.read()
    Baestest2.decrypt(m)
print('解密后明文文件是plaintext.bin')
with open('plaintext.bin','r',encoding = 'utf-8') as f:
    p = f.read()
    print('明文信息是:'+p)
#第三步用A的公钥解密数字签名验证摘要值
bverify = CryptoTest.signverify()
print(bverify.verify('plaintext.bin','Apubkey.bin','../message/digitalsign.bin'))
if (bverify.verify('plaintext.bin','Apubkey.bin','../message/digitalsign.bin')):
    print('验证签名正确')
else:
    print('验证错误')

3.3.5data.txt和aeskey.txt(测试用,可以更改,aeskey长度16位) 

     

3.4运行结果

1、先运行CryptoTest.py和produce_key.py(在sender和receiver里生成相应的公钥私钥)

2、再运行sender,py结果如下图

 此时message目录下生成了所发送的消息(数字信封)

 3、最后运行receiver.py结果如下图

4、运行开始和运行结束后的目录如图 

 

  • 6
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值