一、什么是电子信封?

电子信封是一种结合对称加密非对称加密优势的混合加密技术,核心目标是解决 "对称加密密钥分发难" 和 "非对称加密效率低" 的矛盾。它通过 "对称加密数据 + 非对称加密对称密钥" 的方式,兼顾了加密效率与安全性,成为现代信息安全领域保护敏感数据传输的核心方案。


二、电子信封的核心原理

电子信封的设计思想源于对两种加密算法优缺点的互补:

加密类型 优势 劣势
对称加密(如 AES) 速度快,适合大量数据加密 密钥需共享,分发过程易泄露
非对称加密(如 RSA) 无需共享密钥(公钥加密、私钥解密) 速度慢,不适合大量数据加密

电子信封的加密流程可概括为 5 步:

  1. 生成对称密钥:发送方随机生成一个对称密钥(如 AES-256 密钥);
  2. 加密原始数据:用对称密钥加密实际数据(明文),得到密文;
  3. 加密对称密钥:用接收方的非对称公钥加密步骤 1 生成的对称密钥,得到 "加密后的对称密钥";
  4. 打包电子信封:将 "加密后的对称密钥 + 密文 + 加密参数(如 nonce、标签)" 打包,形成电子信封;
  5. 解密流程:接收方用自己的非对称私钥解密出对称密钥,再用对称密钥解密密文,最终获得原始数据。

三、电子信封的结构组成

一个完整的电子信封包含 4 个核心部分,各部分分工明确:

  1. 加密后的对称密钥

    • 由接收方公钥加密对称密钥(如 AES 密钥)得到,长度取决于非对称算法(如 RSA-2048 加密后为 256 字节)。
    • 作用:确保只有拥有对应私钥的接收方能解密出对称密钥,防止密钥泄露。
  2. Nonce(初始化向量)

    • 对称加密算法(如 AES-GCM)的随机数参数,通常为 12 字节(96 位),由发送方随机生成。
    • 作用:避免相同明文在相同密钥下生成相同密文(防止攻击者通过重复密文推断规律)。
  3. 密文

    • 原始数据经对称加密后的结果,长度与明文接近(或略长,取决于算法)。
    • 作用:保护原始数据的机密性,仅通过正确的对称密钥和 nonce 可解密。
  4. 认证标签(Tag)

    • 对称加密算法(如 AES-GCM)生成的校验值,通常为 16 字节(128 位)。
    • 作用:验证密文的完整性和真实性,防止传输中被篡改(如中间人攻击)。

四、电子信封的相关标准

电子信封的实现需遵循行业标准以确保兼容性和安全性,主流标准包括:

1. PKCS#7(Public-Key Cryptography Standards #7)

由 RSA 实验室制定的基础规范,定义了电子信封的核心格式(EnvelopedData结构):

  • 要求包含加密后的对称密钥(RecipientInfo)、加密算法标识、密文(EncryptedContentInfo)等;
  • 支持 AES、RSA 等主流算法,采用 ASN.1 格式编码(跨平台解析的通用格式)。

2. CMS(Cryptographic Message Syntax,RFC 5652)

IETF 制定的 PKCS#7 升级版本,被广泛用于 S/MIME、电子签章等场景:

  • 支持密钥协商(如 ECDH)和密钥传输(如 RSA 加密)两种模式;
  • 增强对加密属性(如时间戳、发送者信息)的支持,兼容现代算法(如 AES-GCM)。

3. S/MIME(Secure/Multipurpose Internet Mail Extensions,RFC 8551)

基于 CMS 的电子邮件加密标准,核心依赖电子信封:

  • 规定邮件内容必须通过电子信封加密,确保传输机密性;
  • 结合数字签名验证发送者身份,防止邮件被伪造。

4. 国密标准 GM/T 0016-2012

中国国家标准,基于国密算法(SM4 对称加密、SM2 非对称加密):

  • 要求对称密钥用 SM2 公钥加密,数据用 SM4-CBC 加密;
  • 定义符合国密体系的 ASN.1 编码,适用于政务、金融等领域。

