代码解析
要首先生成一个新的钱包地址,我们需要导入go-ethereum crypto包,该包提供用于生成随机私钥的GenerateKey方法。
privateKey, err := crypto.GenerateKey()
if err != nil {
log.Fatal(err)
}
然后我们可以通过导入golangcrypto/ecdsa包并使用FromECDSA方法将其转换为字节。
privateKeyBytes := crypto.FromECDSA(privateKey)
我们现在可以使用 go-ethereum hexutil 包将它转换为十六进制字符串,该包提供了一个带有字节切片的Encode方法。 然后我们在十六进制编码之后删除“0x”。
fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) // 4e6aaa173f18b6160aa6a36a4e54e4e79a5fff8a93d5efe5126c589f4464c052
这就是用于签署交易的私钥,将被视为密码,永远不应该被共享给别人,因为谁拥有它可以访问你的所有资产。
由于公钥是从私钥派生的,因此go-ethereum的加密私钥具有一个返回公钥的Public方法。
publicKey := privateKey.Public()
将其转换为十六进制的过程与我们使用转化私钥的过程类似。 我们剥离了0x和前2个字符04,它始终是EC前缀,不是必需的。
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
}
publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
fmt.Println(hexutil.Encode(publicKeyBytes)[4:]) // 405701f955192319aa5c0b9d7564cd0ff184a498dc12c5bda941c91354382dbf44ff6f1678ba3ea0bf9a545895c00ab7cfb2fbcf0c5cca97569a4bf0aed996c8
现在我们拥有公钥,就可以轻松生成你经常看到的公共地址。 为了做到这一点,go-ethereum加密包有一个PubkeyToAddress方法,它接受一个ECDSA公钥,并返回公共地址。
address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
fmt.Println(address) // 0xe83FF792C385d6935d3b1f58c40de2BDEe3621e9
公共地址其实就是公钥的Keccak-256哈希,然后我们取最后40个字符(20个字节)并用“0x”作为前缀。 以下是使用 golang.org/x/crypto/sha3 的 Keccak256函数手动完成的方法。
hash := sha3.NewLegacyKeccak256()
hash.Write(publicKeyBytes[1:])
fmt.Println(hexutil.Encode(hash.Sum(nil)[12:])) // 0xe83ff792c385d6935d3b1f58c40de2bdee3621e9
完整代码
package main
import (
"crypto/ecdsa"
"fmt"
"log"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/crypto/sha3"
)
func main() {
//生成私钥
privateKey, err := crypto.GenerateKey()
if err != nil {
log.Fatal(err)
}
//打印不含0x的私钥
privateKeyBytes := crypto.FromECDSA(privateKey)
fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) // 4e6aaa173f18b6160aa6a36a4e54e4e79a5fff8a93d5efe5126c589f4464c052
//根据私钥打印16进制公钥
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
}
publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
fmt.Println(hexutil.Encode(publicKeyBytes)[4:]) // 405701f955192319aa5c0b9d7564cd0ff184a498dc12c5bda941c91354382dbf44ff6f1678ba3ea0bf9a545895c00ab7cfb2fbcf0c5cca97569a4bf0aed996c8
//根据公钥返回地址
address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
fmt.Println(address) // 0xe83FF792C385d6935d3b1f58c40de2BDEe3621e9
//使用Keccak256函数手动完成地址解析
hash := sha3.NewLegacyKeccak256()
hash.Write(publicKeyBytes[1:])
fmt.Println(hexutil.Encode(hash.Sum(nil)[12:])) // 0xe83ff792c385d6935d3b1f58c40de2bdee3621e9
}
|