Python脚本之RSA加解密

本文为博主原创,未经授权,严禁转载及使用。
本文链接:https://blog.csdn.net/zyooooxie/article/details/120430654

之前写过一篇 https://blog.csdn.net/zyooooxie/article/details/117022776,关于MD5加密、AES加解密ECB、异或加解密的;最近看到项目有些接口参数值要使用rsa加密,简单分享些;

个人博客:https://blog.csdn.net/zyooooxie

RSA非对称加密-公钥加密,私钥解密

非对称加密算法(公开密钥 加密算法),它需要2个密钥,一个public Key,一个private Key。

数据发送方持有公钥,数据接收方持有私钥。

数据发送方通过加密算法和公钥对明文进行加密,得到密文;将密文发送给接收方;数据接收方通过加密算法和私钥对密文进行解密,获得明文。

PEM格式-pkcs#1、pkcs#8

2种格式的 首尾标签

pkcs#8
    """     
    # 私钥
    -----BEGIN PRIVATE KEY-----
    -----END PRIVATE KEY-----
    
    # 公钥
    -----BEGIN PUBLIC KEY-----
    -----END PUBLIC KEY-----
    """
pkcs#1
    """
    # 私钥
    -----BEGIN RSA PRIVATE KEY-----
    -----END RSA PRIVATE KEY-----

    # 公钥
    -----BEGIN RSA PUBLIC KEY-----
    -----END RSA PUBLIC KEY-----    
    """

pkcs1格式 与 pkcs8格式公钥转换 可以在网上找到 在线工具;

pkcs8-pycryptodome

生成公钥、私钥

from user_log import Log

from Crypto import Random
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1        # 对应pkcs8
from Crypto.Signature import PKCS1_v1_5 as Signature_PKCS1
import base64


def test_export_rsa(pkcs: int = 8):

    random_generator = Random.new().read        # 使用 Crypto.Random.new().read   伪随机数生成器
    rsa_obj = RSA.generate(2048, random_generator)      # 生成RSA密钥对(a new RSA key pair);2048是秘钥的长度

    # exportKey() pkcs (*For private keys only*)、format='PEM'、passphrase=None (*For private keys only*)
    """ 
    参数 pkcs=8
    
    # 私钥
    -----BEGIN PRIVATE KEY-----
    -----END PRIVATE KEY-----
    
    # 公钥
    -----BEGIN PUBLIC KEY-----
    -----END PUBLIC KEY-----
    """

    private_key = rsa_obj.exportKey(pkcs=pkcs)                  # 生成私钥
    with open("private.pem", 'wb') as f:
        f.write(private_key)
    Log.info('private.pem 已生成')

    public_key = rsa_obj.publickey().exportKey(pkcs=pkcs)       # 生成公钥
    with open("public.pem", 'wb') as f:
        f.write(public_key)
    Log.info('public.pem 已生成')

手上有公钥、私钥的pem文件,对msg进行加密和解密



def test_rsa_1(msg: str):
    """
    使用公钥对内容进行rsa加密
    :param msg:
    :return:
    """
    Log.info('明文msg是:{}'.format(msg))

    with open('public.pem') as f:
        key = f.read()

        # import_key() extern_key (string or byte string)、passphrase=None (For private keys only)
        pub_key = RSA.importKey(str(key))       # 对(从文件中读取的)公钥字符串进行处理,处理成可用的加密公钥

        # new()key: RSA key object
        cipher = Cipher_PKCS1.new(pub_key)      # 实例化一个加密对象cipher,传入的参数是公钥

        en_str = cipher.encrypt(bytes(msg.encode("utf8")))
        rsa_text = base64.b64encode(en_str)     # base64 进行编码

    Log.info(f"密文是:{
      
      rsa_text.decode('utf-8')}")

    # 这里每次使用公钥加密后的结果都不一致,跟 对数据的padding即填充 有关
    return rsa_text.decode('utf-8')


def test_rsa_2(encrypted_str: str):
    """
    使用私钥对内容进行rsa解密
    :param encrypted_str:
    :return:
    """
    with open('private.pem') as f:
        key = f.read()

        # 如果私钥有密码 则使用相应密码:import_key() passphrase (string or byte string)
        pri_key = RSA.importKey(key)            # 对(从文件中读取的)私钥字符串进行处理,处理成可用的解密私钥

        cipher = Cipher_PKCS1.new(pri_key)      # 实例化一个解密对象 cipher ,传入的参数是私钥
        back_text = cipher.decrypt(base64.b64decode(encrypted_str), '解密失败')
        # sentinel:The object to return whenever an error is detected.

    Log.info('解密后 得到的明文是:{}'.format(back_text.decode('utf-8')))
    return back_text.decode('utf-8')
    

只有公钥、私钥的str,对msg进行加密和解密