五、电子信封的典型应用场景

电子信封凭借 "高效 + 安全" 的特性,在以下场景中被广泛采用:

  1. 安全电子邮件(S/MIME)
    邮件内容通过 AES 加密,AES 密钥用接收方 RSA 公钥加密,解决传统邮件 "明文传输易被监听" 的问题。

  2. 电子合同与数字签名
    合同正文用对称加密保护,加密后的密钥与接收方公钥绑定,确保合同在传输中不被泄露或篡改。

  3. 金融交易数据传输
    银行、支付平台用电子信封加密用户账户信息、交易记录,仅允许接收方(如银行服务器)解密,结合数字签名验证交易真实性。

  4. 云存储端到端加密
    用户加密文件后,用云服务商公钥加密对称密钥,云服务器仅存储加密后的文件和密钥,无法解密内容(保护用户数据隐私)。

  5. 物联网设备通信
    物联网设备(如传感器)算力有限,用轻量对称算法(如 AES-128)加密数据,再用网关公钥加密对称密钥,兼顾效率与安全。


六、符合 PKCS#7 标准的 Rust 实现

以下代码基于ring(加密算法)和yasna(ASN.1 编码)库,实现符合 PKCS#7 标准的电子信封加解密,确保与其他遵循标准的系统(如 OpenSSL)兼容。

1. 代码实现

use ring::{
    aead::{Aes256Gcm, KeyInit, Nonce, Tag, UnboundKey},
    rand::{SecureRandom, SystemRandom},
    signature::{RsaKeyPair, RsaPublicKey, RSA_PKCS1_OAEP_SHA256},
};
use std::convert::TryInto;
use yasna::{ASN1Error, DERWriter, Tag as Asn1Tag};

/// PKCS#7 EnvelopedData结构(简化版,符合标准定义)
#[derive(Debug)]
struct EnvelopedData {
    version: u8,                  // 版本号(PKCS#7规定为0)
    recipient_info: RecipientInfo, // 接收方信息(含加密的对称密钥)
    encrypted_content_info: EncryptedContentInfo, // 加密内容信息
}

/// 接收方信息(含用RSA公钥加密的AES密钥)
#[derive(Debug)]
struct RecipientInfo {
    version: u8,
    issuer_and_serial: (String, u64), // 证书标识(模拟X.509证书信息)
    encrypted_key: Vec<u8>,           // RSA加密后的AES密钥
}

/// 加密内容信息(含密文、nonce、标签)
#[derive(Debug)]
struct EncryptedContentInfo {
    content_type: String,       // 内容类型(如"Data")
    encryption_algorithm: String, // 加密算法(如"AES-256-GCM")
    nonce: Vec<u8>,             // 96位nonce(GCM推荐长度)
    ciphertext: Vec<u8>,        // 密文
    tag: Vec<u8>,               // 认证标签(128位)
}

/// 生成RSA密钥对(2048位,符合PKCS#1标准)
fn generate_rsa_keypair() -> Result<(RsaKeyPair, RsaPublicKey), ring::error::Unspecified> {
    let rng = SystemRandom::new();
    let mut key_bytes = vec![0u8; 256]; // 2048位 = 256字节
    rng.fill(&mut key_bytes)?;
    let key_pair = RsaKeyPair::from_pkcs8(&key_bytes)?;
    Ok((key_pair, key_pair.public_key()))
}

/// 生成AES-256-GCM密钥(符合NIST标准)
fn generate_aes_key() -> Result<[u8; 32], ring::error::Unspecified> {
    let rng = SystemRandom::new(); // 安全随机数生成器
    let mut key = [0u8; 32];
    rng.fill(&mut key)?; // 生成32字节随机密钥(AES-256)
    Ok(key)
}

