2006-01-17 jrandom
* First pass of the new tunnel creation crypto, specified in the new router/doc/tunnel-alt-creation.html (referenced in the current router/doc/tunnel-alt.html). It isn't actually used anywhere yet, other than in the test code, but the code verifies the technical viability, so further scrutiny would be warranted.
This commit is contained in:
161
router/doc/tunnel-alt-creation.html
Normal file
161
router/doc/tunnel-alt-creation.html
Normal file
@ -0,0 +1,161 @@
|
||||
<code>$Id: tunnel-alt.html,v 1.9 2005/07/27 14:04:07 jrandom Exp $</code>
|
||||
<pre>
|
||||
1) <a href="#tunnelCreate.overview">Tunnel creation</a>
|
||||
1.1) <a href="#tunnelCreate.requestRecord">Tunnel creation request record</a>
|
||||
1.2) <a href="#tunnelCreate.hopProcessing">Hop processing</a>
|
||||
1.3) <a href="#tunnelCreate.replyRecord">Tunnel creation reply record</a>
|
||||
1.4) <a href="#tunnelCreate.requestPreparation">Request preparation</a>
|
||||
1.5) <a href="#tunnelCreate.requestDelivery">Request delivery</a>
|
||||
1.6) <a href="#tunnelCreate.endpointHandling">Endpoint handling</a>
|
||||
1.7) <a href="#tunnelCreate.replyProcessing">Reply processing</a>
|
||||
2) <a href="#tunnelCreate.notes">Notes</a>
|
||||
</pre>
|
||||
|
||||
<h2 id="tunnelCreate.overview">1) Tunnel creation encryption:</h2>
|
||||
|
||||
<p>The tunnel creation is accomplished by a single message passed along
|
||||
the path of peers in the tunnel, rewritten in place, and transmitted
|
||||
back to the tunnel creator. This single tunnel message is made up
|
||||
of a fixed number of records (8) - one for each potential peer in
|
||||
the tunnel. Individual records are asymmetrically encrypted to be
|
||||
read only by a specific peer along the path, while an additional
|
||||
symmetric layer of encryption is added at each hop so as to expose
|
||||
the asymmetrically encrypted record only at the appropriate time.</p>
|
||||
|
||||
<h3 id="tunnelCreate.requestRecord">1.1) Tunnel creation request record</h3>
|
||||
|
||||
<p>Cleartext of the record, visible only to the hop being asked:</p><pre>
|
||||
bytes 0-3: tunnel ID to receive messages as
|
||||
bytes 4-35: local router identity hash
|
||||
bytes 36-39: next tunnel ID
|
||||
bytes 40-71: next router identity hash
|
||||
bytes 72-103: AES-256 tunnel layer key
|
||||
bytes 104-135: AES-256 tunnel IV key
|
||||
bytes 136-167: AES-256 reply key
|
||||
bytes 168-183: reply IV
|
||||
byte 184: flags
|
||||
bytes 185-188: request time (in hours since the epoch)
|
||||
bytes 189-222: uninterpreted / random padding</pre>
|
||||
|
||||
<p>The next tunnel ID and next router identity hash fields are used to
|
||||
specify the next hop in the tunnel, though for an outbound tunnel
|
||||
endpoint, they specify where the rewritten tunnel creation reply
|
||||
message should be sent.</p>
|
||||
|
||||
<p>The flags field currently has two bits defined:</p><pre>
|
||||
bit 0: if set, allow messages from anyone
|
||||
bit 1: if set, allow messages to anyone, and send the reply to the
|
||||
specified next hop in a tunnel message</pre>
|
||||
|
||||
<p>That cleartext record is ElGamal 2048 encrypted with the hop's
|
||||
public encryption key and formatted into a 528 byte record:</p><pre>
|
||||
bytes 0-15: SHA-256-128 of the current hop's router identity
|
||||
bytes 16-527: ElGamal-2048 encrypted request record</pre>
|
||||
|
||||
<p>Since the cleartext uses the full field, there is no need for
|
||||
additional padding beyond <code>SHA256(cleartext) + cleartext</code>.</p>
|
||||
|
||||
<h3 id="tunnelCreate.hopProcessing">1.2) Hop processing</h3>
|
||||
|
||||
<p>When a hop receives a TunnelBuildMessage, it looks through the 8
|
||||
records contained within it for one starting with their own identity
|
||||
hash (trimmed to 8 bytes). It then decryptes the ElGamal block from
|
||||
that record and retrieves the protected cleartext. At that point,
|
||||
they make sure the tunnel request is not a duplicate by feeding the
|
||||
AES-256 reply key into a bloom filter and making sure the request
|
||||
time is within an hour of current. Duplicates or invalid requests
|
||||
are dropped.</p>
|
||||
|
||||
<p>After deciding whether they will agree to participate in the tunnel
|
||||
or not, they replace the record that had contained the request with
|
||||
an encrypted reply block. All other records are AES-256/CBC
|
||||
encrypted with the included reply key and IV (though each is
|
||||
encrypted separately, rather than chained across records).</p>
|
||||
|
||||
<h3 id="tunnelCreate.replyRecord">1.3) Tunnel creation reply record</h3>
|
||||
|
||||
<p>After the current hop reads their record, they replace it with a
|
||||
reply record stating whether or not they agree to participate in the
|
||||
tunnel, and if they do not, they classify their reason for
|
||||
rejection. This is simply a 1 byte value, with 0x0 meaning they
|
||||
agree to participate in the tunnel, and higher values meaning higher
|
||||
levels of rejection. The reply is encrypted with the AES session
|
||||
key delivered to it in the encrypted block, padded with random data
|
||||
until it reaches the full record size:</p><pre>
|
||||
AES-256-CBC(SHA-256(padding+status) + padding + status, key, IV)</pre>
|
||||
|
||||
<h3 id="tunnelCreate.requestPreparation">1.4) Request preparation</h3>
|
||||
|
||||
<p>When building a new request, all of the records must first be
|
||||
built and asymmetrically encrypted. Each record should then be
|
||||
decrypted with the reply keys and IVs of the hops earlier in the
|
||||
path. That decryption should be run in reverse order so that the
|
||||
asymmetrically encrypted data will show up in the clear at the
|
||||
right hop after their predecessor encrypts it.</p>
|
||||
|
||||
<p>The excess records not needed for individual requests are simply
|
||||
filled with random data by the creator.</p>
|
||||
|
||||
<h3 id="tunnelCreate.requestDelivery">1.5) Request delivery</h3>
|
||||
|
||||
<p>For outbound tunnels, the delivery is done directly from the tunnel
|
||||
creator to the first hop, packaging up the TunnelBuildMessage as if
|
||||
the creator was just another hop in the tunnel. For inbound
|
||||
tunnels, the delivery is done through an existing outbound tunnel
|
||||
(and during startup, when no outbound tunnel exists yet, a fake 0
|
||||
hop outbound tunnel is used).</p>
|
||||
|
||||
<h3 id="tunnelCreate.endpointHandling">1.6) Endpoint handling</h3>
|
||||
|
||||
<p>When the request reaches an outbound endpoint (as determined by the
|
||||
'allow messages to anyone' flag), the hop is processed as usual,
|
||||
encrypting a reply in place of the record and encrypting all of the
|
||||
other records, but since there is no 'next hop' to forward the
|
||||
TunnelBuildMessage on to, it instead places the encrypted reply
|
||||
records into a TunnelBuildReplyMessage and delivers it to the
|
||||
reply tunnel specified within the request record. That reply tunnel
|
||||
forwards the reply records down to the tunnel creator for
|
||||
processing, as below.</p>
|
||||
|
||||
<p>When the request reaches the inbound endpoint (also known as the
|
||||
tunnel creator), the router processes each of the replies, as below.</p>
|
||||
|
||||
<h3 id="tunnelCreate.replyProcessing">1.7) Reply processing</h3>
|
||||
|
||||
<p>To process the reply records, the creator simply has to AES decrypt
|
||||
each record individually, using the reply key and IV of each hop in
|
||||
the tunnel after the peer (in reverse order). This then exposes the
|
||||
reply specifying whether they agree to participate in the tunnel or
|
||||
why they refuse. If they all agree, the tunnel is considered
|
||||
created and may be used immediately, but if anyone refuses, the
|
||||
tunnel is discarded.</p>
|
||||
|
||||
<h2 id="tunnelCreate.notes">2) Notes</h2>
|
||||
<ul>
|
||||
<li>This does not prevent two hostile peers within a tunnel from
|
||||
tagging one or more request or reply records to detect that they are
|
||||
within the same tunnel, but doing so can be detected by the tunnel
|
||||
creator when reading the reply, causing the tunnel to be marked as
|
||||
invalid.</li>
|
||||
<li>This does not include a proof of work on the asymmetrically
|
||||
encrypted section, though the 16 byte identity hash could be cut in
|
||||
half with the later replaced by a hashcash function of up to 2^64
|
||||
cost. This will not immediately be pursued, however.</li>
|
||||
<li>This alone does not prevent two hostile peers within a tunnel from
|
||||
using timing information to determine whether they are in the same
|
||||
tunnel. The use of batched and synchronized request delivery
|
||||
could help (batching up requests and sending them off on the
|
||||
(ntp-synchronized) minute). However, doing so lets peers 'tag' the
|
||||
requests by delaying them and detecting the delay later in the
|
||||
tunnel, though perhaps dropping requests not delivered in a small
|
||||
window would work (though doing that would require a high degree of
|
||||
clock synchronization). Alternately, perhaps individual hops could
|
||||
inject a random delay before forwarding on the request?</li>
|
||||
<li>Are there any nonfatal methods of tagging the request?</li>
|
||||
<li>This strategy came about during a discussion on the I2P mailing list
|
||||
between Michael Rogers, Matthew Toseland (toad), and jrandom regarding
|
||||
the predecessor attack. See: <ul>
|
||||
<li><a href="http://dev.i2p.net/pipermail/i2p/2005-October/001073.html">Summary</a></li>
|
||||
<li><a href="http://dev.i2p.net/pipermail/i2p/2005-October/001064.html">Reasoning</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
@ -1,4 +1,4 @@
|
||||
<code>$Id: tunnel-alt.html,v 1.8 2005/07/07 16:16:57 jrandom Exp $</code>
|
||||
<code>$Id: tunnel-alt.html,v 1.9 2005/07/27 14:04:07 jrandom Exp $</code>
|
||||
<pre>
|
||||
1) <a href="#tunnel.overview">Tunnel overview</a>
|
||||
2) <a href="#tunnel.operation">Tunnel operation</a>
|
||||
@ -329,11 +329,11 @@ tunnel to be scrapped and the profiles for peers within it to be adjusted.</p>
|
||||
<h2>3) <a name="tunnel.building">Tunnel building</a></h2>
|
||||
|
||||
<p>When building a tunnel, the creator must send a request with the necessary
|
||||
configuration data to each of the hops in turn, starting with the endpoint,
|
||||
waiting for their reply, then moving on to the next earlier hop. These tunnel request
|
||||
messages and their replies are garlic wrapped so that only the router who knows
|
||||
the key can decrypt it, and the path taken in both directions is tunnel routed
|
||||
as well. There are three important dimensions to keep in mind when producing
|
||||
configuration data to each of the hops and wait for all of them to agree before
|
||||
enabling the tunnel. The requests are encrypted so that only the peers who need
|
||||
to know a piece of information (such as the tunnel layer or IV key) has that
|
||||
data. In addition, only the tunnel creator will have access to the peer's
|
||||
reply. There are three important dimensions to keep in mind when producing
|
||||
the tunnels: what peers are used (and where), how the requests are sent (and
|
||||
replies received), and how they are maintained.</p>
|
||||
|
||||
@ -376,30 +376,12 @@ as controls for the user to select which strategy to use for individual clients.
|
||||
|
||||
<h3>3.2) <a name="tunnel.request">Request delivery</a></h3>
|
||||
|
||||
<p>As mentioned above, once the tunnel creator knows what peers should go into
|
||||
a tunnel and in what order, the creator builds a series of tunnel request
|
||||
messages, each containing the necessary information for that peer. For instance,
|
||||
participating tunnels will be given the 4 byte nonce with which to reply with,
|
||||
the 4 byte tunnel ID on which they are to send out the messages,
|
||||
the 32 byte hash of the next hop's identity, the 32 byte layer key used to
|
||||
remove a layer from the tunnel, and a 32 byte IV key used to encrypt the IV.
|
||||
Of course, outbound tunnel endpoints are not
|
||||
given any "next hop" or "next tunnel ID" information. To allow
|
||||
replies, the request contains a random session tag and a random session key with
|
||||
which the peer should garlic encrypt their decision, as well as the tunnel to which
|
||||
that garlic should be sent. In addition to the above information, various client
|
||||
specific options may be included, such as what throttling to place on the tunnel,
|
||||
what padding or batch strategies to use, etc.</p>
|
||||
|
||||
<p>After building all of the request messages, they are garlic wrapped for the
|
||||
target router and sent out an exploratory tunnel. Upon receipt, that peer
|
||||
determines whether they can or will participate, and if it will, it selects the
|
||||
tunnel ID on which it will receive messages. It then garlic wraps and tunnel
|
||||
routes that agreement, tunnel ID, and the nonce provided in the request using the
|
||||
supplied information (session tag, garlic session key, tunnel ID to reply to, and
|
||||
router on which that tunnel listens). Upon receipt of the reply at the tunnel
|
||||
creator, the tunnel is considered valid on that hop (if accepted). Once all
|
||||
peers have accepted, the tunnel is active.</p>
|
||||
<p>A new tunnel request preparation, delivery, and response method has been
|
||||
<a href="tunnel-alt-creation.html">devised</a>, which reduces the number of
|
||||
predecessors exposed, cuts the number of messages transmitted, verifies proper
|
||||
connectivity, and avoids the message counting attack of traditional telescopic
|
||||
tunnel creation. The old technique is listed below as an <a
|
||||
href="#tunnel.building.exploratory">alternative</a>.</p>
|
||||
|
||||
<p>Peers may reject tunnel creation requests for a variety of reasons, though
|
||||
a series of four increasingly severe rejections are known: probabalistic rejection
|
||||
@ -438,10 +420,9 @@ including the tunnel creator in that set), another alternative is to use the
|
||||
tunnel pathways themselves to pass along the request and response, as is done
|
||||
in <a href="http://tor.eff.org/">TOR</a>. This, however, may lead to leaks
|
||||
during tunnel creation, allowing peers to discover how many hops there are later
|
||||
on in the tunnel by monitoring the timing or packet count as the tunnel is
|
||||
built. Techniques could be used to minimize this issue, such as using each of
|
||||
the hops as endpoints (per <a href="#tunnel.reroute">2.7.2</a>) for a random
|
||||
number of messages before continuing on to build the next hop.</p>
|
||||
on in the tunnel by monitoring the timing or <a
|
||||
href="http://dev.i2p.net/pipermail/2005-October/001057.html">packet count</a> as
|
||||
the tunnel is built.</p>
|
||||
|
||||
<h4>3.4.2) <a name="tunnel.building.nonexploratory">Non-exploratory tunnels for management</a></h4>
|
||||
|
||||
@ -452,6 +433,14 @@ of the network, this should not be necessary, but if the router was partitioned
|
||||
in some way, using non-exploratory pools for tunnel management would reduce the
|
||||
leakage of information about what peers are in the router's partition.</p>
|
||||
|
||||
<h4>3.4.3) <a name="tunnel.building.exploratory">Exploratory request delivery</a></h4>
|
||||
|
||||
<p>A third alternative, used until I2P 0.6.2, garlic encrypts individual tunnel
|
||||
request messages and delivers them to the hops individually, transmitting them
|
||||
through exploratory tunnels with their reply coming back in a separate
|
||||
exploratory tunnel. This strategy has been dropped in favor of the one outlined
|
||||
above.</p>
|
||||
|
||||
<h2>4) <a name="tunnel.throttling">Tunnel throttling</a></h2>
|
||||
|
||||
<p>Even though the tunnels within I2P bear a resemblance to a circuit switched
|
||||
|
Reference in New Issue
Block a user