以太坊-公钥私钥地址转换基础
以太坊geth 公私钥地址签名转换基础
以太坊中使用的椭圆曲线是S256,私钥和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 no 0x \n", hex.EncodeToString(crypto.FromECDSA(key))) ``` ``` 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 no 0x \n", hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey))) ``` ``` 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()) } ```
以太坊中使用的椭圆曲线是S256,私钥和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 no 0x \n", hex.EncodeToString(crypto.FromECDSA(key)))
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 no 0x \n", hex.EncodeToString(crypto.FromECDSAPub(&key.PublicKey)))
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())
}
区块链技术网。
- 发表于 2020-05-23 15:23
- 阅读 ( 2208 )
- 学分 ( 74 )
- 分类:以太坊
评论