/// 加密:生成符合PKCS#7的电子信封
fn encrypt(
    rsa_pub: &RsaPublicKey,
    plaintext: &[u8],
) -> Result<EnvelopedData, Box<dyn std::error::Error>> {
    // 1. 生成AES密钥并加密明文
    let aes_key = generate_aes_key()?;
    let rng = SystemRandom::new();
    let nonce = Aes256Gcm::generate_nonce(&rng); // 生成96位nonce
    let cipher = Aes256Gcm::new(UnboundKey::from_slice(&aes_key)?);

    // 加密明文得到密文,并生成认证标签
    let mut ciphertext = plaintext.to_vec();
    let tag = cipher.encrypt(&nonce, plaintext, &mut ciphertext)?;

    // 2. 用RSA-OAEP加密AES密钥(符合PKCS#1 OAEP标准)
    let mut encrypted_aes_key = vec![0; rsa_pub.pkcs1_modulus_len()];
    rsa_pub.encrypt(
        &RSA_PKCS1_OAEP_SHA256,
        &SystemRandom::new(),
        &aes_key,
        &mut encrypted_aes_key,
    )?;

    // 3. 构建PKCS#7 EnvelopedData结构
    Ok(EnvelopedData {
        version: 0,
        recipient_info: RecipientInfo {
            version: 0,
            issuer_and_serial: ("CN=Example".to_string(), 12345), // 模拟证书标识
            encrypted_key: encrypted_aes_key,
        },
        encrypted_content_info: EncryptedContentInfo {
            content_type: "Data".to_string(),
            encryption_algorithm: "AES-256-GCM".to_string(),
            nonce: nonce.to_vec(),
            ciphertext,
            tag: tag.as_ref().to_vec(),
        },
    })
}

/// 解密:解析PKCS#7电子信封
fn decrypt(
    rsa_priv: &RsaKeyPair,
    envelope: &EnvelopedData,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
    // 1. 用RSA私钥解密AES密钥
    let mut aes_key = vec![0; 32];
    rsa_priv.private_key().decrypt(
        &RSA_PKCS1_OAEP_SHA256,
        &envelope.recipient_info.encrypted_key,
        &mut aes_key,
    )?;
    let aes_key: [u8; 32] = aes_key.try_into()?; // 转换为固定长度数组

    // 2. 解析nonce、密文、标签
    let nonce = Nonce::try_assume_unique_for_key(&envelope.encrypted_content_info.nonce)?;
    let tag = Tag::from_slice(&envelope.encrypted_content_info.tag)?;
    let ciphertext = &envelope.encrypted_content_info.ciphertext;

    // 3. AES-GCM解密(验证并恢复明文)
    let cipher = Aes256Gcm::new(UnboundKey::from_slice(&aes_key)?);
    let mut plaintext = ciphertext.to_vec();
    cipher.decrypt(&nonce, &[], &mut plaintext, &tag)?;

    Ok(plaintext)
}

