签名说明:
- 使用HASH256对数据加密;
- 对哈希结果进行BER编码,并使用PKCS #1.5进行填充;
- 使用私钥对填充后的内容进行加密得到签名结果;
环境准备:
Python3 Crypto库
项目目录:
1. 生成RSA公私钥,并把它们和需要加密的信息文件分别存入该路径下:
create_file.py
from Crypto.PublicKey import RSA
import re
# bit一般为1024的倍数(2048,...), RSA算法的密钥长度至少1024位才能保证其安全性
bits = 3072
i = 0
str1 = ''
key = RSA.generate(bits)
# 创建一个私钥文件,一个公钥文件,一个数据文件
private_key = key.export_key()
public_key = key.publickey().export_key()
data = "月海花千野reimportcontinuebin."
with open("private_key.pem", "wb") as prifile, \
open("public_key.pem", "wb") as pubfile, \
open("data.txt", "w") as datafile:
prifile.write(private_key)
prifile.close() # 关闭I/O流
pubfile.write(public_key)
pubfile.close() # 关闭I/O流
datafile.write(data)
datafile.close() # 关闭I/O流
print("-------RSA数字签名-------")
with open('public_key.pem', "r") as pubfile: #
pubfile.readline() # 读取公钥密码头"-----BEGIN PUBLIC KEY-----",但不接收
pub_key = pubfile.read() # 接收从第二行开始的数据,即公钥
pubfile.close()
while True:
if pub_key[i] == '-': # 遇到'-'结束读取,不接收末尾'-'开始的密码尾部
print("生成的公钥:")
break
str1 += pub_key[i]
i += 1
pub_key = re.sub('\n', '', str1) # 去掉字符串的换行符
print(pub_key)
i = 0
str1 = ''
with open('private_key.pem', "r") as prifile:
prifile.readline() # 读取私钥密码头-----BEGIN RSA PRIVATE KEY-----,但不接收
pri_key = prifile.read() # 接收从第二行开始的数据,即私钥
prifile.close() # 关闭I/O流
while True:
if pri_key[i] == '-': # 遇到'-'结束读取,不接收末尾'-'开始的密码尾部
print("生成的私钥:")
break
str1 += pri_key[i] # 将读取的私钥存入数组
i += 1
pri_key = re.sub('\n', '', str1) # 去掉字符串的换行符
print(pri_key)
print("私钥已存入:private_key.pem\n" + "公钥已存入:public_key.pem\n" + "数据已存入:data.txt\n")
生成与创建结果:
- 文件例:
公钥文件:public_key.pem
私钥文件:private_key.pem
2.通过数字签名脚本,对数据文件进行签名并生成数字签名文件:
signature.py
注意:这里我用的是SHA256进行数据的散列加密,使用md5可在对应代码处取消注释,再注释掉HASH256加密处的代码,并导入MD5库
代码里面有详细注释(^ _ ^)
from Crypto.Signature import pkcs1_15
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
import base64
# 签名
with open("data.txt", "r") as datafile:
data = datafile.read()
# 定义签名函数,能够使用指定的私钥对数据文件进行签名,并将签名结果输出到文件返回
def signaturen(private_key, data):
# md5生成摘要 使用需导入MD5 # from Crypto.Hash import MD5
# data_s_hashencode = MD5.new(data.encode('utf-8'))
# hash256生成摘要
data_s_hashencode = SHA256.new(data.encode('utf-8'))
# 使用私钥对HASH值进行签名
pri_cipher = pkcs1_15.new(private_key)
# 使用base64对签名信息加密
signature = base64.b64encode(pri_cipher.sign(data_s_hashencode))
print("数字签名:")
print(signature.decode('utf-8'))
# 将签名结果写入文件
sig_result = open("sig_result.txt", "wb")
sig_result.write(signature)
sig_result.close() # 关闭I/O流
return sig_result
with open('private_key.pem', 'rb') as prifile, \
open('data.txt', 'r') as datafile:
private_key = RSA.import_key(prifile.read())
data = datafile.read()
datafile.close() # 关闭I/O流
signaturen(private_key, data)
print("签名已写入:sig_result.txt")
签名结果:
3. 数字签名验证脚本,对私钥生成的签名文件进行验证:
verify.py
注意:如果前面的签名算法使用md5对data进行加密,则此处也需要取消对应md5加密代码处的注释,再注释掉HASH256加密处的代码,并导入MD5库
代码里面有详细注释(^ _ ^)
from Crypto.Signature import pkcs1_15
from Crypto.PublicKey import RSA
import base64
from Crypto.Hash import SHA256
import re
i = 0
str1 = ''
# 定义签名验证函数,能够使用指定的公钥对私钥生成的签名文件进行验证,返回验证结果
def Authentication(public_key, data, signature):
# 对验证信息signature先base64解密
signature = base64.b64decode(signature)
# 对接收信息data进行md5进行加密生成散列值 使用需导入MD5 #from Crypto.Hash import MD5
# data_a_hashencode = MD5.new(data.encode('utf-8'))
# 对接收信息data进行hash256加密生成散列值
data_a_hashencode = SHA256.new(data.encode('utf-8'))
print("The result of signature verification:")
print("----------------------------------")
try:
# 使用公钥解密并验证
pkcs1_15.new(public_key).verify(data_a_hashencode, signature)
print("> Success:签名验证成功!!!")
except:
print("> Error:签名无效!!!\n")
print("----------------------------------\n")
with open('public_key.pem', "r") as pubfile: #
pubfile.readline() # 读取公钥密码头"-----BEGIN PUBLIC KEY-----",但不接收
pub_key = pubfile.read() # 接收从第二行开始的数据,即公钥
pubfile.close()
while True:
if pub_key[i] == '-': # 遇到'-'结束读取,不接收末尾'-'开始的密码尾部
print("-----公钥-----")
break
str1 += pub_key[i]
i += 1
pub_key = re.sub('\n', '', str1) # 去掉字符串的换行符
print(pub_key+'\n')
# 打开公钥文件,接收的信息文件,签名文件,对它们进行验证
with open('public_key.pem', 'rb') as pubfile, \
open('data.txt', 'r') as datafile, \
open('sig_result.txt', 'rb') as sigfile:
public_key = RSA.import_key(pubfile.read())
pubfile.close() # 关闭I/O流
data = datafile.read()
print("> data文件中的数据:")
print(data+'\n')
datafile.close() # 关闭I/O流
signature = sigfile.read()
print("> 签名信息:")
print(signature.decode('utf8')+'\n')
sigfile.close() # 关闭I/O流
Authentication(public_key, data, signature)
验证结果:
运行后的项目目录:
最后,对Python文件读写(with as)不熟的同学可以参考下图:
with open('xxx.txt', 'r') as file:
print(file.read())