nostril.c (26094B)
1 2 #include <stdio.h> 3 #include <time.h> 4 #include <stdlib.h> 5 #include <assert.h> 6 #include <errno.h> 7 #include <inttypes.h> 8 #include <unistd.h> 9 10 #include "secp256k1.h" 11 #include "secp256k1_ecdh.h" 12 #include "secp256k1_schnorrsig.h" 13 14 #include "cursor.h" 15 #include "hex.h" 16 #include "nip44.h" 17 #include "base64.h" 18 #include "aes.h" 19 #include "sha256.h" 20 #include "random.h" 21 #include "proof.h" 22 23 #define VERSION "0.1.3" 24 25 #define MAX_TAGS 1024 26 #define MAX_TAG_ELEMS 64 27 28 #define HAS_CREATED_AT (1<<1) 29 #define HAS_KIND (1<<2) 30 #define HAS_ENVELOPE (1<<3) 31 #define HAS_ENCRYPT (1<<4) 32 #define HAS_DIFFICULTY (1<<5) 33 #define HAS_MINE_PUBKEY (1<<6) 34 #define HAS_GIFTWRAP (1<<7) 35 36 struct key { 37 secp256k1_keypair pair; 38 unsigned char secret[32]; 39 unsigned char pubkey[32]; 40 }; 41 42 struct args { 43 unsigned int flags; 44 int kind; 45 int difficulty; 46 47 unsigned char encrypt_to[32]; 48 const char *sec; 49 const char *tags; 50 const char *content; 51 52 uint64_t created_at; 53 }; 54 55 struct nostr_tag { 56 const char *strs[MAX_TAG_ELEMS]; 57 int num_elems; 58 }; 59 60 struct nostr_event { 61 unsigned char id[32]; 62 unsigned char pubkey[32]; 63 unsigned char sig[64]; 64 65 const char *content; 66 67 uint64_t created_at; 68 int kind; 69 70 const char *explicit_tags; 71 72 struct nostr_tag tags[MAX_TAGS]; 73 int num_tags; 74 }; 75 76 void usage() 77 { 78 printf("usage: nostril [OPTIONS]\n"); 79 printf("\n"); 80 printf(" OPTIONS\n"); 81 printf("\n"); 82 printf(" --content <string> the content of the note\n"); 83 printf(" --dm <hex pubkey> make an encrypted dm to said pubkey. sets kind and tags.\n"); 84 printf(" --giftwrap-to <hex pubkey> make an encrypted giftwrap to said pubkey.\n"); 85 printf(" --envelope wrap in [\"EVENT\",...] for easy relaying\n"); 86 printf(" --kind <number> set kind\n"); 87 printf(" --created-at <unix timestamp> set a specific created-at time\n"); 88 printf(" --sec <hex seckey> set the secret key for signing, otherwise one will be randomly generated\n"); 89 printf(" --pow <difficulty> number of leading 0 bits of the id to mine\n"); 90 printf(" --mine-pubkey mine a pubkey instead of id\n"); 91 printf(" --tag <key> <value> add a tag\n"); 92 printf(" --tagn <N> <tags * N...> add a tag with N elements. eg: `--tagn 3 a b c`, `--tagn 0`\n"); 93 printf(" -e <event_id> shorthand for --tag e <event_id>\n"); 94 printf(" -p <pubkey> shorthand for --tag p <pubkey>\n"); 95 printf(" -t <hashtag> shorthand for --tag t <hashtag>\n"); 96 exit(1); 97 } 98 99 100 inline static int cursor_push_escaped_char(struct cursor *cur, char c) 101 { 102 switch (c) { 103 case '"': return cursor_push_str(cur, "\\\""); 104 case '\\': return cursor_push_str(cur, "\\\\"); 105 case '\b': return cursor_push_str(cur, "\\b"); 106 case '\f': return cursor_push_str(cur, "\\f"); 107 case '\n': return cursor_push_str(cur, "\\n"); 108 case '\r': return cursor_push_str(cur, "\\r"); 109 case '\t': return cursor_push_str(cur, "\\t"); 110 // TODO: \u hex hex hex hex 111 } 112 return cursor_push_byte(cur, c); 113 } 114 115 static int cursor_push_jsonstr(struct cursor *cur, const char *str) 116 { 117 int i; 118 int len; 119 120 len = strlen(str); 121 122 if (!cursor_push_byte(cur, '"')) 123 return 0; 124 125 for (i = 0; i < len; i++) { 126 if (!cursor_push_escaped_char(cur, str[i])) 127 return 0; 128 } 129 130 if (!cursor_push_byte(cur, '"')) 131 return 0; 132 133 return 1; 134 } 135 136 static int cursor_push_tag(struct cursor *cur, struct nostr_tag *tag) 137 { 138 int i; 139 140 if (!cursor_push_byte(cur, '[')) 141 return 0; 142 143 for (i = 0; i < tag->num_elems; i++) { 144 if (!cursor_push_jsonstr(cur, tag->strs[i])) 145 return 0; 146 if (i != tag->num_elems-1) { 147 if (!cursor_push_byte(cur, ',')) 148 return 0; 149 } 150 } 151 152 return cursor_push_byte(cur, ']'); 153 } 154 155 static int cursor_push_tags(struct cursor *cur, struct nostr_event *ev) 156 { 157 int i; 158 159 if (ev->explicit_tags) { 160 return cursor_push_str(cur, ev->explicit_tags); 161 } 162 163 if (!cursor_push_byte(cur, '[')) 164 return 0; 165 166 for (i = 0; i < ev->num_tags; i++) { 167 if (!cursor_push_tag(cur, &ev->tags[i])) 168 return 0; 169 if (i != ev->num_tags-1) { 170 if (!cursor_push_str(cur, ",")) 171 return 0; 172 } 173 } 174 175 return cursor_push_byte(cur, ']'); 176 } 177 178 179 int event_commitment(struct nostr_event *ev, unsigned char *buf, int buflen) 180 { 181 char timebuf[16] = {0}; 182 char kindbuf[16] = {0}; 183 char pubkey[65]; 184 struct cursor cur; 185 int ok; 186 187 ok = hex_encode(ev->pubkey, sizeof(ev->pubkey), pubkey, sizeof(pubkey)); 188 assert(ok); 189 190 make_cursor(buf, buf + buflen, &cur); 191 192 snprintf(timebuf, sizeof(timebuf), "%" PRIu64 "", ev->created_at); 193 snprintf(kindbuf, sizeof(kindbuf), "%d", ev->kind); 194 195 ok = 196 cursor_push_str(&cur, "[0,\"") && 197 cursor_push_str(&cur, pubkey) && 198 cursor_push_str(&cur, "\",") && 199 cursor_push_str(&cur, timebuf) && 200 cursor_push_str(&cur, ",") && 201 cursor_push_str(&cur, kindbuf) && 202 cursor_push_str(&cur, ",") && 203 cursor_push_tags(&cur, ev) && 204 cursor_push_str(&cur, ",") && 205 cursor_push_jsonstr(&cur, ev->content) && 206 cursor_push_str(&cur, "]"); 207 208 if (!ok) 209 return 0; 210 211 return cur.p - cur.start; 212 } 213 214 static int make_sig(secp256k1_context *ctx, struct key *key, 215 unsigned char *id, unsigned char sig[64]) 216 { 217 unsigned char aux[32]; 218 219 if (!fill_random(aux, sizeof(aux))) { 220 return 0; 221 } 222 223 return secp256k1_schnorrsig_sign32(ctx, sig, id, &key->pair, aux); 224 } 225 226 static int create_key(secp256k1_context *ctx, struct key *key) 227 { 228 secp256k1_xonly_pubkey pubkey; 229 230 /* Try to create a keypair with a valid context, it should only 231 * fail if the secret key is zero or out of range. */ 232 if (!secp256k1_keypair_create(ctx, &key->pair, key->secret)) 233 return 0; 234 235 if (!secp256k1_keypair_xonly_pub(ctx, &pubkey, NULL, &key->pair)) 236 return 0; 237 238 /* Serialize the public key. Should always return 1 for a valid public key. */ 239 return secp256k1_xonly_pubkey_serialize(ctx, key->pubkey, &pubkey); 240 } 241 242 static int decode_key(secp256k1_context *ctx, const char *secstr, struct key *key) 243 { 244 if (!hex_decode(secstr, strlen(secstr), key->secret, 32)) { 245 fprintf(stderr, "could not hex decode secret key\n"); 246 return 0; 247 } 248 249 return create_key(ctx, key); 250 } 251 252 static inline void xor_mix(unsigned char *dest, const unsigned char *a, const unsigned char *b, int size) 253 { 254 int i; 255 for (i = 0; i < size; i++) 256 dest[i] = a[i] ^ b[i]; 257 } 258 259 static int generate_key(secp256k1_context *ctx, struct key *key, int *difficulty) 260 { 261 uint64_t attempts = 0; 262 uint64_t duration; 263 int bits; 264 double pers; 265 struct timespec t1, t2; 266 267 /* If the secret key is zero or out of range (bigger than secp256k1's 268 * order), we try to sample a new key. Note that the probability of this 269 * happening is negligible. */ 270 if (!fill_random(key->secret, sizeof(key->secret))) { 271 return 0; 272 } 273 274 if (difficulty == NULL) { 275 return create_key(ctx, key); 276 } 277 278 clock_gettime(CLOCK_MONOTONIC, &t1); 279 while (1) { 280 if (!create_key(ctx, key)) 281 return 0; 282 283 attempts++; 284 285 if ((bits = count_leading_zero_bits(key->pubkey)) >= *difficulty) { 286 clock_gettime(CLOCK_MONOTONIC, &t2); 287 duration = ((t2.tv_sec - t1.tv_sec) * 1e9L + (t2.tv_nsec - t1.tv_nsec)) / 1e6L; 288 pers = (double)attempts / (double)duration; 289 fprintf(stderr, "mined pubkey with %d bits after %" PRIu64 " attempts, %" PRId64 " ms, %f attempts per ms\n", bits, attempts, duration, pers); 290 return 1; 291 } 292 293 // NOTE: Get a new secret key by xor mixing the current secret 294 // key with the current public key. This doesn't rely on the 295 // system's crypto number generator so it should be fast. There 296 // shouldn't be any secret key entropy issues since we got a 297 // good source of entropy from the first fill_random call at 298 // the start of the function. 299 xor_mix(key->secret, key->secret, key->pubkey, 32); 300 } 301 } 302 303 304 static int init_secp_context(secp256k1_context **ctx) 305 { 306 unsigned char randomize[32]; 307 308 *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); 309 if (!fill_random(randomize, sizeof(randomize))) { 310 return 0; 311 } 312 313 /* Randomizing the context is recommended to protect against side-channel 314 * leakage See `secp256k1_context_randomize` in secp256k1.h for more 315 * information about it. This should never fail. */ 316 return secp256k1_context_randomize(*ctx, randomize); 317 } 318 319 static int generate_event_id(struct nostr_event *ev, 320 unsigned char *buf, size_t bufsize) 321 { 322 int len; 323 324 if (!(len = event_commitment(ev, buf, bufsize))) { 325 fprintf(stderr, "event_commitment: buffer out of space\n"); 326 return 0; 327 } 328 329 //fprintf(stderr, "commitment: '%.*s'\n", len, buf); 330 331 sha256((struct sha256*)ev->id, buf, len); 332 333 return 1; 334 } 335 336 static int sign_event(secp256k1_context *ctx, struct key *key, struct nostr_event *ev) 337 { 338 if (!make_sig(ctx, key, ev->id, ev->sig)) 339 return 0; 340 341 return 1; 342 } 343 344 static int all_zeros(unsigned char *buf, size_t bufsize) 345 { 346 int i; 347 348 for (i = 0; i < bufsize; i++) { 349 if (buf[i] != 0) 350 return 0; 351 } 352 353 return 1; 354 } 355 356 static int event_to_json(struct cursor *c, struct nostr_event *ev, int envelope) 357 { 358 char shortbuf[128]; 359 360 if (envelope) { 361 if (!cursor_push_str(c, "[\"EVENT\",")) 362 return 0; 363 } 364 365 if (!cursor_push_str(c, "{\"id\":\"")) return 0; 366 if (!cursor_push_hex(c, ev->id, 32)) return 0; 367 if (!cursor_push_str(c, "\",")) return 0; 368 if (!cursor_push_str(c, "\"pubkey\":\"")) return 0; 369 if (!cursor_push_hex(c, ev->pubkey, 32)) return 0; 370 if (!cursor_push_str(c, "\",")) return 0; 371 sprintf(shortbuf, "\"created_at\":%" PRIu64 ",", ev->created_at); 372 if (!cursor_push_str(c, shortbuf)) return 0; 373 sprintf(shortbuf, "\"kind\":%d,", ev->kind); 374 if (!cursor_push_str(c, shortbuf)) return 0; 375 if (!cursor_push_str(c, "\"tags\":")) return 0; 376 if (!cursor_push_tags(c, ev)) return 0; 377 if (!cursor_push_str(c, ",\"content\":")) return 0; 378 if (!cursor_push_jsonstr(c, ev->content)) return 0; 379 380 if (!all_zeros(ev->sig, 64)) { 381 if (!cursor_push_str(c, ",\"sig\":\"")) return 0; 382 if (!cursor_push_hex(c, ev->sig, 64)) return 0; 383 if (!cursor_push_byte(c, '"')) return 0; 384 } 385 386 if (!cursor_push_str(c, "}")) return 0; 387 388 if (envelope) { 389 return cursor_push_c_str(c, "]"); 390 } else { 391 return cursor_push_byte(c, 0); 392 } 393 } 394 395 static int print_event(struct nostr_event *ev, int envelope, 396 unsigned char *buf, size_t bufsize) 397 { 398 struct cursor cur; 399 make_cursor(buf, buf+bufsize, &cur); 400 401 if (!event_to_json(&cur, ev, envelope)) 402 return 0; 403 404 printf("%s\n", buf); 405 406 return 1; 407 } 408 409 static void make_event_from_args(struct nostr_event *ev, struct args *args) 410 { 411 ev->created_at = args->flags & HAS_CREATED_AT? args->created_at : time(NULL); 412 ev->content = args->content; 413 ev->kind = args->flags & HAS_KIND ? args->kind : 1; 414 } 415 416 static int parse_num(const char *arg, uint64_t *t) 417 { 418 *t = strtol(arg, NULL, 10); 419 return errno != EINVAL; 420 } 421 422 static int nostr_add_tag_n(struct nostr_event *ev, const char **ts, int n_ts) 423 { 424 int i; 425 struct nostr_tag *tag; 426 427 if (ev->num_tags + 1 > MAX_TAGS) 428 return 0; 429 430 tag = &ev->tags[ev->num_tags++]; 431 432 tag->num_elems = n_ts; 433 for (i = 0; i < n_ts; i++) { 434 tag->strs[i] = ts[i]; 435 } 436 437 return 1; 438 } 439 440 static int nostr_add_tag(struct nostr_event *ev, const char *t1, const char *t2) 441 { 442 const char *ts[] = {t1, t2}; 443 return nostr_add_tag_n(ev, ts, 2); 444 } 445 446 static int nostr_add_arg_tags(struct nostr_event *ev, int *argc, const char **argv[]) 447 { 448 struct nostr_tag *tag; 449 int i; 450 uint64_t n; 451 uint16_t small_n; 452 const char *arg; 453 454 if (*argc == 0) { 455 fprintf(stderr, "expected more arguments to --tagn\n"); 456 return 0; 457 } 458 459 arg = *(*argv)++; (*argc)--; 460 461 if (!parse_num(arg, &n)) { 462 fprintf(stderr, "expected X to be a number in --tagn X ...\n"); 463 return 0; 464 } 465 466 if (n > MAX_TAG_ELEMS) { 467 fprintf(stderr, "too many --tagn arguments (%"PRIu64" > %d)\n", n, MAX_TAG_ELEMS); 468 return 0; 469 } 470 471 small_n = (uint16_t)n; 472 473 if (ev->num_tags + small_n > MAX_TAGS) { 474 fprintf(stderr, "too many tags (%d + %d > %d)\n", ev->num_tags, small_n, MAX_TAG_ELEMS); 475 return 0; 476 } 477 478 tag = &ev->tags[ev->num_tags++]; 479 tag->num_elems = 0; 480 481 for (i = 0; i < small_n; i++) { 482 if (*argc <= 0) { 483 fprintf(stderr, "expected %d tags: --tagn %d ..., got %d args\n", small_n, small_n, i); 484 return 0; 485 } 486 arg = *(*argv)++; (*argc)--; 487 //fprintf(stderr, "got arg '%s' argc(%d)\n", arg, *argc); 488 tag->strs[i] = arg; 489 tag->num_elems++; 490 } 491 492 return 1; 493 } 494 495 static int parse_args(int argc, const char *argv[], struct args *args, struct nostr_event *ev) 496 { 497 const char *arg, *arg2; 498 uint64_t n; 499 int has_added_tags = 0; 500 501 argv++; argc--; 502 for (; argc; ) { 503 arg = *argv++; argc--; 504 505 if (!strcmp(arg, "--help")) { 506 usage(); 507 } 508 509 if (!argc) { 510 fprintf(stderr, "expected argument: '%s'\n", arg); 511 return 0; 512 } 513 514 if (!strcmp(arg, "--sec")) { 515 args->sec = *argv++; argc--; 516 } else if (!strcmp(arg, "--created-at")) { 517 arg = *argv++; argc--; 518 if (!parse_num(arg, &args->created_at)) { 519 fprintf(stderr, "created-at must be a unix timestamp\n"); 520 return 0; 521 } else { 522 args->flags |= HAS_CREATED_AT; 523 } 524 } else if (!strcmp(arg, "--kind")) { 525 arg = *argv++; argc--; 526 if (!parse_num(arg, &n)) { 527 fprintf(stderr, "kind should be a number, got '%s'\n", arg); 528 return 0; 529 } 530 args->kind = (int)n; 531 args->flags |= HAS_KIND; 532 } else if (!strcmp(arg, "--envelope")) { 533 args->flags |= HAS_ENVELOPE; 534 } else if (!strcmp(arg, "--tags")) { 535 if (args->flags & HAS_DIFFICULTY) { 536 fprintf(stderr, "can't combine --tags and --pow (yet)\n"); 537 return 0; 538 } 539 if (has_added_tags) { 540 fprintf(stderr, "can't combine --tags and --tag (yet)"); 541 return 0; 542 } 543 arg = *argv++; argc--; 544 args->tags = arg; 545 } else if (!strcmp(arg, "-e")) { 546 has_added_tags = 1; 547 arg = *argv++; argc--; 548 if (!nostr_add_tag(ev, "e", arg)) { 549 fprintf(stderr, "couldn't add e tag"); 550 return 0; 551 } 552 } else if (!strcmp(arg, "-p")) { 553 has_added_tags = 1; 554 arg = *argv++; argc--; 555 if (!nostr_add_tag(ev, "p", arg)) { 556 fprintf(stderr, "couldn't add p tag"); 557 return 0; 558 } 559 } else if (!strcmp(arg, "-t")) { 560 has_added_tags = 1; 561 arg = *argv++; argc--; 562 if (!nostr_add_tag(ev, "t", arg)) { 563 fprintf(stderr, "couldn't add t tag"); 564 return 0; 565 } 566 } else if (!strcmp(arg, "--tagn")) { 567 if (!nostr_add_arg_tags(ev, &argc, &argv)) { 568 return 0; 569 } 570 has_added_tags = 1; 571 } else if (!strcmp(arg, "--tag")) { 572 has_added_tags = 1; 573 if (args->tags) { 574 fprintf(stderr, "can't combine --tag and --tags (yet)"); 575 return 0; 576 } 577 arg = *argv++; argc--; 578 if (argc == 0) { 579 fprintf(stderr, "expected two arguments to --tag\n"); 580 return 0; 581 } 582 arg2 = *argv++; argc--; 583 if (!nostr_add_tag(ev, arg, arg2)) { 584 fprintf(stderr, "couldn't add tag '%s' '%s'\n", arg, arg2); 585 return 0; 586 } 587 } else if (!strcmp(arg, "--mine-pubkey")) { 588 args->flags |= HAS_MINE_PUBKEY; 589 } else if (!strcmp(arg, "--pow")) { 590 if (args->tags) { 591 fprintf(stderr, "can't combine --tags and --pow (yet)\n"); 592 return 0; 593 } 594 arg = *argv++; argc--; 595 if (!parse_num(arg, &n)) { 596 fprintf(stderr, "could not parse difficulty as number: '%s'\n", arg); 597 return 0; 598 } 599 args->difficulty = n; 600 args->flags |= HAS_DIFFICULTY; 601 } else if (!strcmp(arg, "--dm")) { 602 arg = *argv++; argc--; 603 if (!hex_decode(arg, strlen(arg), args->encrypt_to, 32)) { 604 fprintf(stderr, "could not decode encrypt-to pubkey"); 605 return 0; 606 } 607 args->flags |= HAS_ENCRYPT; 608 } else if (!strcmp(arg, "--content")) { 609 arg = *argv++; argc--; 610 args->content = arg; 611 } else if (!strcmp(arg, "--giftwrap-to")) { 612 arg = *argv++; argc--; 613 if (!hex_decode(arg, strlen(arg), args->encrypt_to, 32)) { 614 fprintf(stderr, "could not decode giftwrap-to pubkey"); 615 return 0; 616 } 617 args->flags |= HAS_GIFTWRAP; 618 } else { 619 fprintf(stderr, "unexpected argument '%s'\n", arg); 620 return 0; 621 } 622 } 623 624 if (!args->content) 625 args->content = ""; 626 627 return 1; 628 } 629 630 static int aes_encrypt(unsigned char *key, unsigned char *iv, 631 unsigned char *buf, size_t buflen) 632 { 633 struct AES_ctx ctx; 634 unsigned char padding; 635 int i; 636 struct cursor cur; 637 638 padding = 16 - (buflen % 16); 639 make_cursor(buf, buf + buflen + padding, &cur); 640 cur.p += buflen; 641 //fprintf(stderr, "aes_encrypt: len %ld, padding %d\n", buflen, padding); 642 643 for (i = 0; i < padding; i++) { 644 if (!cursor_push_byte(&cur, padding)) { 645 return 0; 646 } 647 } 648 assert(cur.p == cur.end); 649 assert((cur.p - cur.start) % 16 == 0); 650 651 AES_init_ctx_iv(&ctx, key, iv); 652 //fprintf(stderr, "encrypting %ld bytes: ", cur.p - cur.start); 653 //print_hex(cur.start, cur.p - cur.start); 654 AES_CBC_encrypt_buffer(&ctx, cur.start, cur.p - cur.start); 655 656 return cur.p - cur.start; 657 } 658 659 static int copyx(unsigned char *output, const unsigned char *x32, const unsigned char *y32, void *data) { 660 memcpy(output, x32, 32); 661 return 1; 662 } 663 664 static int ensure_nonce_tag(struct nostr_event *ev, int target, int *index) 665 { 666 char *str_target = malloc(8); 667 struct nostr_tag *tag; 668 int i; 669 670 for (i = 0; i < ev->num_tags; i++) { 671 tag = &ev->tags[i]; 672 if (tag->num_elems == 2 && !strcmp(tag->strs[0], "nonce")) { 673 *index = i; 674 return 1; 675 } 676 } 677 678 *index = ev->num_tags; 679 680 snprintf(str_target, 7, "%d", target); 681 const char *ts[] = { "nonce", "0", str_target }; 682 683 return nostr_add_tag_n(ev, ts, 3); 684 } 685 686 static int mine_event(struct nostr_event *ev, int difficulty, 687 unsigned char *buf, size_t bufsize) 688 { 689 char *strnonce = malloc(33); 690 struct nostr_tag *tag; 691 uint64_t nonce; 692 int index, res; 693 694 if (!ensure_nonce_tag(ev, difficulty, &index)) 695 return 0; 696 697 tag = &ev->tags[index]; 698 assert(tag->num_elems == 3); 699 assert(!strcmp(tag->strs[0], "nonce")); 700 tag->strs[1] = strnonce; 701 702 for (nonce = 0;; nonce++) { 703 snprintf(strnonce, 32, "%" PRIu64, nonce); 704 705 if (!generate_event_id(ev, buf, bufsize)) 706 return 0; 707 708 if ((res = count_leading_zero_bits(ev->id)) >= difficulty) { 709 fprintf(stderr, "mined %d bits\n", res); 710 return 1; 711 } 712 } 713 714 return 0; 715 } 716 717 static int make_giftwrap(secp256k1_context *ctx, struct key *key, 718 struct nostr_event *rumor, unsigned char receiver_pubkey[32], 719 unsigned char *buf, size_t bufsize, 720 int is_envelope) 721 { 722 struct nostr_event giftwrap = {0}; 723 struct nostr_event seal = {0}; 724 struct key wrap_key; 725 char *b64, *json; 726 struct cursor arena, *c; 727 ssize_t b64_len; 728 enum ndb_decrypt_result ok; 729 730 c = &arena; 731 make_cursor(buf, buf+bufsize, c); 732 if (!fill_random(wrap_key.secret, sizeof(wrap_key.secret))) 733 return 0; 734 create_key(ctx, &wrap_key); /* giftwrap key */ 735 736 memcpy(rumor->pubkey, key->pubkey, 32); 737 if (!generate_event_id(rumor, c->p, cursor_remaining_capacity(c))) 738 return 0; 739 740 /* rumor data */ 741 json = (char*)c->p; 742 if (!event_to_json(c, rumor, 0)) 743 return 0; 744 745 ok = nip44_encrypt(ctx, key->secret, receiver_pubkey, 746 (unsigned char *)json, c->p - (unsigned char *)json-1, 747 c->p, cursor_remaining_capacity(c), 748 &b64, &b64_len); 749 750 if (ok != NIP44_OK) { 751 fprintf(stderr, "rumor nip44 encrypt failed: %s\n", 752 nip44_err_msg(ok)); 753 return 0; 754 } 755 assert(b64_len % 4 == 0); 756 c->p = b64 + b64_len; 757 if (!cursor_push_byte(c, 0)) 758 return 0; 759 760 fprintf(stderr, "rumor %s\n\n", json); 761 762 /* seal data */ 763 seal.kind = 13; 764 seal.created_at = rumor->created_at; 765 seal.content = b64; 766 assert(strlen(b64) % 4 == 0); 767 768 memcpy(seal.pubkey, key->pubkey, 32); 769 if (!generate_event_id(&seal, c->p, cursor_remaining_capacity(c))) 770 return 0; 771 if (!sign_event(ctx, key, &seal)) 772 return 0; 773 774 json = (char*)c->p; 775 if (!event_to_json(c, &seal, 0)) { 776 fprintf(stderr, "seal -> json failed, not enough space?\n"); 777 return 0; 778 } 779 fprintf(stderr, "seal %.*s\n\n", (int)(c->p - (unsigned char*)json), json); 780 781 /* encrypt seal for giftwrap contents */ 782 ok = nip44_encrypt(ctx, wrap_key.secret, receiver_pubkey, 783 (unsigned char *)json, c->p - (unsigned char *)json - 1, 784 c->p, cursor_remaining_capacity(c), 785 &b64, &b64_len); 786 787 if (ok != NIP44_OK) { 788 fprintf(stderr, "seal nip44 encrypt failed: %s\n", 789 nip44_err_msg(ok)); 790 return 0; 791 } 792 793 assert(b64_len % 4 == 0); 794 c->p = b64 + b64_len; 795 if (!cursor_push_byte(c, 0)) 796 return 0; 797 798 giftwrap.content = b64; 799 800 /* giftwrap data */ 801 json = (char*)c->p; 802 if (!cursor_push_hex(c, wrap_key.secret, 32)) { 803 fprintf(stderr, "buffer too small, bug jb55 to increase\n"); 804 return 0; 805 } 806 fprintf(stderr, "giftwrap_sec %.*s\n\n", 64, json); 807 808 giftwrap.created_at = rumor->created_at; 809 giftwrap.kind = 1059; 810 memcpy(giftwrap.pubkey, wrap_key.pubkey, 32); 811 812 json = (char*)c->p; 813 cursor_push_hex(c, receiver_pubkey, 32); 814 cursor_push_byte(c, 0); 815 nostr_add_tag(&giftwrap, "p", json); 816 817 if (!generate_event_id(&giftwrap, c->p, cursor_remaining_capacity(c))) 818 return 0; 819 if (!sign_event(ctx, &wrap_key, &giftwrap)) 820 return 0; 821 822 json = (char*)c->p; 823 if (!event_to_json(c, &giftwrap, is_envelope)) { 824 fprintf(stderr, "buffer too small, bug jb55 to increase\n"); 825 return 0; 826 } 827 828 printf("%s\n", json); 829 830 free(buf); 831 return 1; 832 } 833 834 static int make_encrypted_dm(secp256k1_context *ctx, struct key *key, 835 struct nostr_event *ev, unsigned char nostr_pubkey[32], int kind) 836 { 837 size_t inl = strlen(ev->content); 838 int enclen = inl + 16; 839 size_t buflen = enclen * 3 + 65 * 10; 840 unsigned char *buf = malloc(buflen); 841 unsigned char shared_secret[32]; 842 unsigned char iv[16]; 843 unsigned char compressed_pubkey[33]; 844 int content_len = strlen(ev->content); 845 unsigned char encbuf[content_len + (content_len % 16) + 1]; 846 struct cursor cur; 847 secp256k1_pubkey pubkey; 848 849 compressed_pubkey[0] = 2; 850 memcpy(&compressed_pubkey[1], nostr_pubkey, 32); 851 852 make_cursor(buf, buf + buflen, &cur); 853 854 if (!secp256k1_ec_seckey_verify(ctx, key->secret)) { 855 fprintf(stderr, "make_encrypted_dm: ec_seckey_verify failed\n"); 856 return 0; 857 } 858 859 if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, compressed_pubkey, 860 sizeof(compressed_pubkey))) { 861 fprintf(stderr, "make_encrypted_dm: ec_pubkey_parse failed\n"); 862 return 0; 863 } 864 865 if (!secp256k1_ecdh(ctx, shared_secret, &pubkey, key->secret, copyx, NULL)) { 866 fprintf(stderr, "make_encrypted_dm: secp256k1_ecdh failed\n"); 867 return 0; 868 } 869 870 if (!fill_random(iv, sizeof(iv))) { 871 fprintf(stderr, "make_encrypted_dm: fill_random failed\n"); 872 return 0; 873 } 874 875 fprintf(stderr, "shared_secret "); 876 print_hex(shared_secret, 32); 877 878 memcpy(encbuf, ev->content, strlen(ev->content)); 879 enclen = aes_encrypt(shared_secret, iv, encbuf, strlen(ev->content)); 880 if (enclen == 0) { 881 fprintf(stderr, "make_encrypted_dm: aes_encrypt failed\n"); 882 free(buf); 883 return 0; 884 } 885 886 if ((enclen = base64_encode((char *)buf, buflen, (const char*)encbuf, enclen)) == -1) { 887 fprintf(stderr, "make_encrypted_dm: base64 encode of encrypted fata failed\n"); 888 return 0; 889 } 890 cur.p += enclen; 891 892 if (!cursor_push_str(&cur, "?iv=")) { 893 fprintf(stderr, "make_encrypted_dm: buffer too small\n"); 894 return 0; 895 } 896 897 if ((enclen = base64_encode((char *)cur.p, cur.end - cur.p, (const char*)iv, 16)) == -1) { 898 fprintf(stderr, "make_encrypted_dm: base64 encode of iv failed\n"); 899 return 0; 900 } 901 cur.p += enclen; 902 903 if (!cursor_push_byte(&cur, 0)) { 904 fprintf(stderr, "make_encrypted_dm: out of memory by 1 byte!\n"); 905 return 0; 906 } 907 908 ev->content = (const char*)cur.start; 909 ev->kind = kind; 910 911 if (!hex_encode(nostr_pubkey, 32, (char*)cur.p, cur.end - cur.p)) 912 return 0; 913 914 if (!nostr_add_tag(ev, "p", (const char*)cur.p)) { 915 fprintf(stderr, "too many tags\n"); 916 return 0; 917 } 918 919 cur.p += 65; 920 921 return 1; 922 } 923 924 static void try_subcommand(int argc, const char *argv[]) 925 { 926 static char buf[128] = {0}; 927 const char *sub = argv[1]; 928 if (strlen(sub) >= 1 && sub[0] != '-') { 929 snprintf(buf, sizeof(buf)-1, "nostril-%s", sub); 930 execvp(buf, (char * const *)argv+1); 931 } 932 } 933 934 935 int main(int argc, const char *argv[]) 936 { 937 struct args args = {0}; 938 struct nostr_event ev = {0}; 939 struct key key; 940 unsigned char *buf; 941 size_t bufsize; 942 secp256k1_context *ctx; 943 944 if (argc < 2) 945 usage(); 946 947 if (!init_secp_context(&ctx)) 948 return 2; 949 950 try_subcommand(argc, argv); 951 952 if (!parse_args(argc, argv, &args, &ev)) { 953 usage(); 954 return 10; 955 } 956 957 if (args.tags) { 958 ev.explicit_tags = args.tags; 959 } 960 961 make_event_from_args(&ev, &args); 962 963 if (args.sec) { 964 if (!decode_key(ctx, args.sec, &key)) { 965 return 8; 966 } 967 } else { 968 int *difficulty = NULL; 969 if ((args.flags & HAS_DIFFICULTY) && (args.flags & HAS_MINE_PUBKEY)) { 970 difficulty = &args.difficulty; 971 } 972 973 if (!generate_key(ctx, &key, difficulty)) { 974 fprintf(stderr, "could not generate key\n"); 975 return 4; 976 } 977 fprintf(stderr, "secret_key "); 978 print_hex(key.secret, sizeof(key.secret)); 979 fprintf(stderr, "\n"); 980 } 981 982 /* 8 MiB */ 983 bufsize = 2 << 22; 984 buf = malloc(bufsize); 985 986 if (args.flags & HAS_ENCRYPT) { 987 int kind = args.flags & HAS_KIND? args.kind : 4; 988 if (!make_encrypted_dm(ctx, &key, &ev, args.encrypt_to, kind)) { 989 fprintf(stderr, "error making encrypted dm\n"); 990 return 1; 991 } 992 } else if (args.flags & HAS_GIFTWRAP) { 993 if (!make_giftwrap(ctx, &key, &ev, args.encrypt_to, 994 buf, bufsize, args.flags & HAS_ENVELOPE)) { 995 fprintf(stderr, "error making encrypted dm\n"); 996 return 1; 997 } 998 return 0; 999 } 1000 1001 // set the event's pubkey 1002 memcpy(ev.pubkey, key.pubkey, 32); 1003 1004 if (args.flags & HAS_DIFFICULTY && !(args.flags & HAS_MINE_PUBKEY)) { 1005 if (!mine_event(&ev, args.difficulty, buf, bufsize)) { 1006 fprintf(stderr, "error when mining id\n"); 1007 return 22; 1008 } 1009 } else { 1010 if (!generate_event_id(&ev, buf, bufsize)) { 1011 fprintf(stderr, "could not generate event id\n"); 1012 return 5; 1013 } 1014 } 1015 1016 if (!sign_event(ctx, &key, &ev)) { 1017 fprintf(stderr, "could not sign event\n"); 1018 return 6; 1019 } 1020 1021 if (!print_event(&ev, args.flags & HAS_ENVELOPE, buf, bufsize)) { 1022 fprintf(stderr, "buffer too small\n"); 1023 return 88; 1024 } 1025 1026 free(buf); 1027 1028 return 0; 1029 } 1030