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

如何将secp256k1密钥X/Y坐标转为压缩十六进制公钥并解决解压报错

解决方案

你的核心问题在于解压函数的实现错误:你直接把压缩公钥的前缀(02/03)当作y坐标传入椭圆曲线点构造函数,这完全不符合secp256k1的压缩公钥规则——前缀仅用于标识y坐标的奇偶性,而非y的实际值。

以下是修正后的完整代码,包含正确的base64url解码、压缩公钥生成、解压公钥逻辑:

import ecdsa
import base64

def base64url_to_bytes(base64url_string):
    # 转换base64url到标准base64,处理填充
    padding = '=' * (4 - (len(base64url_string) % 4)) if len(base64url_string) % 4 != 0 else ''
    base64_string = base64url_string.replace('-', '+').replace('_', '/') + padding
    return base64.b64decode(base64_string)

def get_compressed_public_key(x_bytes, y_bytes):
    """从X/Y字节生成33字节的压缩公钥(十六进制字符串)"""
    x_int = int.from_bytes(x_bytes, byteorder='big')
    y_int = int.from_bytes(y_bytes, byteorder='big')
    # 前缀:02表示y为偶数,03表示y为奇数
    prefix = '02' if y_int % 2 == 0 else '03'
    # 确保x的十六进制是64位(32字节),补前导0
    x_hex = format(x_int, '064x')
    return prefix + x_hex

def decompress_compressed_key(compressed_hex):
    """从压缩公钥十六进制字符串解压出X/Y坐标(十六进制)"""
    prefix = compressed_hex[:2]
    x_hex = compressed_hex[2:]
    x_int = int(x_hex, 16)
    # 根据前缀判断y的奇偶性:02对应偶数,03对应奇数
    is_even = (prefix == '02')
    # 使用secp256k1曲线计算对应的y值
    y_int = ecdsa.SECP256k1.curve.point_for_x(x_int, is_even).y()
    # 转换为64位十六进制字符串
    y_hex = format(y_int, '064x')
    return x_hex, y_hex

# 从Azure Key Vault获取的X/Y坐标
x_base64url = "ARriqkpHlC1Ia1Tk86EM_bqH_9a88Oh2zMYF3fUUGJw"
y_base64url = "wTYd3CEiwTk1n-lFPdpZ51P4Z0EzlVNXLvJMY-k55pQ"

# 解码为字节
x_bytes = base64url_to_bytes(x_base64url)
y_bytes = base64url_to_bytes(y_base64url)

# 生成压缩公钥
compressed_pubkey = get_compressed_public_key(x_bytes, y_bytes)
print("压缩公钥(十六进制):", compressed_pubkey)

# 解压压缩公钥
decompressed_x, decompressed_y = decompress_compressed_key(compressed_pubkey)
print("解压后的X坐标:", decompressed_x)
print("解压后的Y坐标:", decompressed_y)

# 可选:生成非压缩公钥(65字节,前缀04+X+Y)
uncompressed_pubkey = '04' + format(int.from_bytes(x_bytes, 'big'), '064x') + format(int.from_bytes(y_bytes, 'big'), '064x')
print("非压缩公钥(十六进制):", uncompressed_pubkey)

关键修正说明

  1. 解压逻辑修复:
    原代码错误地将前缀值作为y坐标传入Point构造函数,正确做法是使用ecdsa.SECP256k1.curve.point_for_x(x_int, is_even)方法,根据x值和y的奇偶性计算出对应的y坐标,这才符合secp256k1椭圆曲线的数学规则。

  2. 十六进制格式规范:
    确保X/Y的十六进制字符串固定为64位(对应32字节),通过format(x_int, '064x')补前导0,避免因整数转换丢失前导零导致的公钥格式错误。

  3. base64url解码优化:
    补充了对长度刚好是4的倍数时无需添加填充的判断,避免多余的填充字符。

运行修正后的代码,会输出正确的压缩公钥、解压后的X/Y坐标,以及可选的非压缩公钥,且不会再抛出断言错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 06:45:30