github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/crypto/crypto.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:36</date>
    10  //</624450084880257024>
    11  
    12  
    13  package crypto
    14  
    15  import (
    16  	"crypto/ecdsa"
    17  	"crypto/elliptic"
    18  	"crypto/rand"
    19  	"encoding/hex"
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"os"
    26  
    27  	"github.com/ethereum/go-ethereum/common"
    28  	"github.com/ethereum/go-ethereum/common/math"
    29  	"github.com/ethereum/go-ethereum/rlp"
    30  	"golang.org/x/crypto/sha3"
    31  )
    32  
    33  var (
    34  	secp256k1N, _  = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
    35  	secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2))
    36  )
    37  
    38  var errInvalidPubkey = errors.New("invalid secp256k1 public key")
    39  
    40  //keccak256计算并返回输入数据的keccak256哈希。
    41  func Keccak256(data ...[]byte) []byte {
    42  	d := sha3.NewLegacyKeccak256()
    43  	for _, b := range data {
    44  		d.Write(b)
    45  	}
    46  	return d.Sum(nil)
    47  }
    48  
    49  //keccak256 hash计算并返回输入数据的keccak256哈希,
    50  //将其转换为内部哈希数据结构。
    51  func Keccak256Hash(data ...[]byte) (h common.Hash) {
    52  	d := sha3.NewLegacyKeccak256()
    53  	for _, b := range data {
    54  		d.Write(b)
    55  	}
    56  	d.Sum(h[:0])
    57  	return h
    58  }
    59  
    60  //keccak512计算并返回输入数据的keccak512哈希。
    61  func Keccak512(data ...[]byte) []byte {
    62  	d := sha3.NewLegacyKeccak512()
    63  	for _, b := range data {
    64  		d.Write(b)
    65  	}
    66  	return d.Sum(nil)
    67  }
    68  
    69  //createAddress创建一个给定字节和nonce的以太坊地址
    70  func CreateAddress(b common.Address, nonce uint64) common.Address {
    71  	data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
    72  	return common.BytesToAddress(Keccak256(data)[12:])
    73  }
    74  
    75  //createAddress2根据地址字节创建以太坊地址,初始
    76  //合同代码散列和盐。
    77  func CreateAddress2(b common.Address, salt [32]byte, inithash []byte) common.Address {
    78  	return common.BytesToAddress(Keccak256([]byte{0xff}, b.Bytes(), salt[:], inithash)[12:])
    79  }
    80  
    81  //toecdsa创建具有给定d值的私钥。
    82  func ToECDSA(d []byte) (*ecdsa.PrivateKey, error) {
    83  	return toECDSA(d, true)
    84  }
    85  
    86  //ToecdsSaunsafe盲目地将二进制blob转换为私钥。它应该差不多
    87  //除非您确定输入有效并且希望避免敲击,否则不要使用。
    88  //源代码编码错误(0个前缀被切断)。
    89  func ToECDSAUnsafe(d []byte) *ecdsa.PrivateKey {
    90  	priv, _ := toECDSA(d, false)
    91  	return priv
    92  }
    93  
    94  //toECDSA creates a private key with the given D value. The strict parameter
    95  //控制是否应在曲线大小或
    96  //它还可以接受旧编码(0个前缀)。
    97  func toECDSA(d []byte, strict bool) (*ecdsa.PrivateKey, error) {
    98  	priv := new(ecdsa.PrivateKey)
    99  	priv.PublicKey.Curve = S256()
   100  	if strict && 8*len(d) != priv.Params().BitSize {
   101  		return nil, fmt.Errorf("invalid length, need %d bits", priv.Params().BitSize)
   102  	}
   103  	priv.D = new(big.Int).SetBytes(d)
   104  
   105  //私人d必须<n
   106  	if priv.D.Cmp(secp256k1N) >= 0 {
   107  		return nil, fmt.Errorf("invalid private key, >=N")
   108  	}
   109  //优先级d不能为零或负数。
   110  	if priv.D.Sign() <= 0 {
   111  		return nil, fmt.Errorf("invalid private key, zero or negative")
   112  	}
   113  
   114  	priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(d)
   115  	if priv.PublicKey.X == nil {
   116  		return nil, errors.New("invalid private key")
   117  	}
   118  	return priv, nil
   119  }
   120  
   121  //FromECDSA将私钥导出到二进制转储。
   122  func FromECDSA(priv *ecdsa.PrivateKey) []byte {
   123  	if priv == nil {
   124  		return nil
   125  	}
   126  	return math.PaddedBigBytes(priv.D, priv.Params().BitSize/8)
   127  }
   128  
   129  //UnmarshalSubkey将字节转换为secp256k1公钥。
   130  func UnmarshalPubkey(pub []byte) (*ecdsa.PublicKey, error) {
   131  	x, y := elliptic.Unmarshal(S256(), pub)
   132  	if x == nil {
   133  		return nil, errInvalidPubkey
   134  	}
   135  	return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil
   136  }
   137  
   138  func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
   139  	if pub == nil || pub.X == nil || pub.Y == nil {
   140  		return nil
   141  	}
   142  	return elliptic.Marshal(S256(), pub.X, pub.Y)
   143  }
   144  
   145  //hextoecdsa解析secp256k1私钥。
   146  func HexToECDSA(hexkey string) (*ecdsa.PrivateKey, error) {
   147  	b, err := hex.DecodeString(hexkey)
   148  	if err != nil {
   149  		return nil, errors.New("invalid hex string")
   150  	}
   151  	return ToECDSA(b)
   152  }
   153  
   154  //loadecdsa从给定文件加载secp256k1私钥。
   155  func LoadECDSA(file string) (*ecdsa.PrivateKey, error) {
   156  	buf := make([]byte, 64)
   157  	fd, err := os.Open(file)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  	defer fd.Close()
   162  	if _, err := io.ReadFull(fd, buf); err != nil {
   163  		return nil, err
   164  	}
   165  
   166  	key, err := hex.DecodeString(string(buf))
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  	return ToECDSA(key)
   171  }
   172  
   173  //saveecdsa将secp256k1私钥保存到给定文件
   174  //限制权限。密钥数据保存为十六进制编码。
   175  func SaveECDSA(file string, key *ecdsa.PrivateKey) error {
   176  	k := hex.EncodeToString(FromECDSA(key))
   177  	return ioutil.WriteFile(file, []byte(k), 0600)
   178  }
   179  
   180  func GenerateKey() (*ecdsa.PrivateKey, error) {
   181  	return ecdsa.GenerateKey(S256(), rand.Reader)
   182  }
   183  
   184  //validateSignatureValues使用验证签名值是否有效
   185  //给定的链规则。假设v值为0或1。
   186  func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
   187  	if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 {
   188  		return false
   189  	}
   190  //拒绝S值的上限(ECDSA延展性)
   191  //参见secp256k1/libsecp256k1/include/secp256k1.h中的讨论。
   192  	if homestead && s.Cmp(secp256k1halfN) > 0 {
   193  		return false
   194  	}
   195  //前沿:允许S在全N范围内
   196  	return r.Cmp(secp256k1N) < 0 && s.Cmp(secp256k1N) < 0 && (v == 0 || v == 1)
   197  }
   198  
   199  func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
   200  	pubBytes := FromECDSAPub(&p)
   201  	return common.BytesToAddress(Keccak256(pubBytes[1:])[12:])
   202  }
   203  
   204  func zeroBytes(bytes []byte) {
   205  	for i := range bytes {
   206  		bytes[i] = 0
   207  	}
   208  }
   209