Browse Source

sphinx: Using hop_data to serialize per-hop information into onion

Signed-off-by: Christian Decker <decker.christian@gmail.com>
ppa-0.6.1
Christian Decker 8 years ago
parent
commit
83e89f0fe5
  1. 52
      lightningd/sphinx.c
  2. 34
      lightningd/sphinx.h
  3. 5
      test/test_sphinx.c

52
lightningd/sphinx.c

@ -330,9 +330,35 @@ static struct hop_params *generate_hop_params(
return params;
}
static void serialize_hop_data(tal_t *ctx, u8 *dst, const struct hop_data *data)
{
u8 *buf = tal_arr(ctx, u8, 0);
towire_u8(&buf, data->realm);
towire_short_channel_id(&buf, &data->channel_id);
towire_u32(&buf, data->amt_forward);
towire_u32(&buf, data->outgoing_cltv);
towire_pad(&buf, 16);
towire(&buf, data->hmac, SECURITY_PARAMETER);
memcpy(dst, buf, tal_len(buf));
tal_free(buf);
}
static void deserialize_hop_data(struct hop_data *data, const u8 *src)
{
const u8 *cursor = src;
size_t max = HOP_DATA_SIZE;
data->realm = fromwire_u8(&cursor, &max);
fromwire_short_channel_id(&cursor, &max, &data->channel_id);
data->amt_forward = fromwire_u32(&cursor, &max);
data->outgoing_cltv = fromwire_u32(&cursor, &max);
fromwire_pad(&cursor, &max, 16);
fromwire(&cursor, &max, &data->hmac, SECURITY_PARAMETER);
}
struct onionpacket *create_onionpacket(
const tal_t *ctx,
struct pubkey *path,
struct hop_data hops_data[],
const u8 *sessionkey,
const u8 *assocdata,
const size_t assocdatalen
@ -340,7 +366,7 @@ struct onionpacket *create_onionpacket(
{
struct onionpacket *packet = talz(ctx, struct onionpacket);
int i, num_hops = tal_count(path);
u8 filler[2 * (num_hops - 1) * SECURITY_PARAMETER];
u8 filler[(num_hops - 1) * HOP_DATA_SIZE];
struct keyset keys;
u8 nextaddr[20], nexthmac[SECURITY_PARAMETER];
u8 stream[ROUTING_INFO_SIZE];
@ -353,22 +379,22 @@ struct onionpacket *create_onionpacket(
memset(nexthmac, 0, 20);
memset(packet->routinginfo, 0, ROUTING_INFO_SIZE);
generate_header_padding(filler, sizeof(filler), 2 * SECURITY_PARAMETER,
generate_header_padding(filler, sizeof(filler), HOP_DATA_SIZE,
"rho", 3, num_hops, params);
for (i = num_hops - 1; i >= 0; i--) {
memcpy(hops_data[i].hmac, nexthmac, SECURITY_PARAMETER);
generate_key_set(params[i].secret, &keys);
generate_cipher_stream(stream, keys.rho, ROUTING_INFO_SIZE);
/* Rightshift mix-header by 2*SECURITY_PARAMETER */
memmove(packet->routinginfo + 2 * SECURITY_PARAMETER, packet->routinginfo,
ROUTING_INFO_SIZE - 2 * SECURITY_PARAMETER);
memcpy(packet->routinginfo, nextaddr, SECURITY_PARAMETER);
memcpy(packet->routinginfo + SECURITY_PARAMETER, nexthmac, SECURITY_PARAMETER);
memmove(packet->routinginfo + HOP_DATA_SIZE, packet->routinginfo,
ROUTING_INFO_SIZE - HOP_DATA_SIZE);
serialize_hop_data(packet, packet->routinginfo, &hops_data[i]);
xorbytes(packet->routinginfo, packet->routinginfo, stream, ROUTING_INFO_SIZE);
if (i == num_hops - 1) {
size_t len = (NUM_MAX_HOPS - num_hops + 1) * 2 * SECURITY_PARAMETER;
size_t len = (NUM_MAX_HOPS - num_hops + 1) * HOP_DATA_SIZE;
memcpy(packet->routinginfo + len, filler, sizeof(filler));
}
@ -398,7 +424,7 @@ struct route_step *process_onionpacket(
struct keyset keys;
u8 blind[BLINDING_FACTOR_SIZE];
u8 stream[NUM_STREAM_BYTES];
u8 paddedheader[ROUTING_INFO_SIZE + 2 * SECURITY_PARAMETER];
u8 paddedheader[ROUTING_INFO_SIZE + HOP_DATA_SIZE];
step->next = talz(step, struct onionpacket);
step->next->version = msg->version;
@ -421,12 +447,12 @@ struct route_step *process_onionpacket(
compute_blinding_factor(&msg->ephemeralkey, shared_secret, blind);
if (!blind_group_element(&step->next->ephemeralkey, &msg->ephemeralkey, blind))
return tal_free(step);
memcpy(&step->next->nexthop, paddedheader, SECURITY_PARAMETER);
memcpy(&step->next->mac,
paddedheader + SECURITY_PARAMETER,
SECURITY_PARAMETER);
memcpy(&step->next->routinginfo, paddedheader + 2 * SECURITY_PARAMETER, ROUTING_INFO_SIZE);
deserialize_hop_data(&step->hop_data, paddedheader);
memcpy(&step->next->mac, step->hop_data.hmac, SECURITY_PARAMETER);
memcpy(&step->next->routinginfo, paddedheader + HOP_DATA_SIZE, ROUTING_INFO_SIZE);
if (memeqzero(step->next->mac, sizeof(step->next->mac))) {
step->nextcase = ONION_END;

34
lightningd/sphinx.h

@ -9,11 +9,12 @@
#include <ccan/tal/tal.h>
#include <secp256k1.h>
#include <sodium/randombytes.h>
#include <wire/wire.h>
#define SECURITY_PARAMETER 20
#define NUM_MAX_HOPS 20
#define HOP_DATA_SIZE 40
#define ROUTING_INFO_SIZE (HOP_DATA_SIZE * SECURITY_PARAMETER)
#define HOP_DATA_SIZE 53
#define ROUTING_INFO_SIZE (HOP_DATA_SIZE * NUM_MAX_HOPS)
#define TOTAL_PACKET_SIZE (1 + 33 + SECURITY_PARAMETER + ROUTING_INFO_SIZE)
struct onionpacket {
@ -34,23 +35,35 @@ enum route_next_case {
/* BOLT #4:
*
* The format of the per-hop-payload for a version 0 packet is as follows:
* The hops_data field is a structure that holds obfuscated versions of the next hop's address, transfer information and the associated HMAC. It is 1060 bytes long, and has the following structure:
```
+-----------+-------------+----------+-----------+-------------+----------+-----------+
| n_1 realm | n_1 per-hop | n_1 HMAC | n_2 realm | n_2 per-hop | n_2 HMAC | ...filler |
+-----------+-------------+----------+----------+--------------+----------+------------+
```
The realm byte determines the format of the per-hop; so far only realm 0 is defined, and for that, the per-hop format is:
```
+----------------+--------------------------+-------------------------------+--------------------------------------------+
| realm (1 byte) | amt_to_forward (8 bytes) | outgoing_cltv_value (4 bytes) | unused_with_v0_version_on_header (7 bytes) |
+----------------+--------------------------+-------------------------------+--------------------------------------------+
+----------------------+--------------------------+-------------------------------+--------------------+
| channel_id (8 bytes) | amt_to_forward (4 bytes) | outgoing_cltv_value (4 bytes) | padding (16 bytes) |
+----------------------+--------------------------+-------------------------------+--------------------+
```
*/
struct hoppayload {
struct hop_data {
u8 realm;
u64 amt_to_forward;
u32 outgoing_cltv_value;
u8 unused_with_v0_version_on_header[7];
struct short_channel_id channel_id;
u32 amt_forward;
u32 outgoing_cltv;
/* Padding omitted, will be zeroed */
u8 hmac[SECURITY_PARAMETER];
};
struct route_step {
enum route_next_case nextcase;
struct onionpacket *next;
struct hop_data hop_data;
};
/**
@ -69,6 +82,7 @@ struct route_step {
struct onionpacket *create_onionpacket(
const tal_t * ctx,
struct pubkey path[],
struct hop_data hops_data[],
const u8 * sessionkey,
const u8 *assocdata,
const size_t assocdatalen

5
test/test_sphinx.c

@ -131,6 +131,7 @@ int main(int argc, char **argv)
struct pubkey *path = tal_arr(ctx, struct pubkey, num_hops);
u8 privkeys[argc - 1][32];
u8 sessionkey[32];
struct hop_data hops_data[num_hops];
memset(&sessionkey, 'A', sizeof(sessionkey));
@ -141,9 +142,13 @@ int main(int argc, char **argv)
return 1;
}
for (i=0; i<num_hops; i++) {
memset(&hops_data[i], 'A', sizeof(hops_data[i]));
}
struct onionpacket *res = create_onionpacket(ctx,
path,
hops_data,
sessionkey,
assocdata,
sizeof(assocdata));

Loading…
Cancel
Save