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