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  }