欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python 多种方法实现 RSA 加密/解密,签名/验签

程序员文章站 2024-03-19 12:29:40
...

继上篇对 RSA 公钥模数和指数的学习,这次我们针对实际应用中 RSA 加密/解密,签名/验签 的使用,利用 Python 进行具体实现。经过查询整理,发现有三种实现方法,下面我们一一展示。

一、rsa 包的实现
首先需要安装 rsa,pip install rsa

import rsa
import base64

def rsaEncrypt(content, pubkey):
    '''
    对字符串进行公钥加密
    :param content: 被加密的字符串
    :return: 加密后的内容
    '''
    # content = content.encode('utf-8')#明文编码格式

    result = rsa.encrypt(content.encode(), pubkey)
    return result

def rsaDecrypt(result, privkey):
    '''
    利用rsa包进行私钥解密
    :param result: 被加密的内容
    :param privkey: 私钥
    :return: 解密后的内容
    '''
    result = base64.b64decode(result)
    print(result)
    content = rsa.decrypt(result, privkey).decode()
    # content = content.decode('utf-8')

    return content

if __name__ == '__main__':
    ############ 使用公钥 - 私钥对信息进行"加密" + "解密" ##############
    message = 'acorn'

    #利用rsa包生成公钥、私钥,
    (pubkey, privkey) = rsa.newkeys(1024)
    print(pubkey, privkey)
    print(pubkey.save_pkcs1())

    # filename = 'public.pem'
    # save(pubkey, filename)


    result = rsaEncrypt(message, pubkey)
    result = base64.b64encode(result)
    print('加密后的密文为:{}'.format(result))

    content = rsaDecrypt(result, privkey)
    print('解密后的明文为:{}'.format(content))

    ############ 使用私钥 - 公钥对信息进行"签名" + "验签" ##############
    #明文
    mss = '重要指令'
    #私钥签名
    signature = rsa.sign(mss.encode(), privkey, 'SHA-1')
    print(signature)
    #根据收到的明文、密文,然后用公钥验证,进行身份确认
    rsa.verify(mss.encode(), signature, pubkey)

二、Crypto 包的实现

pycrypto,pycrytodome 和 crypto 是一个东西,crypto 在 python 上面的名字是 pycrypto 它是一个第三方库,但是已经停止更新,所以不建议安装这个库;

windows 下 python3.6 版本以上安装比较麻烦(本人是 Python3.7,尝试安装未成功,如果需要尝试安装的,可以参考点击这里),在安装无果的情况下,可以安装 pycryptodome,它是pycrypto 的延伸版本,用法和 pycrypto 是一模一样的;

pip install pycryptodome

安装完成后,在 Python 各种引用包存放路径下,把文件夹 crypto 改为 Crypto 即可。

from Crypto.PublicKey import RSA
from Crypto import Random
from Crypto.Cipher import PKCS1_v1_5    #用于加密
import base64
import Crypto.Signature.PKCS1_v1_5 as sign_PKCS1_v1_5 #用于签名/验签
from Crypto import Hash

def generate_rsa_keys():

    random_generator = Random.new().read
    key = RSA.generate(1024, random_generator) #使用伪随机数来辅助生成

    # key = RSA.generate(1024)

    pubkey = key.publickey().export_key('PEM')  #默认是 PEM的
    privkey = key.export_key('PEM')

    return pubkey, privkey

def rsaEncrypt(message, pubkey):
    '''
    RSA加密
    :param message: 被加密的字符串
    :param pubkey: 公钥
    :return:
    '''
    rsakey = RSA.import_key(pubkey)
    cipher = PKCS1_v1_5.new(rsakey)
    cipher_text = base64.b64encode(cipher.encrypt(message.encode()))


    print(cipher_text)
    return cipher_text

def rsaDecrypt(result, privkey):
    '''
    私钥解密
    :param result:
    :param privkey:
    :return:
    '''
    result = base64.b64decode(result)

    rsakey = RSA.import_key(privkey)
    cipher = PKCS1_v1_5.new(rsakey)
    content = cipher.decrypt(result, Random.new().read).decode()
    print(content)


def save(key, filename):
    # 保存**
    with open(filename, 'w+') as f:
        f.write(key)

def read(filename):
    # 导入**
    with open(filename, 'rb') as f:
        key = f.read()
        return key

def skey_to_pkey(privkey):
    '''
    已知私钥的情况下,生成公钥
    :param privkey:
    :return:
    '''
    s_key = RSA.import_key(privkey)
    p_key = s_key.publickey().export_key()

    return p_key

def sign_with_privkey(message, privkey):
    '''
    私钥签名
    :param message:明文
    :param privkey:
    :return:密文
    '''
    signer = sign_PKCS1_v1_5.new(RSA.import_key(privkey))
    rand_hash = Hash.SHA256.new()
    rand_hash.update(message.encode())
    signature = signer.sign(rand_hash)

    return signature

def verify_with_pubkey(signature, message, pubkey):
    '''
    公钥验签
    :param signature:密文
    :param message:明文
    :param pubkey:公钥
    :return:
    '''
    verifier = sign_PKCS1_v1_5.new(RSA.import_key(pubkey))
    rand_hash = Hash.SHA256.new()
    rand_hash.update(message.encode())
    verify = verifier.verify(rand_hash, signature)

    return verify

