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

Rust中BigInt处理证书签名字节两次输出结果不一致问题

问题分析与解决

问题原因:悬垂引用导致的未定义行为

你的代码中两次调用BigInt::from_signed_bytes_be返回不同结果,核心原因是悬垂引用引发的未定义内存访问:

  1. 代码中let mut signature_bytes = cert.signature().as_slice();这一行存在生命周期错误:
    • cert.signature()返回的X509Signature是临时对象,该行执行完成后会立即被Rust的所有权系统销毁。
    • as_slice()返回的&[u8]切片,其生命周期与这个临时的X509Signature绑定。临时对象销毁后,signature_bytes就变成了悬垂引用,指向已经被释放的内存。
  2. 第一次调用时,该内存区域尚未被其他数据覆盖,所以能得到正确结果;第二次调用时,内存已被改写,输入的字节内容发生变化,最终生成的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,提问作者欧阳奔

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 21:14:57