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