日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > php >内容正文

php

以太坊地址算法php,以太坊ETH源码分析(1):地址生成过程

發(fā)布時(shí)間:2025/3/20 php 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 以太坊地址算法php,以太坊ETH源码分析(1):地址生成过程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、生成一個(gè)以太坊錢包地址

通過以太坊命令行客戶端geth可以很簡單的獲得一個(gè)以太坊地址,如下:

~/go/src/github.com/ethereum/go-ethereum/build/bin$geth account new

INFO [11-03|20:09:33.219] Maximum peer count ETH=25 LES=0 total=25

keydir=/Users/wujinquan/Library/Ethereum/keystore

Your new account is locked with a password. Please give a password. Do not forget this password.

Passphrase:

Repeat passphrase:

Address: {8011cf2892985cdc58f447063bc6a089ba89f514}

~/go/src/github.com/ethereum/go-ethereum/build/bin$

地址0x8011cf2892985cdc58f447063bc6a089ba89f514 (20字節(jié)16進(jìn)制)就是新生成的以太坊地址。

二、根據(jù)源碼解析地址生成過程

func init() {

// Initialize the CLI app and start Geth

app.Action = geth

app.HideVersion = true // we have a command to print the version

app.Copyright = "Copyright 2013-2018 The go-ethereum Authors"

app.Commands = []cli.Command{

// See chaincmd.go:

initCommand,

...

// See monitorcmd.go:

monitorCommand,

// See accountcmd.go:賬戶相關(guān)

accountCommand,

// See consolecmd.go:

}

...

}

var (

...

accountCommand = cli.Command{

Name: "account",

Usage: "Manage accounts",

Category: "ACCOUNT COMMANDS",

Description: ``

Subcommands: []cli.Command{

{

Name: "list",

Usage: "Print summary of existing accounts",

Action: utils.MigrateFlags(accountList),

Flags: []cli.Flag{

utils.DataDirFlag,

utils.KeyStoreDirFlag,

},

Description: `

Print a short summary of all accounts`,

},

{

Name: "new",

Usage: "Create a new account",

Action: utils.MigrateFlags(accountCreate),

Flags: []cli.Flag{

utils.DataDirFlag,

utils.KeyStoreDirFlag,

utils.PasswordFileFlag,

utils.LightKDFFlag,

},

Description: ``

},

},

關(guān)鍵:new一個(gè)新賬戶的時(shí)候,會(huì)調(diào)用accountCreate:

// accountCreate creates a new account into the keystore defined by the CLI flags.

func accountCreate(ctx *cli.Context) error {

// (1)獲取配置

cfg := gethConfig{Node: defaultNodeConfig()}

// Load config file.

if file := ctx.GlobalString(configFileFlag.Name); file != "" {

if err := loadConfig(file, &cfg); err != nil {

utils.Fatalf("%v", err)

}

}

utils.SetNodeConfig(ctx, &cfg.Node)

// (1.1) 從節(jié)點(diǎn)配置中取出相關(guān)配置信息

scryptN, scryptP, keydir, err := cfg.Node.AccountConfig()

if err != nil {

utils.Fatalf("Failed to read configuration: %v", err)

}

// (2)解析用戶密碼

password := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx))

// (3)生成地址

address, err := keystore.StoreKey(keydir, password, scryptN, scryptP) //創(chuàng)建地址的外層函數(shù)

if err != nil {

utils.Fatalf("Failed to create account: %v", err)

}

fmt.Printf("Address: {%x}\n", address)

return nil

}

由此可見,accountCreate分為三個(gè)步驟,其中最關(guān)鍵的為第三步

(1)獲取配置

(2)解析用戶密碼

(3)生成地址

// StoreKey generates a key, encrypts with 'auth' and stores in the given directory

