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

Rust使用Kyber1024时如何传入自定义字符串生成对应密文

核心原因说明

Kyber1024属于密钥封装机制(KEM),并非通用公钥加密算法,原生不支持直接传入自定义字符串输出对应密文。它的设计目标是在通信双方之间协商出一份一致、第三方无法窃取的固定长度对称密钥,要实现自定义字符串加密,需要搭配对称认证加密(AEAD)算法做混合加密,这也是后量子加密场景的标准使用模式。

实现流程
  • 接收方生成Kyber1024公私钥对,公钥公开分发,私钥本地安全存储
  • 发送方获取接收方公钥后,调用encapsulate接口得到Kyber层密文和32字节长度的共享密钥
  • 发送方以该共享密钥作为AES-256-GCM的加密密钥,对自定义字符串做对称加密,同时生成12字节随机nonce
  • 发送方将「Kyber层密文 + nonce + 对称加密后的字符串密文」打包为总密文,发送给接收方
  • 接收方收到总密文后,先用本地私钥调用decapsulate接口解封装Kyber层密文,得到和发送方一致的32字节共享密钥
  • 接收方用该共享密钥解密对称密文,得到原始自定义字符串
具体代码实现

依赖配置

在Cargo.toml中添加以下依赖:

[dependencies]
pqcrypto-kyber = "0.7.6"
aes-gcm = "0.10.3"
rand_core = { version = "0.6.4", features = ["std"] }

核心逻辑代码

use pqcrypto_kyber::kyber1024::{
    self, keypair, encapsulate, decapsulate,
    PublicKey, SecretKey, Ciphertext as KyberCiphertext
};
use aes_gcm::{
    aead::{Aead, KeyInit},
    Aes256Gcm, Nonce
};
use rand_core::{OsRng, RngCore};
use std::error::Error;

// 传输用组合密文结构
pub struct CombinedCiphertext {
    kyber_ct: KyberCiphertext,
    aes_nonce: [u8; 12], // AES-GCM标准nonce长度为12字节,无需保密
    encrypted_payload: Vec<u8>, // 自定义字符串加密后的密文
}

/// 传入接收方公钥和待加密字符串,返回可直接传输的组合密文
pub fn encrypt_string(recipient_pk: &PublicKey, plaintext: &str) -> Result<CombinedCiphertext, Box<dyn Error>> {
    // Kyber层封装得到共享密钥和对应密文
    let (shared_key, kyber_ct) = encapsulate(recipient_pk);

    // 初始化AES-256-GCM加密器,Kyber1024输出的共享密钥刚好32字节,匹配AES256密钥长度要求
    let cipher = Aes256Gcm::new_from_slice(shared_key.as_bytes())?;

    // 生成随机nonce
    let mut aes_nonce = [0u8; 12];
    OsRng.fill_bytes(&mut aes_nonce);
    let nonce = Nonce::from_slice(&aes_nonce);

    // 加密自定义字符串
    let encrypted_payload = cipher.encrypt(nonce, plaintext.as_bytes())?;

    Ok(CombinedCiphertext {
        kyber_ct,
        aes_nonce,
        encrypted_payload,
    })
}

/// 传入本地私钥和收到的组合密文,返回解密后的原始字符串
pub fn decrypt_string(recipient_sk: &SecretKey, combined_ct: &CombinedCiphertext) -> Result<String, Box<dyn Error>> {
    // Kyber层解封装得到相同的共享密钥
    let shared_key = decapsulate(&combined_ct.kyber_ct, recipient_sk);

    // 初始化解密器
    let cipher = Aes256Gcm::new_from_slice(shared_key.as_bytes())?;
    let nonce = Nonce::from_slice(&combined_ct.aes_nonce);

    // 解密并转换为字符串
    let plaintext_bytes = cipher.decrypt(nonce, combined_ct.encrypted_payload.as_ref())?;
    let plaintext = String::from_utf8(plaintext_bytes)?;

    Ok(plaintext)
}

使用示例

fn main() -> Result<(), Box<dyn Error>> {
    // 接收方本地生成公私钥对,公钥公开给发送方,私钥不得泄露
    let (pk, sk) = keypair();

    // 发送方逻辑:加密自定义字符串
    let secret_msg = "测试自定义加密字符串,包含中文、数字123、符号!@#";
    let combined_ct = encrypt_string(&pk, secret_msg)?;
    // 此处可将combined_ct序列化为字节流通过网络发送,序列化可选用bincode/postcard等库

    // 接收方逻辑:解密收到的密文
    let decrypted_msg = decrypt_string(&sk, &combined_ct)?;
    assert_eq!(secret_msg, decrypted_msg);
    println!("解密成功,原始内容:{}", decrypted_msg);

    Ok(())
}
注意事项
  • 禁止修改Kyber算法内部逻辑强行传入自定义字符串,会直接破坏算法的后量子安全属性
  • 对称加密必须选择带身份认证的AEAD算法,禁止使用无认证的CBC/ECB等加密模式,避免密文被篡改、伪造
  • Kyber1024输出的共享密钥固定为32字节,无需额外做密钥派生即可直接用于AES-256加密
  • 组合密文传输前需要做序列化处理,Kyber1024密文固定长度为1568字节,加12字节nonce,固定加密开销很小

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:09:17