identity.go raw
1 //go:build !(js && wasm)
2
3 package database
4
5 import (
6 "errors"
7 "fmt"
8
9 "github.com/dgraph-io/badger/v4"
10 "next.orly.dev/pkg/lol/chk"
11 "next.orly.dev/pkg/lol/log"
12 "next.orly.dev/pkg/nostr/crypto/keys"
13 "next.orly.dev/pkg/nostr/encoders/hex"
14 )
15
16 const relayIdentitySecretKey = "relay:identity:sk"
17
18 // GetRelayIdentitySecret returns the relay identity secret key bytes if present.
19 // If the key is not found, returns (nil, badger.ErrKeyNotFound).
20 func (d *D) GetRelayIdentitySecret() (skb []byte, err error) {
21 err = d.DB.View(func(txn *badger.Txn) error {
22 item, err := txn.Get([]byte(relayIdentitySecretKey))
23 if errors.Is(err, badger.ErrKeyNotFound) {
24 return err
25 }
26 if err != nil {
27 return err
28 }
29 return item.Value(func(val []byte) error {
30 // value stored as hex string
31 b, err := hex.Dec(string(val))
32 if err != nil {
33 return err
34 }
35 skb = make([]byte, len(b))
36 copy(skb, b)
37 return nil
38 })
39 })
40 return
41 }
42
43 // SetRelayIdentitySecret stores the relay identity secret key bytes (expects 32 bytes).
44 func (d *D) SetRelayIdentitySecret(skb []byte) (err error) {
45 if len(skb) != 32 {
46 return fmt.Errorf("invalid secret key length: %d", len(skb))
47 }
48 val := []byte(hex.Enc(skb))
49 return d.DB.Update(func(txn *badger.Txn) error {
50 return txn.Set([]byte(relayIdentitySecretKey), val)
51 })
52 }
53
54 // GetOrCreateRelayIdentitySecret retrieves the existing relay identity secret
55 // key or creates and stores a new one if none exists.
56 func (d *D) GetOrCreateRelayIdentitySecret() (skb []byte, err error) {
57 // Try get fast path
58 if skb, err = d.GetRelayIdentitySecret(); err == nil && len(skb) == 32 {
59 return skb, nil
60 }
61 if err != nil && !errors.Is(err, badger.ErrKeyNotFound) {
62 return nil, err
63 }
64
65 // Create new key and store atomically
66 var gen []byte
67 if gen, err = keys.GenerateSecretKey(); chk.E(err) {
68 return nil, err
69 }
70 if err = d.SetRelayIdentitySecret(gen); chk.E(err) {
71 return nil, err
72 }
73 log.I.F("generated new relay identity key (pub=%s)", mustPub(gen))
74 return gen, nil
75 }
76
77 func mustPub(skb []byte) string {
78 pk, err := keys.SecretBytesToPubKeyHex(skb)
79 if err != nil {
80 return ""
81 }
82 return pk
83 }
84