nostr_bech32.c (7098B)
1 // 2 // nostr_bech32.c 3 // damus 4 // 5 // Created by William Casarin on 2023-04-09. 6 // 7 8 #include "nostr_bech32.h" 9 #include <stdlib.h> 10 #include "cursor.h" 11 #include "str_block.h" 12 #include "nostrdb.h" 13 #include "bolt11/bech32.h" 14 15 #define MAX_TLVS 32 16 17 #define TLV_SPECIAL 0 18 #define TLV_RELAY 1 19 #define TLV_AUTHOR 2 20 #define TLV_KIND 3 21 #define TLV_KNOWN_TLVS 4 22 23 struct nostr_tlv { 24 unsigned char type; 25 unsigned char len; 26 const unsigned char *value; 27 }; 28 29 static int parse_nostr_tlv(struct cursor *cur, struct nostr_tlv *tlv) { 30 // get the tlv tag 31 if (!cursor_pull_byte(cur, &tlv->type)) 32 return 0; 33 34 if (tlv->type >= TLV_KNOWN_TLVS) 35 return 0; 36 37 // get the length 38 if (!cursor_pull_byte(cur, &tlv->len)) 39 return 0; 40 41 // is the reported length greater then our buffer? if so fail 42 if (cur->p + tlv->len > cur->end) 43 return 0; 44 45 tlv->value = cur->p; 46 cur->p += tlv->len; 47 48 return 1; 49 } 50 51 int parse_nostr_bech32_type(const char *prefix, enum nostr_bech32_type *type) { 52 // Parse type 53 if (strncmp(prefix, "note", 4) == 0) { 54 *type = NOSTR_BECH32_NOTE; 55 return 4; 56 } else if (strncmp(prefix, "npub", 4) == 0) { 57 *type = NOSTR_BECH32_NPUB; 58 return 4; 59 } else if (strncmp(prefix, "nsec", 4) == 0) { 60 *type = NOSTR_BECH32_NSEC; 61 return 4; 62 } else if (strncmp(prefix, "nprofile", 8) == 0) { 63 *type = NOSTR_BECH32_NPROFILE; 64 return 8; 65 } else if (strncmp(prefix, "nevent", 6) == 0) { 66 *type = NOSTR_BECH32_NEVENT; 67 return 6; 68 } else if (strncmp(prefix, "nrelay", 6) == 0) { 69 *type = NOSTR_BECH32_NRELAY; 70 return 6; 71 } else if (strncmp(prefix, "naddr", 5) == 0) { 72 *type = NOSTR_BECH32_NADDR; 73 return 5; 74 } 75 76 return 0; 77 } 78 79 static int parse_nostr_bech32_note(struct cursor *cur, struct bech32_note *note) { 80 return pull_bytes(cur, 32, ¬e->event_id); 81 } 82 83 static int parse_nostr_bech32_npub(struct cursor *cur, struct bech32_npub *npub) { 84 return pull_bytes(cur, 32, &npub->pubkey); 85 } 86 87 static int parse_nostr_bech32_nsec(struct cursor *cur, struct bech32_nsec *nsec) { 88 return pull_bytes(cur, 32, &nsec->nsec); 89 } 90 91 static int add_relay(struct ndb_relays *relays, struct nostr_tlv *tlv) 92 { 93 struct ndb_str_block *str; 94 95 if (relays->num_relays + 1 > NDB_MAX_RELAYS) 96 return 0; 97 98 str = &relays->relays[relays->num_relays++]; 99 str->str = (const char*)tlv->value; 100 str->len = tlv->len; 101 102 return 1; 103 } 104 105 static int parse_nostr_bech32_nevent(struct cursor *cur, struct bech32_nevent *nevent) { 106 struct nostr_tlv tlv; 107 int i; 108 109 nevent->event_id = NULL; 110 nevent->pubkey = NULL; 111 nevent->relays.num_relays = 0; 112 113 for (i = 0; i < MAX_TLVS; i++) { 114 if (!parse_nostr_tlv(cur, &tlv)) 115 break; 116 117 switch (tlv.type) { 118 case TLV_SPECIAL: 119 if (tlv.len != 32) 120 return 0; 121 nevent->event_id = tlv.value; 122 break; 123 case TLV_AUTHOR: 124 if (tlv.len != 32) 125 return 0; 126 nevent->pubkey = tlv.value; 127 break; 128 case TLV_RELAY: 129 add_relay(&nevent->relays, &tlv); 130 break; 131 } 132 } 133 134 return nevent->event_id != NULL; 135 } 136 137 static int parse_nostr_bech32_naddr(struct cursor *cur, struct bech32_naddr *naddr) { 138 struct nostr_tlv tlv; 139 int i; 140 141 naddr->identifier.str = NULL; 142 naddr->identifier.len = 0; 143 naddr->pubkey = NULL; 144 naddr->relays.num_relays = 0; 145 146 for (i = 0; i < MAX_TLVS; i++) { 147 if (!parse_nostr_tlv(cur, &tlv)) 148 break; 149 150 switch (tlv.type) { 151 case TLV_SPECIAL: 152 naddr->identifier.str = (const char*)tlv.value; 153 naddr->identifier.len = tlv.len; 154 break; 155 case TLV_AUTHOR: 156 if (tlv.len != 32) return 0; 157 naddr->pubkey = tlv.value; 158 break; 159 case TLV_RELAY: 160 add_relay(&naddr->relays, &tlv); 161 break; 162 } 163 } 164 165 return naddr->identifier.str != NULL; 166 } 167 168 static int parse_nostr_bech32_nprofile(struct cursor *cur, struct bech32_nprofile *nprofile) { 169 struct nostr_tlv tlv; 170 int i; 171 172 nprofile->pubkey = NULL; 173 nprofile->relays.num_relays = 0; 174 175 for (i = 0; i < MAX_TLVS; i++) { 176 if (!parse_nostr_tlv(cur, &tlv)) 177 break; 178 179 switch (tlv.type) { 180 case TLV_SPECIAL: 181 if (tlv.len != 32) return 0; 182 nprofile->pubkey = tlv.value; 183 break; 184 case TLV_RELAY: 185 add_relay(&nprofile->relays, &tlv); 186 break; 187 } 188 } 189 190 return nprofile->pubkey != NULL; 191 } 192 193 static int parse_nostr_bech32_nrelay(struct cursor *cur, struct bech32_nrelay *nrelay) { 194 struct nostr_tlv tlv; 195 int i; 196 197 nrelay->relay.str = NULL; 198 nrelay->relay.len = 0; 199 200 for (i = 0; i < MAX_TLVS; i++) { 201 if (!parse_nostr_tlv(cur, &tlv)) 202 break; 203 204 switch (tlv.type) { 205 case TLV_SPECIAL: 206 nrelay->relay.str = (const char*)tlv.value; 207 nrelay->relay.len = tlv.len; 208 break; 209 } 210 } 211 212 return nrelay->relay.str != NULL; 213 } 214 215 int parse_nostr_bech32_buffer(struct cursor *cur, 216 enum nostr_bech32_type type, 217 struct nostr_bech32 *obj) 218 { 219 obj->type = type; 220 221 switch (obj->type) { 222 case NOSTR_BECH32_NOTE: 223 if (!parse_nostr_bech32_note(cur, &obj->note)) 224 return 0; 225 break; 226 case NOSTR_BECH32_NPUB: 227 if (!parse_nostr_bech32_npub(cur, &obj->npub)) 228 return 0; 229 break; 230 case NOSTR_BECH32_NSEC: 231 if (!parse_nostr_bech32_nsec(cur, &obj->nsec)) 232 return 0; 233 break; 234 case NOSTR_BECH32_NEVENT: 235 if (!parse_nostr_bech32_nevent(cur, &obj->nevent)) 236 return 0; 237 break; 238 case NOSTR_BECH32_NADDR: 239 if (!parse_nostr_bech32_naddr(cur, &obj->naddr)) 240 return 0; 241 break; 242 case NOSTR_BECH32_NPROFILE: 243 if (!parse_nostr_bech32_nprofile(cur, &obj->nprofile)) 244 return 0; 245 break; 246 case NOSTR_BECH32_NRELAY: 247 if (!parse_nostr_bech32_nrelay(cur, &obj->nrelay)) 248 return 0; 249 break; 250 } 251 252 return 1; 253 } 254 255 256 int parse_nostr_bech32_str(struct cursor *bech32, enum nostr_bech32_type *type) { 257 unsigned char *start = bech32->p; 258 unsigned char *data_start; 259 int n; 260 261 if (!(n = parse_nostr_bech32_type((const char *)bech32->p, type))) { 262 bech32->p = start; 263 return 0; 264 } 265 266 data_start = start + n; 267 if (!consume_until_non_alphanumeric(bech32, 1)) { 268 bech32->p = start; 269 return 0; 270 } 271 272 // must be at least 59 chars for the data part 273 //ndb_debug("bech32_data_size %ld '%c' '%c' '%.*s'\n", bech32->p - data_start, *(bech32->p-1), *data_start, (int)(bech32->p - data_start), data_start); 274 if (bech32->p - data_start < 59) { 275 bech32->p = start; 276 return 0; 277 } 278 279 return 1; 280 } 281 282 283 int parse_nostr_bech32(unsigned char *buf, int buflen, 284 const char *bech32_str, size_t bech32_len, 285 struct nostr_bech32 *obj) { 286 unsigned char *start; 287 size_t parsed_len, u5_out_len, u8_out_len; 288 enum nostr_bech32_type type; 289 static const int MAX_PREFIX = 8; 290 struct cursor cur, bech32, u8; 291 292 make_cursor(buf, buf + buflen, &cur); 293 make_cursor((unsigned char*)bech32_str, (unsigned char*)bech32_str + bech32_len, &bech32); 294 295 start = bech32.p; 296 if (!parse_nostr_bech32_str(&bech32, &type)) 297 return 0; 298 299 parsed_len = bech32.p - start; 300 301 // some random sanity checking 302 if (parsed_len < 10 || parsed_len > 10000) 303 return 0; 304 305 unsigned char u5[parsed_len]; 306 char prefix[MAX_PREFIX]; 307 308 if (bech32_decode_len(prefix, u5, &u5_out_len, (const char*)start, 309 parsed_len, MAX_PREFIX) == BECH32_ENCODING_NONE) 310 { 311 return 0; 312 } 313 314 if (!bech32_convert_bits(cur.p, &u8_out_len, 8, u5, u5_out_len, 5, 0)) 315 return 0; 316 317 make_cursor(cur.p, cur.p + u8_out_len, &u8); 318 319 return parse_nostr_bech32_buffer(&u8, type, obj); 320 } 321