RSA(python)

请添加图片描述
**

生成非对称密钥对

**
generateKey.py

from Crypto import Random
from Crypto.PublicKey import RSA

# 伪随机数生成器
random_generator = Random.new().read
# rsa算法生成实例
rsa = RSA.generate(1024, random_generator)
# 私钥的生成
private_pem = rsa.exportKey()
with open("private.pem", "wb") as f:
    f.write(private_pem)
# 公钥的生成
public_pem = rsa.publickey().exportKey()
with open("public.pem", "wb") as f:
    f.write(public_pem)

请添加图片描述
**

加密(公钥)

**

import base64
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5

# 加密
message = "Hello,This is RSA加密"
data = open("public.pem").read()
rsakey = RSA.importKey(data)
# 创建用于执行pkcs1_v1_5加密或者解密的密码
cipher = PKCS1_v1_5.new(rsakey) 
cipher_text = base64.b64encode(cipher.encrypt(message.encode()))
print(cipher_text.decode())

结果

BoNOpo+YEcYoI/vOqmf0AtqfZn49MxiWbYXE+qY7Coz3TjmkGKxkooQ6Mwa2lCRjc2CoPee8YTcuGUA6ncLB+C1JlRTSzbHqfbch22SivsriPMUNoWWZUMY6nNDTE95aZrcNZs32MP7IGrLP/Yev/548Z9iIPzPg/+UHPyLgtPo=

这里每次使用公钥加密后的结果都不一致,跟对数据的padding即填充有关。

加密时支持的最大字节数与证书有一定关系。加密时支持的最大字节数:证书位数/8 -11(比如:2048位的证书,支持的最大加密字节数:2048/8 - 11 = 245)

1024位的证书,加密时最大支持117个字节,解密时为128;
  2048位的证书,加密时最大支持245个字节,解密时为256。

如果需要加密的字节数超出证书能加密的最大字节数,此时就需要进行分段加密。
**

解密(私钥)

**

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64

cipher_text ="BoNOpo+YEcYoI/vOqmf0AtqfZn49MxiWbYXE+qY7Coz3TjmkGKxkooQ6Mwa2lCRjc2CoPee8YTcuGUA6ncLB+C1JlRTSzbHqfbch22SivsriPMUNoWWZUMY6nNDTE95aZrcNZs32MP7IGrLP/Yev/548Z9iIPzPg/+UHPyLgtPo="

encrypt_text = cipher_text.encode()
rsakey = RSA.importKey(open("private.pem").read())
# 创建用于执行pkcs1_v1_5加密或者解密的密码
cipher = PKCS1_v1_5.new(rsakey) 
text = cipher.decrypt(base64.b64decode(encrypt_text), False)
print(text.decode('utf-8'))

结果

Hello,This is RSA加密

**

签名(私钥)

使用私钥加签,每次签名是一致的。
**

from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA
import base64

#加签
message = "This is a request message..."
rsakey = RSA.importKey(open("private.pem").read())
signer = PKCS1_v1_5.new(rsakey)
digest = SHA.new()
digest.update(message.encode("utf-8"))
sign = signer.sign(digest)
signature = base64.b64encode(sign)
print(signature.decode('utf-8'))

结果

g4jS1+6Y7EMjTXZo5TYEXxBbAmzo1W3LgED43STOh6oZ8DqN5CvaNLG5W7f3d0PX/v+39dD4iMHzoIyfHo5CBMoAdnUA5YGbJdUqbY0Gad/9aIGn2AKhCOXqXnvKAfrVZXfM44hzFGwba7OcYFO+TMvi9uqmst3ImL0g/gbWf4c=

**

验签(公钥)

**

from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA
import base64

#验签
message_verify = "This is a request message..."
signature = "g4jS1+6Y7EMjTXZo5TYEXxBbAmzo1W3LgED43STOh6oZ8DqN5CvaNLG5W7f3d0PX/v+39dD4iMHzoIyfHo5CBMoAdnUA5YGbJdUqbY0Gad/9aIGn2AKhCOXqXnvKAfrVZXfM44hzFGwba7OcYFO+TMvi9uqmst3ImL0g/gbWf4c="
rsakey = RSA.importKey(open("public.pem").read())
verifier = PKCS1_v1_5.new(rsakey)
hsmsg = SHA.new()
hsmsg.update(message_verify.encode("utf-8"))
is_verify = verifier.verify(hsmsg, base64.b64decode(signature))
print(is_verify)

结果

True

问题:对长字符串如何进行加密报错

File “E:\venv\practice_env\lib\site-packages\Crypto\Cipher\PKCS1_v1_5.py”, line 107, in encrypt
raise ValueError(“Plaintext is too long.”)
ValueError: Plaintext is too long.

import base64
import json

from Crypto.Cipher import PKCS1_v1_5 as PKCS1_v1_5_cipper
from Crypto.Signature import PKCS1_v1_5
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA

import Crypto

# 使用 rsa库进行RSA签名和加解密
# 公钥私钥在线生成网站:http://web.chacuo.net/netrsakeypair