func StoreKey(dir, auth string, scryptN, scryptP int) (common.Address, error) {

//返回Key{Id uuid.UUID ,Address common.Address,PrivateKey *ecdsa.PrivateKey}

_, a, err := storeNewKey(&keyStorePassphrase{dir, scryptN, scryptP, false}, rand.Reader, auth)

return a.Address, err

}

func storeNewKey(ks keyStore, rand io.Reader, auth string) (*Key, accounts.Account, error) {

// 創(chuàng)建一個(gè)新的賬戶

key, err := newKey(rand)

fmt.Printf("key.Id=%v,key.Address=%x,key.PrivateKey=%v\n",key.Id,key.Address,key.PrivateKey)

if err != nil {

return nil, accounts.Account{}, err

}

a := accounts.Account{Address: key.Address, URL: accounts.URL{Scheme: KeyStoreScheme, Path: ks.JoinPath(keyFileName(key.Address))}}

if err := ks.StoreKey(a.URL.Path, key, auth); err != nil {

zeroKey(key.PrivateKey)

return nil, a, err

}

return key, a, err

}

func newKey(rand io.Reader) (*Key, error) {

// (1) 選擇secp256k1曲線、采用橢圓曲線數(shù)字簽名算法(ECDSA)生成公私鑰對

privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand)

if err != nil {

return nil, err

}

// (2)由公鑰算出地址并構(gòu)建一個(gè)自定義的Key

return newKeyFromECDSA(privateKeyECDSA), nil

}

可以看到,newKey創(chuàng)建新賬戶時(shí),

1、由secp256k1曲線生成私鑰,是由32字節(jié)隨機(jī)數(shù)組成

2、采用橢圓曲線數(shù)字簽名算法(ECDSA)將私鑰映射成公鑰,一個(gè)私鑰只能映射出一個(gè)公鑰。

3、然后由公鑰算出地址并構(gòu)建一個(gè)自定義的Key

繼續(xù)看公鑰是怎樣算出地址并構(gòu)建一個(gè)自定義的Key

func newKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key {

id := uuid.NewRandom()

key := &Key{

Id: id,

//由公鑰推出地址

Address: crypto.PubkeyToAddress(privateKeyECDSA.PublicKey),

PrivateKey: privateKeyECDSA,

}

return key

}

func PubkeyToAddress(p ecdsa.PublicKey) common.Address {

// (1) 將pubkey轉(zhuǎn)換為字節(jié)序列

pubBytes := FromECDSAPub(&p)

// (2) pubBytes為04 開頭的65字節(jié)公鑰,去掉04后剩下64字節(jié)進(jìn)行Keccak256運(yùn)算

// (3) 經(jīng)過Keccak256運(yùn)算后變成32字節(jié),最終取這32字節(jié)的后20字節(jié)作為真正的地址

return common.BytesToAddress(Keccak256(pubBytes[1:])[12:])

}

// Keccak256 calculates and returns the Keccak256 hash of the input data.

func Keccak256(data ...[]byte) []byte {

d := sha3.NewKeccak256()

for _, b := range data {

d.Write(b)

}

return d.Sum(nil)

}

可以看到公鑰(64字節(jié))經(jīng)過Keccak-256單向散列函數(shù)變成了32字節(jié),然后取后20字節(jié)作為地址。本質(zhì)上是從32字節(jié)的私鑰映射到20字節(jié)的公共地址。這意味著一個(gè)賬戶可以有不止一個(gè)私鑰。

三、總結(jié)

以太坊地址的生成過程如下:

由secp256k1曲線生成私鑰,是由32字節(jié)的隨機(jī)數(shù)生成

采用橢圓曲線數(shù)字簽名算法(ECDSA)將私鑰(32字節(jié))映射成公鑰(65字節(jié))。

公鑰(去掉04后剩下64字節(jié))經(jīng)過Keccak-256單向散列函數(shù)變成了32字節(jié),然后取后20字節(jié)作為地址

總結(jié)

以上是生活随笔為你收集整理的以太坊地址算法php,以太坊ETH源码分析(1):地址生成过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。