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