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)
posted @ 2022-06-10 15:49  ChaosMoor  阅读(963)  评论(0编辑  收藏  举报