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

如何用Rust将SEC1编码的ECDSA公钥序列化为ASN.1 DER格式

SEC1编码ECDSA公钥转ASN.1 DER的Rust实现(无OpenSSL)

我已经实现了该转换的Python版本,但不知道怎么编写对应的Rust版本,且Rust代码不能使用openssl包。查资料后确定可以用k256="0.13.1"和der="0.7.5"库替代。目前已知公钥为Vec<u8>类型,不清楚如何将SEC1编码的ECDSA公钥转换为ASN.1 DER编码。以下是我写的部分代码:

use der::{Encoder, Length};
use k256::elliptic_curve::sec1::{ToEncodedPoint, FromEncodedPoint};
use k256::{PublicKey, EncodedPoint};
use der::asn1::{BitString, ObjectIdentifier};

fn sec1_to_der(sec1_key: &[u8]) -> Result<Vec<u8>, der::Error> {
    // Load the SEC1-encoded ECDSA public key as the public key object
    let public_key = PublicKey::from_sec1_bytes(sec1_key).expect("error");

    // Define the OID for secp256k1 (1.3.132.0.10)
    let secp256k1_oid: ObjectIdentifier = k256::pkcs8::ObjectIdentifier::new("1.3.132.0.10");

    // TODO: How to serialize SEC1-encoded ECDSA to ASN.1 DER format here

}

fn main() {
    let der_encoded_public_key:Vec<u8> = vec![3, 89, 191, 147, 51, 6, 188, 19, 231, 106, 80, 5, 56, 106, 114, 19, 115, 17, 94, 22, 217, 162, 205, 241, 154, 223, 129, 72, 143, 27, 102, 251, 246];;
    let der_key = sec1_to_der(&der_encoded_public_key);
    match der_key {
        Ok(der_key) => {
            println!("{:?}", der_key);
        }
        Err(e) => {
            println!("{:?}", e);
        }
    }
}

补充:预期转换后的DER编码字节数组为:

[48, 86, 48, 16, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 5, 43, 129, 4, 0, 10, 3, 66, 0, 4, 89, 191, 147, 51, 6, 188, 19, 231, 106, 80, 5, 56, 106, 114, 19, 115, 17, 94, 22, 217, 162, 205, 241, 154, 223, 129, 72, 143, 27, 102, 251, 246, 250, 38, 107, 239, 240, 74, 233, 61, 164, 22, 115, 130, 240, 115, 219, 245, 176, 223, 219, 226, 248, 174, 2, 113, 126, 158, 15, 175, 50, 83, 25, 191]

完整实现代码

要完成转换,需要构造符合X.509标准的ASN.1 DER结构,它由算法标识符和公钥比特串两个核心部分组成。以下是补全后的可运行代码:

use der::{asn1::{BitString, ObjectIdentifier, Null}, Encoder, Sequence, Writer};
use k256::elliptic_curve::sec1::ToEncodedPoint;
use k256::PublicKey;

// 定义算法标识符的ASN.1序列结构
#[derive(Sequence)]
struct AlgorithmIdentifier {
    oid: ObjectIdentifier,
    parameters: Null,
}

fn sec1_to_der(sec1_key: &[u8]) -> Result<Vec<u8>, der::Error> {
    // 从SEC1字节加载公钥,返回错误而不是panic
    let public_key = PublicKey::from_sec1_bytes(sec1_key)?;

    // 构造secp256k1的算法标识符
    let alg_id = AlgorithmIdentifier {
        oid: k256::pkcs8::OID, // 直接使用k256库预定义的secp256k1 OID
        parameters: Null,
    };

    // 获取公钥的未压缩SEC1编码点,转换为比特串
    let encoded_point = public_key.to_encoded_point(false);
    let pub_key_bitstring = BitString::from_bytes(encoded_point.as_bytes())?;

    // 构造顶层ASN.1序列:包含算法标识符和公钥比特串
    let mut buf = Vec::new();
    let mut writer = der::Writer::new(&mut buf);
    
    writer.sequence(|seq| {
        seq.encode(&alg_id)?;
        seq.encode(&pub_key_bitstring)
    })?;

    Ok(buf)
}

fn main() {
    let sec1_key: Vec<u8> = vec![3, 89, 191, 147, 51, 6, 188, 19, 231, 106, 80, 5, 56, 106, 114, 19, 115, 17, 94, 22, 217, 162, 205, 241, 154, 223, 129, 72, 143, 27, 102, 251, 246];
    match sec1_to_der(&sec1_key) {
        Ok(der_key) => {
            println!("{:?}", der_key);
            // 验证是否与预期结果一致
            let expected = vec![48, 86, 48, 16, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 5, 43, 129, 4, 0, 10, 3, 66, 0, 4, 89, 191, 147, 51, 6, 188, 19, 231, 106, 80, 5, 56, 106, 114, 19, 115, 17, 94, 22, 217, 162, 205, 241, 154, 223, 129, 72, 143, 27, 102, 251, 246, 250, 38, 107, 239, 240, 74, 233, 61, 164, 22, 115, 130, 240, 115, 219, 245, 176, 223, 219, 226, 248, 174, 2, 113, 126, 158, 15, 175, 50, 83, 25, 191];
            assert_eq!(der_key, expected, "转换结果与预期不符");
            println!("转换成功,结果符合预期");
        }
        Err(e) => {
            eprintln!("转换失败: {:?}", e);
        }
    }
}

关键步骤说明

  1. 算法标识符构造:ASN.1中的算法标识符是一个序列,包含椭圆曲线的OID和参数(secp256k1的参数固定为NULL),这里直接使用k256::pkcs8::OID避免手动构造OID的错误。
  2. 公钥比特串转换:将公钥的未压缩SEC1编码点转换为ASN.1比特串,这是X.509公钥要求的格式。
  3. 顶层序列编码:使用der库的Writer将算法标识符和公钥比特串组合成一个顶层ASN.1序列,最终编码为DER字节数组。
  4. 错误处理:替换原代码中的expect为?,符合Rust的错误处理最佳实践,避免程序panic。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:17:01