p8k.mx raw

   1  // Package p8k provides a signer.I implementation using the secp256k1/schnorr packages.
   2  package p8k
   3  
   4  import (
   5  	"crypto/sha256"
   6  	"fmt"
   7  
   8  	"smesh.lol/pkg/nostr/ec/secp256k1"
   9  	"smesh.lol/pkg/nostr/ec/schnorr"
  10  	"smesh.lol/pkg/nostr/signer"
  11  )
  12  
  13  type Signer struct {
  14  	sec *secp256k1.SecretKey
  15  	pub *secp256k1.PublicKey
  16  }
  17  
  18  var _ signer.I = (*Signer)(nil)
  19  
  20  func New() (*Signer, error) {
  21  	return &Signer{}, nil
  22  }
  23  
  24  func MustNew() *Signer {
  25  	return &Signer{}
  26  }
  27  
  28  func (s *Signer) Generate() error {
  29  	sk, err := secp256k1.GenerateSecretKey()
  30  	if err != nil {
  31  		return err
  32  	}
  33  	s.sec = sk
  34  	s.pub = sk.PubKey()
  35  	return nil
  36  }
  37  
  38  func (s *Signer) InitSec(sec []byte) error {
  39  	sk := secp256k1.SecKeyFromBytes(sec)
  40  	if sk == nil {
  41  		return fmt.Errorf("invalid secret key")
  42  	}
  43  	s.sec = sk
  44  	s.pub = sk.PubKey()
  45  	return nil
  46  }
  47  
  48  func (s *Signer) InitPub(pub []byte) error {
  49  	pk, err := schnorr.ParsePubKey(pub)
  50  	if err != nil {
  51  		return err
  52  	}
  53  	s.pub = pk
  54  	return nil
  55  }
  56  
  57  func (s *Signer) Sec() []byte {
  58  	if s.sec == nil {
  59  		return nil
  60  	}
  61  	return s.sec.Serialize()
  62  }
  63  
  64  func (s *Signer) Pub() []byte {
  65  	if s.pub == nil {
  66  		return nil
  67  	}
  68  	return schnorr.SerializePubKey(s.pub)
  69  }
  70  
  71  func (s *Signer) Sign(msg []byte) ([]byte, error) {
  72  	if s.sec == nil {
  73  		return nil, fmt.Errorf("no secret key")
  74  	}
  75  	sig, err := schnorr.Sign(s.sec, msg)
  76  	if err != nil {
  77  		return nil, err
  78  	}
  79  	return sig.Serialize(), nil
  80  }
  81  
  82  func (s *Signer) Verify(msg, sig []byte) (bool, error) {
  83  	if s.pub == nil {
  84  		return false, fmt.Errorf("no public key")
  85  	}
  86  	parsed, err := schnorr.ParseSignature(sig)
  87  	if err != nil {
  88  		return false, err
  89  	}
  90  	return parsed.Verify(msg, s.pub), nil
  91  }
  92  
  93  func (s *Signer) Zero() {
  94  	if s.sec != nil {
  95  		s.sec.Zero()
  96  		s.sec = nil
  97  	}
  98  	s.pub = nil
  99  }
 100  
 101  func (s *Signer) ECDH(pub []byte) ([]byte, error) {
 102  	raw, err := s.ECDHRaw(pub)
 103  	if err != nil {
 104  		return nil, err
 105  	}
 106  	h := sha256.Sum256(raw)
 107  	return h[:], nil
 108  }
 109  
 110  func (s *Signer) ECDHRaw(pub []byte) ([]byte, error) {
 111  	if s.sec == nil {
 112  		return nil, fmt.Errorf("no secret key")
 113  	}
 114  	pk, err := schnorr.ParsePubKey(pub)
 115  	if err != nil {
 116  		return nil, err
 117  	}
 118  	return secp256k1.GenerateSharedSecret(s.sec, pk), nil
 119  }
 120