def test_encrypt(msg: str, public_key: str):
    """

    :param msg:
    :param public_key:
    :return:
    """
    Log.info('明文message是:{}'.format(msg))
    pubkey_str = '\n'.join(['-----BEGIN PUBLIC KEY-----', public_key, '-----END PUBLIC KEY-----'])
    # Log.info('pubkey_str是:{}'.format(pubkey_str))

    cipher = Cipher_PKCS1.new(RSA.importKey(pubkey_str))
    crypto = base64.b64encode(cipher.encrypt(msg.encode('utf-8')))
    Log.info('密文是:{}'.format(crypto.decode()))
    return crypto.decode()


def test_decrypt(encrypted_msg: str, private_key: str):
    """

    :param encrypted_msg:
    :param private_key:
    :return:
    """
    private_str = '-----BEGIN PRIVATE KEY-----' + '\n' + private_key + '\n' + '-----END PRIVATE KEY-----'
    # Log.info('private_str是:{}'.format(private_str))

    cipher = Cipher_PKCS1.new(RSA.importKey(private_str))
    decrypt_str = cipher.decrypt(base64.b64decode(encrypted_msg.encode('utf-8')), 'DecryptError')
    Log.info('解密后 得到的明文是:{}'.format(decrypt_str.decode()))
    return decrypt_str.decode()

pkcs1-rsa

生成公钥、私钥

import rsa
import base64

def test_rsa_export():
    # newkeys() nbits: the number of bits required to store
    (public_key, private_key) = rsa.newkeys(1024)   # Generates public and private keys,and returns them as (pub, priv)

    with open('public_1.pem', 'wb') as f:
        f.write(public_key.save_pkcs1())                # save_pkcs1() format: str = 'PEM'
    Log.info('public_1.pem 已生成')

    with open('private_1.pem', 'wb') as f:
        f.write(private_key.save_pkcs1())
    Log.info('private_1.pem 已生成')

    """
    # 私钥
    -----BEGIN RSA PRIVATE KEY-----
    -----END RSA PRIVATE KEY-----

    # 公钥
    -----BEGIN RSA PUBLIC KEY-----
    -----END RSA PUBLIC KEY-----    
    """

只有公钥、私钥的str,对message进行加密和解密


def test_pkcs1_1(message: str, public_key: str, private_key: str):
    """

    :param message:
    :param public_key:
    :param private_key:
    :return:
    """
    Log.info('明文message是:{}'.format(message))

    pubkey_str = '\n'.join(['-----BEGIN RSA PUBLIC KEY-----', public_key, '-----END RSA PUBLIC KEY-----'])

    # load_pkcs1() keyfile: bytes, format: str = 'PEM'
    pubkey = rsa.PublicKey.load_pkcs1(pubkey_str.encode())      # 返回 the loaded key

    # encrypt() message: bytes, pub_key: key.PublicKey
    cipher_text = rsa.encrypt(message.encode(), pubkey)

    crypto = base64.b64encode(cipher_text)                      # base64进行二进制编码
    Log.info('密文是:{}'.format(crypto.decode()))

    private_str = '\n'.join(['-----BEGIN RSA PRIVATE KEY-----', private_key, '-----END RSA PRIVATE KEY-----'])

    privkey = rsa.PrivateKey.load_pkcs1(private_str.encode())

    # decrypt() crypto: bytes, priv_key: key.PrivateKey
    plain_text = rsa.decrypt(cipher_text, privkey)
    Log.info('解密后 得到的明文是:{}'.format(plain_text.decode()))

手上有公钥、私钥的pem文件,对message进行加密和解密


def test_pkcs1_2(message: str):
    """

    :param message:
    :return:
    """
    Log.info('明文message是:{}'.format(message))

    with open('public_1.pem', 'r') as f:
        pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())

    crypto_text = rsa.encrypt(message.encode(), pubkey)
    crypto = base64.b64encode(crypto_text)
    Log.info('密文是:{}'.format(crypto.decode()))

    with open('private_1.pem', 'rb') as f:
        privkey = rsa.PrivateKey.load_pkcs1(f.read())

    plain_text = rsa.decrypt(crypto_text, privkey)
    Log.info('解密后 得到的明文是:{}'.format(plain_text.decode()))

实际rsa库是能对pkcs8的公钥 做load的,使用的是 load_pkcs1_openssl_pem()


def test_pkcs8(message: str, public_key: str, private_key: str):
    Log.info('明文message是:{}'.format(message))

    pubkey_str = """-----BEGIN PUBLIC KEY-----""" + '\n' + public_key + '\n' + """-----END PUBLIC KEY-----"""
    pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(pubkey_str.encode())

    cipher_text = rsa.encrypt(message.encode(), pubkey)

    crypto = base64.b64encode(cipher_text)
    Log.info('密文是:{}'.format(crypto.decode()))

这篇内容就这些;本文链接:https://blog.csdn.net/zyooooxie/article/details/120430654

交流技术 欢迎+QQ 153132336 zy
个人博客 https://blog.csdn.net/zyooooxie

おすすめ

転載: blog.csdn.net/zyooooxie/article/details/120430654