Python-RSA 分段加解密
1. RSA 介绍
RSA 加密算法是一种非对称
加密算法,何为非对称加密算法?它需要两个密钥,一个是公开密钥,另一个是私有密钥;公钥用作加密,私钥则用作解密。使用公钥把明文加密后所得的密文,只能用相对应的私钥才能解密并得到原本的明文。由于加密和解密需要两个不同的密钥,故被称为非对称加密
不同于加密和解密都使用同一个密钥的对称加密。公钥可以公开,可任意向外发布;私钥不可以公开,必须由用户自行严格秘密保管,绝不透过任何途径向任何人提供,也不会透露给被信任的要通信的另一方
2. Python-RSA 模块
这是该模块的文档地址,虽然是全英文的,但相对也比较简单,作者示例比较有趣,可以看看
Python-RSA 文档开头这段简明扼要地说明了,Python-RSA 是用 Python 对 RSA 算法的实现,支持加密、解密、签名、验证签名、参照 PKCS#1 加密标准产生公钥和私钥
注意!!:Python-RSA 只能用 PKCS#1 加密标准,如果别人给你的是 PKCS#8 加密标准的秘钥,需要转换,笔者这里提供一个在线的转换地址
2.1 PKCS#1 与 PKCS#8
可以从可视化秘钥进行区分:
PKCS#1 秘钥格式:
-----BEGIN RSA PUBLIC KEY-----
xxxx
-----END RSA PUBLIC KEY-----
PKCS#8 秘钥格式:
-----BEGIN PUBLIC KEY-----
xxxxx
-----END PRIVATE KEY-----
2.2 安装
pip install rsa
3. 分段加密
3.1 加/解密大小
RSA 算法只能加密比公钥小的信息,加密最大长度 = (x bit // 8 - 11) bytes;解密最大长度 = (x bit // 8 ) bytes;因此对于稍微大一些的文本信息都是需要分段加密以及分段解密的
class RsaTools(object):
'''Module RSA offcial docs: https://stuvel.eu/python-rsa-doc/usage.html
---------------------------- Pay Attention To ----------------------------
there are two type of keys: pkcs#1 and pkcs#8, module rsa only support pkcs1.
if your key's type is pkcs8, you can convert it on http://www.metools.info/code/c85.html
if you have a x bits of public key, you could encrypt max message length is x/8 - 11;
'''
def __init__(self):
self._public_key = None
self._private_key = None
self._encrypt_length = None
self._decrypt_length = None
def gen_key(self, length: int) -> None:
self._public_key, self._private_key = rsa.newkeys(length)
self._decrypt_length = length // 8
self._encrypt_length = self._decrypt_length - 11
def get_public_key(self) -> str:
return self._public_key.save_pkcs1().decode('utf-8')
def get_private_key(self) -> str:
return self._private_key.save_pkcs1().decode('utf-8')
def set_public_key(self, public_key_str: bytes, length: int = 1024) -> None:
'''load outer public key'''
self._public_key = rsa.PublicKey.load_pkcs1(public_key_str)
self._encrypt_length = length // 8 - 11
def set_private_key(self, private_key_str: bytes, length: int = 1024) -> None:
'''load outer private key'''
self._decrypt_length = length // 8
self._private_key = rsa.PrivateKey.load_pkcs1(private_key_str)
def encrypt(self, text: str) -> str:
ret = BytesIO()
text_bytes = BytesIO(text.encode("utf-8"))
encrypt_segment = text_bytes.read(self._encrypt_length)
while encrypt_segment:
ret.write(rsa.encrypt(encrypt_segment, self._public_key))
encrypt_segment = text_bytes.read(self._encrypt_length)
return base64.b64encode(ret.getvalue()).decode('utf-8')
def decrypt(self, text: str) -> str:
ret = BytesIO()
text_bytes = base64.b64decode(text.encode("utf-8"))
text_byte_fragments = self._text_bytes_split(text_bytes, self._decrypt_length)
for fragment in text_byte_fragments:
ret.write(rsa.decrypt(fragment, self._private_key))
return ret.getvalue().decode()
def _text_bytes_split(self, text_bytes: bytes, per_size: int) -> list:
max_legth = len(text_bytes)
ret = list()
current_index = 0
while current_index < max_legth:
ret.append(text_bytes[current_index: current_index + per_size])
current_index += per_size
return ret
if __name__ == "__main__":
instance = RsaTools()
instance.gen_key(1024)
message = json.dumps({
"syncTaskId": "913100007109368748202205171650740110",
"merchandiseData": [
{
"merchandiseId": 1,
"merchandiseName": "BG 105 Engine System Cleaner",
"ownerId": "必技汽车用品贸易(上海)有限公司",
"ownerName": "必技汽车用品贸易(上海)有限公司",
"isMixture": 1,
"chemicalName": "加氢处理的重环烷石油馏出物",
"mixChemicleName": "加氢处理的重环烷石油馏出物,4-甲基-2-戊醇",
"physicalState": 2,
"otherAttribute": "4,7,10,16,27,36",
"unCode": "1993",
"casCode": "64742-52-5",
"riskGhsItemCategory": "060003,280001",
"riskItemCategory": "3",
"fireRisk": "丙",
"deleterious": 0
}
]
})
encrypted_message = instance.encrypt(message)
print(encrypted_message)
decrypted_message = test_rsa_tools_object.decrypt(encrypted_message)
print(decrypted_message)