You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PyCryptodome中用ECC替代RSA实现混合加密

如何用PyCryptodome实现ECC+AES混合加密

你遇到的问题很典型——PKCS1_OAEP是专门为RSA设计的加密模式,完全不能和ECC公钥配合使用!在ECC体系下,要安全地加密AES会话密钥,我们通常采用两种方案:ECIES(椭圆曲线集成加密方案)(贴近你原有的“用公钥加密密钥”思路),或者通过ECDH密钥交换生成共享会话密钥。下面给你详细的修正实现:

方案一:手动实现ECDH+AES混合加密

这种方式不需要依赖第三方库,完全基于PyCryptodome原生功能实现,最贴合你原有的代码逻辑:

from Crypto.PublicKey import ECC
from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto.Protocol.KDF import HKDF
import base64

def generate_keys():
    # 生成P-256曲线的ECC密钥(安全强度等效于3072位RSA)
    key = ECC.generate(curve='P-256')
    private_key = key.export_key(format='PEM')
    with open('private_key.pem', 'wt') as f:
        f.write(private_key)
    public_key = key.public_key().export_key(format='PEM')
    with open('public_key.pem', 'wt') as f:
        f.write(public_key)

def encrypt(username, msg):
    # 读取接收方的ECC公钥
    with open(f"{username}.pem", 'rt') as f:
        recipient_pub_key = ECC.import_key(f.read())
    
    # 步骤1:生成临时ECC密钥对,用于ECDH密钥交换
    ephemeral_key = ECC.generate(curve='P-256')
    # 计算双方共享的秘密值
    shared_secret = ephemeral_key.d * recipient_pub_key.pointQ
    # 用HKDF派生安全的AES会话密钥(避免直接使用原始共享值)
    derived_key = HKDF(shared_secret.x.to_bytes(32, byteorder='big'), 16, salt=None, hashmod=SHA256)
    
    # 步骤2:用派生密钥加密明文(和原AES逻辑一致)
    cipher_aes = AES.new(derived_key, AES.MODE_EAX)
    ciphertext, tag = cipher_aes.encrypt_and_digest(msg.encode('utf-8'))
    
    # 步骤3:打包加密数据(临时公钥 + 分隔符 + nonce + tag + 密文)
    ephemeral_pub = ephemeral_key.public_key().export_key(format='PEM').encode('utf-8')
    encrypted_data = ephemeral_pub + b'||' + cipher_aes.nonce + tag + ciphertext
    encrypted_data = base64.b64encode(encrypted_data)
    return encrypted_data.decode()

def decrypt(encrypted_data):
    # 读取自己的ECC私钥
    with open('private_key.pem', 'rt') as f:
        private_key = ECC.import_key(f.read())
    
    # 解码并拆分加密数据
    encrypted_data = base64.b64decode(encrypted_data)
    ephemeral_pub_bytes, rest = encrypted_data.split(b'||', 1)
    nonce = rest[:16]
    tag = rest[16:32]
    ciphertext = rest[32:]
    
    # 导入临时公钥,计算共享密钥
    ephemeral_pub = ECC.import_key(ephemeral_pub_bytes)
    shared_secret = private_key.d * ephemeral_pub.pointQ
    derived_key = HKDF(shared_secret.x.to_bytes(32, byteorder='big'), 16, salt=None, hashmod=SHA256)
    
    # AES解密并验证完整性
    cipher_aes = AES.new(derived_key, AES.MODE_EAX, nonce=nonce)
    plaintext = cipher_aes.decrypt_and_verify(ciphertext, tag)
    return plaintext.decode('utf-8')

关键修改说明:

  • 移除了错误的PKCS1_OAEP调用,改用ECDH密钥交换生成共享密钥,再通过HKDF派生安全的AES会话密钥
  • 生成临时ECC密钥对并将其公钥随加密数据一起发送,确保接收方能用自己的私钥计算出相同的共享密钥
  • 用||作为简单分隔符区分临时公钥和加密数据段(生产环境建议用更严谨的二进制格式,比如ASN.1)

方案二:用ECIES简化实现(第三方库辅助)

如果不想手动实现密钥交换逻辑,可以用eciespy库(需提前安装),它封装了成熟的ECIES实现:

pip install eciespy

简化后的代码如下:

from ecies import encrypt, decrypt
from ecies.utils import generate_eth_key
import base64

def generate_keys():
    # 生成secp256k1曲线的密钥(也支持P-256等标准曲线)
    key = generate_eth_key()
    private_key = key.to_hex()
    public_key = key.public_key.to_hex()
    with open('private_key.txt', 'wt') as f:
        f.write(private_key)
    with open('public_key.txt', 'wt') as f:
        f.write(public_key)

def encrypt(username, msg):
    # 读取接收方公钥
    with open(f"{username}.txt", 'rt') as f:
        recipient_pub_key = f.read().strip()
    # ECIES自动完成会话密钥加密+明文加密的全流程
    encrypted_bytes = encrypt(recipient_pub_key, msg.encode('utf-8'))
    return base64.b64encode(encrypted_bytes).decode()

def decrypt(encrypted_data):
    # 读取自己的私钥
    with open('private_key.txt', 'rt') as f:
        private_key = f.read().strip()
    encrypted_bytes = base64.b64decode(encrypted_data)
    plaintext = decrypt(private_key, encrypted_bytes)
    return plaintext.decode('utf-8')

核心原理说明

RSA基于大整数分解难题,而ECC基于椭圆曲线离散对数难题,两者数学基础完全不同,因此RSA的加密模式(如PKCS1_OAEP)无法直接应用在ECC上。ECC的核心优势就是用更短的密钥长度达到和RSA相同的安全强度,所以必须使用ECC专属的密钥交换或加密方案。

内容的提问来源于stack exchange,提问作者Ahmed Salama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:00:30