github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/crypto/signature_cgo.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  //</624450085547151360>
    11  
    12  
    13  //+建设!NaCl,!JS!NOCGO
    14  
    15  package crypto
    16  
    17  import (
    18  	"crypto/ecdsa"
    19  	"crypto/elliptic"
    20  	"fmt"
    21  
    22  	"github.com/ethereum/go-ethereum/common/math"
    23  	"github.com/ethereum/go-ethereum/crypto/secp256k1"
    24  )
    25  
    26  //ecrecover返回创建给定签名的未压缩公钥。
    27  func Ecrecover(hash, sig []byte) ([]byte, error) {
    28  	return secp256k1.RecoverPubkey(hash, sig)
    29  }
    30  
    31  //sigtopub返回创建给定签名的公钥。
    32  func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
    33  	s, err := Ecrecover(hash, sig)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	x, y := elliptic.Unmarshal(S256(), s)
    39  	return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil
    40  }
    41  
    42  //sign计算ECDSA签名。
    43  //
    44  //此函数容易受到选中的可能泄漏的明文攻击
    45  //有关用于签名的私钥的信息。来电者必须
    46  //请注意,给定的哈希不能由对手选择。共同的
    47  //解决方案是在计算签名之前散列任何输入。
    48  //
    49  //生成的签名采用[R V]格式,其中V为0或1。
    50  func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
    51  	if len(hash) != 32 {
    52  		return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))
    53  	}
    54  	seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8)
    55  	defer zeroBytes(seckey)
    56  	return secp256k1.Sign(hash, seckey)
    57  }
    58  
    59  //VerifySignature checks that the given public key created signature over hash.
    60  //公钥应为压缩(33字节)或未压缩(65字节)格式。
    61  //签名应采用64字节[r_s]格式。
    62  func VerifySignature(pubkey, hash, signature []byte) bool {
    63  	return secp256k1.VerifySignature(pubkey, hash, signature)
    64  }
    65  
    66  //解压缩PubKey以33字节的压缩格式解析公钥。
    67  func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) {
    68  	x, y := secp256k1.DecompressPubkey(pubkey)
    69  	if x == nil {
    70  		return nil, fmt.Errorf("invalid public key")
    71  	}
    72  	return &ecdsa.PublicKey{X: x, Y: y, Curve: S256()}, nil
    73  }
    74  
    75  //compresspubkey将公钥编码为33字节的压缩格式。
    76  func CompressPubkey(pubkey *ecdsa.PublicKey) []byte {
    77  	return secp256k1.CompressPubkey(pubkey.X, pubkey.Y)
    78  }
    79  
    80  //s256返回secp256k1曲线的一个实例。
    81  func S256() elliptic.Curve {
    82  	return secp256k1.S256()
    83  }
    84