热门搜索:和平精英 原神 街篮2 

您的位置:首页 > > 教程攻略 > web3.0 >Web3wallet中助记词和生成私钥、公钥、地址的基本原理

Web3wallet中助记词和生成私钥、公钥、地址的基本原理

来源:互联网 更新时间:2026-06-18 22:01

从零动手:用Go生成以太坊私钥、公钥与地址

学密码学、搞区块链,最怕的就是纸上谈兵。于是有了这个系列文章,记录学习研究的成果。从技术角度看,用代码一步步生成私钥、公钥、地址,是更直观的学习方式。接下来就用Go语言来实现。

写代码之前,先补充一些必备知识。

1. 椭圆曲线是什么?

以太坊和比特币在底层密码学上共享了同一个椭圆曲线,就是 secp256k1。公钥本质上就是这个曲线上的一个点,有 (x, y) 坐标,这两个坐标值完全由私钥唯一决定。

x 和 y 各占 32 字节,所以公钥一共 64 字节。但你可能会见到 65 字节的公钥,那是因为遵循了 SECG 行业标准的一种序列化编码——在最前面加一个字节的前缀。前缀 04 表示非压缩格式,即完整存储了 x 和 y 的坐标。

那为什么要区分压缩和非压缩两种格式呢?

关键在于 secp256k1 的椭圆曲线方程中,只要知道 x,就能通过方程解出 y(或者反过来)。因此完全可以只存储其中一个坐标,这样省下 32 字节。压缩格式的公钥由此而来,前缀用 02 或 03 表示。

总结一下:非压缩格式公钥 65 字节(前缀 04 + 64 字节实际坐标),压缩格式公钥 33 字节(前缀 02/03 + 32 字节单坐标)。

2. 私钥的简单介绍

私钥本质上就是一个随机生成的 256 位数字。注意,必须是“随机”——而且是密码学意义上的安全随机,这一点再怎么强调都不为过。理论上来讲,你甚至可以用硬币抛 256 次,得到一个二进制数作为私钥,只要这个过程完全不可预测、不可重复。

实际开发中,我们通过代码生成私钥,最关键的一步就是找到一个密码学安全的随机源。千万不要自己瞎写随机算法,更不要偷懒用编程语言自带的简单随机数函数。必须使用密码学安全随机数,这一点至关重要。

关于私钥的重要性,也值得多说一句:私钥绝对不可以丢失。和银&行卡密码不一样,私钥丢了就再也找不回来,这是去中心化的本质特征——没有客服中心可以帮你重置。

3. 助记词

助记词涉及到钱&包的行业标准,这个会在系列第三篇详细展开。现在简单了解背景:私钥只是一个随机数字,但如果你需要管理 10 个账户、100 个账户,甚至上百万个账户呢?难道要随机生成上百万个私钥?这么多私钥又怎么管理和保存?助记词的诞生正是为了解决这个问题。

助记词可以管理成千上万个私钥,这就要说到以太坊的两种钱&包类型。从下一篇文章开始,后续将逐步介绍钱&包以及如何开发一个钱&包工具。

使用 Go 语言生成私钥、公钥、地址

下面这张图概括了生成私钥、公钥、地址的基本原理。根据这个流程图,我们来写对应的代码。

Web3wallet中助记词和生成私钥、公钥、地址的基本原理

首先引入必要的包:

import (
    "crypto/elliptic"
    "crypto/rand"
    "encoding/hex"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/crypto"
    "github.com/ethereum/go-ethereum/crypto/secp256k1"
)

创建一个椭圆曲线实例:

curve := secp256k1.S256()

生成私钥(32字节):核心其实就是生成一个 32 字节的随机数,确保落在椭圆曲线的合法范围内。

b := make([]byte, curve.Params().N.BitLen()/8)
io.ReadFull(rand.Reader, b)
key := new(big.Int).SetBytes(b) // key就是私钥
// 打印私钥
fmt.Println("key:", len(key.Bytes()))
fmt.Println("key:", hex.EncodeToString(key.Bytes()))

生成公钥:对私钥进行椭圆曲线标量乘法运算,得到公钥(64字节)。

X, Y := curve.ScalarBaseMult(key.Bytes())
pubKey := elliptic.Marshal(curve, X, Y)
fmt.Println("pubKey:", pubKey)

生成地址:去掉公钥的第一个字节(前缀 04),然后用 keccak256 算法对剩余部分进行哈希,取最后 20 字节就是地址。

compressPubKey := crypto.Keccak256(pubKey[1:])
addr := common.BytesToAddress(compressPubKey[12:])
fmt.Println("addr:", addr.String())

验证私钥和地址是否匹配:将上面生成的私钥导入 MetaMask,查看 MetaMask 显示的地址,应该跟我们计算出来的一致。

总结

记住上面的基本原理流程图,就算是学会了本文最重要的内容。从椭圆曲线到私钥生成,再到公钥和地址的推导,整个过程环环相扣。动手试一次,比看十遍文档都管用。

热门手游

相关攻略

手机号码测吉凶
本站所有软件,都由网友上传,如有侵犯你的版权,请发邮件haolingcc@hotmail.com 联系删除。 版权所有 Copyright@2012-2013 haoling.cc