github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/btc/key.go (about) 1 package btc 2 3 import ( 4 "errors" 5 "encoding/hex" 6 "github.com/piotrnar/gocoin/lib/secp256k1" 7 ) 8 9 type PublicKey struct { 10 secp256k1.XY 11 } 12 13 type Signature struct { 14 secp256k1.Signature 15 HashType byte 16 } 17 18 func NewPublicKey(buf []byte) (res *PublicKey, e error) { 19 res = new(PublicKey) 20 if !res.XY.ParsePubkey(buf) { 21 e = errors.New("NewPublicKey: Unknown format: "+hex.EncodeToString(buf[:])) 22 res = nil 23 } 24 return 25 } 26 27 28 func NewSignature(buf []byte) (*Signature, error) { 29 sig := new(Signature) 30 le := sig.ParseBytes(buf) 31 if le < 0 { 32 return nil, errors.New("NewSignature: ParseBytes error") 33 } 34 if le<len(buf) { 35 sig.HashType = buf[len(buf)-1] 36 } 37 return sig, nil 38 } 39 40 // RecoverPublicKey recovers the public key from a signature. 41 func (sig *Signature) RecoverPublicKey(msg []byte, recid int) (key *PublicKey) { 42 key = new(PublicKey) 43 if !secp256k1.RecoverPublicKey(sig.R.Bytes(), sig.S.Bytes(), msg, recid, &key.XY) { 44 key = nil 45 } 46 return 47 } 48 49 50 func (sig *Signature) IsLowS() bool { 51 return sig.S.Cmp(&secp256k1.TheCurve.HalfOrder.Int)<1 52 } 53 54 55 // Bytes returns a serialized canoncal signature followed by a hash type. 56 func (sig *Signature) Bytes() []byte { 57 return append(sig.Signature.Bytes(), sig.HashType) 58 }