0%

Python RSA文件加密系列——生成公私钥、文件签名

前言

个人认为后续工作中可能需要涉及到相关信息的唯一性以及相关信息传输的保密性,因此尝试现阶段学习一下相关加密技术(呜呜呜应该复习考公的)

需要

  • python环境(感觉什么都可以)
  • 第三方库:rsa

过程

生成公私钥

使用函数: rsa.newkeys(num),其中:

  • num:必要参数,存储n=q*p所需要的位数

  • accurate:可选参数,默认是True

    当它为真时,上述参数中的 n必定为你所需要的位数(创建速度会慢)

    当它为假时,上述参数中的 n的数值可能会小(处理速度快)

  • poolsize:可选参数,默认是 1

    用于生成素数的进程数 数字。如果设置为大于 1 的数字,将使用并行算法。 这需要 Python 2.6 或更高版本。

  • exponent:可选参数,默认65537

    他是密钥的指数;更改它的时候你要对此有极大的了解,因为指数会影响破解私钥的难度。

它会返回一个公钥和私钥,因此需要创建一个元组去接值

整体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import rsa

(pubkey, privkey) = rsa.newkeys(2048)
pub = pubkey.save_pkcs1()
pubfile = open('public.pem', 'wb')
pubfile.write(pub)
pubfile.close()

pri = privkey.save_pkcs1()
prifile = open('private.pem', 'wb')
prifile.write(pri)
prifile.close()

# 创建一个公钥和私钥到你本地目录下

读取公私钥

这里仅贴代码仅供参考

1
2
3
4
5
6
7
# 加载公私钥
with open('public.pem', 'r') as f:
pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())
f.close()
with open('private.pem', 'r') as f:
privkey = rsa.PrivateKey.load_pkcs1(f.read().encode())
f.close()

生成签名

当你要给别人发消息时候,需要确保消息的真实性,不会被别人所截获,因此会需要使用到私钥对你的数据进行签名,到对方手上的时候,对方可以使用你所给的公钥进行验签,这里讲解如何实现签名的生成

此处使用函数:rsa.sign(),其中:

  • message:必要参数,要签名的消息。

    可以是 8 位字符串或类似文件 目的。如果 messageread() 方法,它被假定为 类文件对象。

  • priv_key:必要参数,使用的私钥信息。

需要先加载私钥信息才可使用

  • hash_method:必要参数,所使用的哈希算法。

    通常参数为:MD5SHA-1SHA-224SHA-256SHA-384SHA-512

    具体参数优劣请自行查询其他文档

可能会出现的异常信息: OverflowError:如果私钥信息过小,可能无法包含相关信息

可选函数:base64.b64encode(你需要编码的信息),使用其将上述信息进行二次编码,方便后续传输

部分代码如下:

1
2
3
4
5
6
7
8
9
10
def sign_by(data: str, privkey: rsa.PrivateKey):
"""
私钥加密,使用此函数对相应信息进行加密
:param data: 所需要加密的信息,字符串格式
:param privkey: 私钥信息,已经读取好的
:return: 返回私钥签名好的信息
"""
sign = rsa.sign(data.encode(), privkey, 'SHA-256')
sign = base64.b64encode(sign)
return sign

验证签名

当对方拿到你发的信息以及所生成的签名之后,他需要使用公钥对其进行判断,确保在传输过程中没有信息有所损失。

使用函数:rsa.verify(),其中:

  • message:必要参数。需要验证的信息内容(需要字节流信息)
  • signature:必要参数。拿到的签名信息
  • pub_key:必要参数。你手上的公钥信息

可能会出现的异常信息:rsa.VerificationError:当验证签名信息失败的时候进行抛出,否则返回的是所使用的签名算法名称

部分代码片段(为方便,用try函数判定是否出现,并返回布尔型数据):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def checkout_sign(data: str, sign: bytes, pubkey):
"""
使用公钥验证签名信息
:param data: 需要检验的信息
:param sign: 签名信息,base64编码格式文件
:param pubkey: 公钥信息,已经读取好的
:return: 根据是否验签成功,如果检验成功则返回True,如果不成功则返回False
"""
sign = base64.b64decode(sign)
try:
rsa.verify(data.encode(), sign, pubkey)
except rsa.VerificationError:
return False
else:
return True

整体代码

增加了一丢丢代码之后的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# -*- coding: utf-8 -*-
# @Time : 2022/9/25 19:23
# @Author : ZHYCarge
# @Email : ZHYCarge@126.com
# @File : 生成签名.py
# @Brief :使用私钥生成签名以获得一个概览信息
import base64
import sys
import rsa


message = 'Tmq2JoRvPCfvVKUhC2pjaiEu5c9EZxu5NlC7wGw6jl766r1Aqv/7I/Cmi2vIT15Icye/TiwArV0NNG4XqGP40oTebkfaCLfU5R91QnJFgUFnXAHLWO62ehWXcigmt5mSo4DojwfvmlMbzbuEZ0Qdj0XoVdqn96qEPvFGLAixzG/9+4KzBjgIKr3N4iQwBz3TIWM6iQU4TIxTZqJv9CvRQBZye1exj5PPB1ppWtNqsa5zx39FFwZdRXKfiUNGcSoNVAjXP3TU76cuWsCPIe7HLqDdtV4hTmjTvJ2trQ2SWne4p+SzvzsOUHGRLCIob1l2w4+EB6FvEvFhOjagwd0ieQ=='
# 加载公私钥
with open('public.pem', 'r') as f:
pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())
f.close()
with open('private.pem', 'r') as f:
privkey = rsa.PrivateKey.load_pkcs1(f.read().encode())
f.close()


def sign_by(data: str, privkey: rsa.PrivateKey):
"""
私钥加密,使用此函数对相应信息进行加密
:param data: 所需要加密的信息,字符串格式
:param privkey: 私钥信息,已经读取好的
:return: 返回私钥签名好的信息
"""
sign = rsa.sign(data.encode(), privkey, 'SHA-256')
sign = base64.b64encode(sign)
return sign


def checkout_sign(data: str, sign: bytes, pubkey):
"""
使用公钥验证签名信息
:param data: 需要检验的信息
:param sign: 签名信息,base64编码格式文件
:param pubkey: 公钥信息,已经读取好的
:return: 根据是否验签成功,如果检验成功则返回True,如果不成功则返回False
"""
sign = base64.b64decode(sign)
try:
rsa.verify(data.encode(), sign, pubkey)
except rsa.VerificationError:
return False
else:
return True


if __name__ == '__main__':
try:
filename = sys.argv[1]
method = sys.argv[2]
except:
print("操作2:进行验签,返回True或者False\n"
"操作1:进行签名,将数据进行签名")
methods = input("请输入你所需要操作的文件以及需要的操作(用空格进行分开)")
methods = methods.split(" ")
try:
filename = methods[0]
method = methods[1]
except:
print("输入的信息格式错误,请重新输入!")
if method == "2":
sign = input("请输入签名信息:")
print(checkout_sign(message, sign.encode(), pubkey))
elif method == "1":
sign = sign_by(message, privkey)
print("签名信息如下,请保存:")
print(str(sign)[2:-1])
else:
print("你所输入的信息不满足,进程已停止")

-------------我也是有底线的哦如需更多,欢迎打赏-------------