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

继上篇对 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)

你可能感兴趣的:(密码学习)