static int get_sha1_1(const char *name, int len, unsigned char *sha1) { int parent, ret; const char *cp; /* foo^[0-9] or foo^ (== foo^1); we do not do more than 9 parents. */ if (len > 2 && name[len-2] == '^' && name[len-1] >= '0' && name[len-1] <= '9') { parent = name[len-1] - '0'; len -= 2; } else if (len > 1 && name[len-1] == '^') { parent = 1; len--; } else parent = -1; if (parent >= 0) return get_parent(name, len, sha1, parent); /* "name~3" is "name^^^", * "name~12" is "name^^^^^^^^^^^^", and * "name~" and "name~0" are name -- not "name^0"! */ parent = 0; for (cp = name + len - 1; name <= cp; cp--) { int ch = *cp; if ('0' <= ch && ch <= '9') continue; if (ch != '~') parent = -1; break; } if (!parent && *cp == '~') { int len1 = cp - name; cp++; while (cp < name + len) parent = parent * 10 + *cp++ - '0'; return get_nth_ancestor(name, len1, sha1, parent); } ret = peel_onion(name, len, sha1); if (!ret) return 0; ret = get_sha1_basic(name, len, sha1); if (!ret) return 0; return get_short_sha1(name, len, sha1, 0); }
int main(int argc, char *argv[]) { secp256k1_context *ctx; struct onion onion; bool generate = false, decode = false; assert(EVP_CIPHER_iv_length(EVP_aes_128_ctr()) == sizeof(struct iv)); opt_register_noarg("--help|-h", opt_usage_and_exit, "--generate <pubkey>... OR\n" "--decode <privkey>\n" "Either create an onion message, or decode one step", "Print this message."); opt_register_noarg("--generate", opt_set_bool, &generate, "Generate onion through the given hex pubkeys"); opt_register_noarg("--decode", opt_set_bool, &decode, "Decode onion given the private key"); opt_register_version(); opt_parse(&argc, argv, opt_log_stderr_exit); ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); if (generate) { secp256k1_pubkey pubkeys[MAX_HOPS]; char *msgs[MAX_HOPS]; size_t i; if (argc == 1) opt_usage_exit_fail("Expected at least one pubkey"); if (argc-1 > MAX_HOPS) opt_usage_exit_fail("Expected at most %u pubkeys", MAX_HOPS); for (i = 1; i < argc; i++) { if (!parse_onion_pubkey(ctx, argv[i], &pubkeys[i-1])) errx(1, "Bad pubkey '%s'", argv[i]); msgs[i-1] = make_message(ctx, &pubkeys[i-1]); } if (!create_onion(pubkeys, msgs, argc - 1, &onion)) errx(1, "Creating onion packet failed"); if (!write_all(STDOUT_FILENO, &onion, sizeof(onion))) err(1, "Writing onion packet"); return 0; } else if (decode) { struct seckey seckey; secp256k1_pubkey pubkey; struct enckey enckey; struct iv pad_iv; if (argc != 2) opt_usage_exit_fail("Expect a privkey with --decode"); if (!hex_decode(argv[1], strlen(argv[1]), &seckey, sizeof(seckey))) errx(1, "Invalid private key hex '%s'", argv[1]); if (!secp256k1_ec_pubkey_create(ctx, &pubkey, seckey.u.u8)) errx(1, "Invalid private key '%s'", argv[1]); if (!read_all(STDIN_FILENO, &onion, sizeof(onion))) errx(1, "Reading in onion"); if (!decrypt_onion(&seckey, &onion, &enckey, &pad_iv)) errx(1, "Failed decrypting onion for '%s'", argv[1]); if (strncmp((char *)myhop(&onion)->msg, make_message(ctx, &pubkey), sizeof(myhop(&onion)->msg))) errx(1, "Bad message '%s'", (char *)myhop(&onion)->msg); if (!peel_onion(&onion, &enckey, &pad_iv)) errx(1, "Peeling onion for '%s'", argv[1]); if (!write_all(STDOUT_FILENO, &onion, sizeof(onion))) err(1, "Writing onion packet"); return 0; } else opt_usage_exit_fail("Need --decode or --generate"); secp256k1_context_destroy(ctx); return 0; }