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