利用Python的 Crypto 库对数据进行RSA加密

1、安装crypto

pip install pycryptodome

Python的 Crypto 库(也称为 pycryptodome 库)是一个功能强大且广泛使用的工具。它提供了许多加密算法和功能,使您能够保护敏感数据的安全性。

2、生成密钥对

from Crypto.PublicKey import RSA

# 生成RSA密钥对
key = RSA.generate(2048)

# 保存私钥到文件
private_key = key.export_key()
with open('private_key.pem', 'wb') as f:
    f.write(private_key)

# 保存公钥到文件
public_key = key.publickey().export_key()
with open('public_key.pem', 'wb') as f:
    f.write(public_key)

3、使用公钥加密数据

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

# 加载公钥
with open('public_key.pem', 'rb') as f:
    public_key = RSA.import_key(f.read())

# 创建RSA加密对象
cipher = PKCS1_OAEP.new(public_key)

# 要加密的数据
data = b"Hello, this is a secret message."

# 加密数据
ciphertext = cipher.encrypt(data)

print("Encrypted:", ciphertext)

4、使用私钥解密数据

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

# 加载私钥
with open('private_key.pem', 'rb') as f:
    private_key = RSA.import_key(f.read())

# 创建RSA解密对象
cipher = PKCS1_OAEP.new(private_key)

# 解密数据
plaintext = cipher.decrypt(ciphertext)

print("Decrypted:", plaintext.decode('utf-8'))

5、数据填充方案

5.1 PKCS1_OAEP

PKCS1_OAEP 是一种填充方案,用于在使用 RSA 加密算法进行数据加密时,增加数据的安全性和可靠性。它是一种在 RSA 加密和解密过程中,对原始数据进行填充和处理的方法,以增加对抗各种攻击的能力。

PKCS1_OAEP 提供了以下几个关键特性:

  1. 随机性和唯一性 :在加密过程中,每次对同一数据使用不同的填充,生成的密文都是不同的,这增加了加密的安全性。
  2. 抗选择明文攻击PKCS1_OAEP 防止攻击者根据多次加密结果的不同来猜测明文的可能性。
  3. 抗重放攻击 :填充方案确保每次加密的密文都是唯一的,从而防止攻击者恶意重放加密结果。
  4. 错误检测PKCS1_OAEP 通过添加纠错码来检测密文传输中的错误。

5.2 PKCS1_v1_5

PKCS1_v1_5,全称为 "Public-Key Cryptography Standards #1 - Version 1.5",是另一种在使用 RSA 加密算法进行数据加密时的填充方案。它是早期的一种填充方式,用于在 RSA 加密和解密过程中对数据进行填充和处理,以提供加密数据的完整性和安全性。

PKCS1_OAEP 不同,PKCS1_v1_5 使用固定的字节序列进行填充,其主要特点包括:

  1. 填充字节 :在加密前,将数据填充到特定长度,通常为密钥长度减去固定填充字节的长度。填充字节的内容为一个字节序列,通常以 0x00、0x02 和随机非零字节开头。
  2. 随机性限制 :相对于 PKCS1_OAEPPKCS1_v1_5 的填充过程中的随机性较弱,这使得在一些特定攻击场景下可能更容易受到攻击。
  3. 安全性较弱 :由于设计时的一些弱点,PKCS1_v1_5 在某些情况下可能容易受到攻击,如 Bleichenbacher 攻击等。

6、我项目中用到的

6.1 背景

  • 发送post请求获取数据,密码需要经过加密,选择的是RSA非对称加密算法、Crypto库
  • 公钥不需要自己创建,需事先向对方请求公钥。

6.2 密码加密

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


……
def make_pem_from_string(public_key):
    header = '-----BEGIN PUBLIC KEY-----'
    content = '\n'.join([public_key[i:i+64] for i in range(0, len(public_key), 64)])
    footer = '-----END PUBLIC KEY-----'
    x509 = '\n'.join([header, content, footer])
    return x509


def public_encrypt(public_key, password):
    x509 = make_pem_from_string(public_key)
    rsa_key = RSA.importKey(x509)
    cipher = PKCS1_v1_5.new(rsa_key)
    text = cipher.encrypt(password.encode("utf-8"))
    return base64.b64encode(text).decode("utf-8")

……

参数:

  • public_key:公钥
  • password:密码

逻辑:

  • make_pem_from_string:将一行字符串形式的公钥(可能是DER编码的二进制数据)转换为PEM格式(Privacy Enhanced Mail格式)的公钥。PEM格式是一种常见的用于存储和传输加密证书、密钥等数据的文本格式。
    • headerfooter 变量分别存储了PEM格式公钥的开始和结束标记,即-----BEGIN PUBLIC KEY----------END PUBLIC KEY-----
    • content 部分是将输入的公钥字符串按照每行64个字符的方式切分,以适应PEM格式的要求。这个步骤是为了使PEM格式的公钥更易于阅读和处理,因为PEM格式的公钥通常在每行显示64个字符,以提高可读性。
    • x509 变量将 headercontentfooter 以换行符连接起来,形成完整的PEM格式的公钥。
  • RSA.importKey :将一个包含RSA密钥信息的字符串或文件内容解析为一个RSA密钥对象,以便在代码中使用这个密钥进行各种加密、解密和其他RSA操作。简而言之,导入公钥/私钥。
  • PKCS1_v1_5.new :创建RSA加密对象
  • cipher.encrypt :加密数据
  • 返回:
    • 编码为可读字符串 :将加密后的二进制数据进行 Base64 编码,可以将其转换为一串可打印的 ASCII 字符串,方便在文本环境中传输和存储。
    • 文本表示 :将加密后的二进制数据以 Base64 编码的形式转换为字符串,使其可以直接用于文本通信,例如在网络传输中或存储在文本文件中。
  • 加密完成

7、注意

Base64 编码并不会增加数据的安全性,只是将数据进行了格式转换,使其适用于文本环境。如果你在处理敏感数据(如密码)时需要更高的安全性,建议在加密之后使用安全的存储和传输方法,而不仅仅依赖于 Base64 编码。


发表评论

评论列表,共 0 条评论

    暂无评论