class RsaUtil(object):
    # PUBLIC_KEY_PATH = r'E:\code\actionultra\practice\RSA(python)\public.pem'  # 公钥
    public_key = """-----BEGIN PUBLIC KEY-----
    -----END PUBLIC KEY-----"""

    # PRIVATE_KEY_PATH = r'E:\code\actionultra\practice\RSA(python)\private.pem'  # 私钥
    private_key = """-----BEGIN RSA PRIVATE KEY-----
    -----END RSA PRIVATE KEY-----"""

    def __init__(self,
                 public_key=public_key ,
                 private_key=private_key):

        if public_key:
            self.company_public_key = RSA.importKey(public_key)
        if private_key:
            self.company_private_key = RSA.importKey(private_key)

    def get_max_length(self, rsa_key, encrypt=True):
        """加密内容过长时 需要分段加密 换算每一段的长度.
            :param rsa_key: 钥匙.
            :param encrypt: 是否是加密.
        """
        blocksize = Crypto.Util.number.size(rsa_key.n) / 8
        reserve_size = 11  # 预留位为11
        if not encrypt:  # 解密时不需要考虑预留位
            reserve_size = 0
        maxlength = blocksize - reserve_size
        return maxlength

    # 加密 支付方公钥
    def encrypt_by_public_key(self, encrypt_message):
        """使用公钥加密.
            :param encrypt_message: 需要加密的内容.
            加密之后需要对接过进行base64转码
        """
        encrypt_result = b''
        max_length = int(self.get_max_length(self.company_public_key))
        cipher = PKCS1_v1_5_cipper.new(self.company_public_key)
        while encrypt_message:
            input_data = encrypt_message[:max_length]
            encrypt_message = encrypt_message[max_length:]
            out_data = cipher.encrypt(input_data.encode(encoding='utf-8'))
            encrypt_result += out_data
        encrypt_result = base64.b64encode(encrypt_result).decode()
        return encrypt_result

    # 加密 支付方私钥
    def encrypt_by_private_key(self, encrypt_message):
        """使用私钥加密.
            :param encrypt_message: 需要加密的内容.
            加密之后需要对接过进行base64转码
        """
        encrypt_result = ""
        max_length = int(self.get_max_length(self.company_private_key))
        cipher = PKCS1_v1_5_cipper.new(self.company_public_key)
        while encrypt_message:
            input_data = encrypt_message[:max_length]
            encrypt_message = encrypt_message[max_length:]
            out_data = cipher.encrypt(input_data.encode(encoding='utf-8').strip())
            encrypt_result += out_data
        encrypt_result = base64.b64encode(encrypt_result)
        return encrypt_result

    def decrypt_by_public_key(self, decrypt_message):
        """使用公钥解密.
            :param decrypt_message: 需要解密的内容.
            解密之后的内容直接是字符串,不需要在进行转义
        """
        decrypt_result = b""
        max_length = self.get_max_length(self.company_public_key, False)
        decrypt_message = base64.b64decode(decrypt_message)
        cipher = PKCS1_v1_5_cipper.new(self.company_public_key)
        while decrypt_message:
            input_data = decrypt_message[:max_length]
            decrypt_message = decrypt_message[max_length:]
            out_data = cipher.decrypt(input_data.encode(encoding='utf-8'), '')
            decrypt_result += out_data
        return decrypt_result

    def decrypt_by_private_key(self, decrypt_message):
        """使用私钥解密.
            :param decrypt_message: 需要解密的内容.
            解密之后的内容直接是字符串,不需要在进行转义
        """
        decrypt_result = b""
        max_length = int(self.get_max_length(self.company_private_key, False))
        decrypt_message = base64.b64decode(decrypt_message)
        cipher = PKCS1_v1_5_cipper.new(self.company_private_key)
        while decrypt_message:
            input_data = decrypt_message[:max_length]
            decrypt_message = decrypt_message[max_length:]
            out_data = cipher.decrypt(input_data, '')
            decrypt_result += out_data.decode(encoding='utf-8').encode(encoding='utf-8').strip() # 此处不能使用 str(out_data) 直接转换bytes
        return decrypt_result.decode(encoding='utf-8')

    # 签名 商户私钥 base64转码
    def sign_by_private_key(self, message):
        """私钥签名.
            :param message: 需要签名的内容.
            签名之后,需要转义后输出
        """
        cipher = PKCS1_v1_5.new(self.company_private_key)  # 用公钥签名,会报错 raise TypeError("No private key") 如下
        # if not self.has_private():
        #   raise TypeError("No private key")
        hs = SHA.new(message)
        signature = cipher.sign(hs)
        return base64.b64encode(signature)

    def verify_by_public_key(self, message, signature):
        """公钥验签.
            :param message: 验签的内容.
            :param signature: 对验签内容签名的值(签名之后,会进行b64encode转码,所以验签前也需转码).
        """
        signature = base64.b64decode(signature)
        cipher = PKCS1_v1_5.new(self.company_public_key)
        hs = SHA.new(message)

        # digest = hashlib.sha1(message).digest()  # 内容摘要的生成方法有很多种,只要签名和解签用的是一样的就可以

        return cipher.verify(hs, signature)


if __name__ == '__main__':


    message = {
            "machine_code": "TOUG:OH2S:QIBB:ZFWD:VDVJ:DBDV:T6Q4:Z5LH:XNYA:2OKR:OIZB:3P5N",
            "max_people_count": 70,
            "expire_time": "2022-08-31"
        }
    message = json.dumps(message)
    # message = ['HY2S:QKUL:J3Y5:IAJT:CID4:PV3N:NALY:BKXC:SCQF:NBN5:D7XA:ZTUN',"20","2022-05-12"]
    # message = json.dumps(message)
    print("明文内容:>>> ")
    print(message)
    rsaUtil = RsaUtil()
    encrypy_result = rsaUtil.encrypt_by_public_key(message)
    print("加密结果:>>> ")
    print(type(encrypy_result),encrypy_result)
    with open("./licence.key", "w", encoding='utf-8') as f:
        f.write(encrypy_result)
    print("licence.key---------写入成功")
    decrypt_result = rsaUtil.decrypt_by_private_key(encrypy_result)
    print("解密结果:>>> ")
    print(decrypt_result)




运行安装模块

pip install pycryptodome==3.14.1

在这里插入图片描述
按照报错信息,缺少依赖信息

解决办法:

python -m pip install --upgrade --force pip

pip install pycryptodome==3.14.1

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值