sphinx: Add functions to decompress

Also implements a way to decompress an onion using the devtools/onion tool

Changelog-Added: devtools: The `onion` tool can now generate, compress and decompress onions for rendez-vous routing
This commit is contained in:
Christian Decker 2020-02-28 17:55:43 +01:00 committed by Rusty Russell
parent 4724d55e80
commit 49a3321d7e
3 changed files with 64 additions and 0 deletions

View File

@ -785,3 +785,27 @@ u8 *unwrap_onionreply(const tal_t *ctx,
return tal_free(final);
return final;
}
u8 *sphinx_decompress(const tal_t *ctx, const u8 *compressed,
struct secret *shared_secret)
{
size_t compressedlen = tal_bytelen(compressed);
size_t prefill_size = TOTAL_PACKET_SIZE - compressedlen;
u8 *dst;
int p = 0;
assert(prefill_size >= 0);
assert(compressedlen >= VERSION_SIZE + PUBKEY_SIZE + HMAC_SIZE);
dst = tal_arrz(ctx, u8, TOTAL_PACKET_SIZE);
write_buffer(
dst, compressed,
VERSION_SIZE + PUBKEY_SIZE + ROUTING_INFO_SIZE - prefill_size, &p);
/* We can just XOR here since we initialized the array with zeros. */
sphinx_prefill_stream_xor(dst + p, prefill_size, shared_secret);
p += prefill_size;
write_buffer(dst, compressed + compressedlen - HMAC_SIZE, HMAC_SIZE,
&p);
return dst;
}

View File

@ -246,6 +246,13 @@ u8 *serialize_compressed_onion(const tal_t *ctx,
bool sphinx_path_set_rendezvous(struct sphinx_path *sp,
const struct node_id *rendezvous_id);
/**
* Given a compressed onion expand it by re-generating the prefiller and
* inserting it in the appropriate place.
*/
u8 *sphinx_decompress(const tal_t *ctx, const u8 *compressed,
struct secret *shared_secret);
#if DEVELOPER
/* Override to force us to reject valid onion packets */
extern bool dev_fail_process_onionpacket;

View File

@ -290,6 +290,30 @@ static void runtest(const char *filename)
tal_free(ctx);
}
static void decompress(char *hexprivkey, char *hexonion)
{
struct privkey rendezvous_key;
size_t onionlen = hex_data_size(strlen(hexonion));
u8 *compressed, *decompressed;
struct pubkey ephkey;
struct secret shared_secret;
if (!hex_decode(hexprivkey, strlen(hexprivkey), &rendezvous_key, sizeof(rendezvous_key)))
errx(1, "Invalid private key hex '%s'", hexprivkey);
compressed = tal_arr(NULL, u8, onionlen);
if (!hex_decode(hexonion, strlen(hexonion), compressed, onionlen))
errx(1, "Invalid onion hex '%s'", hexonion);
if (onionlen < HMAC_SIZE + 1 + PUBKEY_SIZE)
errx(1, "Onion is too short to contain the version, ephemeral key and HMAC");
pubkey_from_der(compressed + 1, PUBKEY_SIZE, &ephkey);
decompressed = sphinx_decompress(NULL, compressed, &shared_secret);
printf("Decompressed Onion: %s\n", tal_hex(NULL, decompressed));
}
/* Tal wrappers for opt. */
static void *opt_allocfn(size_t size)
{
@ -353,6 +377,15 @@ int main(int argc, char **argv)
do_generate(argc, argv, assocdata, NULL);
else
do_generate(argc, argv, assocdata, &rendezvous_id);
} else if (streq(method, "decompress")) {
if (argc != 4) {
errx(2,
"'%s decompress' requires a private key and a "
"compressed onion",
argv[0]);
}
decompress(argv[2], argv[3]);
} else if (streq(method, "decode")) {
do_decode(argc, argv, assocdata);
} else {