330 lines
14 KiB
HTML
330 lines
14 KiB
HTML
{% extends "global/layout.html" %}
|
|
{% block title %}ElGamal/AES + SessionTag Encryption{% endblock %}
|
|
{% block content %}
|
|
Updated February 2011, current as of router version 0.8.3
|
|
<h2>Overview</h2>
|
|
<p>
|
|
ElGamal/AES+SessionTags is used for end-to-end encryption.
|
|
</p>
|
|
<p> As an unreliable, unordered, message based system, I2P uses a simple combination
|
|
of asymmetric and symmetric encryption algorithms to provide data confidentiality
|
|
and integrity to garlic messages. As a whole, the combination is referred
|
|
to as ElGamal/AES+SessionTags, but that is an excessively verbose way to describe
|
|
the use of 2048bit ElGamal, AES256, SHA256, and 32 byte nonces. </p>
|
|
<p> The first time a router wants to encrypt a garlic message to another router,
|
|
they encrypt the keying material for an AES256 session key with ElGamal and
|
|
append the AES256/CBC encrypted payload after that encrypted ElGamal block.
|
|
In addition to the encrypted payload, the AES encrypted section contains the
|
|
payload length, the SHA256 hash of the unencrypted payload, as well as a number
|
|
of "session tags" - random 32 byte nonces. The next time the sender wants
|
|
to encrypt a garlic message to another router, rather than ElGamal encrypt
|
|
a new session key they simply pick one of the previously delivered session
|
|
tags and AES encrypt the payload like before, using the session key used with
|
|
that session tag, prepended with the session tag itself. When a router receives
|
|
a garlic encrypted message, they check the first 32 bytes to see if it matches
|
|
an available session tag - if it does, they simply AES decrypt the message,
|
|
but if it does not, they ElGamal decrypt the first block. </p>
|
|
<p> Each session tag can be used only once so as to prevent internal adversaries
|
|
from unnecessarily correlating different messages as being between the same
|
|
routers. The sender of an ElGamal/AES+SessionTag encrypted message chooses
|
|
when and how many tags to deliver, prestocking the recipient with enough tags
|
|
to cover a volley of messages. Garlic messages may detect the successful tag
|
|
delivery by bundling a small additional message as a clove (a "delivery status
|
|
message") - when the garlic message arrives at the intended recipient and
|
|
is decrypted successfully, this small delivery status message is one of the
|
|
cloves exposed and has instructions for the recipient to send the clove back
|
|
to the original sender (through an inbound tunnel, of course). When the original
|
|
sender receives this delivery status message, they know that the session tags
|
|
bundled in the garlic message were successfully delivered. </p>
|
|
<p> Session tags themselves have a short lifetime, after which they are
|
|
discarded if not used. In addition, the quantity stored for each key is limited,
|
|
as are the number of keys themselves - if too many arrive, either new or old
|
|
messages may be dropped. The sender keeps track whether messages using session
|
|
tags are getting through, and if there isn't sufficient communication it may
|
|
drop the ones previously assumed to be properly delivered, reverting back
|
|
to the full expensive ElGamal encryption.
|
|
A session will continue to exist until all its tags are exhausted or expire.
|
|
</p><p>
|
|
Sessions are unidirectional. Tags are delivered from Alice to Bob,
|
|
and Alice then uses the tags, one by one, in subsequent messages to Bob.
|
|
</p><p>
|
|
Sessions may be established between Destinations, between Routers, or
|
|
between a Router and a Destination.
|
|
Each Router and Destination maintains its own Session Key Manager to
|
|
keep track of Session Keys and Session Tags.
|
|
Separate Session Key Managers prevents correlation of multiple Destinations
|
|
to each other or a Router by adversaries.
|
|
</p>
|
|
|
|
|
|
|
|
<h2>Message Reception</h2>
|
|
<p>
|
|
Each message received has one of two
|
|
the two possible conditions:</p>
|
|
|
|
<OL>
|
|
<li> It is part of an existing session and contains a Session Tag and an AES encrypted block</li>
|
|
<li> It is for a new session and contains both ElGamal and AES encrypted blocks</li>
|
|
</OL>
|
|
When a router receives a message, it will first assume it is from
|
|
an existing session and attempt to look up the Session Tag and decrypt the following data using AES.
|
|
If that fails, it will assume it is for a new session and attempt to
|
|
decrypt it using ElGamal.
|
|
</p>
|
|
|
|
|
|
|
|
<h2 id="new">New Session Message Specification</h2>
|
|
<p>
|
|
A New Session ElGamal Message contains two parts, an encrypted ElGamal block
|
|
and an encrypted AES block.
|
|
</p><p>
|
|
The encrypted message contains:
|
|
<PRE>
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| ElGamal Encrypted Block |
|
|
~ ~
|
|
| |
|
|
+ +----+----+----+----+----+----+
|
|
| | |
|
|
+----+----+ +
|
|
| |
|
|
+ +
|
|
| AES Encrypted Block |
|
|
~ ~
|
|
| |
|
|
+ +----+----+----+----+----+----+
|
|
| +
|
|
+----+----+
|
|
|
|
</PRE>
|
|
</p>
|
|
<h3>ElGamal Block</h3>
|
|
<p>
|
|
The encrypted ElGamal Block is always 514 bytes long.
|
|
</p><p>
|
|
The unencrypted ElGamal data is 222 bytes long, containing:
|
|
<PRE>
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| Session Key |
|
|
+ +
|
|
| |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| Pre-IV |
|
|
+ +
|
|
| |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
+ +
|
|
| |
|
|
+ +
|
|
| 158 bytes random padding |
|
|
~ ~
|
|
| |
|
|
+ +----+----+
|
|
| |
|
|
+----+----+----+----+----+----+
|
|
</PRE>
|
|
The 32-byte
|
|
<a href="common_structures_spec#type_SessionKey">Session Key</a>
|
|
is the identifier for the session.
|
|
The 32-byte Pre-IV will be used to generate the IV for the AES block that follows;
|
|
the IV is the first 16 bytes of the SHA-256 Hash of the Pre-IV.
|
|
</p><p>
|
|
The 222 byte payload is encrypted
|
|
<a href="{{ site_url('docs/how/cryptography') }}#elgamal">using ElGamal</a>
|
|
and the encrypted block is 514 bytes long.
|
|
</p>
|
|
|
|
<h3 id="aes">AES Block</h3>
|
|
<p>The unencrypted data in the AES block contains the following:
|
|
<PRE>
|
|
+----+----+----+----+----+----+----+----+
|
|
|tag count| |
|
|
+----+----+ +
|
|
| |
|
|
+ +
|
|
| Session Tags |
|
|
~ ~
|
|
| |
|
|
+ +
|
|
| |
|
|
+ +----+----+----+----+----+----+
|
|
| | payload size | |
|
|
+----+----+----+----+----+----+ +
|
|
| |
|
|
+ +
|
|
| Payload Hash |
|
|
+ +
|
|
| |
|
|
+ +----+----+
|
|
| |flag| |
|
|
+----+----+----+----+----+----+----+ +
|
|
| |
|
|
+ +
|
|
| New Session Key (opt.) |
|
|
+ +
|
|
| |
|
|
+ +----+
|
|
| | |
|
|
+----+----+----+----+----+----+----+ +
|
|
| |
|
|
+ +
|
|
| Payload |
|
|
~ ~
|
|
| |
|
|
+ +----//---+----+
|
|
| | |
|
|
+----+----+----//---+----+ +
|
|
| Padding to 16 bytes |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
tag count: 2-byte <a href="common_structures_spec#type_Integer">Integer</a>, 0-200
|
|
|
|
Session Tags: That many 32-byte <a href="common_structures_spec#type_SessionTag">Session Tags</a>
|
|
|
|
payload size: 4-byte <a href="common_structures_spec#type_Integer">Integer</a>
|
|
|
|
Payload Hash: The 32-byte <a href="common_structures_spec#type_Hash">SHA256 Hash</a> of the payload
|
|
|
|
flag: A one-byte value. Normally == 0. If == 0x01, a Session Key follows
|
|
|
|
New Session Key: A 32-byte <a href="common_structures_spec#type_SessionKey">Session Key</a>,
|
|
to replace the old key, and is only present if preceding flag is 0x01
|
|
|
|
Payload: the data
|
|
|
|
Padding: Random data to a multiple of 16 bytes for the total length.
|
|
May contain more than the minimum required padding.
|
|
|
|
Minimum length: 48 bytes
|
|
|
|
</PRE>
|
|
|
|
</p><p>
|
|
The data is then <a href="{{ site_url('docs/how/cryptography') }}">AES Encrypted</a>,
|
|
using the session key and IV (calculated from the pre-IV) from the ElGamal section.
|
|
The encrypted AES Block length is variable but is always a multiple of 16 bytes.
|
|
</p>
|
|
<h4>Notes</h4>
|
|
<ul>
|
|
<li>
|
|
Actual max payload length, and max block length, is less than 64 KB; see the <a href="i2np.html">I2NP Overview</a>.
|
|
</li><li>
|
|
New Session Key is currently unused and is never present.
|
|
</li></ul>
|
|
|
|
|
|
|
|
<h2 id="existing">Existing Session Message Specification</h2>
|
|
|
|
<p>The session tags delivered successfully are remembered for a
|
|
brief period (15 minutes currently) until they are used or discarded.
|
|
A tag is used by packaging one in an Existing Session Message that
|
|
contains only an AES encrypted block, and
|
|
is not preceded by an
|
|
ElGamal block.
|
|
</p><p?>
|
|
The existing session message is
|
|
as follows:
|
|
|
|
<PRE>
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| Session Tag |
|
|
+ +
|
|
| |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ +
|
|
| AES Encrypted Block |
|
|
~ ~
|
|
| |
|
|
+ +
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
Session Tag: A 32-byte <a href="common_structures_spec#type_SessionTag">Session Tag</a>
|
|
previously delivered in an AES block
|
|
|
|
AES Encrypyted Block: As specified <a href="#aes">above</a>.
|
|
|
|
</PRE>
|
|
The session tag also serves as
|
|
the pre-IV. The IV is the first 16 bytes of the SHA-256 Hash of the sessionTag.
|
|
</p><p>
|
|
To decode a message from an existing session, a router looks up the Session Tag to find an
|
|
associated Session Key. If the Session Tag is found, the AES block is decrypted using the associated Session Key.
|
|
If the tag is not found, the message is assumed to be a <a href="#new">New Session Message</a>.
|
|
</p>
|
|
|
|
|
|
|
|
<h2 id="future">Future Work</h2>
|
|
<p>
|
|
There are many possible areas to tune the Session Key Manager's algorithms;
|
|
some may interact with the streaming library behavior, or have significant
|
|
impact on overall performance.
|
|
<ul><li>
|
|
Delivery of too many tags at one time may impose substantial overhead for brief streaming connections
|
|
or datagrams, and increase the chance of message loss.
|
|
We currently deliver 40 tags at a time (1280 bytes).
|
|
32 (1024 bytes) may be better for tunnel fragmentation.
|
|
</li><li>
|
|
A few tags could be delivered in each of several messages, or lots of tags all at once.
|
|
</li><li>
|
|
It is also important to study and tune
|
|
the low-tag thresholds at which more tags are sent.
|
|
</li><li>
|
|
The number of tags delivered could depend on message size, keeping in mind
|
|
the eventual padding to 1KB at the tunnel message layer.
|
|
</li><li>
|
|
Clients could send an estimate of session lifetime to the router, as an advisory
|
|
on the number of tags required.
|
|
</li><li>
|
|
Delivery of too few tags causes the router to fall back to an expensive ElGamal encryption.
|
|
</li><li>
|
|
The router may assume delivery of Session Tags, or await acknowledgement before using them;
|
|
there are tradeoffs for each strategy.
|
|
</li><li>
|
|
For very brief messages, almost the full 222 bytes of the pre-IV and padding fields in the ElGamal block
|
|
could be used for the entire message, instead of establishing a session.
|
|
</li><li>
|
|
Evaluate padding strategy; currently we pad to a minimum of 128 bytes.
|
|
Would be better to add a few tags to small messages than pad.
|
|
</li><li>
|
|
Perhaps things could be more efficient if the Session Tag system was bidirectional,
|
|
so tags delivered in the 'forward' path could be used in the 'reverse' path,
|
|
thus avoiding ElGamal in the initial response.
|
|
The router currently plays some tricks like this when sending
|
|
tunnel test messages to itself.
|
|
</li><li>
|
|
Change from Session Tags to
|
|
<a href="performance.html#prng">a synchronized PRNG</a>.
|
|
</li><li>
|
|
Several of these ideas may require a new I2NP message type, or
|
|
set a flag in the
|
|
<a href="tunnel_message_spec.html#delivery">Delivery Instructions</a>,
|
|
or set a magic number in the first few bytes of the Session Key field
|
|
and accept a small risk of the random Session Key matching the magic number.
|
|
</li></ul>
|
|
|
|
</p>
|
|
|
|
|
|
|
|
{% endblock %}
|