一、实验目的
借助Python的标准库和扩展库,实现数字签名的产生和验证过程。
二、实验所用仪器(或实验环境)
Python3.8
三、实验基本原理及步骤(或方案设计及理论计算)
Python标准库hashlib实现了SHA1,SHA224以及MD5等多个安全哈希算法,Python扩展库pycryptodome和cryptography提供了SHA系列算法和其他哈希算法,以及DES,AES,RSA等多个加密算法和数字签名算法的实现。
搜索发现相关类似的库名比较多,例如crypto,pycrypto以及pycryptodome,一时之间很迷糊。搜索后发现
crypto是GPG加解密库,该库已于2016年停更,且pythongnupg库才是最主流的GPG加解密库。
PyCrypto是Python前主流加解密库,但已停更。
PyCryptodome是当前最主流的Python加解密库,如果遇到代码中import Crypto等字样,就需要安装这个库。
安装pycryptodome: pip install pycryptodome
RSA数字签名和验证过程:
任务一:生成公私钥对
实际RSA算法中的密钥长度为1024或者2048位,目前被破解的最长RSA密钥是768位。
参考该网站:
https://pycryptodome.readthedocs.io/en/latest/src/examples.html#generate-public-key-and-private-key
方法二:
https://pycryptodome.readthedocs.io/en/latest/src/vs_pycrypto.html
以下任务主要参考目录
任务二三:
首先形成摘要,利用Crypto.Hash模块。即:
from Crypto.Hash import <algorithm>
digest = <algorithm>.new(data = bytes)
参考网址:
https://pycryptodome.readthedocs.io/en/latest/src/hash/hash.html
然后形成签名,Crypto.Signature.pkcs1_15或Crypto.Signature.pss可用于使用RSA签名,本次我用的是Crypto.Signature.pss库。(分别使用两种库,所写的代码基本一样)
在这里注意file.read()的使用,在文本模式下,它会读取一些数据并将其作为字符串返回,在二进制模式下,会将其作为字节对象返回。
参考网址:
https://pycryptodome.readthedocs.io/en/latest/src/signature/pkcs1_pss.html#module-Crypto.Signature.pss
四、实验数据记录(或仿真及软件设计)
程序及运行结果:
# -*- coding: utf-8 -*-
"""
Created on Sun May 17 12:05:17 2020
@author: natur
"""
from Crypto.PublicKey import RSA
from Crypto.Signature import pss
from Crypto.Hash import SHA256
#https://pycryptodome.readthedocs.io/en/latest/src/examples.html#encrypt-data-with-aes
key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()
message = "you are my shine.".encode("utf-8")
with open("private.pem", "wb") as f1,\
open("public.pem", "wb") as f2,\
open("plain_data.txt","wb") as f3:
f1.write(private_key)
f2.write(public_key)
f3.write(message)
f1.close()
f2.close()
f3.close()
#https://www.pycryptodome.org/en/latest/src/signature/pkcs1_pss.html#module-Crypto.Signature.pss
def Signature(message,private_key):
h = SHA256.new(message.encode("utf-8"))
signature = pss.new(private_key).sign(h)
with open("signature.txt", "wb") as f:
f.write(signature)
f.close()
return f
def Verification(message,public_key,signature):
h = SHA256.new(message.encode("utf-8"))
verifier = pss.new(public_key)
try:
verifier.verify(h, signature)
print("签名是真的")
except (ValueError, TypeError):
print("签名是假的")
if __name__ == '__main__':
with open("plain_data.txt","rb") as message,\
open("signature.txt","rb") as signa:
message = message.read()
#print(message)
message = bytes.decode(message) #str to bytes
private_key = RSA.import_key(open('private.pem').read())
public_key = RSA.import_key(open('public.pem').read())
Signature(message,private_key)
signature = signa.read()
Verification(message,public_key,signature)
五、实验结果分析及回答问题(或测试环境及测试结果)
这次实验比较前几次都比较容易,都是套用现成的库,但是以前的方法和现在的方法种类太多,主要花费在选择上。