Python实现RSA数字签名一

利用Python实现RSA数字签名的产生和验证过程。

任务1:准备一个私钥文件,一个公钥文件,一个数据文件;
  任务2:定义一个函数,能够使用指定的私钥对数据文件进行签 名,并将签名结果输出到文件返回;
  任务3:定义一个函数,能够使用指定的公钥对任务2中的签名    文件进行验证,返回验证结果;
  任务4:利用任务1中的文件对任务2和3中的函数进行测试。

标准库Hashlib

实现了SHA1,SHA224以及MD5等多个安全哈希算法,

pycryptodome的使用

  • Python扩展库pycryptodome和cryptography,提供了SHA系列算法和其他哈希算法,以及DES,AES,RSA等多个加密算法和签名算法的实现
  • pycryptodome是加密库
  • pycryptodome模块不是Python的内置模块,pycryptodome模块实现了各种算法和协议的加密模块的结合,结合了各种加密方式对应的多种加密算法的实现,包括单向加密、对称加密以及公钥加密和随机数操作。
    区别:
    crypto是GPG加解密库,该库已于2016年停更,且pythongnupg库才是最主流的GPG加解密库。
    PyCrypto是Python前主流加解密库,但已停更。
    PyCryptodome是当前最主流的Python加解密库,如果遇到代码中import Crypto等字样,就需要安装这个库。
    安装pycryptodome: pip install pycryptodome

1、公钥加密

Crypto.PubicKey.RSA生成私公密钥对

  • 在该模块下的RSA.py源代码中提供了直接生成原始密钥的函数,所以要使用Crypto.Random模块生成
from Crypto.PublicKey import RSA

key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()

print(key)
# print(private_key)
# print(public_key)

输出:

Private RSA key at 0x1A81094DF70

用generate函数生成的密钥是一个私钥对象,通过export_key()函数返回这个密钥:

2、RSA.import_key获得公私密钥

  • 上文已经可以输出一对公私密钥,还要用import_key函数
  • 因为publicKey是一个公钥的实例化对象,即public_key的实例化对象,在使用PKCS1_OAEP实例化加密套件时传入的参数必须是这个对象,查阅PKCS1_OAEP.py的源代码也发现传入的参数key应该是一个对象

3、RSA加密

from Crypto.PublicKey import RSA

key = RSA.generate(2048)
private_key = key.export_key()
public_key = key.publickey().export_key()

# print(key)
# print(private_key)
# print(public_key)

from Crypto.Cipher import PKCS1_OAEP

data = b"123456"

publicKey = RSA.import_key(public_key)
# print(publicKey)
# 加密
cipher = PKCS1_OAEP.new(publicKey)
encrypted_data = cipher.encrypt(data)
print(encrypted_data)

输出

b'"9\x8fW+b\x83\xbf\xc7y\xfc3\xb5R@`\xf4\xad}\x9a\x11\x81\xf2\x0f\xf1\xc6_\xf0K\xb7\xf7t\xcb\xaevK\x08\x8cg\xa1\x8ai\x94\xdf8\xc6\\\xb5\xb8\x98\xfd}A\xb3\\\xf7\x91J\x88\x84/\xdc\xd8\xe7<\xe4\xfa[\n`X\xf5\xf6K\xd9`s\x17\x11F\x80~\xcdt$>$R\x86b\x11*m\xeb\xe0\x87,):&g\x98\'\x90\xbf\x8cK\xef\xbb-\xfc\xecF\x93G!\xf7\xff&\x91\xdc\xdcY\xff\xf76\x91\xcb\n\x1a\xb4\xf3\xcep6\xde5\xf0^\xe1\'\xf7\t\xc5\xdbU6\x83\xc7\xf5\xe2\xeb\xf7\xe3;J\xd1\x9b\xd0\x925!\x98s\x189\xdd\xa8=\xbfw^\xe8R\xdc\xce\xb8\xdb`\x96 f\x85\xd7\x10>\xea\x97\x05p\x8c\x00\xd5\xf0\xae\xea\x0c\xf9\x03\xd98N\xbc\xd8RD]\x97Y\x8a/\n\xec\xb5\xe5\xe9\x8ea\x87\xaeE\x9fM\xc7\\\x0c\xefE*}\xea\xcd*\x1f\xacR\xd7X\x85\xea\xbfl\xcc\xa5\xed\x91\x90\x07\x13\xdd\x97\x8c\xfcl\xf2y'

