如何从Dart端将x、y坐标编码为Python ecdsa的VerifyingKey格式
secp256k1公钥Dart端导出、Python端导入实现方案
核心格式说明
Python ecdsa 库的VerifyingKey.from_string()默认接受的是未压缩secp256k1公钥原始字节串,固定格式为:0x04 前缀 + 32字节大端X坐标 + 32字节大端Y坐标,总长度65字节。
Dart端导出逻辑(使用spec256k1库)
你可以直接通过公钥的X、Y坐标拼接出符合要求的字节串,示例代码如下:
import 'package:secp256k1/secp256k1.dart'; import 'dart:convert'; import 'package:hex/hex.dart'; // 假设你已经生成了密钥对 final keyPair = generateKeyPair(); final publicKey = keyPair.publicKey; // 取X、Y坐标的32位大端字节数组 final xBytes = publicKey.X.toBigInt().toUint8List(32); final yBytes = publicKey.Y.toBigInt().toUint8List(32); // 拼接为未压缩公钥字节 final uncompressedPubkeyBytes = [0x04, ...xBytes, ...yBytes]; // 转成hex字符串传输即可,也可以用base64 final stringSentToServer = HEX.encode(uncompressedPubkeyBytes);
Python端导入逻辑
对应Dart端传输的hex字符串,导入代码如下:
import ecdsa from ecdsa import SECP256k1 import codecs string_sent_from_app = "..." # Dart端传过来的hex字符串 # 先把hex转成原始字节,显式指定曲线为SECP256k1 pubkey_bytes = codecs.decode(string_sent_from_app, 'hex') my_vk = ecdsa.VerifyingKey.from_string(pubkey_bytes, curve=SECP256k1) # 验证签名的时候直接用my_vk.verify即可
可选优化方案:使用压缩公钥
如果要减少传输体积,可以使用33字节的压缩公钥:
- Dart端直接调用公钥的
toCompressed()方法拿到压缩公钥字节,再转成hex/base64传输 - Python端导入时不需要改逻辑,
ecdsa库自动兼容压缩公钥格式
注意事项
- 两端必须显式指定曲线为secp256k1,不要依赖库的默认曲线配置
- 坐标转字节时必须使用大端序,避免字节顺序错误导致公钥解析失败
- 公钥字节转字符串传输时优先使用hex或者base64编码,避免原始字节在传输过程中被转码损坏
内容的提问来源于stack exchange,提问作者יהוידע שטינמץ
相关产品推荐
相关产品推荐