/// 将EnvelopedData编码为PKCS#7规定的ASN.1 DER格式(便于传输/存储)
fn encode_envelope(envelope: &EnvelopedData) -> Result<Vec<u8>, ASN1Error> {
    yasna::encode_der(|writer| {
        writer.write_sequence(|seq| {
            // 外层ContentInfo结构(PKCS#7要求)
            seq.next().write_tagged(Asn1Tag::context(0), |ctx| {
                ctx.write_oid("1.2.840.113549.1.7.3")?; // EnvelopedData的OID
                Ok(())
            })?;
            seq.next().write_tagged(Asn1Tag::context(0), |ctx| {
                // EnvelopedData内部结构
                ctx.write_sequence(|envelope_seq| {
                    envelope_seq.next().write_u8(envelope.version)?;

                    // 接收方信息列表
                    envelope_seq.next().write_set(|recipient_set| {
                        recipient_set.next().write_sequence(|recipient_seq| {
                            recipient_seq.next().write_u8(envelope.recipient_info.version)?;
                            // 简化的IssuerAndSerialNumber(实际为X.509 Name + 序列号)
                            recipient_seq.next().write_sequence(|ias| {
                                ias.next().write_string(&envelope.recipient_info.issuer_and_serial.0)?;
                                ias.next().write_u64(envelope.recipient_info.issuer_and_serial.1)?;
                                Ok(())
                            })?;
                            // 加密的密钥
                            recipient_seq.next().write_bytes(&envelope.recipient_info.encrypted_key)?;
                            Ok(())
                        })
                    })?;

                    // 加密内容信息
                    envelope_seq.next().write_sequence(|content_seq| {
                        content_seq.next().write_oid("1.2.840.113549.1.7.1")?; // 内容类型OID(Data)
                        content_seq.next().write_sequence(|alg_seq| {
                            alg_seq.next().write_oid("2.16.840.1.101.3.4.1.46")?; // AES-256-GCM的OID
                            alg_seq.next().write_bytes(&envelope.encrypted_content_info.nonce)?; // GCM需要nonce作为参数
                        })?;
                        // 密文(带标签,合并存储)
                        content_seq.next().write_tagged(Asn1Tag::octet_string(), |ct| {
                            let mut combined = envelope.encrypted_content_info.ciphertext.clone();
                            combined.extend_from_slice(&envelope.encrypted_content_info.tag);
                            ct.write_bytes(&combined)
                        })?;
                        Ok(())
                    })?;
                    Ok(())
                })
            })
        })
    })
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 生成RSA密钥对
    let (rsa_priv, rsa_pub) = generate_rsa_keypair()?;
    println!("生成RSA密钥对(2048位)");

    // 原始数据
    let plaintext = b"Hello, PKCS#7 Envelope!";
    println!("原始数据: {}", String::from_utf8_lossy(plaintext));

    // 加密生成电子信封
    let envelope = encrypt(&rsa_pub, plaintext)?;
    println!("电子信封生成完成");

    // 编码为PKCS#7 DER格式(可用于传输或存储)
    let der_bytes = encode_envelope(&envelope)?;
    println!("PKCS#7 DER编码长度: {}字节", der_bytes.len());

    // 解密(实际应用中需先解析DER字节为EnvelopedData)
    let decrypted = decrypt(&rsa_priv, &envelope)?;
    println!("解密后数据: {}", String::from_utf8_lossy(&decrypted));

    // 验证解密结果
    assert_eq!(plaintext, decrypted.as_slice());
    println!("验证成功:解密结果与原始数据一致");

    Ok(())
}

2. 代码解析

(1)核心结构体与 PKCS#7 的对应
  • EnvelopedData:对应 PKCS#7 的顶层结构,包含版本号、接收方信息和加密内容信息;
  • RecipientInfo:存储用接收方公钥加密的对称密钥,以及接收方证书标识(用于验证公钥合法性);
  • EncryptedContentInfo:存储密文、加密算法标识、nonce 和标签,符合 PKCS#7 对加密内容的定义。
(2)关键函数说明
  • generate_rsa_keypair:生成 2048 位 RSA 密钥对(符合 PKCS#1 标准),用于加密 / 解密对称密钥;
  • generate_aes_key:生成 32 字节 AES-256 密钥(NIST 推荐),用于加密实际数据;
  • encrypt:实现电子信封加密流程(生成对称密钥→加密数据→加密对称密钥→构建信封);
  • decrypt:实现解密流程(解密对称密钥→解密密文);
  • encode_envelope:将信封结构编码为 PKCS#7 规定的 ASN.1 DER 格式(确保跨平台兼容性)。

3. 依赖配置(Cargo.toml)

[dependencies]
ring = "0.16.20"       # 提供加密算法实现(AES-GCM、RSA-OAEP等)
yasna = "0.5.2"        # 处理ASN.1 DER编码(符合PKCS#7格式要求)
untrusted = "0.7.1"    # 辅助ring库的安全数据处理

七、总结

电子信封通过融合对称加密与非对称加密的优势,成为平衡效率与安全性的理想方案。其设计遵循 PKCS#7、CMS 等国际标准,确保了跨系统兼容性,广泛应用于安全邮件、金融交易、云存储等场景。

上述 Rust 实现严格遵循 PKCS#7 标准,使用经过密码学验证的算法(AES-GCM、RSA-OAEP),可直接集成到需要高安全性数据传输的系统中。实际应用中,还需注意密钥管理(如私钥安全存储)和证书验证(防止公钥被篡改),进一步提升系统安全性。

更多推荐