github.com/annchain/OG@v0.0.9/deprecated/ogcrypto/signer_secp256k1_noncgo.go (about) 1 // Copyright © 2019 Annchain Authors <EMAIL ADDRESS> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // +build noncgo 15 16 package ogcrypto 17 18 import ( 19 "crypto/ecdsa" 20 "crypto/rand" 21 "fmt" 22 "github.com/annchain/OG/arefactor/ogcrypto" 23 "github.com/annchain/OG/deprecated" 24 "github.com/annchain/OG/deprecated/ogcrypto/ecies" 25 "github.com/annchain/OG/deprecated/ogcrypto_interface" 26 "github.com/btcsuite/btcd/btcec" 27 "math/big" 28 ) 29 30 type SignerSecp256k1 struct { 31 } 32 33 func (s *SignerSecp256k1) GetCryptoType() ogcrypto_interface.CryptoType { 34 return ogcrypto_interface.CryptoTypeSecp256k1 35 } 36 37 // Sign calculates an ECDSA signature. 38 // 39 // This function is susceptible to chosen plaintext attacks that can leak 40 // information about the private key that is used for signing. Callers must 41 // be aware that the given hash cannot be chosen by an adversery. Common 42 // solution is to hash any input before calculating the signature. 43 // 44 // The produced signature is in the [R || S || V] format where V is 0 or 1. 45 func (s *SignerSecp256k1) Sign(privKey ogcrypto_interface.PrivateKey, msg []byte) ogcrypto_interface.Signature { 46 prv, _ := ToECDSA(privKey.KeyBytes) 47 hash := deprecated.Sha256(msg) 48 if len(hash) != 32 { 49 panic(fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))) 50 } 51 if prv.Curve != btcec.S256() { 52 panic(fmt.Errorf("private key curve is not secp256k1")) 53 } 54 sig, err := btcec.SignCompact(btcec.S256(), (*btcec.PrivateKey)(prv), hash, false) 55 //sig, err := btcec.Sign(btcec.S256(), (*btcec.PrivateKey)(prv), hash, false) 56 if err != nil { 57 panic(err) 58 } 59 // Convert to Ethereum signature format with 'recovery id' v at the end. 60 v := sig[0] - 27 61 copy(sig, sig[1:]) 62 sig[64] = v 63 return deprecated.SignatureFromBytes(s.GetCryptoType(), sig) 64 } 65 66 // VerifySignature checks that the given public key created signature over hash. 67 // The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format. 68 // The signature should have the 64 byte [R || S] format. 69 func (s *SignerSecp256k1) Verify(pubKey ogcrypto_interface.PublicKey, signature ogcrypto_interface.Signature, msg []byte) bool { 70 hash := deprecated.Sha256(msg) 71 signature = s.DealRecoverID(signature) 72 sigs := signature.SignatureBytes 73 sig := &btcec.Signature{R: new(big.Int).SetBytes(sigs[:32]), S: new(big.Int).SetBytes(sigs[32:])} 74 key, err := btcec.ParsePubKey(pubKey.KeyBytes, btcec.S256()) 75 if err != nil { 76 fmt.Println(err) 77 return false 78 } 79 // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. 80 if sig.S.Cmp(secp256k1halfN) > 0 { 81 fmt.Println("sec") 82 return false 83 } 84 return sig.Verify(hash, key) 85 } 86 87 func (s *SignerSecp256k1) PubKey(privKey ogcrypto_interface.PrivateKey) ogcrypto_interface.PublicKey { 88 _, ecdsapub := btcec.PrivKeyFromBytes(btcec.S256(), privKey.KeyBytes) 89 pub := FromECDSAPub((*ecdsa.PublicKey)(ecdsapub)) 90 return deprecated.PublicKeyFromBytes(ogcrypto_interface.CryptoTypeSecp256k1, pub[:]) 91 } 92 93 func (s *SignerSecp256k1) PublicKeyFromBytes(b []byte) ogcrypto_interface.PublicKey { 94 return deprecated.PublicKeyFromBytes(s.GetCryptoType(), b) 95 } 96 97 func (s *SignerSecp256k1) Encrypt(p ogcrypto_interface.PublicKey, m []byte) (ct []byte, err error) { 98 pub, err := UnmarshalPubkey(p.KeyBytes) 99 if err != nil { 100 panic(err) 101 } 102 eciesPub := ecies.ImportECDSAPublic(pub) 103 return ecies.Encrypt(rand.Reader, eciesPub, m, nil, nil) 104 } 105 106 func (s *SignerSecp256k1) Decrypt(p ogcrypto_interface.PrivateKey, ct []byte) (m []byte, err error) { 107 prive, err := ToECDSA(p.KeyBytes) 108 ecisesPriv := ecies.ImportECDSA(prive) 109 return ecisesPriv.Decrypt(ct, nil, nil) 110 //return nil, nil 111 } 112 113 const sigLength int = 64 114 115 func (s *SignerSecp256k1) DealRecoverID(sig ogcrypto_interface.Signature) ogcrypto_interface.Signature { 116 l := len(sig.SignatureBytes) 117 if l == sigLength+1 { 118 sig.SignatureBytes = sig.SignatureBytes[:l-1] 119 } 120 return sig 121 } 122 123 func (s *SignerSecp256k1) RandomKeyPair() (publicKey ogcrypto_interface.PublicKey, privateKey ogcrypto_interface.PrivateKey) { 124 privKeyBytes := [32]byte{} 125 copy(privKeyBytes[:], ogcrypto.CRandBytes(32)) 126 127 privateKey = deprecated.PrivateKeyFromBytes(ogcrypto_interface.CryptoTypeSecp256k1, privKeyBytes[:]) 128 publicKey = s.PubKey(privateKey) 129 return 130 } 131 132 // Ecrecover returns the uncompressed public key that created the given signature. 133 func Ecrecover(hash, sig []byte) ([]byte, error) { 134 pub, err := SigToPub(hash, sig) 135 if err != nil { 136 return nil, err 137 } 138 bytes := (*btcec.PublicKey)(pub).SerializeUncompressed() 139 return bytes, err 140 } 141 142 // SigToPub returns the public key that created the given signature. 143 func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { 144 // Convert to btcec input format with 'recovery id' v at the beginning. 145 btcsig := make([]byte, 65) 146 btcsig[0] = sig[64] + 27 147 copy(btcsig[1:], sig) 148 149 pub, _, err := btcec.RecoverCompact(btcec.S256(), btcsig, hash) 150 return (*ecdsa.PublicKey)(pub), err 151 } 152 153 func (s *SignerSecp256k1) CanRecoverPubFromSig() bool { 154 return false 155 }