如何在Rust中从openssl::pkey::Private类型EcKey提取EC Point的X、Y坐标
从Rust OpenSSL的EcKey中提取公钥X、Y坐标
我来帮你搞定这个问题!其实你不用先把公钥转成压缩字节再手动解析——OpenSSL的Rust绑定已经提供了直接提取坐标的API,既简单又不容易出错。下面是修改后的完整代码,我会一步步解释:
use openssl::bn::{BigNum, BigNumContext}; use openssl::ec::{EcGroup, EcKey, PointConversionForm}; use openssl::nid::Nid; pub fn exportpubkey(key: &EcKey<openssl::pkey::Private>) { // 获取对应的椭圆曲线组(这里是secp256k1) let group = EcGroup::from_curve_name(Nid::SECP256K1).unwrap(); let mut ctx = BigNumContext::new().unwrap(); // 获取公钥对应的点 let pub_key_point = key.public_key(); // 初始化存储X、Y坐标的BigNum变量 let mut x = BigNum::new().unwrap(); let mut y = BigNum::new().unwrap(); // 从公钥点中提取 affine 坐标(X和Y) pub_key_point.get_affine_coordinates_gfp(&group, &mut x, &mut y, &mut ctx).unwrap(); // 输出坐标的十六进制格式(也可以转成字节数组) println!("X坐标: {}", x.to_hex_str().unwrap()); println!("Y坐标: {}", y.to_hex_str().unwrap()); // 如果需要字节数组,可以这样做: let x_bytes = x.to_vec(); let y_bytes = y.to_vec(); println!("X字节: {:?}", x_bytes); println!("Y字节: {:?}", y_bytes); }
关键步骤解释:
pub_key_point.get_affine_coordinates_gfp:这个方法是核心,它直接从EC点中提取出对应的X和Y坐标,存储到传入的BigNum变量里。gfp表示我们使用的是有限域上的椭圆曲线(secp256k1就是这类)。- 用
BigNum处理坐标:因为椭圆曲线的坐标是大整数,BigNum是OpenSSL专门用来处理大数字的类型,支持转十六进制、字节数组等常用格式。
如果你一定要用压缩字节解析(不推荐):
如果坚持要从你已经拿到的压缩字节数组解析,需要注意:
- 压缩格式的第一个字节是
0x02或0x03,表示Y坐标的奇偶性 - 后面的32字节是X坐标(secp256k1的坐标长度是32字节)
- Y坐标需要通过椭圆曲线方程
y² = x³ + 7(secp256k1的方程)计算出来,还要根据第一个字节确定奇偶性。这种方法需要手动实现域上的平方根计算,容易出错,所以更推荐用上面的API方法。
内容的提问来源于stack exchange,提问作者Frigyes
相关产品推荐
相关产品推荐