加密完成

4、RSA解密

# 解密
privateKey = RSA.import_key(private_key)
cipher = PKCS1_OAEP.new(privateKey)
data = cipher.decrypt(encrypted_data)
print(data)

输出

b'123456'

三、数字签名与验签

  • 数字签名与验签,简单来说步骤为:A使用自己的私钥对消息进行签名,将签名后的信息和公钥发送给B,B使用公钥验证签名是否属于A。
  • 使用Crypto.Publickey,Crypto.Hash,Crypto.Signature三个库,即公钥加密、摘要算法、数字签名三个库
  • 1、Crypto.Hash获取消息的HASH值

  • 这里会用到摘要算法,常用的摘要算法有:MD2,MD4,MD5,SHA-1,SHA-256,RIPEMD128,RIPEMD160等等,用什么摘要算法不重要,只要在验证时有相同的摘要算法即可。这里选择MD5.
  • 2、Crypho.Signature对HASH值使用私钥进行签名

  • 本质上是使用私钥对HASH值进行加密,将公钥私钥以及消息分别放在public_key.pem、private_key.pem、data.txt三个文件中,
  • 有两个注意:获得公私钥要用import_key函数;从data.txt中读取信息后要使用相应的编码格式,digest=MD5.new(data.encode(‘utf-8’))
  • 在Crypto.Signature中随便选择一个模式,选择pkcs1_15模式对消息进行签名
  • 3、签名验证

  • 签名验证部分需要传入三个信息:消息原文(data)、摘要算法(MD5)、HASH值签名结果(signature)

实验总代码

from Crypto.PublicKey import RSA

key = RSA.generate(2048)

# 任务1:准备一个私钥文件,一个公钥文件,一个数据文件
private_key = key.export_key()
public_key = key.publickey().export_key()
data = "I love you"
with open("private_key.pem", "wb") as prifile,\
    open("public_key.pem", "wb") as pubfile,\
    open("data.txt","a") as datafile:
    prifile.write(private_key)
    pubfile.write(public_key)
    datafile.write(data)

from Crypto.Signature import pkcs1_15
from Crypto.Hash import MD5
from Crypto.PublicKey import RSA

# 签名
with open("data.txt", "r") as datafile:
    data = datafile.read()


# print(data)

# 任务2:定义签名函数,能够使用指定的私钥对数据文件进行签名,并将签名结果输出到文件返回
def signaturer(private_key, data):
    # 获取消息的HASH值,摘要算法MD5,验证时也必须用MD5
    digest = MD5.new(data.encode('utf-8'))
    # 使用私钥对HASH值进行签名
    signature = pkcs1_15.new(private_key).sign(digest)
    # 将签名结果写入文件
    sig_results = open("sig_results.txt", "wb")
    sig_results.write(signature)
    sig_results.close()
    return sig_results


# 任务3:定义签名验证函数,能够使用指定的公钥对任务2中的签名文件进行验证,返回验证结果
def verifier(public_key, data, signature):
    digest = MD5.new(data.encode('utf-8'))
    try:
        pkcs1_15.new(public_key).verify(digest, signature)
        print("验证成功!!!")
    except:
        print("签名无效!!!")


# 任务4:利用任务1中的文件对任务2和3中的函数进行测试。
with open('private_key.pem') as prifile, \
        open('data.txt') as datafile:
    private_key = RSA.import_key(prifile.read())
    data = datafile.read()

    signaturer(private_key, data)

with open('public_key.pem') as pubfile, \
        open('data.txt') as datafile, \
        open('sig_results.txt', 'rb') as sigfile:
    public_key = RSA.import_key(pubfile.read())
    data = datafile.read()
    signature = sigfile.read()

    verifier(public_key, data, signature)


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值