2016-11-15 02:23:20 +01:00
# BOLT #4: Onion Routing Protocol
2016-11-14 20:42:56 +01:00
## Overview
This document describes the construction of an onion routed packet that is used to route a payment from a _origin node_ to a _final node_ , over a number of intermediate nodes, called _hops_ .
The routing schema is based on the
[Sphinx ](http://www.cypherpunks.ca/~iang/pubs/Sphinx_Oakland09.pdf )
construction, and is extended with a per-hop payload.
Intermediate nodes forwarding the message can verify the integrity of
the packet, and can learn about which node they should forward the
packet to. They cannot learn about which other nodes, besides their
predecessor or successor, are part of this route, nor can they learn
the length of the route and their position within it. The packet is
obfuscated at each hop, so that a network level attacker cannot
associate packets belonging to the same route, i.e., packets belonging
to a route do not share any identifying information. Notice that this
does not preclude the possibility to associate packets by performing a
traffic analysis.
The route is constructed by the sender, which knows a public key of
each intermediate node. Knowing the intermediate node's public key
allows the sender to create a shared secret using ECDH for each
intermediate node, including the final recipient. The shared secret is then
used to generate a _pseudo-random stream_ of bytes to obfuscate the
packet, and a number of _keys_ used to encrypt the payload and compute
HMACs ensuring integrity at each hop.
This specification describes version 0 of the packet format and
routing mechanism. Should a node receive a higher version packet that
it does not implement it MUST report a route failure to the sending
node and discard the packet.
## Conventions
2016-12-07 10:04:57 +01:00
There are a number of conventions we will adhere to throughout the document:
2016-11-14 20:42:56 +01:00
- The maximum route length is limited to 20 hops.
- Nodes are addressed using 20 byte identifiers. These are computed
from the node's public key, in accordance to the Bitcoin address
creation, as `RIPEMD160(SHA256(pubkey))` where `pubkey` is the
serialized compressed public key of the node. Refer to
[`OP_HASH160` ](https://en.bitcoin.it/wiki/Script#Crypto ) for
details.
2016-12-11 11:44:07 +01:00
- HMAC: the integrity verification of the packet is based on Keyed-Hash Message Authentication Code as defined by the [FIPS 198 Standard ](http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf )/[RFC 2104](https://tools.ietf.org/html/rfc2104), using `SHA256` as hashing algorithm.
2016-11-14 20:42:56 +01:00
The resulting HMAC is then truncated at 20 bytes in order to reduce the overhead.
- Elliptic Curve: for all computations involving elliptic curves, the
Bitcoin curve, [`secp256k1` ](http://www.secg.org/sec2-v2.pdf ), is used.
- Pseudo-Random Stream: [`ChaCha20` ](https://tools.ietf.org/html/rfc7539 ) is used to generate a pseudo-random byte stream.
For the generation we use a fixed null-nonce (`0x0000000000000000`), a key derived from a shared secret and a `0x00` -byte stream of the desired output size as message.
- We use the terms _hop_ and _node_ interchangeably.
- A _peer_ is a direct neighbor of the processing node in the overlay network.
## Key Generation
2016-12-07 10:04:57 +01:00
A number of encryption and verification keys are derived from the shared secret:
2016-11-14 20:42:56 +01:00
2016-12-08 07:54:35 +01:00
- _rho_: used as key when generating the pseudo-random byte stream
2016-11-14 20:42:56 +01:00
used to obfuscate the routing information.
2016-12-08 07:54:35 +01:00
- _gamma_: used as key when generating the pseudo-random byte stream used to obfuscate the per-hop payloads.
2016-11-14 20:42:56 +01:00
- _mu_: used during the HMAC generation.
The key generation takes a key-type (_rho_=`0x72686F`, _gamma_ =`0x67616d6d61` or _mu_ =`0x6d75`) and a 32 byte secret as inputs and returns a 32 byte key.
Keys are generated by computing an HMAC, with `SHA256` as hashing algorithm, using the key-type, i.e., _rho_ , _mu_ or _gamma_ , as HMAC-key and the 32 byte shared secret as the message.
The resulting HMAC is then returned as the key.
Notice that the key-type does not include a C-style `0x00` termination-byte, e.g., the length of the _gamma_ key-type is 5 bytes, not 6.
## Pseudo Random Byte Stream
2016-12-08 07:54:35 +01:00
The pseudo-random byte stream is used to obfuscate the packet at each hop of the path, so that each hop may only recover the address of the next hop as well as the HMAC for the next hop.
The pseudo-random byte stream is generated by encrypting a `0x00` -byte stream of the required length with `ChaCha20` , initialized with a key derived from the shared secret and a zero-nonce (`0x00000000000000`).
2016-11-14 20:42:56 +01:00
The use of a fixed nonce is safe since the keys are never reused.
## Packet Structure
The packet consists of 2 parts:
- The fixed size _header_ containing meta information about the
packet and the routing information necessary to forward the
message.
- A fixed size _per-hop payload_ containing information for each hop
as they forward the message.
The overall structure of the packet is depicted below. The network format of the packet consists of the individual parts being serialized into one continguous byte-stream and then transferred to the recipient of the packet. Due to the fixed size of the packet it does not need to be prefixed by its length when transferred over a connection.
~~~~
+--------+-----------------+
| header | per-hop payload |
+--------+-----------------+
~~~~
The header is a fixed 854 byte array containing the necessary information for each hop to identify the next hop, and verify the integrity of the packet.
2016-12-07 10:04:57 +01:00
It consists of a version byte, a 33 byte compressed `secp256k1` public key, used during the shared secret generation, a 20 byte HMAC used to verify the packet's integrity and an 800 byte routing information field.
2016-11-14 20:42:56 +01:00
For this specification the version byte has a constant value of `0x00` .
~~~~
+------------------+-----------------------+-----------------+------------...-----------+
| Version (1 byte) | Public Key (33 bytes) | HMAC (20 bytes) | Routing Info (800 bytes) |
+------------------+-----------------------+-----------------+------------...-----------+
~~~~
The routing info field is a structure that holds obfuscated versions of the next hop's address and the associated HMAC.
It is 800 bytes long, i.e., 20 byte MAC and 20 byte address times 20 hops, and has the following structure:
~~~~
+-------------+----------+-------------+----------+-----+--------+
| n_1 address | n_1 HMAC | n_2 address | n_2 HMAC | ... | filler |
+-------------+----------+-------------+----------+-----+--------+
~~~~
Where the `filler` consists of obfuscated deterministically generated
padding. For details about how the `filler` is generated please see
2016-12-07 10:04:57 +01:00
below. In addition, every _(address, HMAC)_ -pair is incrementally
2016-11-14 20:42:56 +01:00
obfuscated at each hop.
The per-hop payloads has a similar structure:
~~~~
+-------------+-------------+-------------+-----+------------+
| n_1 payload | n_2 payload | n_3 payload | ... | hop filler |
+-------------+-------------+-------------+-----+------------+
~~~~
With the `hopfiller` being constructed in the same way as the routing
info `filler` and each payload being incrementally obfuscated at each
hop.
2016-12-20 01:24:42 +01:00
### Per Hop Payload Format
Using the per-hop-payload, the sender is able to precisely specify the path and
structure of the HTLC's forwarded at each hop. As the per-hop-payload is
protected under the packet-wide HMAC, the information within the
per-hop-payload is fully authenticated with each pair-wise relationship between
the HTLC sender, and each intermediate node in the path. Using this end-to-end
authentication, forwarding nodes are able to ensure that the incoming node
didn't forward an ill-crafted HTLC by cross-checking the HTLC parameters with
the values as specified within the per-hop-payload.
The format of the per-hop-payload for a version 0 packet is as follows:
```
+----------------+--------------------------+-------------------------------+--------------------------------------------+
2017-01-06 00:26:11 +01:00
| realm (1 byte) | amt_to_forward (8 bytes) | outgoing_cltv_value (2 bytes) | unused_with_v0_version_on_header (9 bytes) |
2016-12-20 01:24:42 +01:00
+----------------+--------------------------+-------------------------------+--------------------------------------------+
```
Field Description:
* `realm` - The realm (chain) link that the outgoing HTLC should be forwarded
on. Within a version 0 packet, this field currently carries no meaning as
cross-chain forwarding has not yet been fully specified.
* `amt_to_forward` - The amount in milli-satoshi to forward to the next
(outgoing) hop specified within the routing information.
This value MUST factor in the computed fee for this particular hop. When
processing an incoming Sphinx packet along with the HTLC message it's
encapsulated within, if the following inequality doesn't hold, then the
HTLC should be rejected as it indicates a prior node in the path has
deviated from the specified paramters:
incoming_htlc_amt - fee >= amt_to_forward
Where `fee` is calculated according to the receving node's advertised fee
schema as described in [BOLT 7 ](https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md#htlc-fees ).
2017-01-06 00:26:11 +01:00
* `outgoing_cltv_value` - The CLTV value that the _outgoing_ HTLC carrying
2016-12-20 01:24:42 +01:00
the packet should have.
2017-01-06 00:26:11 +01:00
cltv-expiry - cltv-expiry-delta = outgoing_cltv_value
Inclusion of this field allows a node to both authenticate the information
specified by the original sender and the paramaters of the HTLC forwarded,
and ensure the original sender is using the current `cltv-expiry-delta` value.
2016-12-20 01:24:42 +01:00
If the values don't correspond, then the HTLC should be failed+rejected as
2017-01-06 00:26:11 +01:00
this indicates the incoming node has tampered with the intended HTLC
values, or the origin has an obsolete `cltv-expiry-delta` value.
2016-12-20 01:24:42 +01:00
Nodes forwarding HTLC's MUST construct the outgoing HTLC as specified within
the per-hop-payload. Otherwise, deviation from the specified HTLC parameters
may lead to extraneous routing failure.
2016-11-14 20:42:56 +01:00
## Packet Construction
Assuming a _sender node_ `n_0` wants to route a packet to a _final recipient_ `n_r` .
The sender computes a route `{n_0, n_1, ..., n_{r-1}, n_r}` , where `n_0` is the sender itself and `n_r` is the final recipient.
The nodes `n_i` and `n_{i+1}` MUST be peers in the overlay network.
The sender gathers the public keys for `n_1` to `n_r` and generates a random 32 byte `sessionkey` .
Optionally the sender may pass in _associated data_ , i.e., data that the packet commits to, but is not included in the packet itself.
Associated data will be included in the HMACs and has to match the associated data provided during integrity verification at each hop.
For each node the sender computes an _ephemeral public key_ , a _shared secret_ and a _blinding factor_ .
The blinding factor is used at each hop to blind the ephemeral public key for the next hop.
The node receiving the header will perform ECDH with the ephemeral public key and its private key to derive the same shared secret.
However, when generating the packet we do not have access to the node's private key.
Hence, we use the commutative property of multiplication and blind the node's public key with all previous blinding factors and perform ECDH using the node's blinded public key and the `sessionkey` .
The transformations at hop `k` are given by the following:
- The shared secret `ss_k` is computed by first blinding the node's public key `nodepk_k` with all previous blinding factors `{b_1, ..., b_{k-1}}` , if any, and then executing ECDH with the blinded public key and the `sessionkey` .
- The blinding factor is the `SHA256` hash of the concatenation between the node's public key `nodepk_k` and the hop's shared secret `ss_k` .
Before concatenation the node's public key is serialized in the compressed format.
- The ephemeral public key `epk_k` is computed by blinding the previous hop's ephemeral public key `epk_{k-1}` with the previous hop's blinding factor `b_{k-1}` .
This recursive algorithm is initialized by setting the first hop's (`k=1`) ephemeral public key to the public key corresponding with the `sessionkey` , i.e., `secp256k1` is used to derive a public key for the randomly selected `sessionkey` .
The sender then iteratively computes the ephemeral public keys, shared secrets and blinding factors for nodes `{n_2, ..., n_r}` .
Once the sender has all the required information it can construct the packet.
Constructing a packet routed over `r` hops requires `r` 32 byte ephemeral public keys, `r` 32 byte shared secrets, `r` 32 byte blinding factors and `r` 20 byte per-hop payloads.
The construction returns one 1254 byte packet and the first hop's address.
The packet construction is performed in reverse order of the route, i.e., the last hop's operations are applied first.
The per-hop payload is initialized with 400 `0x00` bytes.
The routing info is initialized with 800 `0x00` bytes.
The next address and the HMAC are initialized to 20 `0x00` bytes each.
Two fillers are generated with the shared secrets: a routing info filler with 40 byte hopsize and a per-hop payload filler with 20 byte hopsize.
See below for details on filler generation.
For each hop in the route in reverse order the sender applies the
following operations:
- It generates a _rho_ -key, _mu_ -key and a _gamma_ -key using the hop's shared secret.
- The routing info field is right-shifted by 40 bytes, discarding the last 40 bytes that exceed the 800 bytes.
The address is copied into the first 20 bytes of the routing info and the HMAC is copied into
the following 20 bytes.
2016-12-08 07:54:35 +01:00
The _rho_ -key is used to generate 800 bytes of pseudo-random byte stream and applied with `XOR` to the routing info field.
2016-11-14 20:42:56 +01:00
Should this be the last hop, i.e., the first iteration, then the tail of the routing info field is overwritten with the routing info `filler` .
- The per-hop payload field is right-shifted by 20 bytes, and the last 20 bytes discarded, resulting in 400 bytes of per-hop payload.
The current hop's per-hop payload is copied into the first 20 bytes.
2016-12-08 07:54:35 +01:00
The _gamma_ -key is used to generate 400 bytes of pseudo-random byte stream which are then applied using `XOR` to the per-hop payloads field.
2016-11-14 20:42:56 +01:00
Should this be the last hop then the tail of the per-hop payloads field is overwritten with the per-hop payload filler.
- The next HMAC is computed over the concatenated routing info, per-hop payload and associated data, with the _mu_ -key as HMAC-key.
- The next address is computed from the current node's public key using the Bitcoin address hash derivation.
The final value for the HMAC is the HMAC as it should be sent to the first hop.
The packet generation returns the serialized packet, consisting of the version byte, the ephemeral pubkey for the first hop, the HMAC for the first hop, the obfuscated routing info and the obfuscated per-hop payload.
The following code implements the packet construction in Go:
```Go
func ConstructPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey,
rawHopPayloads [][]byte) ([]byte) {
numHops := len(paymentPath)
ephemeralpks := make([]*btcec.PublicKey, numHops)
sharedsecrets := make([][sha256.Size]byte, numHops)
blindingfactors := make([][sha256.Size]byte, numHops)
ephemeralpks[0] = sessionKey.PubKey()
sharedsecrets[0] = sha256.Sum256(btcec.GenerateSharedSecret(sessionKey, paymentPath[0]))
blindingfactors[0] = computeBlindingFactor(ephemeralpks[0], sharedsecrets[0][:])
for i := 1; i < = numHops-1; i++ {
ephemeralpks[i] = blindGroupElement(ephemeralpks[i-1], blindingfactors[i-1][:])
bpk := blindGroupElement(paymentPath[i], sessionKey.D.Bytes())
sharedsecrets[i] = sha256.Sum256(multiScalarMult(bpk, blindingfactors[:i]).X.Bytes())
blindingfactors[i] = computeBlindingFactor(ephemeralpks[i], sharedsecrets[i][:])
}
filler := generate_filler("rho", numHops, 2*20, sharedsecrets)
hopfiller := generate_filler("gamma", numHops, 20, sharedsecrets)
// Initialize all of these to 0x00-arrays
var header [20 * 40]byte
var hoppayloads [20 * 20]byte
var next_hmac [20]byte
var next_address [20]byte
// Compute header in reverse path order
for i := numHops - 1; i >= 0; i-- {
rhoKey := generateKey("rho", sharedsecrets[i])
gammaKey := generateKey("gamma", sharedsecrets[i])
piKey := generateKey("pi", sharedsecrets[i])
muKey := generateKey("mu", sharedsecrets[i])
// Shift and obfuscate header
stream := generateStream(rhoKey, numStreamBytes)
rightShift(header[:], 2*20)
copy(header[:], next_address[:])
copy(header[20:], next_hmac[:])
xor(header[:], header[:], streamBytes[:routingInfoSize])
// Shift and obfuscate per-hop payload
stream = generateStream(gammaKey, uint(len(hoppayloads)))
rightShift(hoppayloads[:], 20)
copy(hoppayloads[:], rawHopPayloads[i])
xor(hoppayloads[:], hoppayloads[:], hopStreamBytes)
// Add fillers if this is the last hop
if i == numHops-1 {
copy(header[len(header)-len(filler):], filler)
copy(hoppayloads[len(hoppayloads)-len(hopfiller):], hopfiller)
}
cipher, _ := chacha20.New(piKey[:], bytes.Repeat([]byte{0x00}, 8))
next_hmac = ComputeMac(muKey, append(append(header[:], hoppayloads[:]...), onion[:]...))
next_address = btcutil.Hash160(paymentPath[i].SerializeCompressed())
}
// Assemble packet
var packet [2258]byte
version = []byte{0x00}
copy(packet[:], version)
copy(packet[1:], ephemeralpks[0].SerializeCompressed())
copy(packet[34:], next_hmac)
copy(packet[54:], header)
copy(packet[854:], hoppayloads)
return packet
}
```
## Packet Forwarding
2016-12-07 10:04:57 +01:00
Upon receiving a packet, a node compares the version byte of the packet with its supported versions and aborts otherwise.
This specification is limited to version `0` packets and the structure of future versions may change.
2016-11-14 20:42:56 +01:00
The receiving node then splits the packet into its fields.
The node MUST check that the ephemeral public key is on the `secp256k1` curve.
Should this not be the case the node MUST abort processing the packet and report a route failure to the sender.
The node then computes the shared secret as described below, using the private key corresponding to its public key and the ephemeral key from the packet.
The node MUST keep a log of previously used shared secrets.
Should the shared secret already be in the log it MUST abort processing the packet and report a route failure, since this is likely a replay attack, otherwise the shared secret is added to the log.
The shared secret is used to compute a _mu_ -key. The node then computes the HMAC of the packet, starting from byte 54, which corresponds to the routing info, per-hop payloads and associated data, using the _mu_ -key.
The resulting HMAC is compared with the HMAC from the packet.
Should the computed HMAC and the HMAC from the packet differ then the node MUST abort processing and report a route failure.
Comparison of the computed HMAC and the HMAC from the packet MUST be time-constant to avoid leaking information.
At this point the node can generate a _rho_ -key and a _gamma_ -key.
The routing info is deobfuscated and the information about the next hop is extracted.
2016-12-08 07:54:35 +01:00
In order to do so the node copies the routing info field, appends 40 `0x00` bytes and generates 840 pseudo-random bytes using the _rho_ -key and applies it using `XOR` to the copy of the routing information.
2016-11-14 20:42:56 +01:00
The first 20 bytes of the resulting routing info are the address of the next hop, followed by the 20 byte HMAC.
The routing info for the outgoing packet, destined for the next hop, consists of the 800 bytes starting at byte 40.
The per-hop payload is deobfuscated in a similar way.
The node creates a copy of the per-hop payloads field and appends 20 `0x00` bytes of padding.
2016-12-08 07:54:35 +01:00
It generates 420 bytes of pseudo-random bytes using the _gamma_ -key and applies it using `XOR` to the padded copy of the per-hop payloads.
2016-11-14 20:42:56 +01:00
The first 20 bytes of the padded copy are the node's per-hop payload, while the remaining 400 bytes are the per-hop payload destined for the next hop.
A special HMAC value of 20 `0x00` bytes indicates that the currently processing hop is the intended recipient and that the packet should not be forwarded.
Should the HMAC not indicate route termination and the next hop be a peer of the current node, then the new packet is assembled by blinding the ephemeral key with the current node's public key and shared secret, and serializing the routing info and per-hop payload.
The resulting packet is then forwarded to the addressed peer.
The addressed peer MUST be a direct neighbor of the node processing the packet.
Should the processing node not have a peer with the matching address, then it MUST drop the packet and signal a route failure.
## Shared secret
The sender performs ECDH with each hop of the route in order to establish a secret.
For each message a new _sessionkey_ is generated.
The sessionkey is a 32 byte EC private key.
The shared secret creation receives a public key and a 32 byte secret as input and returns a 32 byte secret as output.
In the packet generation phase the secret is the `sessionkey` and the public key is the node's public key, blinded with all previous blinding factors.
In the pocessing phase the secret is the node's private key and the public key is the ephemeral public key from the packet, which has been incrementally blinded by the predecessors.
The public key is multiplied by the secret, using to the `secp256k1` curve.
2016-12-12 01:11:45 +01:00
The DER compressed representation of the multiplication result is serialized and hashed using `SHA256` .
2016-11-14 20:42:56 +01:00
The resulting hash is returned as the shared secret.
2016-12-12 01:11:45 +01:00
Notice that this is the ECDH variant implemented in `libsecp256k1` .
2016-11-14 20:42:56 +01:00
## Filler Generation
2016-12-07 10:04:57 +01:00
Upon receiving a packet, each node extracts the information destined for that node from the route info and the per-hop payload.
2016-11-14 20:42:56 +01:00
The extraction is done by deobfuscating and left-shifting the field.
This would make the field shorter at each hop, allowing an attacker to deduce the route length.
For this reason the field is padded before forwarding.
Since the padding is part of the HMAC the sender will have to generate an identical padding in order to compute the HMACs correctly for each hop.
The filler is also used to pad the field-length in case the selected route is shorter than the maximum allowed route length.
We call the number of bytes extracted from the field _hopsize_ .
In case of the route info the hopsize is 40 bytes (20 bytes address and 20 bytes HMAC), while in the case of the per-hop payload it is 20 bytes.
2016-12-07 10:04:57 +01:00
Before deobfuscating the field, the node pads the field with hopsize `0x00` bytes, such that the total length of the field is `(20 + 1) * hopsize` .
2016-12-08 07:54:35 +01:00
It then generates the pseudo-random byte stream of matching length and applies it with `XOR` to the field.
2016-11-14 20:42:56 +01:00
This deobfuscates the information destined for it, and simultaneously obfuscates the added
`0x00` -bytes at the end.
In order to compute the correct HMAC, the sender has to generate the field's state at the hop.
This also includes the incrementally obfuscated padding added by each hop.
The incrementally obfuscated padding is called the _filler_ .
The following code shows how the filler is generated:
```Go
func generateFiller(key string, numHops int, hopSize int, sharedSecrets [][sharedSecretSize]byte) []byte {
fillerSize := uint((numMaxHops + 1) * hopSize)
filler := make([]byte, fillerSize)
// The last hop does not obfuscate, it's not forwarding anymore.
for i := 0; i < numHops-1 ; i + + {
// Left-shift the field
copy(filler[:], filler[hopSize:])
// Zero-fill the last hop
copy(filler[len(filler)-hopSize:], bytes.Repeat([]byte{0x00}, hopSize))
2016-12-08 07:54:35 +01:00
// Generate pseudo-random byte stream
2016-11-14 20:42:56 +01:00
streamKey := generateKey(key, sharedSecrets[i])
streamBytes := generateCipherStream(streamKey, fillerSize)
// Obfuscate
xor(filler, filler, streamBytes)
}
// Cut filler down to the correct length (numHops+1)*hopSize
// bytes will be prepended by the packet generation.
return filler[(numMaxHops-numHops+2)*hopSize:]
}
```
Notice that this implementation is for demonstration purposes only, the filler can be generated much more efficiently.
The last hop does not obfuscate the filler since it will not forward the packet and will not extract an HMAC for any followup hops.
## Blinding EC Points
In order to vary the ephemeral public key (the EC point) between hops, it is blinded at each hop.
The inputs for the blinding process are the EC point to be blinded, the node's public key and a 32 byte shared secret, while the output is a single EC point, representing the blinded element.
Blinding is done by computing a blinding factor from the node's public key and the shared secret for that hop.
The blinding factor is the result of serializing the node's public key into its compressed format, appending the shared secret and computing the `SHA256` hash.
The blinded EC point then is the result of the scalar multiplication between the EC point and the blinding factor.
2017-01-06 00:24:11 +01:00
## Returning Errors
2016-11-14 20:42:56 +01:00
2017-01-06 00:24:11 +01:00
The protocol includes a simple mechanism to return encrypted error messages to the origin node.
The returned messages may either be failures reported by any intermediate hop, or the final node.
The format of the forward packet is not usable for the return path, since no node other than the origin has the required information. Note that these error messages are not reliable, as they are not placed on-chain in the case of node failure.
2016-11-14 20:42:56 +01:00
2017-01-06 00:24:11 +01:00
Intermediate hops store the shared secret from the forward path and reuse it to obfuscate the error packet on each hop.
2016-11-14 20:42:56 +01:00
In addition each node locally stores the previous hop it received the forward packet from, in order to determine where to send an eventual return packet.
The node returning the message builds a return packet consisting of the following fields:
2017-01-06 00:26:44 +01:00
1. data:
* [20:hmac]
* [4:failure-code]
* [2:additional-len]
* [additional-len:additional]
* [2:pad-len]
* [pad-len:pad]
Where `hmac` is an HMAC authenticating the remainder of the packet, with a key using the above key generation with key type "_um_", `failure-code` and `additional` are defined below, and `pad` as extra bytes to conceal length.
2017-01-06 00:26:44 +01:00
The node SHOULD set `pad` such that the `additional length` plus `pad length` is equal to 128.
This is 30 bytes longer than then the longest currently-defined message.
2016-11-14 20:42:56 +01:00
The node then generates a new key, using the key type `ammag` .
2017-01-06 00:26:44 +01:00
This key is then used to generate a pseudo-random stream, which is then applied to the packet using `XOR` .
2016-11-14 20:42:56 +01:00
The obfuscation step is repeated by every node on the return path.
Upon receiving a packet the node will generate its `ammag` , generate the pseudo-random byte stream and apply it to the packet before forwarding.
The origin node detects that it is the final hop of the return message since it was the origin of the corresponding forward packet.
Having the shared secrets of all intermediate nodes it can unwrap the packet until the HMAC is a valid HMAC for the packet, which also identifies the sender of the return message.
The association between forward and return packet is handled outside of the protocol, e.g., by association to an HTLC in a payment channel.
2016-11-22 20:52:59 +01:00
2017-01-06 00:26:44 +01:00
### Failure Codes
The following `failure-code` values are supported. A node MUST select one of
these codes when creating an error message, and MUST include the
appropriate `additional` data.
In the case of more than one error, a node SHOULD select the first one
listed.
The top byte of `failure-code` can be read as a set of flags:
* 0x80000000 (BADONION): unparsable onion, encrypted by previous node.
* 0x40000000 (PERM): permanent failure (otherwise transient)
* 0x20000000 (NODE): node failure (otherwise channel)
* 0x10000000 (UPDATE): new channel update enclosed
Any node MAY return one of the following errors:
If the realm byte is unknown:
1. type: PERM|1 (`invalid_realm`)
If an otherwise unspecified transient error occurs for the entire
node:
1. type: NODE|2 (`temporary_node_failure`)
If an otherwise unspecified permanent error occurs for the entire
node:
1. type: PERM|NODE|2 (`permanent_node_failure`)
If a node has requirement advertised in its `node_announcement`
`features` which were not present in the onion:
1. type: PERM|NODE|3 (`required_node_feature_missing`)
A forwarding node MAY return one of the following errors, the final
node MUST NOT:
If the onion version byte is unknown:
1. type: BADONION|PERM|4 (`invalid_onion_version`)
2. data:
* [32:sha256-of-onion]
If the onion HMAC is incorrect:
1. type: BADONION|PERM|5 (`invalid_onion_hmac`)
2. data:
* [32:sha256-of-onion]
If the ephemeral key in the onion is unparsable:
1. type: BADONION|PERM|6 (`invalid_onion_key`)
2. data:
* [32:sha256-of-onion]
If an otherwise unspecified transient error occurs for the outgoing
channel (eg. peer unresponsive, channel capacity reached):
1. type: 7 (`temporary_channel_failure`)
If an otherwise unspecified permanent error occurs for the outgoing
channel (eg. channel (recently) closed):
1. type: PERM|8 (`permanent_channel_failure`)
If the outgoing channel has requirement advertised in its
`channel_announcement` `features` which were not present in the onion:
1. type: PERM|9 (`required_channel_feature_missing`)
If the next peer specified by the onion is not known:
1. type: PERM|10 (`unknown_next_peer`)
If the HTLC does not reach the current minimum amount, we tell them
the amount of the incoming HTLC and the current channel setting for
the outgoing channel:
1. type: UPDATE|11 (`amount_below_minimum`)
2. data:
* [4:htlc-msat]
* [2:len]
* [len:channel_update]
If the HTLC does not pay sufficient fee, we tell them the amount of
the incoming HTLC and the current channel setting for the outgoing
channel:
1. type: UPDATE|12 (`fee_insufficient`)
2. data:
* [4:htlc-msat]
* [2:len]
* [len:channel_update]
If `outgoing_cltv_value` does not match the`update_add_htlc`'s
`cltv-expiry` minus `cltv-expiry-delta` for the outgoing channel, we
tell them the `cltv-expiry` and the current channel setting for the
outgoing channel:
1. type: UPDATE|13 (`incorrect_cltv_expiry`)
2. data:
* [4:cltv-expiry]
* [2:len]
* [len:channel_update]
If the ctlv-expiry is too near, we tell them the the current channel
setting for the outgoing channel:
1. type: UPDATE|14 (`expiry_too_soon`)
2. data:
* [2:len]
* [len:channel_update]
The final node may return one of the following errors, intermediate
nodes MUST NOT:
If the payment hash has already been paid, the final node MAY treat
the payment hash as unknown, or may succeed in accepting the HTLC.
If the payment hash is unknown, the final node MUST fail the HTLC:
1. type: PERM|15 (`unknown_payment_hash`)
If the amount paid is less than the amount expected, the final node
MUST fail the HTLC. If the amount paid is more than the amount
expected, the final node SHOULD fail the HTLC:
1. type: PERM|16 (`incorrect_payment_amount`)
If the `cltv-expiry` is too low, the final node MUST fail the HTLC:
1. type: 17 (`final_expiry_too_soon`)
### Receiving Failure Codes
If node sending the error is the final node:
* If the PERM bit is set, the origin node SHOULD fail the payment,
otherwise it MAY retry the payment if the error code is understood
and valid. (In particular, `final_expiry_too_soon` can occur if the
block height has changed since sending, `temporary_node_failure`
could resolve within a few seconds).
Otherwise, the node sending the error is an intermediate node:
* If the NODE bit is set, the origin node SHOULD remove all channels
connected with the sending node from consideration.
* If the PERM bit is not set, the origin node SHOULD restore the
channels as it sees new `channel_update` s.
* Otherwise, if UPDATE is set, and the `channel_update` is valid
and more recent than the `channel_update` used to send the payment:
* The origin node MAY treat the `channel_update` as invalid if it
should not have caused the failure.
* Otherwise, the origin node SHOULD apply the `channel_update` .
* The origin node MAY queue the `channel_update` for broadcast.
* Otherwise, the origin node SHOULD eliminate the channel outgoing
from the sending node from consideration.
* If the PERM bit is not set, the origin node SHOULD restore the
channel as it sees a new `channel_update` .
* The origin node SHOULD then retry routing and sending the payment.
The origin node MAY use the data specified in the various types of
failure for debugging purposes.
2017-01-10 15:33:34 +01:00
## Test Vector
### Packet Creation
The following is an in-depth trace of the packet creation, including intermediate data.
#### Parameters
pubkey[0] 0x02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619
pubkey[1] 0x0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c
pubkey[2] 0x027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007
pubkey[3] 0x032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991
pubkey[4] 0x02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145
nhops = 5/20
sessionkey = 0x4141414141414141414141414141414141414141414141414141414141414141
associated data = 0x4242424242424242424242424242424242424242424242424242424242424242
hop_payload[0] = 0x4141414141414141414141414141414141414141
hop_payload[1] = 0x4141414141414141414141414141414141414141
hop_payload[2] = 0x4141414141414141414141414141414141414141
hop_payload[3] = 0x4141414141414141414141414141414141414141
hop_payload[4] = 0x4141414141414141414141414141414141414141
#### Per-Hop Information
hop_shared_secret[0] = 0xa6254636b0f9fe6a871ef7057de6b1fa0f31e6f0e46990747fda49f7871a9f1f
hop_blinding_factor[0] = 0xba28bc80518475b45dbfd34b7913aadfa0cadb50dfaa6e60dfe4b139464a85a7
hop_ephemeral_pubkey[0] = 0x02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619
hop_shared_secret[1] = 0x9f92cb2d7183bdf6c5384474f3d4d288cd2777a131e80a3fa75ac1b86126c1b7
hop_blinding_factor[1] = 0xcf33098d43f7d135a2f8d49261c6cdb671ed94a51bfe80985cc2bcce5ef2d9ce
hop_ephemeral_pubkey[1] = 0x03ae8f827ad6ae3ee63f5871faecc87d3bc34150ab9749397c7b7e08e2441c7009
hop_shared_secret[2] = 0xc6a3a735ab50268046065c4c276250a27a3add7702229ef0441c2e18df039dd7
hop_blinding_factor[2] = 0xaf93c41ddc218beb558b73b94380b4659341aa2dfb628114ce321f703e8e1415
hop_ephemeral_pubkey[2] = 0x02bf096c11288d38b28dfa18ec1827b3188f9fbf26282b7e1319f3dcc01eeed730
hop_shared_secret[3] = 0x3356733c8f96d15c95790e9e231d5ce512ff52bb02beb97d0fef1d025c183c15
hop_blinding_factor[3] = 0x8b0e2106c0fca2438c3e88b651f806f8d98cd9ae1cb53cea0e96e0bd349c9ec8
hop_ephemeral_pubkey[3] = 0x03af0a99d58a5107ed64d83345be1085966f884a18aeed088ba0b8d61cda1624e2
hop_shared_secret[4] = 0x59c454311fac6557dc7d78b733206c328d42b1a224b3d46af979216426c22a07
hop_blinding_factor[4] = 0x8a5b28754ac5394a7b4e080a4f9054a2528fd1ef3d0e79eef5c2a3c10c647278
hop_ephemeral_pubkey[4] = 0x027cb8f0151cfe8ece72d2dc8bbf70640ea34b1aaa604e0876186815e069a831d4
#### Per-Packet Information
filler = 0x92a8972e27719cff74818e2b68fe95a69d4c4e9e9263721d9cab974352a9064246406a8065e9f54960c730081f9fb7a2b82ed439507411a94b24429340cb4954c69a39da48ad8a63de960894aab5f4665b54bc8eba0bdcec31d150a69a46c2da6564d70aaa0d71b44a187006ae7ae82b6818971d2fbc6c0cc599912826d150926c9983c4809ba079abf3148d35a2bc38d86d83aa003ecd7cd45400da3a03648f
hop_filler = 0xb0940f21b1c76ac7940f88da48bda8b71880e6236249e99895f97b315dfcbd753276019f706a6ebaf15c5c6eaaca13565aa018befaed4afb7a166ce38a32a6e49507a4152d895977f3b4a680637360e0
#### Wrapping the Onion
rhokey[4] = 0x90669bfa9efe512777213daab9afc13b024d8b8760448bf1e7ff30e96be8e5f2
gammakey[4] = 0x7f2855c90fda9c28653c132780ad71c3c3f700b7b40bdd8baa3b6bf224c86d5a
mukey[4] = 0x9876c95638345dbad8bdfb986f5ec8b5c096ab7b18d7935c372a13484c2efbc6
routing_info[4] (unencrypted) = 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
routing_info[4] (encrypted) = 0xc04ad1e406ca69c8ab4951f70aed589da7916d85c0d0bd8ce4b5ab52c629a9b1b31df22b4c4751aef3c608186576aa5317d19db9674e0326bd766e25cb9066fe6b57ec31999a9acb2ced6fcf28df33ef32f91cab7249e967c305ea00c91672f10e6c2af7c6d5a7ac366d2a94334182c102875e97bcee6f859f9d0fc87ffdf40390a1d959724869ff68345d44dcdec9996e5ba66acb1cf4caf7ac9f40df58db1f286d75d199d5a15d92a1bd3680586109f81fb93e1a088c3bbf9916c6299768ac8be1788e8fcb96db000ab49967045edb198dfadd0c31be70c876f7c5507eab253237c4a0b0dd22b64fcf2e7a7ffd88697d21ce7ffe92a036180bf52216fe33d34b761b7a7975fc10e24d9e7ddb82e4a2308ef56fca5c7e8cdadd7a5d7475288fc2d39bb1a60f14d4c29daf0a112bfce0353fd128bd423801774b64d615a8e520af9c73c6fcfe4a602a57b534c5bd8cf32b88685e184ce17fd89490d4d873a8cddea0d0bea9eb17022e965108e731fd5b77c13a4131e0c9eb73ea15875123d8eb94da86ef4db1a03c744bc81c26976419fae391930f0c64b046ef2e8d90ecb3a7ee78751bac1e4b70dcee4d44330c4ca8a72b18f2470dd8c17b600cd7c29bf08cbac13831b94b030ee078801b9fcf66c28f25d48f584d1ef902c3f8508fc6e7b44d4ea097641e8b6296ba383395d584baf268ab4cb789cf45460f944036a16a5256a62a400c591a964a3ec5bed5a1544e2412038facb616a12f8ce0a5cd14f33b87fed771af2e26147f64a4ff242655c568262a1615e11c446dd11b1d2d4bcd93911feea173638160cc2f60064427a403b75cb439421eeec72c5e71875d97160e9dd1ec87888ebe18ad54b68bc5e5b66eabfc2cc954319461a5ebdf1e942d3b660c1ab3f2b90bedbe03d7e8f6c51ddf1662a4dc23a2217e4b9043cd1f7c95a29b919c474042c59f30d7e1f6d9ef4d8932c9d365104fe0cb1f6d1d4a2fb2299169314e46d34ae418e2a5a38b5a37de5dea22170e5765494e7ff304fd0f19cc46957d45573673743fda798c9f41b0b82ef1ff762e2540babe34aa5eabd7e3690b8068d4c762309305c159f04afa35a67cf28afc80eefe6e19e154511217f7e7294a
hop_payloads[4] (unencrypted) = 0x41414141414141414141414141414141414141410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
hop_payloads[4] (encrypted) = 0xa1e2021607b8e61af363646121ea6107881dc0a5748f60e077fa1f233b0f4af1625041c755618deddc0c1ccc177fb3f7b100cc4aec8a65594ca05d325b276a74bfbd3f67f5b28d1ad823f9cf48b289f79220089cd080ddda57ee4fdfc556c56754a3be5297b1bf33da67a141687974479544c0ac94f54b464cecd1c28e831fa7a9617afd2b28a1b65010a1db2d4c09557addb056bbc12f8b3f9b91274f087e705170faeef83ac109cf8d552d919a7803db77cc4e1fd8a8a6bac8b1ccfd0f0bdf7952996f9ffe9f6c565ccc3bb551fa3be59a3cc44c2ed215425e38fe848ad49f62d3a73d4f743f254dffddde7acc9c6c9dbfcdb8a977a61d96d7663a3a80881850d21b01f3d87f8efcf9069c0306551ec03b04702ad8564119aa48b9fc96c881d9314524fd700f648ec7e242e33cb19f6a0b6d8ad8c24b5848c702c673b6cb0348682472f977bc37eea040388d618bbeff3da67d266dfe7893f73d9b14834da904090af8e7b96cc293f0229097d5199fe31e21c323f1c0c267e0ddf9bd4eab59548e655abbdb7021643463755e13d1f0
hmac_data[4] = 0xc04ad1e406ca69c8ab4951f70aed589da7916d85c0d0bd8ce4b5ab52c629a9b1b31df22b4c4751aef3c608186576aa5317d19db9674e0326bd766e25cb9066fe6b57ec31999a9acb2ced6fcf28df33ef32f91cab7249e967c305ea00c91672f10e6c2af7c6d5a7ac366d2a94334182c102875e97bcee6f859f9d0fc87ffdf40390a1d959724869ff68345d44dcdec9996e5ba66acb1cf4caf7ac9f40df58db1f286d75d199d5a15d92a1bd3680586109f81fb93e1a088c3bbf9916c6299768ac8be1788e8fcb96db000ab49967045edb198dfadd0c31be70c876f7c5507eab253237c4a0b0dd22b64fcf2e7a7ffd88697d21ce7ffe92a036180bf52216fe33d34b761b7a7975fc10e24d9e7ddb82e4a2308ef56fca5c7e8cdadd7a5d7475288fc2d39bb1a60f14d4c29daf0a112bfce0353fd128bd423801774b64d615a8e520af9c73c6fcfe4a602a57b534c5bd8cf32b88685e184ce17fd89490d4d873a8cddea0d0bea9eb17022e965108e731fd5b77c13a4131e0c9eb73ea15875123d8eb94da86ef4db1a03c744bc81c26976419fae391930f0c64b046ef2e8d90ecb3a7ee78751bac1e4b70dcee4d44330c4ca8a72b18f2470dd8c17b600cd7c29bf08cbac13831b94b030ee078801b9fcf66c28f25d48f584d1ef902c3f8508fc6e7b44d4ea097641e8b6296ba383395d584baf268ab4cb789cf45460f944036a16a5256a62a400c591a964a3ec5bed5a1544e2412038facb616a12f8ce0a5cd14f33b87fed771af2e26147f64a4ff242655c568262a1615e11c446dd11b1d2d4bcd93911feea173638160cc2f60064427a403b75cb439421eeec72c5e71875d97160e9dd1ec87888ebe18ad54b68bc5e5b66eabfc2cc954319461a5ebdf1e942d3b6692a8972e27719cff74818e2b68fe95a69d4c4e9e9263721d9cab974352a9064246406a8065e9f54960c730081f9fb7a2b82ed439507411a94b24429340cb4954c69a39da48ad8a63de960894aab5f4665b54bc8eba0bdcec31d150a69a46c2da6564d70aaa0d71b44a187006ae7ae82b6818971d2fbc6c0cc599912826d150926c9983c4809ba079abf3148d35a2bc38d86d83aa003ecd7cd45400da3a03648fa1e2021607b8e61af363646121ea6107881dc0a5748f60e077fa1f233b0f4af1625041c755618deddc0c1ccc177fb3f7b100cc4aec8a65594ca05d325b276a74bfbd3f67f5b28d1ad823f9cf48b289f79220089cd080ddda57ee4fdfc556c56754a3be5297b1bf33da67a141687974479544c0ac94f54b464cecd1c28e831fa7a9617afd2b28a1b65010a1db2d4c09557addb056bbc12f8b3f9b91274f087e705170faeef83ac109cf8d552d919a7803db77cc4e1fd8a8a6bac8b1ccfd0f0bdf7952996f9ffe9f6c565ccc3bb551fa3be59a3cc44c2ed215425e38fe848ad49f62d3a73d4f743f254dffddde7acc9c6c9dbfcdb8a977a61d96d7663a3a80881850d21b01f3d87f8efcf9069c0306551ec03b04702ad8564119aa48b9fc96c881d9314524fd700f648ec7e242e33cb19f6a0b6d8ad8c24b5848c702c673b6cb03b0940f21b1c76ac7940f88da48bda8b71880e6236249e99895f97b315dfcbd753276019f706a6ebaf15c5c6eaaca13565aa018befaed4afb7a166ce38a32a6e49507a4152d895977f3b4a680637360e04242424242424242424242424242424242424242424242424242424242424242
hmac[4] = 0x0d81da741a3ed601416269e6c9b166a71d126600
rhokey[3] = 0x03ce1f6a80411ae003940cca4334d09461dd5f201caf7d0a0024fedec77616fc
gammakey[3] = 0x15f11365bbec9e0e86d36bcf416e6f36d88478dac860174ccfea4d27c788267e
mukey[3] = 0xf0c62caee5169c63b8becdd88d02c1ed896e954db7ad1a35c1c29ce0cc19c4c8
routing_info[3] (unencrypted) = 0x61e068f8204f315c5909db270f3b75278b89d6910d81da741a3ed601416269e6c9b166a71d126600c04ad1e406ca69c8ab4951f70aed589da7916d85c0d0bd8ce4b5ab52c629a9b1b31df22b4c4751aef3c608186576aa5317d19db9674e0326bd766e25cb9066fe6b57ec31999a9acb2ced6fcf28df33ef32f91cab7249e967c305ea00c91672f10e6c2af7c6d5a7ac366d2a94334182c102875e97bcee6f859f9d0fc87ffdf40390a1d959724869ff68345d44dcdec9996e5ba66acb1cf4caf7ac9f40df58db1f286d75d199d5a15d92a1bd3680586109f81fb93e1a088c3bbf9916c6299768ac8be1788e8fcb96db000ab49967045edb198dfadd0c31be70c876f7c5507eab253237c4a0b0dd22b64fcf2e7a7ffd88697d21ce7ffe92a036180bf52216fe33d34b761b7a7975fc10e24d9e7ddb82e4a2308ef56fca5c7e8cdadd7a5d7475288fc2d39bb1a60f14d4c29daf0a112bfce0353fd128bd423801774b64d615a8e520af9c73c6fcfe4a602a57b534c5bd8cf32b88685e184ce17fd89490d4d873a8cddea0d0bea9eb17022e965108e731fd5b77c13a4131e0c9eb73ea15875123d8eb94da86ef4db1a03c744bc81c26976419fae391930f0c64b046ef2e8d90ecb3a7ee78751bac1e4b70dcee4d44330c4ca8a72b18f2470dd8c17b600cd7c29bf08cbac13831b94b030ee078801b9fcf66c28f25d48f584d1ef902c3f8508fc6e7b44d4ea097641e8b6296ba383395d584baf268ab4cb789cf45460f944036a16a5256a62a400c591a964a3ec5bed5a1544e2412038facb616a12f8ce0a5cd14f33b87fed771af2e26147f64a4ff242655c568262a1615e11c446dd11b1d2d4bcd93911feea173638160cc2f60064427a403b75cb439421eeec72c5e71875d97160e9dd1ec87888ebe18ad54b68bc5e5b66eabfc2cc954319461a5ebdf1e942d3b6692a8972e27719cff74818e2b68fe95a69d4c4e9e9263721d9cab974352a9064246406a8065e9f54960c730081f9fb7a2b82ed439507411a94b24429340cb4954c69a39da48ad8a63de960894aab5f4665b54bc8eba0bdcec31d150a69a46c2da6564d70aaa0d71b44a187006ae7ae82b6818971d2fbc6c0c
routing_info[3] (encrypted) = 0xdeb9c914888898aaedd4ff4471ec5d426cee4215ac2d2a6508b6c04265e0205aa29d6e97d55da714016a153ab3e2863b8c75b1ad4b1dd2922e26e6ff134939fc8fc5d6ccd82f94110251396310180871e62d155b9342eba01210c088de342504365b35097b7ff28074d90d6b0c23e760715d2752aea2aef5d047a253bb640cd61c646f2e0f4aec89766963248c5279a8b805b11ac31990849bdcdbabec03e2fa7efefdf39214fdb9cf0fba06ea19d4c534e3ad1da1ac690fef99a670f7ca2c9097cb11432db1d73db7279833ce534f4411e5f8808784b5312627a011607720c83b0348a86c9e60fd5fac1912b1b6e455f9c4ecc751931c8132658fc28cf42e68592fd028a02eddcee444c24dbab124d196531c8f2544e8de8b0304888f6c363558dfeab1260db3338e1314b43d6ea7f01861b56b2cc8efb001a1f6c4683cd29cee54c3e15cb50a6b3314b2dc8c5a1310c2cfa11be830f6373fa15c9455ccc4007268ef2b6074853244ffe15c3ea909f1478418353453be3b02c129be244cf6445221403e13a4d910a7548efc87a394bbf8ecbfe24b98c667a2b575af515eaf4a5eb691cf59011f2d8bef763e5cd7f25dc63d62378fbc861a1dcc2c173bdc41b4dcd0d8ffafdf5a8da47155fb632f3edbe7a08ef717c9498f6cb9d209ee839fc7deb0fe518c19b2bf77129f71bc2e2925745314ff899efa6dae7fe79bc51a1b6d5d10a06da0579bc256e7f4679745c89ea8a220ad4ae0ed20dd69d1e563cbcff04870e6741b0b2ce47b75e99388034bb4e225815945fab313cbc790adeaf7515368c80f4df9ae3847f78d7f99b7f17b0dda4c9d23d16b9dfa3cad0d829268979db904cb6a13a524b0ababad4bfa6e69aa664c0063341bc3f4352ca03bb8b68c823c8e0c9b94c79f6eb5f8a1aba104ff72fd772aedefaec1862a08f6a74abd832d61b2bc8205063dae5eac4e86d64dc076aa49e38be0f726203c25c50d45fb02237652884778bf356c774d11077e50ad8ad5aca38a225a3623225ba03a5a005fc445447c2d50296929c998bd21a90d6f56446dc685515f264da98b773063a3e201604dd3bdbcc1dfac3253ecaf6a4d557c59ba369ca9e89faf15e777d5ab5c34c5
hop_payloads[3] (unencrypted) = 0x4141414141414141414141414141414141414141a1e2021607b8e61af363646121ea6107881dc0a5748f60e077fa1f233b0f4af1625041c755618deddc0c1ccc177fb3f7b100cc4aec8a65594ca05d325b276a74bfbd3f67f5b28d1ad823f9cf48b289f79220089cd080ddda57ee4fdfc556c56754a3be5297b1bf33da67a141687974479544c0ac94f54b464cecd1c28e831fa7a9617afd2b28a1b65010a1db2d4c09557addb056bbc12f8b3f9b91274f087e705170faeef83ac109cf8d552d919a7803db77cc4e1fd8a8a6bac8b1ccfd0f0bdf7952996f9ffe9f6c565ccc3bb551fa3be59a3cc44c2ed215425e38fe848ad49f62d3a73d4f743f254dffddde7acc9c6c9dbfcdb8a977a61d96d7663a3a80881850d21b01f3d87f8efcf9069c0306551ec03b04702ad8564119aa48b9fc96c881d9314524fd700f648ec7e242e33cb19f6a0b6d8ad8c24b5848c702c673b6cb03b0940f21b1c76ac7940f88da48bda8b71880e6236249e99895f97b315dfcbd753276019f706a6ebaf15c5c6eaaca13565aa018befaed4afb7a166ce3
hop_payloads[3] (encrypted) = 0x9f5affca113b6d897323ca09b755aa637c7089fbdbfdf678db4c718510bb9ebd3935d57bb38e4daad9db669ab97f57810c9c27632a178ecb90265611242ecb39899d22ff7fd1c67296e334d3a2f0899dc75aee8d2e3610535370f9391b1fa94e56d000120f3ffaf51d15f693713e9466a91a8a1d9c087c14b37f83c90b6505b760b1983781fc9c4eed3dd16645148527ba999bc95e5f3ca54ab486d05af65237e658a2bd3de5fa70b95b1e614ffff730ab12bd35b8bec04f60436d05d84d107f8cbd0f9730306f7eb309272b3df796313d4a0b48cc92420ce2fe8ebc81df3aa7b3f967c9b82f8c387df0f10660fd874fcdce297e04d4b7b04e3c1085773655baf560d3b7895a9ecd5f8deb7839f0ddaef4e70707fd3cef6c006023cbc72d122814d37d70c814915e2445ce87fe63a0657c8bd19ebad4f05aef07e477ede2cb11d4cc005587e96f64bc173cc752a948b61d292a9c248e614ef5f76d7df30508fac3bd0954a1f25842afb4442cf984d3dfb7f3e3d96d237901eff918faa489849aec8d48953a18fa3130a837986533a8db
hmac_data[3] = 0xdeb9c914888898aaedd4ff4471ec5d426cee4215ac2d2a6508b6c04265e0205aa29d6e97d55da714016a153ab3e2863b8c75b1ad4b1dd2922e26e6ff134939fc8fc5d6ccd82f94110251396310180871e62d155b9342eba01210c088de342504365b35097b7ff28074d90d6b0c23e760715d2752aea2aef5d047a253bb640cd61c646f2e0f4aec89766963248c5279a8b805b11ac31990849bdcdbabec03e2fa7efefdf39214fdb9cf0fba06ea19d4c534e3ad1da1ac690fef99a670f7ca2c9097cb11432db1d73db7279833ce534f4411e5f8808784b5312627a011607720c83b0348a86c9e60fd5fac1912b1b6e455f9c4ecc751931c8132658fc28cf42e68592fd028a02eddcee444c24dbab124d196531c8f2544e8de8b0304888f6c363558dfeab1260db3338e1314b43d6ea7f01861b56b2cc8efb001a1f6c4683cd29cee54c3e15cb50a6b3314b2dc8c5a1310c2cfa11be830f6373fa15c9455ccc4007268ef2b6074853244ffe15c3ea909f1478418353453be3b02c129be244cf6445221403e13a4d910a7548efc87a394bbf8ecbfe24b98c667a2b575af515eaf4a5eb691cf59011f2d8bef763e5cd7f25dc63d62378fbc861a1dcc2c173bdc41b4dcd0d8ffafdf5a8da47155fb632f3edbe7a08ef717c9498f6cb9d209ee839fc7deb0fe518c19b2bf77129f71bc2e2925745314ff899efa6dae7fe79bc51a1b6d5d10a06da0579bc256e7f4679745c89ea8a220ad4ae0ed20dd69d1e563cbcff04870e6741b0b2ce47b75e99388034bb4e225815945fab313cbc790adeaf7515368c80f4df9ae3847f78d7f99b7f17b0dda4c9d23d16b9dfa3cad0d829268979db904cb6a13a524b0ababad4bfa6e69aa664c0063341bc3f4352ca03bb8b68c823c8e0c9b94c79f6eb5f8a1aba104ff72fd772aedefaec1862a08f6a74abd832d61b2bc8205063dae5eac4e86d64dc076aa49e38be0f726203c25c50d45fb02237652884778bf356c774d11077e50ad8ad5aca38a225a3623225ba03a5a005fc445447c2d50296929c998bd21a90d6f56446dc685515f264da98b773063a3e201604dd3bdbcc1dfac3253ecaf6a4d557c59ba369ca9e89faf15e777d5ab5c34c59f5affca113b6d897323ca09b755aa637c7089fbdbfdf678db4c718510bb9ebd3935d57bb38e4daad9db669ab97f57810c9c27632a178ecb90265611242ecb39899d22ff7fd1c67296e334d3a2f0899dc75aee8d2e3610535370f9391b1fa94e56d000120f3ffaf51d15f693713e9466a91a8a1d9c087c14b37f83c90b6505b760b1983781fc9c4eed3dd16645148527ba999bc95e5f3ca54ab486d05af65237e658a2bd3de5fa70b95b1e614ffff730ab12bd35b8bec04f60436d05d84d107f8cbd0f9730306f7eb309272b3df796313d4a0b48cc92420ce2fe8ebc81df3aa7b3f967c9b82f8c387df0f10660fd874fcdce297e04d4b7b04e3c1085773655baf560d3b7895a9ecd5f8deb7839f0ddaef4e70707fd3cef6c006023cbc72d122814d37d70c814915e2445ce87fe63a0657c8bd19ebad4f05aef07e477ede2cb11d4cc005587e96f64bc173cc752a948b61d292a9c248e614ef5f76d7df30508fac3bd0954a1f25842afb4442cf984d3dfb7f3e3d96d237901eff918faa489849aec8d48953a18fa3130a837986533a8db4242424242424242424242424242424242424242424242424242424242424242
hmac[3] = 0x392e4264273dd3acef95aefc86ecf2a6219f13f2
rhokey[2] = 0xbb47a96384965e7435f2d2f7d8daf8ea2093b413d431cefb573f95edf4f69762
gammakey[2] = 0xd47275c3e7b6faf8e76deb8982a37c31ed45847c66ccd2c7f7d2746222bb46e5
mukey[2] = 0x26b9dfca615e5c05ffdd9189fbb63a269b060f115e19a4b98fad6d9e9f11182b
routing_info[2] (unencrypted) = 0xcc1b07838e387deacd0e5232e1e8b49f4c29e484392e4264273dd3acef95aefc86ecf2a6219f13f2deb9c914888898aaedd4ff4471ec5d426cee4215ac2d2a6508b6c04265e0205aa29d6e97d55da714016a153ab3e2863b8c75b1ad4b1dd2922e26e6ff134939fc8fc5d6ccd82f94110251396310180871e62d155b9342eba01210c088de342504365b35097b7ff28074d90d6b0c23e760715d2752aea2aef5d047a253bb640cd61c646f2e0f4aec89766963248c5279a8b805b11ac31990849bdcdbabec03e2fa7efefdf39214fdb9cf0fba06ea19d4c534e3ad1da1ac690fef99a670f7ca2c9097cb11432db1d73db7279833ce534f4411e5f8808784b5312627a011607720c83b0348a86c9e60fd5fac1912b1b6e455f9c4ecc751931c8132658fc28cf42e68592fd028a02eddcee444c24dbab124d196531c8f2544e8de8b0304888f6c363558dfeab1260db3338e1314b43d6ea7f01861b56b2cc8efb001a1f6c4683cd29cee54c3e15cb50a6b3314b2dc8c5a1310c2cfa11be830f6373fa15c9455ccc4007268ef2b6074853244ffe15c3ea909f1478418353453be3b02c129be244cf6445221403e13a4d910a7548efc87a394bbf8ecbfe24b98c667a2b575af515eaf4a5eb691cf59011f2d8bef763e5cd7f25dc63d62378fbc861a1dcc2c173bdc41b4dcd0d8ffafdf5a8da47155fb632f3edbe7a08ef717c9498f6cb9d209ee839fc7deb0fe518c19b2bf77129f71bc2e2925745314ff899efa6dae7fe79bc51a1b6d5d10a06da0579bc256e7f4679745c89ea8a220ad4ae0ed20dd69d1e563cbcff04870e6741b0b2ce47b75e99388034bb4e225815945fab313cbc790adeaf7515368c80f4df9ae3847f78d7f99b7f17b0dda4c9d23d16b9dfa3cad0d829268979db904cb6a13a524b0ababad4bfa6e69aa664c0063341bc3f4352ca03bb8b68c823c8e0c9b94c79f6eb5f8a1aba104ff72fd772aedefaec1862a08f6a74abd832d61b2bc8205063dae5eac4e86d64dc076aa49e38be0f726203c25c50d45fb02237652884778bf356c774d11077e50ad8ad5aca38a225a3623225ba03a5a005fc445447c2d50296929c998bd21a90d6f56446dc685515f264d
routing_info[2] (encrypted) = 0xc7b3379ff00a16032cf7e6652b138994eebf00aa581a2968d08616b6a6432358736f78349a0c5e99fbe8f3c2b5703075870f54335248fadb86996a24d7f3ab1ac8db9965a87d3342ba0c5c61a55d9dbc4930e27d1bd05eb01df872e179b5b8b1a880d6aac1431916f3dedbbbdb6484c7982e6e7588780278c1e030438de1d032df9c0b7cfbd14e94b7c6cc05c465442241c0f4ce8c9b01d3915988ac1d67dec747bc152b28e9e91fa6db15fc3e1f807bcaf8569eb77a97c3226bdcbbc8e6b67da0598e58f8ed25a83c15c6e33631754c717083d1668cf14d4fc86211dce81f905321db6f7864de3dc0c998066725905874cf4f3d43a00c07404b70318835e5e0e1f4d8a995884c6a3e9ca76f5cc113a1ef5f1bcab348188e41bd87e25d39913fa1d795e6cb0f3b0f21fbdb4f5ee4af36aade9e1440ebcf6f93f3f0204da19c80a841d1e5ad2e9e12f75cdc50ab8d2f7a0040ab8285c4b58e3d3fbc532ae6590bd9fdc26d1239f9674cdb5ab8757d35d3cadf8dc1de680a378b77f5febfb2fcffed547092da9a8be0be82829d64d249605031cd1aa40cf8c6d5d9598b434c23d6480105eca7b0ca1de6a2d9b914c5d5538563276bfa3583c9b975c9739282fdc8d3a772c650c7ab1d744ab95a6e2d59c3d22ae4f5f354479bcd967d93bd4f88b8027f423d5138a23d24f8f0068d7886373aacd3aeb6b5a2c80cb40b2599e1592442ee02305fd44d9c3ec7bd9e11eeab414b4c3f03a32fab8b0ac01849a292bf00388539c7c6c97b9579d29e8fac3221f0cc2c0e252afce0821a63d40e8ad128fc556692787914399bd32f44f9f8a2ea50f882b2bdb3b2c71a72ed368a30eaa3c4bb0a55e50836a2af2913d4bbd69178a60f875d4a29f1e2fb5e0c30d2d0073f1091df31383a0fcbd187903f03d2f8ddb918aa4c326494c1d1ffa8a030ff5e3c5cebb55aabc5e2f340247d187316abe374b68375dc524d9beba4718c7248fcb5c90d0b62995a141a18f11eed5539fd486c4ebf60023ce6463e218633f3c526262f199e1e91afe0f0b6fe12bce282023441c14dfffe678e29727d1320e24a0e878634d253123ba3320ad0c2e1639f781ea4033fb2f973e622ba3c5cd34c2abf9d2e
hop_payloads[2] (unencrypted) = 0x41414141414141414141414141414141414141419f5affca113b6d897323ca09b755aa637c7089fbdbfdf678db4c718510bb9ebd3935d57bb38e4daad9db669ab97f57810c9c27632a178ecb90265611242ecb39899d22ff7fd1c67296e334d3a2f0899dc75aee8d2e3610535370f9391b1fa94e56d000120f3ffaf51d15f693713e9466a91a8a1d9c087c14b37f83c90b6505b760b1983781fc9c4eed3dd16645148527ba999bc95e5f3ca54ab486d05af65237e658a2bd3de5fa70b95b1e614ffff730ab12bd35b8bec04f60436d05d84d107f8cbd0f9730306f7eb309272b3df796313d4a0b48cc92420ce2fe8ebc81df3aa7b3f967c9b82f8c387df0f10660fd874fcdce297e04d4b7b04e3c1085773655baf560d3b7895a9ecd5f8deb7839f0ddaef4e70707fd3cef6c006023cbc72d122814d37d70c814915e2445ce87fe63a0657c8bd19ebad4f05aef07e477ede2cb11d4cc005587e96f64bc173cc752a948b61d292a9c248e614ef5f76d7df30508fac3bd0954a1f25842afb4442cf984d3dfb7f3e3d96d237901eff918fa
hop_payloads[2] (encrypted) = 0xd0636998d242fd7967210f23cc72a96913d58c7abc04a134a3dbd8edb46d6130b22bb37998eddc6bb3a19f4f1562abeeb37814c76894aa617629eb63faaaff5cc93c3a33628279a1f17c1840ee95a85d1378ad331029210f6bf373acaa5e7b7df9710898c0bd5e48692935582c7765e5f93ebfe5faaaf6f6ea035799e7003a05c4c0233d2f947ff33b8a99a2e2bf44b2ca36ebf66de01f0adbb8dbb96a6bdcfd8dec662401df27cc4a1e7daaf1c8a378b43cd76f270d7737e02c0b1f362a4193c00fdc02882dfa4a7f4e0cc2ab20f83c9a9ad16cf1a32509a8fc50770551980691947cfa317b2bbe2b7713374c35eadad465ee4b9078c9a84fdea7bd581bc43a7a4229b15bb62861c7191e46ebff7ccc83ce7d8aef7410aadad87317b91778c2eb9c82623f5e7015d591ab9fbcf2ba9db8dea189f74838d806ad219eb6e15e93ddc57735eac09f3d047d5185ae191b29cc65d19776505b586d556f64147ace110040cc8fd330d71032409003ef28179319033e48689a929aecf0c028eac78f98ec7e7b0d897f159b3075502ef716c85c
hmac_data[2] = 0xc7b3379ff00a16032cf7e6652b138994eebf00aa581a2968d08616b6a6432358736f78349a0c5e99fbe8f3c2b5703075870f54335248fadb86996a24d7f3ab1ac8db9965a87d3342ba0c5c61a55d9dbc4930e27d1bd05eb01df872e179b5b8b1a880d6aac1431916f3dedbbbdb6484c7982e6e7588780278c1e030438de1d032df9c0b7cfbd14e94b7c6cc05c465442241c0f4ce8c9b01d3915988ac1d67dec747bc152b28e9e91fa6db15fc3e1f807bcaf8569eb77a97c3226bdcbbc8e6b67da0598e58f8ed25a83c15c6e33631754c717083d1668cf14d4fc86211dce81f905321db6f7864de3dc0c998066725905874cf4f3d43a00c07404b70318835e5e0e1f4d8a995884c6a3e9ca76f5cc113a1ef5f1bcab348188e41bd87e25d39913fa1d795e6cb0f3b0f21fbdb4f5ee4af36aade9e1440ebcf6f93f3f0204da19c80a841d1e5ad2e9e12f75cdc50ab8d2f7a0040ab8285c4b58e3d3fbc532ae6590bd9fdc26d1239f9674cdb5ab8757d35d3cadf8dc1de680a378b77f5febfb2fcffed547092da9a8be0be82829d64d249605031cd1aa40cf8c6d5d9598b434c23d6480105eca7b0ca1de6a2d9b914c5d5538563276bfa3583c9b975c9739282fdc8d3a772c650c7ab1d744ab95a6e2d59c3d22ae4f5f354479bcd967d93bd4f88b8027f423d5138a23d24f8f0068d7886373aacd3aeb6b5a2c80cb40b2599e1592442ee02305fd44d9c3ec7bd9e11eeab414b4c3f03a32fab8b0ac01849a292bf00388539c7c6c97b9579d29e8fac3221f0cc2c0e252afce0821a63d40e8ad128fc556692787914399bd32f44f9f8a2ea50f882b2bdb3b2c71a72ed368a30eaa3c4bb0a55e50836a2af2913d4bbd69178a60f875d4a29f1e2fb5e0c30d2d0073f1091df31383a0fcbd187903f03d2f8ddb918aa4c326494c1d1ffa8a030ff5e3c5cebb55aabc5e2f340247d187316abe374b68375dc524d9beba4718c7248fcb5c90d0b62995a141a18f11eed5539fd486c4ebf60023ce6463e218633f3c526262f199e1e91afe0f0b6fe12bce282023441c14dfffe678e29727d1320e24a0e878634d253123ba3320ad0c2e1639f781ea4033fb2f973e622ba3c5cd34c2abf9d2ed0636998d242fd7967210f23cc72a96913d58c7abc04a134a3dbd8edb46d6130b22bb37998eddc6bb3a19f4f1562abeeb37814c76894aa617629eb63faaaff5cc93c3a33628279a1f17c1840ee95a85d1378ad331029210f6bf373acaa5e7b7df9710898c0bd5e48692935582c7765e5f93ebfe5faaaf6f6ea035799e7003a05c4c0233d2f947ff33b8a99a2e2bf44b2ca36ebf66de01f0adbb8dbb96a6bdcfd8dec662401df27cc4a1e7daaf1c8a378b43cd76f270d7737e02c0b1f362a4193c00fdc02882dfa4a7f4e0cc2ab20f83c9a9ad16cf1a32509a8fc50770551980691947cfa317b2bbe2b7713374c35eadad465ee4b9078c9a84fdea7bd581bc43a7a4229b15bb62861c7191e46ebff7ccc83ce7d8aef7410aadad87317b91778c2eb9c82623f5e7015d591ab9fbcf2ba9db8dea189f74838d806ad219eb6e15e93ddc57735eac09f3d047d5185ae191b29cc65d19776505b586d556f64147ace110040cc8fd330d71032409003ef28179319033e48689a929aecf0c028eac78f98ec7e7b0d897f159b3075502ef716c85c4242424242424242424242424242424242424242424242424242424242424242
hmac[2] = 0xe9ec4ec6ac9ce0afe1fe3a0f6986935f0dcb9cb7
rhokey[1] = 0x2177517448e618a0d00d3914e1553e98fb17edf9d9c17617634e04c30f8141ec
gammakey[1] = 0xa7687eb2b9b1c6ffcc30e554a34c4a430d4d271efe316ab3a52687bc8e7b1129
mukey[1] = 0x4df5d231ca8576500efe62ffcb779ea5ad7ac51ee1126a1d37b9376e79f954a9
routing_info[1] (unencrypted) = 0x331eb609f3aacffe680f86309d6b7470e7215b0ce9ec4ec6ac9ce0afe1fe3a0f6986935f0dcb9cb7c7b3379ff00a16032cf7e6652b138994eebf00aa581a2968d08616b6a6432358736f78349a0c5e99fbe8f3c2b5703075870f54335248fadb86996a24d7f3ab1ac8db9965a87d3342ba0c5c61a55d9dbc4930e27d1bd05eb01df872e179b5b8b1a880d6aac1431916f3dedbbbdb6484c7982e6e7588780278c1e030438de1d032df9c0b7cfbd14e94b7c6cc05c465442241c0f4ce8c9b01d3915988ac1d67dec747bc152b28e9e91fa6db15fc3e1f807bcaf8569eb77a97c3226bdcbbc8e6b67da0598e58f8ed25a83c15c6e33631754c717083d1668cf14d4fc86211dce81f905321db6f7864de3dc0c998066725905874cf4f3d43a00c07404b70318835e5e0e1f4d8a995884c6a3e9ca76f5cc113a1ef5f1bcab348188e41bd87e25d39913fa1d795e6cb0f3b0f21fbdb4f5ee4af36aade9e1440ebcf6f93f3f0204da19c80a841d1e5ad2e9e12f75cdc50ab8d2f7a0040ab8285c4b58e3d3fbc532ae6590bd9fdc26d1239f9674cdb5ab8757d35d3cadf8dc1de680a378b77f5febfb2fcffed547092da9a8be0be82829d64d249605031cd1aa40cf8c6d5d9598b434c23d6480105eca7b0ca1de6a2d9b914c5d5538563276bfa3583c9b975c9739282fdc8d3a772c650c7ab1d744ab95a6e2d59c3d22ae4f5f354479bcd967d93bd4f88b8027f423d5138a23d24f8f0068d7886373aacd3aeb6b5a2c80cb40b2599e1592442ee02305fd44d9c3ec7bd9e11eeab414b4c3f03a32fab8b0ac01849a292bf00388539c7c6c97b9579d29e8fac3221f0cc2c0e252afce0821a63d40e8ad128fc556692787914399bd32f44f9f8a2ea50f882b2bdb3b2c71a72ed368a30eaa3c4bb0a55e50836a2af2913d4bbd69178a60f875d4a29f1e2fb5e0c30d2d0073f1091df31383a0fcbd187903f03d2f8ddb918aa4c326494c1d1ffa8a030ff5e3c5cebb55aabc5e2f340247d187316abe374b68375dc524d9beba4718c7248fcb5c90d0b62995a141a18f11eed5539fd486c4ebf60023ce6463e218633f3c526262f199e1e91afe0f0b6fe12bce282023441c14dfffe678e2972
routing_info[1] (encrypted) = 0x7828c23ac6aa47913308eaeeee077ea4443b6d8dda637167a93c0ef8923f686c01c604b66a75da22ca9958ffe17c7a07939670401f60f5688df085ef510e28affcc048b5ab3a5f8dc128b3c982ce646b5bd6aa35345ea92643e8b27af6c3e354bdb9fdfd90c6690e8bb2121f31852029814bfc38a9eaadb7ae6239b22c8eb13cd1181e4d468b478bc9629c89798236540c624deaa8d9ae7bde0c5911ba013fa0f3373b5a903459560b21f17051b6c88c91ed4c7441a36832bb0bf7f2e26611fb21397df92c80c702c4e158c2dbec559300ad563eb4775d283b6c7ad9d6cd8fc885f1050c2fb133457c7d74f3ea2ec2056c9f3bb603a8ba743317ce939f60d554f81cfa0513fac6b23a565f3864bf30f97fc7f3fb452a6e3e990fb5cbc388021076d4deffeec3e78f0beaf0b2eeb5549f83635587c08ddb5559d24148bdc59d420c63555532ab099d949bb02abbca40d152a7f3340813860f9a661fc038dfb0c1c34d049f71ba8e4e34b230b44ab1c066307bc5feea10257a56641df6ab0b5f910658195b99ea285d19d399dcabb0d5e2b03273f113ab5341f544b0931c353a0dbac89dd17b7930116b09093c07cf9b6787b3a7fc03275fc418053db44d387511c5ee6561948e1cdfe6e60ffe043895827c171f745bcac48ec5a0c753c181c0b992d0a59e28506058c6a02900e0b30c180810bb450c96d41c583e80a86634350ad5d8f343f9103ac081253aae7aa96c1143612866e23742cd09e1d89494a0f4b03ae1c120af615a4a7a1559d99acb54132d2b8374817ffbb5934ccab1459d2e29ad70a9415104d1f033862f4efb626ae0cdaad85df450d45bf4a5a365d151a0c15908e70e4d54a1b07b2443e20e9d7a3f27829dfaa99f756088cacdafad732b83c488edf76bf3db12a86019b57a78aa9188021cf3cc3331846bb8c9d4ea91485773582f8594294c45ff49206003671c5d714484a7f5849684fa3ea73f65e6b02e034a10bd7b94ff04877daaa621f82062d00b8d35fedd616ea602b375c2b58f7b0d89deff9d7c5aeb8e7970078f4bf74a94601d4cc25df1dc95b6258a78ab0186a33a41794e220af845a0a4e48bead9994be3f20fdedaeb64ad86c2a03e662ba8
hop_payloads[1] (unencrypted) = 0x4141414141414141414141414141414141414141d0636998d242fd7967210f23cc72a96913d58c7abc04a134a3dbd8edb46d6130b22bb37998eddc6bb3a19f4f1562abeeb37814c76894aa617629eb63faaaff5cc93c3a33628279a1f17c1840ee95a85d1378ad331029210f6bf373acaa5e7b7df9710898c0bd5e48692935582c7765e5f93ebfe5faaaf6f6ea035799e7003a05c4c0233d2f947ff33b8a99a2e2bf44b2ca36ebf66de01f0adbb8dbb96a6bdcfd8dec662401df27cc4a1e7daaf1c8a378b43cd76f270d7737e02c0b1f362a4193c00fdc02882dfa4a7f4e0cc2ab20f83c9a9ad16cf1a32509a8fc50770551980691947cfa317b2bbe2b7713374c35eadad465ee4b9078c9a84fdea7bd581bc43a7a4229b15bb62861c7191e46ebff7ccc83ce7d8aef7410aadad87317b91778c2eb9c82623f5e7015d591ab9fbcf2ba9db8dea189f74838d806ad219eb6e15e93ddc57735eac09f3d047d5185ae191b29cc65d19776505b586d556f64147ace110040cc8fd330d71032409003ef28179319033e48689a929aecf0c028
hop_payloads[1] (encrypted) = 0x5bf5bacecf09d3eb3c19bf73b377ffbfc72798b93554b7f5e1d9844a9f7afb75b49633d29e87b01510be75ab697ad6a311189c121b3f2b035f9a019e7fdca46c22dc7500c1d60758cabf18121617b07b90428e1260ddd026554c23dee5c50d236827b5a7bd625af7dc4457d0b704a5f4266416b7005a9a6cad09d9d48eae69c31d34890098078dfe67be61fd417cfd84a541978a32ec5a7b5c149119a7f74ac4e645611989e1881e783673a86748e1d353885b170027d70ca35fca8d63a6085ee16acb08aa4a2e738ca57b19dcdb89ec0f9dfbffe5bed646953cc4517a7c38cb51d4c6772c067b6eebbb11f9cccb29bc160e1ba1f4e89fbc122a3fe29baede0836f2e50a3e4751e4e47f0882353d461289647e5c9b4d16366861c22e4f4ec0c1f29f29d30d2ef72f9bb07140ea4194a415fd9d1293d825154260a99c548ca5f7ec29ca52e158356a495de2c95be233c306af5b8a779fe3ec724189f72097289fd6f06a1d1f679df8cd30372eb07607d3ebcde9465af8a79504243bba21333b6a434f464330bf3fac8fe118009d37806e
hmac_data[1] = 0x7828c23ac6aa47913308eaeeee077ea4443b6d8dda637167a93c0ef8923f686c01c604b66a75da22ca9958ffe17c7a07939670401f60f5688df085ef510e28affcc048b5ab3a5f8dc128b3c982ce646b5bd6aa35345ea92643e8b27af6c3e354bdb9fdfd90c6690e8bb2121f31852029814bfc38a9eaadb7ae6239b22c8eb13cd1181e4d468b478bc9629c89798236540c624deaa8d9ae7bde0c5911ba013fa0f3373b5a903459560b21f17051b6c88c91ed4c7441a36832bb0bf7f2e26611fb21397df92c80c702c4e158c2dbec559300ad563eb4775d283b6c7ad9d6cd8fc885f1050c2fb133457c7d74f3ea2ec2056c9f3bb603a8ba743317ce939f60d554f81cfa0513fac6b23a565f3864bf30f97fc7f3fb452a6e3e990fb5cbc388021076d4deffeec3e78f0beaf0b2eeb5549f83635587c08ddb5559d24148bdc59d420c63555532ab099d949bb02abbca40d152a7f3340813860f9a661fc038dfb0c1c34d049f71ba8e4e34b230b44ab1c066307bc5feea10257a56641df6ab0b5f910658195b99ea285d19d399dcabb0d5e2b03273f113ab5341f544b0931c353a0dbac89dd17b7930116b09093c07cf9b6787b3a7fc03275fc418053db44d387511c5ee6561948e1cdfe6e60ffe043895827c171f745bcac48ec5a0c753c181c0b992d0a59e28506058c6a02900e0b30c180810bb450c96d41c583e80a86634350ad5d8f343f9103ac081253aae7aa96c1143612866e23742cd09e1d89494a0f4b03ae1c120af615a4a7a1559d99acb54132d2b8374817ffbb5934ccab1459d2e29ad70a9415104d1f033862f4efb626ae0cdaad85df450d45bf4a5a365d151a0c15908e70e4d54a1b07b2443e20e9d7a3f27829dfaa99f756088cacdafad732b83c488edf76bf3db12a86019b57a78aa9188021cf3cc3331846bb8c9d4ea91485773582f8594294c45ff49206003671c5d714484a7f5849684fa3ea73f65e6b02e034a10bd7b94ff04877daaa621f82062d00b8d35fedd616ea602b375c2b58f7b0d89deff9d7c5aeb8e7970078f4bf74a94601d4cc25df1dc95b6258a78ab0186a33a41794e220af845a0a4e48bead9994be3f20fdedaeb64ad86c2a03e662ba85bf5bacecf09d3eb3c19bf73b377ffbfc72798b93554b7f5e1d9844a9f7afb75b49633d29e87b01510be75ab697ad6a311189c121b3f2b035f9a019e7fdca46c22dc7500c1d60758cabf18121617b07b90428e1260ddd026554c23dee5c50d236827b5a7bd625af7dc4457d0b704a5f4266416b7005a9a6cad09d9d48eae69c31d34890098078dfe67be61fd417cfd84a541978a32ec5a7b5c149119a7f74ac4e645611989e1881e783673a86748e1d353885b170027d70ca35fca8d63a6085ee16acb08aa4a2e738ca57b19dcdb89ec0f9dfbffe5bed646953cc4517a7c38cb51d4c6772c067b6eebbb11f9cccb29bc160e1ba1f4e89fbc122a3fe29baede0836f2e50a3e4751e4e47f0882353d461289647e5c9b4d16366861c22e4f4ec0c1f29f29d30d2ef72f9bb07140ea4194a415fd9d1293d825154260a99c548ca5f7ec29ca52e158356a495de2c95be233c306af5b8a779fe3ec724189f72097289fd6f06a1d1f679df8cd30372eb07607d3ebcde9465af8a79504243bba21333b6a434f464330bf3fac8fe118009d37806e4242424242424242424242424242424242424242424242424242424242424242
hmac[1] = 0x4e254891eca07783ac67d3dd6253cb679245d697
rhokey[0] = 0xeef6cd73ab6044bec9bd9056fa42fc26ccb17115d2c736efc93b80696efd2e3b
gammakey[0] = 0xeec24d6429d9951878dc891c1622ace8f46fc410e99e5b6492c10b56017bb99c
mukey[0] = 0xa82f49ffdedac154ed7a8d09a5cba00827617afacaa9127275a71308a7f953c2
routing_info[0] (unencrypted) = 0x14db4138d56a2ecfb10881a9be394d9f321985b24e254891eca07783ac67d3dd6253cb679245d6977828c23ac6aa47913308eaeeee077ea4443b6d8dda637167a93c0ef8923f686c01c604b66a75da22ca9958ffe17c7a07939670401f60f5688df085ef510e28affcc048b5ab3a5f8dc128b3c982ce646b5bd6aa35345ea92643e8b27af6c3e354bdb9fdfd90c6690e8bb2121f31852029814bfc38a9eaadb7ae6239b22c8eb13cd1181e4d468b478bc9629c89798236540c624deaa8d9ae7bde0c5911ba013fa0f3373b5a903459560b21f17051b6c88c91ed4c7441a36832bb0bf7f2e26611fb21397df92c80c702c4e158c2dbec559300ad563eb4775d283b6c7ad9d6cd8fc885f1050c2fb133457c7d74f3ea2ec2056c9f3bb603a8ba743317ce939f60d554f81cfa0513fac6b23a565f3864bf30f97fc7f3fb452a6e3e990fb5cbc388021076d4deffeec3e78f0beaf0b2eeb5549f83635587c08ddb5559d24148bdc59d420c63555532ab099d949bb02abbca40d152a7f3340813860f9a661fc038dfb0c1c34d049f71ba8e4e34b230b44ab1c066307bc5feea10257a56641df6ab0b5f910658195b99ea285d19d399dcabb0d5e2b03273f113ab5341f544b0931c353a0dbac89dd17b7930116b09093c07cf9b6787b3a7fc03275fc418053db44d387511c5ee6561948e1cdfe6e60ffe043895827c171f745bcac48ec5a0c753c181c0b992d0a59e28506058c6a02900e0b30c180810bb450c96d41c583e80a86634350ad5d8f343f9103ac081253aae7aa96c1143612866e23742cd09e1d89494a0f4b03ae1c120af615a4a7a1559d99acb54132d2b8374817ffbb5934ccab1459d2e29ad70a9415104d1f033862f4efb626ae0cdaad85df450d45bf4a5a365d151a0c15908e70e4d54a1b07b2443e20e9d7a3f27829dfaa99f756088cacdafad732b83c488edf76bf3db12a86019b57a78aa9188021cf3cc3331846bb8c9d4ea91485773582f8594294c45ff49206003671c5d714484a7f5849684fa3ea73f65e6b02e034a10bd7b94ff04877daaa621f82062d00b8d35fedd616ea602b375c2b58f7b0d89deff9d7c5aeb8e7970078f4bf74a94601d4cc25df1dc
routing_info[0] (encrypted) = 0xb4e6b2070f0115e5e0a96713417bdb0cc2d6f253036a2589c3b43d4dfc930e1a206ac6197903a6769723b918b5f5e887ab1f662c2cbd4b7075ac38c222b5485e01525caa69cfd90e82f1c4b224c164a6f4695ba61a4add4fc7dd9cc8543e1be58b0478c6cf522b888e74a27ec9f9a84319ace8f7c850376f75e680cc0f8dc12daca52967feb41a729050a0766683db4b6a3bf0ec9a1c89bc88982916705d80de4094d083272c1c09668bfe1fc75e8102479d3d50ed8978570c387e14f01615f10527eadd88b45ffcf2ba029ca52e5bd8a9cce0f01cecdd9d37d144f24e49393f1702e9efd4bbe19b2471a946a3a28d4a799b6cb98065481e794988caa43309a34fa58530755fd929d6ee28ab7ef5fd283475ab7da17ed67c33e6966e81fb86f201266c6e9c2cf4fcf49bee62fbbda8bd773f13e54784c476b832e07d42e0e020aefbd2143f6baf55cc6b908148381a1ff415c49d758d42bc2d1bc512558cf03d5001571d1ef0087adec4ddbc8efb409318767ca6ffa34b39ed2dc8556b791216e751e68961083ce0f7c78dd64532d474c78894b721c04329e26f39e06459c0c703eb22558fc8be3e9aec9425de682d3d15911065a87deaa7be246226d1999ef268e35d2c51be34fcaa8d639194158395602aea68fbb1cdebdfc90f2152921e14c2fdd3b1693f21885b56b406f061f09cca1726c346cb07d6bde7e0042474c3c6ddbd368582e5a889fff25f76e73f09bafbbf8ef0dfb34c7b417646f4d5cc3498f9821943eb549575e2909c60702c7c35aa95f6209dea8663ec87a2d1a74f7c19108a0a49952de6fe2c9f2c7d375a117ec66fa58871a52d456da5287b1c1c18f214da32cf56ff94d1736d3da6846f074745ec08596c6d627282f442cc5f5f3c295703c8eb0da8b3df6de781fdf305a5b14094dd17b88cfb87ad5e6ff8f270cc6e239abce0d8dedc8305cae170d42f57734f824d8efa6ee07317dcdeee7cf723be87d4ca2f0b0f62b1c0e44ca17a0de3196530b398dfd4a556bfce04f4e359d86aa2564c77d256f8f884195e3783d54152ac9d39c0da191c05e4cfe9b205ad243c86a480cccd75d6d5030e54c995c8ade802323f69620f6b800c29da5462b95fd3
hop_payloads[0] (unencrypted) = 0x41414141414141414141414141414141414141415bf5bacecf09d3eb3c19bf73b377ffbfc72798b93554b7f5e1d9844a9f7afb75b49633d29e87b01510be75ab697ad6a311189c121b3f2b035f9a019e7fdca46c22dc7500c1d60758cabf18121617b07b90428e1260ddd026554c23dee5c50d236827b5a7bd625af7dc4457d0b704a5f4266416b7005a9a6cad09d9d48eae69c31d34890098078dfe67be61fd417cfd84a541978a32ec5a7b5c149119a7f74ac4e645611989e1881e783673a86748e1d353885b170027d70ca35fca8d63a6085ee16acb08aa4a2e738ca57b19dcdb89ec0f9dfbffe5bed646953cc4517a7c38cb51d4c6772c067b6eebbb11f9cccb29bc160e1ba1f4e89fbc122a3fe29baede0836f2e50a3e4751e4e47f0882353d461289647e5c9b4d16366861c22e4f4ec0c1f29f29d30d2ef72f9bb07140ea4194a415fd9d1293d825154260a99c548ca5f7ec29ca52e158356a495de2c95be233c306af5b8a779fe3ec724189f72097289fd6f06a1d1f679df8cd30372eb07607d3ebcde9465af8a79504243bba
hop_payloads[0] (encrypted) = 0x341de209dd46c1229914da6caeb9d3c3212d83680e5042e0cfb711c630f08a1f4d739d751353acf0e8d6fa5ad3b49b82989570d87ddd738e49be106f5bcd627be97f10fb347e2b778f91b27cf36bfb7928805b79e024e94e55c9848da048d2688a3bd2297f88139f3434498f0e0d508154dc96dcf0f7a2b7533752b8218c4cf9abacda3cd75e0cb85084ff060eb4338ddf79cdfe63e96802178fcf9c020b70851f46555983d1cad6f52b27f6c362021562323ae29dcc794439051a70feaa7f776ed266f8f131c0e5322989ab7e98e0a75d601b602d07ca39d595ac69e717a5c142441e7a0a44c09abdb2b4611279718878c1e84acc53608ca94ec17408a3874a0612a53e862bf959dc0315c78a92c6f518de423054055ee0d003615908ceef0d832421885a46d28623f65a5b2a6adfab4b85426a3375c12f0b9355beb6a48d971d5349e5daf156d6fc2d33e09bad3b00e906ec985bce922afaa67e5c0a09bcf4910f31ac45505b22d44a35394bfea2ab05884ce72caeec4f3b824a7a15842b50966e3f7624e79bdd897b0107d31c6838
hmac_data[0] = 0xb4e6b2070f0115e5e0a96713417bdb0cc2d6f253036a2589c3b43d4dfc930e1a206ac6197903a6769723b918b5f5e887ab1f662c2cbd4b7075ac38c222b5485e01525caa69cfd90e82f1c4b224c164a6f4695ba61a4add4fc7dd9cc8543e1be58b0478c6cf522b888e74a27ec9f9a84319ace8f7c850376f75e680cc0f8dc12daca52967feb41a729050a0766683db4b6a3bf0ec9a1c89bc88982916705d80de4094d083272c1c09668bfe1fc75e8102479d3d50ed8978570c387e14f01615f10527eadd88b45ffcf2ba029ca52e5bd8a9cce0f01cecdd9d37d144f24e49393f1702e9efd4bbe19b2471a946a3a28d4a799b6cb98065481e794988caa43309a34fa58530755fd929d6ee28ab7ef5fd283475ab7da17ed67c33e6966e81fb86f201266c6e9c2cf4fcf49bee62fbbda8bd773f13e54784c476b832e07d42e0e020aefbd2143f6baf55cc6b908148381a1ff415c49d758d42bc2d1bc512558cf03d5001571d1ef0087adec4ddbc8efb409318767ca6ffa34b39ed2dc8556b791216e751e68961083ce0f7c78dd64532d474c78894b721c04329e26f39e06459c0c703eb22558fc8be3e9aec9425de682d3d15911065a87deaa7be246226d1999ef268e35d2c51be34fcaa8d639194158395602aea68fbb1cdebdfc90f2152921e14c2fdd3b1693f21885b56b406f061f09cca1726c346cb07d6bde7e0042474c3c6ddbd368582e5a889fff25f76e73f09bafbbf8ef0dfb34c7b417646f4d5cc3498f9821943eb549575e2909c60702c7c35aa95f6209dea8663ec87a2d1a74f7c19108a0a49952de6fe2c9f2c7d375a117ec66fa58871a52d456da5287b1c1c18f214da32cf56ff94d1736d3da6846f074745ec08596c6d627282f442cc5f5f3c295703c8eb0da8b3df6de781fdf305a5b14094dd17b88cfb87ad5e6ff8f270cc6e239abce0d8dedc8305cae170d42f57734f824d8efa6ee07317dcdeee7cf723be87d4ca2f0b0f62b1c0e44ca17a0de3196530b398dfd4a556bfce04f4e359d86aa2564c77d256f8f884195e3783d54152ac9d39c0da191c05e4cfe9b205ad243c86a480cccd75d6d5030e54c995c8ade802323f69620f6b800c29da5462b95fd3341de209dd46c1229914da6caeb9d3c3212d83680e5042e0cfb711c630f08a1f4d739d751353acf0e8d6fa5ad3b49b82989570d87ddd738e49be106f5bcd627be97f10fb347e2b778f91b27cf36bfb7928805b79e024e94e55c9848da048d2688a3bd2297f88139f3434498f0e0d508154dc96dcf0f7a2b7533752b8218c4cf9abacda3cd75e0cb85084ff060eb4338ddf79cdfe63e96802178fcf9c020b70851f46555983d1cad6f52b27f6c362021562323ae29dcc794439051a70feaa7f776ed266f8f131c0e5322989ab7e98e0a75d601b602d07ca39d595ac69e717a5c142441e7a0a44c09abdb2b4611279718878c1e84acc53608ca94ec17408a3874a0612a53e862bf959dc0315c78a92c6f518de423054055ee0d003615908ceef0d832421885a46d28623f65a5b2a6adfab4b85426a3375c12f0b9355beb6a48d971d5349e5daf156d6fc2d33e09bad3b00e906ec985bce922afaa67e5c0a09bcf4910f31ac45505b22d44a35394bfea2ab05884ce72caeec4f3b824a7a15842b50966e3f7624e79bdd897b0107d31c68384242424242424242424242424242424242424242424242424242424242424242
hmac[0] = 0xebe196af63529ae84e42071df1de234c8c21d692
#### Final Packet
onionpacket = 0x0102eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619ebe196af63529ae84e42071df1de234c8c21d692b4e6b2070f0115e5e0a96713417bdb0cc2d6f253036a2589c3b43d4dfc930e1a206ac6197903a6769723b918b5f5e887ab1f662c2cbd4b7075ac38c222b5485e01525caa69cfd90e82f1c4b224c164a6f4695ba61a4add4fc7dd9cc8543e1be58b0478c6cf522b888e74a27ec9f9a84319ace8f7c850376f75e680cc0f8dc12daca52967feb41a729050a0766683db4b6a3bf0ec9a1c89bc88982916705d80de4094d083272c1c09668bfe1fc75e8102479d3d50ed8978570c387e14f01615f10527eadd88b45ffcf2ba029ca52e5bd8a9cce0f01cecdd9d37d144f24e49393f1702e9efd4bbe19b2471a946a3a28d4a799b6cb98065481e794988caa43309a34fa58530755fd929d6ee28ab7ef5fd283475ab7da17ed67c33e6966e81fb86f201266c6e9c2cf4fcf49bee62fbbda8bd773f13e54784c476b832e07d42e0e020aefbd2143f6baf55cc6b908148381a1ff415c49d758d42bc2d1bc512558cf03d5001571d1ef0087adec4ddbc8efb409318767ca6ffa34b39ed2dc8556b791216e751e68961083ce0f7c78dd64532d474c78894b721c04329e26f39e06459c0c703eb22558fc8be3e9aec9425de682d3d15911065a87deaa7be246226d1999ef268e35d2c51be34fcaa8d639194158395602aea68fbb1cdebdfc90f2152921e14c2fdd3b1693f21885b56b406f061f09cca1726c346cb07d6bde7e0042474c3c6ddbd368582e5a889fff25f76e73f09bafbbf8ef0dfb34c7b417646f4d5cc3498f9821943eb549575e2909c60702c7c35aa95f6209dea8663ec87a2d1a74f7c19108a0a49952de6fe2c9f2c7d375a117ec66fa58871a52d456da5287b1c1c18f214da32cf56ff94d1736d3da6846f074745ec08596c6d627282f442cc5f5f3c295703c8eb0da8b3df6de781fdf305a5b14094dd17b88cfb87ad5e6ff8f270cc6e239abce0d8dedc8305cae170d42f57734f824d8efa6ee07317dcdeee7cf723be87d4ca2f0b0f62b1c0e44ca17a0de3196530b398dfd4a556bfce04f4e359d86aa2564c77d256f8f884195e3783d54152ac9d39c0da191c05e4cfe9b205ad243c86a480cccd75d6d5030e54c995c8ade802323f69620f6b800c29da5462b95fd3341de209dd46c1229914da6caeb9d3c3212d83680e5042e0cfb711c630f08a1f4d739d751353acf0e8d6fa5ad3b49b82989570d87ddd738e49be106f5bcd627be97f10fb347e2b778f91b27cf36bfb7928805b79e024e94e55c9848da048d2688a3bd2297f88139f3434498f0e0d508154dc96dcf0f7a2b7533752b8218c4cf9abacda3cd75e0cb85084ff060eb4338ddf79cdfe63e96802178fcf9c020b70851f46555983d1cad6f52b27f6c362021562323ae29dcc794439051a70feaa7f776ed266f8f131c0e5322989ab7e98e0a75d601b602d07ca39d595ac69e717a5c142441e7a0a44c09abdb2b4611279718878c1e84acc53608ca94ec17408a3874a0612a53e862bf959dc0315c78a92c6f518de423054055ee0d003615908ceef0d832421885a46d28623f65a5b2a6adfab4b85426a3375c12f0b9355beb6a48d971d5349e5daf156d6fc2d33e09bad3b00e906ec985bce922afaa67e5c0a09bcf4910f31ac45505b22d44a35394bfea2ab05884ce72caeec4f3b824a7a15842b50966e3f7624e79bdd897b0107d31c6838
2016-11-22 20:52:59 +01:00
![Creative Commons License ](https://i.creativecommons.org/l/by/4.0/88x31.png "License CC-BY" )
< br >
This work is licensed under a [Creative Commons Attribution 4.0 International License ](http://creativecommons.org/licenses/by/4.0/ ).