keys.go raw

   1  // Package keys is a set of helpers for generating and converting public/secret
   2  // keys to hex and back to binary.
   3  package keys
   4  
   5  import (
   6  	"bytes"
   7  
   8  	"next.orly.dev/pkg/nostr/crypto/ec/schnorr"
   9  	"next.orly.dev/pkg/nostr/encoders/hex"
  10  	"next.orly.dev/pkg/nostr/interfaces/signer/p8k"
  11  	"next.orly.dev/pkg/nostr/utils"
  12  	"next.orly.dev/pkg/lol/chk"
  13  )
  14  
  15  // GeneratePrivateKey - deprecated, use GenerateSecretKeyHex
  16  var GeneratePrivateKey = func() string { return GenerateSecretKeyHex() }
  17  
  18  // GenerateSecretKey creates a new secret key and returns the bytes of the secret.
  19  func GenerateSecretKey() (skb []byte, err error) {
  20  	var signer *p8k.Signer
  21  	if signer, err = p8k.New(); chk.E(err) {
  22  		return
  23  	}
  24  	if err = signer.Generate(); chk.E(err) {
  25  		return
  26  	}
  27  	skb = signer.Sec()
  28  	return
  29  }
  30  
  31  // GenerateSecretKeyHex generates a secret key and encodes the bytes as hex.
  32  func GenerateSecretKeyHex() (sks string) {
  33  	skb, err := GenerateSecretKey()
  34  	if chk.E(err) {
  35  		return
  36  	}
  37  	return hex.Enc(skb)
  38  }
  39  
  40  // GetPublicKeyHex generates a public key from a hex encoded secret key.
  41  func GetPublicKeyHex(sk string) (pk string, err error) {
  42  	var b []byte
  43  	if b, err = hex.Dec(sk); chk.E(err) {
  44  		return
  45  	}
  46  	var signer *p8k.Signer
  47  	if signer, err = p8k.New(); chk.E(err) {
  48  		return
  49  	}
  50  	if err = signer.InitSec(b); chk.E(err) {
  51  		return
  52  	}
  53  
  54  	return hex.Enc(signer.Pub()), nil
  55  }
  56  
  57  // SecretBytesToPubKeyHex generates a public key from secret key bytes.
  58  func SecretBytesToPubKeyHex(skb []byte) (pk string, err error) {
  59  	var signer *p8k.Signer
  60  	if signer, err = p8k.New(); chk.E(err) {
  61  		return
  62  	}
  63  	if err = signer.InitSec(skb); chk.E(err) {
  64  		return
  65  	}
  66  	return hex.Enc(signer.Pub()), nil
  67  }
  68  
  69  // SecretBytesToPubKeyBytes generates a public key bytes from secret key bytes.
  70  func SecretBytesToPubKeyBytes(skb []byte) (pkb []byte, err error) {
  71  	var signer *p8k.Signer
  72  	if signer, err = p8k.New(); chk.E(err) {
  73  		return
  74  	}
  75  	if err = signer.InitSec(skb); chk.E(err) {
  76  		return
  77  	}
  78  	return signer.Pub(), nil
  79  }
  80  
  81  // SecretBytesToSigner creates a signer from secret key bytes.
  82  func SecretBytesToSigner(skb []byte) (signer *p8k.Signer, err error) {
  83  	if signer, err = p8k.New(); chk.E(err) {
  84  		return
  85  	}
  86  	if err = signer.InitSec(skb); chk.E(err) {
  87  		return
  88  	}
  89  	return
  90  }
  91  
  92  // IsValid32ByteHex checks that a hex string is a valid 32 bytes lower case hex encoded value as
  93  // per nostr NIP-01 spec.
  94  func IsValid32ByteHex[V []byte | string](pk V) bool {
  95  	if utils.FastEqual(bytes.ToLower([]byte(pk)), []byte(pk)) {
  96  		return false
  97  	}
  98  	var err error
  99  	dec := make([]byte, 32)
 100  	if _, err = hex.DecBytes(dec, []byte(pk)); chk.E(err) {
 101  	}
 102  	return len(dec) == 32
 103  }
 104  
 105  // IsValidPublicKey checks that a hex encoded public key is a valid BIP-340 public key.
 106  func IsValidPublicKey[V []byte | string](pk V) bool {
 107  	v, _ := hex.Dec(string(pk))
 108  	_, err := schnorr.ParsePubKey(v)
 109  	return err == nil
 110  }
 111  
 112  // HexPubkeyToBytes decodes a pubkey from hex encoded string/bytes.
 113  func HexPubkeyToBytes[V []byte | string](hpk V) (pkb []byte, err error) {
 114  	return hex.DecAppend(nil, []byte(hpk))
 115  }
 116