def execute_without_signature(pubkey, privkey):
    '''
    公钥加密,私钥解密
    :param pubkey:
    :param privkey:
    :return:
    '''
    message = 'acorn'
    result = rsaEncrypt(message, pubkey)
    rsaDecrypt(result, privkey)
    print("rsa test success!")


def execute_with_signature(pubkey, privkey):
    '''
    签名验证,不加密
    :param pubkey:
    :param privkey:
    :return:
    '''
    text = 'herish'
    assert verify_with_pubkey(sign_with_privkey(text,privkey), text, pubkey)
    print("rsa Signature verified!")

if __name__ == '__main__':
    pubkey, privkey = generate_rsa_keys()
    print(pubkey, privkey)

    ############ 使用公钥 - 私钥对信息进行"加密" + "解密" ##############
    execute_without_signature(pubkey, privkey)

    ############ 使用私钥 - 公钥对信息进行"签名" + "验签" ##############
    execute_with_signature(pubkey, privkey)

三、cryptography 包的实现

首先安装 cryptography,pip install cryptography

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa,padding
from cryptography.hazmat.primitives import serialization,hashes
from cryptography.hazmat.primitives.serialization import NoEncryption,\
    Encoding, PrivateFormat, PublicFormat
import base64
from cryptography.exceptions import InvalidSignature

ALGORITHM_DICT = {
        'sha1': hashes.SHA1(),
        'sha224': hashes.SHA224(),
        'sha256': hashes.SHA256(),
        'sha384': hashes.SHA384(),
        'sha512': hashes.SHA512()
    }

def generate_keys():
    '''
    生成公钥和私钥
    :return:
    '''
    privkey = rsa.generate_private_key(
        public_exponent=65537,
        key_size=1024,
        backend=default_backend(),
    )

    new_privkey = privkey.private_bytes(
        Encoding.PEM,
        PrivateFormat.PKCS8,
        NoEncryption()
    )

    pubkey = privkey.public_key()

    new_pubkey = pubkey.public_bytes(
        Encoding.PEM,
        PublicFormat.SubjectPublicKeyInfo,
    )

    print(new_pubkey, new_privkey)
    return pubkey, privkey

def rsaEncrypt(message, pubkey, algorithm='sha1'):
    '''
    公钥加密
    :param message:
    :param pubkey:
    :param algorithm:密码散列函数算法
    :return:
    '''
    if not isinstance(message, bytes):
        message = message.encode()

    algorithm = ALGORITHM_DICT.get(algorithm)
    padding_data = padding.OAEP(
        mgf=padding.MGF1(algorithm=algorithm),
        algorithm=algorithm,
        label=None
    )
    ciphertext = pubkey.encrypt(message, padding_data)
    ciphertext = base64.b64encode(ciphertext)
    print(ciphertext)

    return ciphertext

def rsaDecrypt(result, privkey, algorithm='sha1'):
    '''
    私钥解密
    :param result:加密后的内容
    :param privkey:
    :param algorithm:密码散列函数算法
    :return:
    '''
    algorithm = ALGORITHM_DICT.get(algorithm)
    padding_data = padding.OAEP(
        mgf=padding.MGF1(algorithm=algorithm),
        algorithm=algorithm,
        label=None
    )

    result = base64.b64decode(result)

    content = privkey.decrypt(result, padding_data).decode()
    print(content)

    return content

def execute_without_signature(pubkey, privkey):
    #公钥加密,私钥解密
    message = 'herish'
    ciphertext = rsaEncrypt(message, pubkey, 'sha256')
    content = rsaDecrypt(ciphertext, privkey, 'sha256')

    print("rsa test success!")

def sign(message, privkey, algorithm='sha1'):
    '''
    私钥签名
    :param message:
    :param privkey:
    :param algorithm:
    :return:
    '''
    if not isinstance(message, bytes):
        message = message.encode()

    algorithm = ALGORITHM_DICT.get(algorithm)
    padding_data = padding.PSS(
        mgf=padding.MGF1(algorithm),
        salt_length=padding.PSS.MAX_LENGTH
    )

    return privkey.sign(message, padding_data, algorithm)


def verify(message, signature, pubkey, padding_mode='pss', algorithm='sha1'):
    '''
    公钥验签
    :param message:
    :param signature:
    :param pubkey:
    :param padding_mode:
    :param algorithm:
    :return:
    '''
    if not isinstance(message, bytes):
        message = message.encode()

    algorithm = ALGORITHM_DICT.get(algorithm)

    if padding_mode == 'pkcs1':
        padding_data = padding.PKCS1v15()
    else:
        padding_data = padding.PSS(
        mgf=padding.MGF1(algorithm),
        salt_length=padding.PSS.MAX_LENGTH
    )

    try:
        pubkey.verify(signature, message,
                          padding_data, algorithm)
    except InvalidSignature:
        padd_verify = False
    else:
        padd_verify = True

    return padd_verify

def execute_with_signature(pubkey, privkey):

    text = 'herish'
    signature = sign(text, privkey, 'sha256')
    assert verify(message=text, signature=signature, pubkey=pubkey, algorithm='sha256')
    print("rsa Signature verified!")

if __name__ == '__main__':
    pubkey, privkey = generate_keys()

    ############ 使用公钥 - 私钥对信息进行"加密" + "解密" ##############
    # execute_without_signature(pubkey, privkey)

    ############ 使用私钥 - 公钥对信息进行"签名" + "验签" ##############
    execute_with_signature(pubkey, privkey)
相关标签: RSA