以太坊解析-(1) 公钥私钥地址字符串公钥推导

以太坊中私钥和HASH都为32位,公钥为65位其中第一位是压缩字节0x04,压缩公钥为33字节,地址是是公钥的后64位hash后取后20个字节​作为地址。签名数据为65位,R,S各32位,65位为0和1.​

生成私钥

//生成私钥
    key, err := crypto.GenerateKey()
    if err != nil {
        t.Fatalf("failed GenerateKey with %s.", err)
    }
  //带有0x的私钥
    fmt.Println("private key have 0x   \n", hexutil.Encode(crypto.FromECDSA(key)))
    //不含0x的私钥
    fmt.Println("private key no 0x \n", hex.EncodeToString(crypto.FromECDSA(key)))
private key have 0x   
 0xb1fb9a42d8478cf19bbc1cb4e75625ced1728c8de8691845f546b2ad84a7d379
private key no 0x 
 b1fb9a42d8478cf19bbc1cb4e75625ced1728c8de8691845f546b2ad84a7d379

私钥存储

//本地生成privatekey文件,保存私钥
    if err := crypto.SaveECDSA("privatekey", key); err != nil {
        log.Error(fmt.Sprintf("Failed to persist node key: %v", err))
    }
b1fb9a42d8478cf19bbc1cb4e75625ced1728c8de8691845f546b2ad84a7d379

公钥16进制打印

    fmt.Println("public key have 0x   \n", hexutil.Encode(crypto.FromECDSAPub(&key.PublicKey)))
    fmt.Println("public key no 0x \n", hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey)))
public key have 0x   
 0x0425b775a01b5df335cd71170f6a16d8b43704e68b8eb87a8e6ebfd3deafbfc1151d76bbe078002ffb7caaca06441b1c3976c3ca3b1e1fda9cf0f4591d799758e4
public key no 0x 
 0425b775a01b5df335cd71170f6a16d8b43704e68b8eb87a8e6ebfd3deafbfc1151d76bbe078002ffb7caaca06441b1c3976c3ca3b1e1fda9cf0f4591d799758e4

字符串转私钥和地址

    //由私钥字符串转换私钥和地址
    //由私钥字符串转换私钥
    acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
    address1 := crypto.PubkeyToAddress(acc1Key.PublicKey)
    fmt.Println("address ", address1.String())

    dummyAddr := common.HexToAddress("9b2055d370f73ec7d8a03e965129118dc8f5bf83")
    fmt.Println("dummyAddr",dummyAddr.String())
address  0x703c4b2bD70c169f5717101CaeE543299Fc946C7
dummyAddr 0x9B2055d370F73eC7d8a03E965129118dC8F5bf83

字节转HASH和地址

    //字节转地址
    addr3      := common.BytesToAddress([]byte("ethereum"))
    fmt.Println("address ",addr3.String())

    //字节转hash
    hash1 := common.BytesToHash([]byte("topic1"))
    fmt.Println("hash ",hash1.String())
address  0x000000000000000000000000657468657265756D
hash  0x0000000000000000000000000000000000000000000000000000746f70696331

签名和摘要推出公钥

    var testAddrHex = "970e8128ab834e8eac17ab8e3812f010678cf791"
    var testPrivHex = "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032"
    key1, _ := crypto.HexToECDSA(testPrivHex)
    addrtest := common.HexToAddress(testAddrHex)

    msg := crypto.Keccak256([]byte("foo"))
    sig, err := crypto.Sign(msg, key1)
    //推出公钥字节
    recoveredPub, err := crypto.Ecrecover(msg, sig)
    //字节转公钥
    pubKey, _ := crypto.UnmarshalPubkey(recoveredPub)
    recoveredAddr := crypto.PubkeyToAddress(*pubKey)

    // 摘要和签名推出公钥
    recoveredPub2, _ := crypto.SigToPub(msg, sig)
    recoveredAddr2 := crypto.PubkeyToAddress(*recoveredPub2)

    fmt.Println("addrtest ",addrtest.String())
    fmt.Println("recoveredAddr ",recoveredAddr.String())
    fmt.Println("recoveredAddr2 ",recoveredAddr2.String())
addrtest  0x970E8128AB834E8EAC17Ab8E3812F010678CF791
recoveredAddr  0x970E8128AB834E8EAC17Ab8E3812F010678CF791
recoveredAddr2  0x970E8128AB834E8EAC17Ab8E3812F010678CF791

压缩公钥

//压缩公钥为33字节
compressed := CompressPubkey(key)
// 解压缩33字节数据为公钥
DecompressPubkey

完整代码

在以太坊顶级目录新建test目录,新建file_test.go文件,拷贝代码即可运行

package test

import (
    "encoding/hex"
    "fmt"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/common/hexutil"
    "github.com/ethereum/go-ethereum/crypto"
    "github.com/ethereum/go-ethereum/log"
    "testing"
)

func TestGenerateKey(t *testing.T) {
    key, err := crypto.GenerateKey()
    if err != nil {
        t.Fatalf("failed GenerateKey with %s.", err)
    }

    fmt.Println("private key have 0x   \n", hexutil.Encode(crypto.FromECDSA(key)))
    fmt.Println("private key no 0x \n", hex.EncodeToString(crypto.FromECDSA(key)))

    if err := crypto.SaveECDSA("privatekey", key); err != nil {
        log.Error(fmt.Sprintf("Failed to persist node key: %v", err))
    }

    fmt.Println("public key have 0x   \n", hexutil.Encode(crypto.FromECDSAPub(&key.PublicKey)))
    fmt.Println("public key no 0x \n", hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey)))

    //由私钥字符串转换私钥
    acc1Key, _ := crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
    address1 := crypto.PubkeyToAddress(acc1Key.PublicKey)
    fmt.Println("address ", address1.String())

    dummyAddr := common.HexToAddress("9b2055d370f73ec7d8a03e965129118dc8f5bf83")
    fmt.Println("dummyAddr",dummyAddr.String())

    //字节转地址
    addr3      := common.BytesToAddress([]byte("ethereum"))
    fmt.Println("address ",addr3.String())

    //字节转hash
    hash1 := common.BytesToHash([]byte("topic1"))
    fmt.Println("hash ",hash1.String())


    var testAddrHex = "970e8128ab834e8eac17ab8e3812f010678cf791"
    var testPrivHex = "289c2857d4598e37fb9647507e47a309d6133539bf21a8b9cb6df88fd5232032"
    key1, _ := crypto.HexToECDSA(testPrivHex)
    addrtest := common.HexToAddress(testAddrHex)

    msg := crypto.Keccak256([]byte("foo"))
    sig, err := crypto.Sign(msg, key1)
    recoveredPub, err := crypto.Ecrecover(msg, sig)
    pubKey, _ := crypto.UnmarshalPubkey(recoveredPub)
    recoveredAddr := crypto.PubkeyToAddress(*pubKey)

    // should be equal to SigToPub
    recoveredPub2, _ := crypto.SigToPub(msg, sig)
    recoveredAddr2 := crypto.PubkeyToAddress(*recoveredPub2)

    fmt.Println("addrtest ",addrtest.String())
    fmt.Println("recoveredAddr ",recoveredAddr.String())
    fmt.Println("recoveredAddr2 ",recoveredAddr2.String())
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342