nip19.mx raw
1 package bech32encoding
2
3 import (
4 "bytes"
5 "crypto/sha256"
6 "encoding/binary"
7
8 "smesh.lol/pkg/nostr/ec/bech32"
9 "smesh.lol/pkg/nostr/ec/schnorr"
10 "smesh.lol/pkg/nostr/bech32encoding/pointers"
11 "smesh.lol/pkg/nostr/bech32encoding/tlv"
12 "smesh.lol/pkg/nostr/hex"
13 "smesh.lol/pkg/nostr/kind"
14 "smesh.lol/pkg/lol/chk"
15 "smesh.lol/pkg/lol/errorf"
16 "smesh.lol/pkg/lol/log"
17 )
18
19 var (
20 NoteHRP = []byte("note")
21 NsecHRP = []byte("nsec")
22 NpubHRP = []byte("npub")
23 NprofileHRP = []byte("nprofile")
24 NeventHRP = []byte("nevent")
25 NentityHRP = []byte("naddr")
26 )
27
28 func Decode(bech32string []byte) (prefix []byte, value any, err error) {
29 var bits5 []byte
30 if prefix, bits5, err = bech32.DecodeNoLimit(bech32string); chk.D(err) {
31 return
32 }
33 var data []byte
34 if data, err = bech32.ConvertBits(bits5, 5, 8, false); chk.D(err) {
35 return prefix, nil, errorf.E([]byte("failed translating data into 8 bits: %s"), err.Error())
36 }
37 buf := bytes.NewBuffer(data)
38 switch {
39 case bytes.Equal(prefix, NpubHRP) ||
40 bytes.Equal(prefix, NsecHRP) ||
41 bytes.Equal(prefix, NoteHRP):
42 if len(data) < 32 {
43 return prefix, nil, errorf.E([]byte("data is less than 32 bytes (%d)"), len(data))
44 }
45 b := []byte{:schnorr.PubKeyBytesLen*2}
46 hex.EncBytes(b, data[:32])
47 return prefix, b, nil
48 case bytes.Equal(prefix, NprofileHRP):
49 var result pointers.Profile
50 for {
51 t, v := tlv.ReadEntry(buf)
52 if len(v) == 0 {
53 if len(result.PublicKey) < 1 {
54 return prefix, result, errorf.E([]byte("no pubkey found for nprofile"))
55 }
56 return prefix, result, nil
57 }
58 switch t {
59 case tlv.Default:
60 if len(v) < 32 {
61 return prefix, nil, errorf.E([]byte("pubkey is less than 32 bytes (%d)"), len(v))
62 }
63 result.PublicKey = []byte{:schnorr.PubKeyBytesLen*2}
64 hex.EncBytes(result.PublicKey, v)
65 case tlv.Relay:
66 result.Relays = append(result.Relays, v)
67 }
68 }
69 case bytes.Equal(prefix, NeventHRP):
70 var result pointers.Event
71 for {
72 t, v := tlv.ReadEntry(buf)
73 if v == nil {
74 if len(result.ID) == 0 {
75 return prefix, result, errorf.E([]byte("no id found for nevent"))
76 }
77 return prefix, result, nil
78 }
79 switch t {
80 case tlv.Default:
81 if len(v) < 32 {
82 return prefix, nil, errorf.E([]byte("id is less than 32 bytes (%d)"), len(v))
83 }
84 result.ID = v
85 case tlv.Relay:
86 result.Relays = append(result.Relays, v)
87 case tlv.Author:
88 if len(v) < 32 {
89 return prefix, nil, errorf.E([]byte("author is less than 32 bytes (%d)"), len(v))
90 }
91 result.Author = []byte{:schnorr.PubKeyBytesLen*2}
92 hex.EncBytes(result.Author, v)
93 case tlv.Kind:
94 result.Kind = kind.New(binary.BigEndian.Uint32(v))
95 }
96 }
97 case bytes.Equal(prefix, NentityHRP):
98 var result pointers.Entity
99 for {
100 t, v := tlv.ReadEntry(buf)
101 if v == nil {
102 if result.Kind.ToU16() == 0 ||
103 len(result.Identifier) < 1 ||
104 len(result.PublicKey) < 1 {
105 return prefix, result, errorf.E([]byte("incomplete naddr"))
106 }
107 return prefix, result, nil
108 }
109 switch t {
110 case tlv.Default:
111 result.Identifier = v
112 case tlv.Relay:
113 result.Relays = append(result.Relays, v)
114 case tlv.Author:
115 if len(v) < 32 {
116 return prefix, nil, errorf.E([]byte("author is less than 32 bytes (%d)"), len(v))
117 }
118 result.PublicKey = []byte{:schnorr.PubKeyBytesLen*2}
119 hex.EncBytes(result.PublicKey, v)
120 case tlv.Kind:
121 result.Kind = kind.New(binary.BigEndian.Uint32(v))
122 default:
123 log.D.Ln([]byte("got a bogus TLV type code %d"), t)
124 }
125 }
126 }
127 return prefix, data, errorf.E([]byte("unknown tag %s"), prefix)
128 }
129
130 func EncodeNote(eventIDHex []byte) (s []byte, err error) {
131 b := []byte{:sha256.Size}
132 if _, err = hex.DecBytes(b, eventIDHex); chk.D(err) {
133 return
134 }
135 var bits5 []byte
136 if bits5, err = bech32.ConvertBits(b, 8, 5, true); chk.D(err) {
137 return
138 }
139 return bech32.Encode(NoteHRP, bits5)
140 }
141
142 func EncodeProfile(publicKeyHex []byte, relays [][]byte) (s []byte, err error) {
143 buf := &bytes.Buffer{}
144 pb := []byte{:schnorr.PubKeyBytesLen}
145 if _, err = hex.DecBytes(pb, publicKeyHex); chk.D(err) {
146 return
147 }
148 tlv.WriteEntry(buf, tlv.Default, pb)
149 for _, url := range relays {
150 tlv.WriteEntry(buf, tlv.Relay, url)
151 }
152 var bits5 []byte
153 if bits5, err = bech32.ConvertBits(buf.Bytes(), 8, 5, true); chk.D(err) {
154 return
155 }
156 return bech32.Encode(NprofileHRP, bits5)
157 }
158
159 func EncodeEvent(eventIDHex []byte, relays [][]byte, author []byte) (s []byte, err error) {
160 buf := &bytes.Buffer{}
161 id := []byte{:sha256.Size}
162 if _, err = hex.DecBytes(id, eventIDHex); chk.D(err) || len(id) != 32 {
163 return nil, errorf.E([]byte("invalid id %d '%s': %v"), len(id), eventIDHex, err)
164 }
165 tlv.WriteEntry(buf, tlv.Default, id)
166 for _, url := range relays {
167 tlv.WriteEntry(buf, tlv.Relay, url)
168 }
169 pubkey := []byte{:schnorr.PubKeyBytesLen}
170 if _, err = hex.DecBytes(pubkey, author); len(pubkey) == 32 {
171 tlv.WriteEntry(buf, tlv.Author, pubkey)
172 }
173 var bits5 []byte
174 if bits5, err = bech32.ConvertBits(buf.Bytes(), 8, 5, true); chk.D(err) {
175 return
176 }
177 return bech32.Encode(NeventHRP, bits5)
178 }
179
180 func EncodeEntity(pk []byte, k *kind.K, id []byte, relays [][]byte) (s []byte, err error) {
181 buf := &bytes.Buffer{}
182 tlv.WriteEntry(buf, tlv.Default, id)
183 for _, url := range relays {
184 tlv.WriteEntry(buf, tlv.Relay, url)
185 }
186 pb := []byte{:schnorr.PubKeyBytesLen}
187 if _, err = hex.DecBytes(pb, pk); chk.D(err) {
188 return nil, errorf.E([]byte("invalid pubkey '%s': %w"), pb, err)
189 }
190 tlv.WriteEntry(buf, tlv.Author, pb)
191 kindBytes := []byte{:4}
192 binary.BigEndian.PutUint32(kindBytes, uint32(k.K))
193 tlv.WriteEntry(buf, tlv.Kind, kindBytes)
194 var bits5 []byte
195 if bits5, err = bech32.ConvertBits(buf.Bytes(), 8, 5, true); chk.D(err) {
196 return nil, errorf.E([]byte("failed to convert bits: %w"), err)
197 }
198 return bech32.Encode(NentityHRP, bits5)
199 }
200