Rust中BigInt处理证书签名字节两次输出结果不一致问题
问题分析与解决
问题原因:悬垂引用导致的未定义行为
你的代码中两次调用BigInt::from_signed_bytes_be返回不同结果,核心原因是悬垂引用引发的未定义内存访问:
- 代码中
let mut signature_bytes = cert.signature().as_slice();这一行存在生命周期错误:cert.signature()返回的X509Signature是临时对象,该行执行完成后会立即被Rust的所有权系统销毁。as_slice()返回的&[u8]切片,其生命周期与这个临时的X509Signature绑定。临时对象销毁后,signature_bytes就变成了悬垂引用,指向已经被释放的内存。
- 第一次调用时,该内存区域尚未被其他数据覆盖,所以能得到正确结果;第二次调用时,内存已被改写,输入的字节内容发生变化,最终生成的
BigInt自然不同。
修复代码
需要先保存X509Signature实例,确保切片的生命周期与证书一致:
use std::fs::File; use std::io::Read; use num_bigint::BigInt; use openssl::x509::X509; fn main() -> Result<(), Box<dyn std::error::Error>> { let mut file = File::open("ca.crt")?; let mut cert_buffer = Vec::new(); file.read_to_end(&mut cert_buffer)?; let cert = X509::from_pem(&cert_buffer)?; // 先保存X509Signature实例,避免临时对象被销毁 let signature = cert.signature(); let signature_bytes = signature.as_slice(); println!("获取证书签名密文 x"); println!("{}", BigInt::from_signed_bytes_be(signature_bytes)); println!("获取证书签名密文 x: {}", BigInt::from_signed_bytes_be(signature_bytes)); Ok(()) }
额外提示:需求与代码的偏差
注意到你提到“想要获取证书的公钥并以BigInt格式打印”,但当前代码处理的是证书签名而非公钥。如果需要提取公钥(比如RSA公钥的模数n和指数e),可以参考以下示例:
// 提取RSA公钥并转换为BigInt use openssl::pkey::PKey; use openssl::rsa::Rsa; // ... 前面读取证书的代码 ... let pkey = cert.public_key()?; let rsa = Rsa::from_public_key(pkey.as_ref())?; // 将公钥的模数和指数转换为BigInt let n = BigInt::from_bytes_be(num_bigint::Sign::Plus, rsa.n().to_vec().as_slice()); let e = BigInt::from_bytes_be(num_bigint::Sign::Plus, rsa.e().to_vec().as_slice()); println!("公钥模数n: {}", n); println!("公钥指数e: {}", e);
内容的提问来源于stack exchange,提问作者欧阳奔
相关产品推荐
相关产品推荐

