生成私钥。其实在go-ethereum中的私钥、公钥只是ecdsa的简单包装。
// 第一种方法: 使用go-ethereum包装的方法
prv ,err := ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
if err != nil {
panic(err)
}
// 第二种方法: 使用golang标准库方法
priv ,err := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
if err != nil {
panic(err)
}
主函数PubkeyToAddress()
func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
pubBytes := FromECDSAPub(&p)
return common.BytesToAddress(Keccak256(pubBytes[1:])[12:])
}
子函数FromECDSAPub()
func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
if pub == nil || pub.X == nil || pub.Y == nil {
return nil
}
return elliptic.Marshal(S256(), pub.X, pub.Y)
}
// S256()是特定的椭圆曲线,在程序启动的时候进行初始化,后来调用只是获取其引用而已。
// elliptic.Marshal(...)为标准库函数,按照非压缩形式得到相应的[]byte
func Marshal(curve Curve, x, y *big.Int) []byte {
byteLen := (curve.Params().BitSize + 7) >> 3
ret := make([]byte, 1+2*byteLen)
ret[0] = 4 // uncompressed point
xBytes := x.Bytes()
copy(ret[1+byteLen-len(xBytes):], xBytes)
yBytes := y.Bytes()
copy(ret[1+2*byteLen-len(yBytes):], yBytes)
return ret
}
子函数Keccak256()
// 对除了符号位(第一个字节)的其他字节数组进行sha3处理.
// sha3的结果共有32字节。
// 取sha3结果的最后20字节,生成地址。在以太坊中,地址为: type Address [AddressLength]byte
func Keccak256(data ...[]byte) []byte {
d := sha3.NewKeccak256()
for _, b := range data {
d.Write(b)
}
return d.Sum(nil)
}
子函数BytesToAddress()
// BytesToAddress其实就是字节拷贝
func BytesToAddress(b []byte) Address {
var a Address
a.SetBytes(b)
return a
}
// SetBytes()考虑到了字节数量不匹配的情况
func (a *Address) SetBytes(b []byte) {
if len(b) > len(a) {
b = b[len(b)-AddressLength:]
}
copy(a[AddressLength-len(b):], b)
}