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

如何在Golang中将十六进制ASN.1格式数据解码为比特币兼容公钥

解决方案

你手里的DER格式公钥是标准X.509 SubjectPublicKeyInfo结构,包含secp256k1算法标识和公钥原始坐标,直接用Go标准库即可完成解析,不需要依赖第三方工具。

完整代码示例

package main

import (
	"crypto/ecdsa"
	"crypto/x509"
	"encoding/hex"
	"fmt"

	"github.com/btcsuite/btcd/btcutil"
	"github.com/btcsuite/btcd/chaincfg"
)

func main() {
	// 此处可直接替换为HSM返回的原始DER公钥[]byte,无需经过hex编解码
	derPubHex := "3056301006072a8648ce3d020106052b8104000a034200049bb8e80670371f45508b5f8f59946a7c4dea4b3a23a036cf24c1f40993f4a1daad1716de8bd664ecb4596648d722a4685293de208c1d2da9361b9cba74c3d1ec"
	derPubBytes, err := hex.DecodeString(derPubHex)
	if err != nil {
		panic(err)
	}

	// 解析X.509公钥结构
	pubInterface, err := x509.ParsePKIXPublicKey(derPubBytes)
	if err != nil {
		panic(err)
	}

	// 断言为ECDSA公钥类型
	ecdsaPub, ok := pubInterface.(*ecdsa.PublicKey)
	if !ok {
		panic("解析结果非ECDSA公钥")
	}

	// 拼接0x04开头的65字节未压缩公钥:固定标识0x04 + 32字节X坐标 + 32字节Y坐标
	uncompressedPub := make([]byte, 65)
	uncompressedPub[0] = 0x04
	copy(uncompressedPub[1:33], ecdsaPub.X.Bytes())
	copy(uncompressedPub[33:], ecdsaPub.Y.Bytes())

	// 输出验证,和你用在线工具得到的0x04开头结果完全一致
	fmt.Printf("0x%s\n", hex.EncodeToString(uncompressedPub))

	// 直接生成比特币地址
	addrPubKey, err := btcutil.NewAddressPubKey(uncompressedPub, &chaincfg.TestNet3Params)
	if err != nil {
		panic(err)
	}
	fmt.Println("测试网地址:", addrPubKey.EncodeAddress())

	// 如需33字节压缩公钥,直接调用内置方法转换即可
	compressedPub := addrPubKey.SerializeCompressed()
	fmt.Printf("33字节压缩公钥:0x%s\n", hex.EncodeToString(compressedPub))
}

说明

  • 核心逻辑依赖Go标准库x509.ParsePKIXPublicKey,直接解析DER格式的公钥结构,自动识别secp256k1曲线参数
  • 如果你已经拿到HSM返回的原始DER公钥[]byte,可跳过hex编解码步骤,直接传入解析方法,运行效率更高
  • 代码同时支持输出65字节未压缩公钥和33字节压缩公钥,可按需选用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 11:45:04