latest data structures spec (v 1.6, 2003/08/01)
<auto97841-revL73yDgGBWk0Htik3J/[email protected]> Fri, 1 Aug 2003 13:34:28 -0700
| Newsgroups | gmane.comp.security.invisiblenet.iip.devel |
|---|---|
| Message-ID | <[email protected]> |
ok, updated the data structures spec in cvs, and attached here. changes include: - the new dual-scenario Payload encryption (as described before) - the AES IV location in the Payload structure - the shrinking of the Payload size structure to at most 2^32+4 bytes - the addition of the MessagePayloadMessage - the addition of DSA keys (PublicSigningKey and PrivateSigningKey), with the associated change to the Signature structure Still left to be implemented in the Java I2P Client API: - finish up the crypto - implement the hashcash - debug Hezekiah, et al> I still owe you a spec on the proper I2CP message sequence. The code in net.invisiblenet.i2p.cient.*MessageHandler and I2CPMessageProducer implements the scenario, but I'll doc that up this weekend (as well as the administrative side of things) -jrandom
datastructures.html
(text/html, 44.7 KB)
<html>
<header>
<title>I2P Data Structures Specification $Revision: 1.6 $ $Date: 2003/08/01 20:57:12 $</title>
</header>
<body><a name="Contents"> </a>
<table border="1" >
<tr>
<td width="10%" nowrap valign="top">
<ol>
<li><a href="#DataTypes">Data Types</a><ol>
<li><a href="#Integer">Integer</a></li>
<li><a href="#Date">Date</a></li>
<li><a href="#String">String</a></li>
<li><a href="#Boolean">Boolean</a></li>
<li><a href="#Mapping">Mapping</a></li>
<li><a href="#PublicKey">Public Key</a></li>
<li><a href="#PrivateKey">Private Key</a></li>
<li><a href="#SessionKey">Session Key</a></li>
<li><a href="#SigningPublicKey">Signing Public Key</a></li>
<li><a href="#SigningPrivateKey">Signing Private Key</a></li>
<li><a href="#Signature">Signature</a></li>
<li><a href="#Hash">Hash</a></li>
<li><a href="#Certificate">Certificate</a></li></ol></li>
<li><a href="#CommonStructures">Common Structures</a><ol>
<li><a href="#Destination">Destination</a></li>
<li><a href="#Lease">Lease</a></li>
<li><a href="#LeaseRevocation">LeaseRevocation</a></li>
<li><a href="#LeaseRevocationPrivateKey">LeaseRevocationPrivateKey</a></li>
<li><a href="#Payload">Payload</a></li>
<li><a href="#RouterIdentity">RouterIdentity</a></li>
<li><a href="#RouterInfo">RouterInfo</a></li>
<li><a href="#RouterAddress">RouterAddress</a></li>
<li><a href="#TunnelId">TunnelId</a></li></ol></li>
<li><a href="#I2PCPStructures">I2P Client Protocol Structures</a><ol>
<li><a href="#SessionConfig">SessionConfig</a></li>
<li><a href="#SessionId">SessionId</a></li>
<li><a href="#MessageId">MessageId</a></li>
<li><a href="#AuthenticationKey">AuthenticationKey</a></li>
<li><a href="#BandwidthLimits">BandwidthLimits</a></li>
<li><a href="#AbuseReason">AbuseReason</a></li>
<li><a href="#AbuseSeverity">AbuseSeverity</a></li></ol></li>
<li><a href="#I2PCPMessages">I2P Client Protocol Messages</a><ol>
<li><a href="#ClientToRouterMessages">Client To Router</a><ol>
<li><a href="#CreateSessionMessage">CreateSessionMessage</a></li>
<li><a href="#ReconfigureSessionMessage">ReconfigureSessionMessage</a></li>
<li><a href="#DestroySessionMessage">DestroySessionMessage</a></li>
<li><a href="#CreateLeaseMessage">CreateLeaseMessage</a></li>
<li><a href="#SendMessageMessage">SendMessageMessage</a></li>
<li><a href="#ReceiveMessageBeginMessage">ReceiveMessageBeginMessage</a></li>
<li><a href="#ReceiveMessageEndMessage">ReceiveMessageEndMessage</a></li></ol></li>
<li><a href="#ClientAdminToRouterMessages">Client Admin To Router</a><ol>
<li><a href="#GetBandwidthLimitsMessage">GetBandwidthLimitsMessage</a></li>
<li><a href="#SetBandwidthLimitsMessage">SetBandwidthLimitsMessage</a></li>
<li><a href="#GetTrustedRoutersMessage">GetTrustedRoutersMessage</a></li>
<li><a href="#SetTrustedRoutersMessage">SetTrustedRoutersMessage</a></li>
<li><a href="#GetAddressVisibilityMessage">GetAddressVisibilityMessage</a></li>
<li><a href="#SetAddressVisibilityMessage">SetAddressVisibilityMessage</a></li>
<li><a href="#GetAddressRotationPeriodMessage">GetAddressRotationPeriodMessage</a></li>
<li><a href="#SetAddressRotationPeriodMessage">SetAddressRotationPeriodMessage</a></li>
<li><a href="#ForceAddressRotationMessage">ForceAddressRotationMessage</a></li>
<li><a href="#GetPeersMessage">GetPeersMessage</a></li>
<li><a href="#SetPeersMessage">SetPeersMessage</a></li>
<li><a href="#SetPasswordMessage">SetPasswordMessage</a></li></ol></li>
<li><a href="#RouterToClientMessages">Router To Client</a><ol>
<li><a href="#SessionStatusMessage">SessionStatusMessage</a></li>
<li><a href="#RequestLeaseMessage">RequestLeaseMessage</a></li>
<li><a href="#MessageStatusMessage">MessageStatusMessage</a></li>
<li><a href="#MessagePayloadMessage">MessagePayloadMessage</a></li></ol></li>
<li><a href="#RouterToClientAdminMessages">Router To Client Admin</a><ol>
<li><a href="#BandwidthLimitsMessage">BandwidthLimitsMessage</a></li>
<li><a href="#TrustedRoutersMessage">TrustedRoutersMessage</a></li>
<li><a href="#AddressVisibilityMessage">AddressVisibilityMessage</a></li>
<li><a href="#AddressRotationPeriodMessage">AddressRotationPeriodMessage</a></li>
<li><a href="#LastAddressRotationMessage">LastAddressRotationMessage</a></li>
<li><a href="#PeersMessage">PeersMessage</a></li></ol></li>
<li><a href="#BidirectionalMessages">Bidirectional</a><ol>
<li><a href="#ReportAbuseMessage">ReportAbuseMessage</a></li>
<li><a href="#DisconnectMessage">DisconnectMessage</a></li></ol></li></ol></li>
<li><a href="#Todo">Todo</a></li>
<li><a href="#Changes">Changes</a></li>
</ol>
</td>
<td valign="top">
<b><font color="red">Note: Images have not been updated lately and the text is authoritative. If someone
could update the images to match the spec, that'd be great. if not, the images should be pulled</font></b><p />
<h1>Data Types<a name="DataTypes"></a> <font size="-1"><a href="#Contents">(top)</a></font></h1>
<h2>Integer<a name="Integer"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
Integers are a fixed number of bytes (1, 2, 4, 8), stored as unsigned integers in network byte order.<br />
<img src="bitfields/Integer.png">
<h2>Date<a name="Date"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A date is an 8 byte unsigned integer in network byte order specifying the
number of milliseconds since midnight on January 1, 1970 in the GMT timezone.
If the number is 0, the date is undefined or null. (yes, this means you can't represent
midnight on 1/1/1970)<br />
<img src="bitfields/Date.png">
<h2>String<a name="String"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A string is 1 or more bytes where the first byte is the number of bytes (not characters!) in the string and
the remaining 0-255 bytes are the non-null terminated UTF-8 encoded character array.<br />
<img src="bitfields/String.png">
<h2>Boolean<a name="Boolean"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A boolean is 1 byte that is either 0 (false), 1 (true), or 2 (null)<br />
<img src="bitfields/Boolean.png">
<h2>Mapping<a name="Mapping"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A mapping is a set of key / value pairs. It starts with a 2 byte <a href="#Integer">Integer</a>
defining how many bytes make up the mapping. After that comes that many bytes making up a set of
UTF-8 encoded characters. The characters are organized as <code>key=value;</code>. The key is a
<a href="#String">String</a> unique as a key within the current mapping that does not include the UTF-8 characters
'=' or ';'. After the key comes the literal UTF-8 character '='. After that comes a <a href="#String">String</a>
for the value. Finally after that comes the literal UTF-8 character ';'. This <code>key=value;</code> is
repeated until there are no more bytes (not characters!) left as defined by the first two byte integer.<br />
<img src="bitfields/Mapping.png">
<h2>Public Key<a name="PublicKey"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A public key is 256byte <a href="#Integer">Integer</a> used for ElGamal encryption. The public key represents only the exponent,
not the primes, which are constant and defined in the crypto spec.<br />
<img src="bitfields/PublicKey.png">
<h2>Private Key<a name="PrivateKey"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A private key is 256byte <a href="#Integer">Integer</a> used for ElGamal decryption. The private key represents only the exponent,
not the primes, which are constant and defined in the crypto spec.<br />
<img src="bitfields/PrivateKey.png">
<h2>Session Key<a name="SessionKey"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A session key is 32byte <a href="#Integer">Integer</a> used for AES256 encryption and decryption.<br />
<img src="bitfields/SessionKey.png">
<h2>Signing Public Key<a name="SigningPublicKey"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A signing public key is 256byte <a href="#Integer">Integer</a> used for DSA signatures of various
data structures. The public key represents only the exponent, not the primes, which are constant and
defined in the crypto spec.<br />
<img src="bitfields/SigningPublicKey.png">
<h2>Signing Private Key<a name="SigningPrivateKey"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A signing private key is 256byte <a href="#Integer">Integer</a> used for DSA signatures of various
data structures. The private key represents only the exponent,
not the primes, which are constant and defined in the crypto spec.<br />
<img src="bitfields/SigningPrivateKey.png">
<h2>Signature<a name="Signature"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A signature is a 40byte <a href="#Integer">Integer</a> verifying the authenticity of some data created with
the DSA <a href="#SigningPrivateKey">SigningPrivateKey</a> and verified with the
<a href="#SigningPublicKey">SigningPublicKey</a>.<br />
<img src="bitfields/Signature.png">
<h2>Hash<a name="Hash"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
A hash is the SHA-256 of some data, taking up 32 bytes.<br />
<img src="bitfields/Hash.png">
<h2>Certificate<a name="Certificate"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The certificate starts with a 1 byte <a href="#Integer">Integer</a> specifying the certificate type,
then by a 2 byte <a href="#Integer">Integer</a> specifying the size of the certificate payload, and finally
the raw payload of the certificate. For certificates type of zero, the certificate is null and the
payload is ignored. For certificate type of one, the certificate is a hashcash calculation, and the
payload is a 1 byte <a href="#Integer">Integer</a> specifying the number of bits (K) for the hash
collision, followed by a non-trivial hash collision (aka non-identity) against the first K bits of the certified data.
The hash function is the hashcash function specified at
<a href="http://www.cypherspace.org/hashcash/hashcash.pdf">http://www.cypherspace.org/hashcash/hashcash.pdf</a>.
Other certificate types, such as real cash payment certificates, or CA signed keys, can be added later.<br />
<img src="bitfields/Certificate.png">
<h1>Common Structures<a name="CommonStructures"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
<h2>Destination<a name="Destination"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The Destination is the <a href="#PublicKey">PublicKey</a> of the destination, followed by a
<a href="#SigningPublicKey">SigningPublicKey</a> and finally the <a href="#Certificate">Certificate</a>
entangled with the public key.<br />
<img src="bitfields/Destination.png">
<h2>Lease<a name="Lease"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The Lease contains the <a href="#Destination">Destination</a>, followed by the <a href="#RouterIdentity">RouterIdentity</a> at
which messages should be delivered, then the <a href="#TunnelId">TunnelId</a>, then a the start <a href="#Date">Date</a> for the
lease, then the end <a href="#Date">Date</a> for the lease, followed by the <a href="#SigningPublicKey">SigningPublicKey</a> that can be used
to revoke the lease, and finally a <a href="#Signature">Signature</a> of the rest of the bytes in the Lease built from the
<a href="#Destination">Destination</a>'s <a href="#SigningPrivateKey">SigningPrivateKey</a>, and verifiable by its
<a href="#SigningPublicKey">SigningPublicKey</a>.<br />
<img src="bitfields/Lease.png">
<h2>LeaseRevocation<a name="LeaseRevocation"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The LeaseRevocation is very similar to a Lease for data points. It contains the <a href="#Destination">Destination</a>,
followed by the <a href="#RouterIdentity">RouterIdentity</a> of the <a href="#Lease">Lease</a>'s gateway, then the
<a href="#TunnelId">TunnelId</a>, then a the start <a href="#Date">Date</a> for the
lease, then the end <a href="#Date">Date</a> for the lease, and finally the <a href="#Signature">Signature</a> of the rest of
the bytes in the LeaseRevocation using the <a href="#Lease">Lease</a>'s
<a href="#LeaseRevocationPrivateKey">LeaseRevocationPrivateKey</a>.<br />
<img src="bitfields/LeaseRevocation.png">
<h2>LeaseRevocationPrivateKey<a name="LeaseRevocationPrivateKey"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The LeaseRevocationPrivateKey is a <a href="#SigningPrivateKey">SigningPrivateKey</a> associated with the <a href="#Lease">Lease</a>'s
<a href="#SigningPublicKey">SigningPublicKey</a>.<br />
<img src="bitfields/LeaseRevocationPrivateKey.png">
<h2>Payload<a name="Payload"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The Payload is the contents of the message encrypted via <font color="red">ElGamal and AES256</font> to the
<a href="#Destination">Destination</a>'s <a href="#PublicKey">PublicKey</a>. The first 4 bytes make up an
<a href="#Integer">Integer</a> specifying the number of bytes in the Payload data structure (including these
first 4 bytes). After that, one of two scenarios can occur. If the next 32 bytes are not equal to a known
and unused session tag, as defined by a previous message, the first scenario takes place. Otherwise, the
second takes place. <ol>
<li><b>Scenario 1: unknown session tag, or incorrect hash of session key</b><br />
The first 512 bytes after the payload structure size is decrypted with ElGamal to the
<a href="#Destination">Destination</a>'s <a href="#PublicKey">PublicKey</a> (containing 256 unencrypted bytes).
The first 32 bytes unencrypted make up the SessionKey. After that comes 32 bytes which, when hashed with
SHA256 and the first 16 bytes of that <a href="#Hash">Hash</a> is retrieved, turns into the AES256 initialization
vector (IV). The remaining 192 bytes of the cleartext is random data. Following that is the rest of the payload
decrypted with the AES <a href="#SessionKey">SessionKey</a> and the IV: <ul>
<li>The content starts with a 2 byte <a href="#Integer">Integer</a> specifying the number of
session tags that follow. After that comes that many 32 byte random
<a href="#Integer">Integer</a>s that act as session tags. After that comes an 4 byte
<a href="#Integer">Integer</a> specifying the real size of the body of the payload to follow.
Then comes the <a href="#Hash">Hash</a> of the the unencrypted body, for verification. The
remainder is the actual body of the message, padded with random bytes to match the size specified
in the first 4 bytes.</li></ul>
</li>
<li><b>Scenario 2: known session key, known unused session tag</b><br />
The 32 bytes acting as the session tag are hashed with SHA256 and the first 16 bytes of that <a href="#Hash">Hash</a>
is retrieved and turned into the AES256 initialization vector (IV). The remainder of the payload is considered to be
encrypted with the <a href="#SessionKey">SessionKey</a> from the message in which the session tag was specified and the IV.
The decrypted text is as follows:<ul>
<li>The decrypted body starts with a <a href="#Hash">Hash</a> of the
<a href="#SessionKey">SessionKey</a> in use. If this doesn't match the one in use, then
scenario 2 is aborted and the message is treated according to scenario 1. If it does match, then
the processing continues, where the rest of the decrypted body is the same as defined in scenario 1.</li></ul>
</li></ol>
Session tags received should be kept for <b>1 hour</b> after being received, or until they are used (whichever comes
first). Once a session tag is used or the time has passed, it should be discarded and further messages should not be
checked for that tag. The client APIs implementing the session tagging and verification may keep a list of tags that
have been used with a particular session ID and make sure the other party doesn't try to reuse a session tag. Note:
for extremely slow transports, extremely paranoid people (using many tunnel hops), or any other scenario where a message
may take more than an hour to be received, the client APIs should use scenario 1 exclusively.<p />
To the observer, there should be no way to tell whether the message begins with a session tag or an
ElG cypher. If this isn't the case, an observer can tell that some destination somewhere is
recieving follow-on traffic. Since session tags change constantly, there is no way for an observer
to know what session a tagged message belongs so (even *if* they were able to detect a tagged vs
ElG'ed message)<p />
The private <a href="#SessionKey">SessionKey</a>s will be changed frequently, providing perfect forward secrecy with
regard to the messages passed over the network (though if the <a href="#PrivateKey">PrivateKey</a> of the
<a href="#Destination">Destination</a> is compromised, all messages recorded will be broken, so endpoints should periodically
change their <a href="#Destination">Destination</a>). <br />
<img src="bitfields/Payload.png">
<h2>RouterIdentity<a name="RouterIdentity"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The RouterIdentity is a <a href="#PublicKey">PublicKey</a> of the router, followed by a
<a href="#SigningPublicKey">SigningPublicKey</a> and finally the <a href="#Certificate">Certificate</a>
entangled with that public key. <br />
<img src="bitfields/RouterIdentity.png">
<h2>RouterInfo<a name="RouterInfo"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The RouterInfo structure contains the <a href="#RouterIdentity">RouterIdentity</a>, followed by a 2 byte
<a href="#Integer">Integer</a> determining the version of the RouterInfo, then a 1 byte <a href="#Integer">Integer</a>
specifying how many <a href="#RouterAddress">RouterAddress</a> structures follow, and then those actual structures.
After this comes a 1 byte <a href="#Integer">Integer</a> specifying how many peers the RouterInfo
includes, followed by the <a href="#Hash">Hash</a> of those peers' <a href="#RouterIdentity">RouterIdentity</a>.
Following this is a <a href="#Mapping">Mapping</a> allowing the router to publish some metadata about itself, such as statistics,
capabilities, or configuration options. Finishing off the RouterInfo structure is a <a href="#Signature">Signature</a> of the
entire structure using the router's <a href="#SigningPrivateKey">SigningPrivateKey</a>.<br />
<img src="bitfields/RouterInfo.png">
<h2>RouterAddress<a name="RouterAddress"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The RouterAddress structure contains a 1 byte <a href="#Integer">Integer</a> specifying the relative cost of using the address,
where 0 means free and 255 means really expensive. After that comes the <a href="#Date">Date</a> after which the address should
be considered expired and no longer used (or if null, the address never expires). Next up comes a 1 byte
<a href="Integer">Integer</a> determining the transport protocol for use in contacting this address.
The protocol values are currently not defined, but will include protocols such as bidirectional TCP, UDP, direct HTTP, polling
HTTP, and email. Finally there is a is a <a href="#Mapping">Mapping</a> providing options necessary for configuring the
particular transport to communicate with the address, such as IP address, port number, email address, URL, etc. <br />
<img src="bitfields/RouterAddress.png">
<h2>TunnelId<a name="TunnelId"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The TunnelId is a 4 byte <a href="#Integer">Integer</a> that identifies the tunnel id that the messages may pass through on
the router.<br />
<img src="bitfields/TunnelId.png">
<h1>I2P Client Protocol Structures<a name="I2PCPStructures"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
<h2>SessionConfig<a name="SessionConfig"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The SessionConfig data structure is the session's <a href="#Destination">Destination</a> followed by
a one byte <a href="#Integer">Integer</a> specifying the number of <a href="#LeaseRevocation">LeaseRevocation</a>s in the
SessionConfig, then the the actual list of zero or more <a href="#LeaseRevocation">LeaseRevocation</a> structures. After
that list comes a <a href="#Mapping">Mapping</a> providing options necessary to configure the router implementation regarding
the current client's session. Finally comes a <a href="#Signature">Signature</a> by the <a href="#Destination">Destination</a>'s
<a href="#SigningPrivateKey">SigningPrivateKey</a> of the structure, authenticating the session. <br />
<img src="bitfields/SessionConfig.png">
<h2>SessionId<a name="SessionId"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The sessionId is a 2 byte <a href="#Integer">Integer</a> that identifies the session between the router and the client. <br />
<img src="bitfields/SessionId.png">
<h2>MessageId<a name="MessageId"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The sessionId is a 1 byte <a href="#Integer">Integer</a> that identifies the message number that the current
router/client session is referring to.<br />
<img src="bitfields/MessageId.png">
<h2>AuthenticationKey<a name="AuthenticationKey"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The AuthenticationKey is a <a href="#Hash">Hash</a> of the the passphrase required to access the administrative
functions of the router.<br />
<img src="bitfields/AuthenticationKey.png">
<h2>BandwidthLimits<a name="BandwidthLimits"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The BandwidthLimits are mappings of router to class and class to limit, where zero or more routers are assigned to a class and
each class has a set average and peak upload and download rate, measured in bytes/second. The BandwidthLimits object is
serialized by first providing a one byte <a href="#Integer">Integer</a> which represents the number of classes defined.
This is followed by that many limit structures, each of which is made up of a <a href="#String">String</a> containing
the user specified name for the class in which uniquely identifies the class, a 1 byte <a href="#Integer">Integer</a>
specifying the number of routers making up this class, and then that many <a href="#Hash">Hash</a>es made from those
router's <a href="#RouterIdentity">RouterIdentity</a>. At the end of each of these limit structures is a set of four
<a href="#Integer">Integer</a>s definint the the maximum average bytes per second downloaded, maximum average bytes per second
uploaded, maximum peak bytes per second downloaded, and maximum peak bytes per second uploaded, respectively. There must be one
limit structure containing no routers which serves as the default class. <br />
<img src="bitfields/BandwidthLimits.png">
<h2>AbuseReason<a name="AbuseReason"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The AbuseReason is a <a href="#String">String</a> in which there may be a description of the cause of abuse.<br />
<img src="bitfields/AbuseReason.png">
<h2>AbuseSeverity<a name="AbuseSeverity"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
The AbuseSeverity is a 1 byte <a href="#Integer">Integer</a> specifying the severity of the abuse, with 0 being minimally
abusive and 255 being completely abusive.<br />
<img src="bitfields/AbuseSeverity.png">
<h1>I2P Client Protocol (I2CP) Messages<a name="I2PCPMessages"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
What follows are the currently defined messages in the Invisible Internet Client Protocol (I2CP), including their bitbuckets.
For simplicity, all I2CP messages begin with the same structure, though that structure is not listed below. Specifically,
all I2CP messages transmitted begin with a 4 byte <a href="#Integer">Integer</a> specifying the entire size of the current
message's body (the body being what's specified below), followed by a 1 byte <a href="#Integer">Integer</a>
specifying the type of message (the id field below), after which the rest of the message is formatted according to the type of
message, as specified below. <p />
If there is a fatal error causing either the client or the router to desire to cancel sending a message part way through, it
should drop its connection. Administrative sessions are not stateful (aka each administrative message from client to router must
provide authentication), but normal client sessions are stateful and survive disconnects. Client sessions expire when either the
client sends a DestroySessionMessage or the router times out the session according to its own configurable timer. If a client
sends any message other than a <a href="#CreateSessionMessage">CreateSessionMessage</a> when there is no valid session, the router must reply with a
<a href="#SessionStatusMessage">SessionStatusMessage</a> specifying that the session is not valid.
<h2>Client to Router<a name="ClientToRouterMessages"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
<table border="1">
<tr><td valign="top"><b>Name:</b></td><td>CreateSessionMessage<a name="CreateSessionMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>1</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
This is what the client sends to its local trusted router to join the network
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionConfig">SessionConfig</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>o
<tr><td valign="top"><b>Name:</b></td><td>ReconfigureSessionMessage<a name="ReconfigureSessionMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>2</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
This is what the client sends to the router to have a session changed - various options reconfigured
and possibly some resources released
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a> followed by
<a href="#SessionConfig">SessionConfig</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>DestroySessionMessage<a name="DestroySessionMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>3</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
This is what the client sends to the router to have a session destroyed and all resources released
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>CreateLeaseMessage<a name="CreateLeaseMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>4</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
This is how the client grants a lease to the router for a tunnel, including the private key
the router can use to revoke the lease later on if necessary.
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a> followed by
<a href="#LeaseRevocationPrivateKey">LeaseRevocationPrivateKey</a> and finally
<a href="#Lease">Lease</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>SendMessageMessage<a name="SendMessageMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>5</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
This is how a client sends a message (the payload) to the destination. The API implementation of
this access layer should provide transparent encryption of the payload to the destination's public
key in the same way that it should handle transparent decryption of the payload when received via
deliverMessage below - the private keys should never be given to the router. As such, the router
shouldn't do any encryption of the message beyond transport layer encryption, but the access libraries should.
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a> followed by
<a href="#Destination">Destination</a> and finally
<a href="#Payload">Payload</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>ReceiveMessageBeginMessage<a name="ReceiveMessageBeginMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>6</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Request the router to deliver a message that it was previously notified of
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a> followed by
<a href="#MessageId">MessageId</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>ReceiveMessageEndMessage<a name="ReceiveMessageEndMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>7</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Tell the router that delivery of a message was completed successfully and that the router can discard the message
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a> followed by
<a href="#MessageId">MessageId</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
</table>
<h2>Client Admin to Router<a name="ClientAdminToRouterMessages"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
<table border="1">
<tr><td valign="top"><b>Name:</b></td><td>GetBandwidthLimitsMessage<a name="GetBandwidthLimitsMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>8</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Request that the router tell the application what its current bandwidth limits are
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>SetBandwidthLimitsMessage<a name="SetBandwidthLimitsMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>9</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Configure the router with new bandwidth limits
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a> followed by
<a href="#BandwidthLimits">BandwidthLimits</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>GetTrustedRoutersMessage<a name="GetTrustedRoutersMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>10</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Retrieve the set of trusted routers
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>SetTrustedRoutersMessage<a name="SetTrustedRoutersMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>11</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Configure what routers the local router should trust
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a> followed by a
2 byte <a href="#Integer">Integer</a> specifying how many hashes follow, and then finally that
many <a href="#Hash">Hash</a>es of the respective router's <a href="#RouterIdentity">RouterIdentity</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>GetAddressVisibilityMessage<a name="GetAddressVisibilityMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>12</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Determine if the router is hiding its addresses or not
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>SetAddressVisibilityMessage<a name="SetAddressVisibilityMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>13</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Determine if the router is hiding its addresses or not
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a> followed by a <a href="#Boolean">Boolean</a> (true = visible)
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>GetAddressRotationPeriodMessage<a name="GetAddressRotationPeriodMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>14</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Determine after how long the router will automatically rotate its addresses
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>SetAddressRotationPeriodMessage<a name="SetAddressRotationPeriodMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>15</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Configure the router to periodically rotate its addresses
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a> followed by a
2 byte <a href="#Integer">Integer</a> specifying how many seconds to wait before rotating addresses
(or 0 for never rotate)
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>ForceAddressRotationMessage<a name="ForceAddressRotationMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>16</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Instruct the router to rotate its addresses as soon as possible
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>GetPeersMessage<a name="GetPeersMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>17</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Retrieve the set of peers the router knows about and will communicate with
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>SetPeersMessage<a name="SetPeersMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>18</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Configure the set of peers the router knows about and will communicate with
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a>, followed by a two byte
<a href="#Integer">Integer</a> specifying how many <a href="#RouterInfo">RouterInfo</a>
structures follow (not how many bytes, but how many structures), then those actual
structures.
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>SetPasswordMessage<a name="SetPasswordMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>19</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Set the new password to control the router
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#AuthenticationKey">AuthenticationKey</a>, which is the current key,
followed by another <a href="#AuthenticationKey">AuthenticationKey</a>, which is the new
key.
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
</table>
<h2>Router to Client<a name="RouterToClientMessages"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
<table border="1">
<tr><td valign="top"><b>Name:</b></td><td>SessionStatusMessage<a name="SessionStatusMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>20</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Instruct the client as to the status of its session
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a> followed by a 1 byte <a href="#Integer">Integer</a>
specifying the status of the session. Status values include zero for destroyed,
one for created, two for updated, and three for invalid session.
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>RequestLeaseMessage<a name="RequestLeaseMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>21</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Request that a client authorize the creation of an inbound tunnel through a Lease
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a> followed by a <a href="#RouterIdentity">RouterIdentity</a>, then
a <a href="#TunnelId">TunnelId</a>, the requested start <a href="#Date">Date</a>, and the requested end
<a href="#Date">Date</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>MessageStatusMessage<a name="MessageStatusMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>22</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Notify the client of the delivery status of a message
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a> followed by <a href="#MessageId">MessageId</a>, a
1 byte <a href="#Integer">Integer</a> specifying the status of the message, and finally a
4 byte <a href="#Integer">Integer</a> specifying the size of the message in bytes. The known
status values are 0 for message is available, 1 for accepted, 2 for best effort succeeded,
3 for best effort failed, 4 for guaranteed succeeded, 5 for guaranteed failed.
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>MessagePayloadMessage<a name="MessagePayloadMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>31</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Deliver the payload of a message to the client
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a> followed by <a href="#MessageId">MessageId</a>, and finally
the <a href="#Payload">Payload</a> of the message being delivered.
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
</table>
<h2>Router to Client Admin<a name="RouterToClientAdminMessages"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
<table border="1">
<tr><td valign="top"><b>Name:</b></td><td>BandwidthLimitsMessage<a name="BandwidthLimitsMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>23</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Tell the client what the router's current bandwidth limits are
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#BandwidthLimits">BandwidthLimits</a>
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>TrustedRoutersMessage<a name="TrustedRoutersMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>24</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Tell the client what routers are currently trusted
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
A 2 byte <a href="#Integer">Integer</a> specifying how many hashes follow, and then the
actual set of zero or more <a href="#Hash">Hash</a> structures, calculated against the
router's <a href="#RouterInfo">RouterInfo</a>.
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>AddressVisibilityMessage<a name="AddressVisibilityMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>25</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Tell the client whether the router currently publishes its address information publicly
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#Boolean">Boolean</a> (true = visible)
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>AddressRotationPeriodMessage<a name="AddressRotationPeriodMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>26</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Tell the client after how long the router will automatically rotate its addresses
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
2 byte <a href="#Integer">Integer</a> specifying the number of seconds after which the router is obliged
to rotate its contact addresses. If this number is all zeroes, then the router is never obliged to rotate
its contact addresses.
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>LastAddressRotationMessage<a name="LastAddressRotationMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>27</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Tell the client when the last address rotation was
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#Date">Date</a> the address was last rotated (null for never)
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>PeersMessage<a name="PeersMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>28</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Provide the client with all of the routers that the local router is communicating with
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
2 byte <a href="#Integer">Integer</a> specifying how many <a href="#RouterInfo">RouterInfo</a>
structures follow, and then those actual structures.
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
</table>
<h2>Bidirectional<a name="BidirectionalMessages"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
<table border="1">
<tr><td valign="top"><b>Name:</b></td><td>ReportAbuseMessage<a name="ReportAbuseMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>29</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Tell the other party that they are under attack, potentially with reference to a particular messageId.
If the router is under attack, the client may decide to migrate to another router, and if a client is
under attack, the router may rebuild its routers or shitlist some of the peers that sent it messages
delivering the attack.
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#SessionId">SessionId</a> followed by
<a href="#AbuseSeverity">AbuseSeverity</a>, then
<a href="#AbuseReason">AbuseReason</a>, and finally
<a href="#MessageId">MessageId</a> (which is 0, if irrelevent)
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
<tr><td valign="top"><b>Name:</b></td><td>DisconnectMessage<a name="DisconnectMessage"></a></td></tr>
<tr><td valign="top"><b>Id:</b></td><td>30</td></tr>
<tr><td valign="top"><b>Description:</b></td><td>
Tell the other party that there are problems and the current connection is about to be destroyed.
This does not necessarily end a session.
</td></tr>
<tr><td valign="top"><b>Byte layout:</b></td><td>
<a href="#String">String</a> describing why disconnect
</td></tr>
<tr><td colspan="2"><hr /></td></tr>
</table>
<font color="red">
<h1>Todo <a name="Todo"></a></h1>
<ul>
<li>Finish the rest of the bitbucket diagrams</li>
<li>Verify encryption related data structure sizes (<a href="#Signature">Signature</a>, <a href="#PublicKey">PublicKey</a>,
<a href="#PrivateKey">PrivateKey</a>, <a href="#Hash">Hash</a>)</li>
</ul>
</font>
<h1>Changes<a name="Changes"></a> <font size="-1"><a href="#Contents">(top)</a></font></h2>
<i>See source for changelog. current version: $Id: datastructures.html,v 1.6 2003/08/01 20:57:12 jrand0m Exp $</i>
<!--
$Log: datastructures.html,v $
Revision 1.6 2003/08/01 20:57:12 jrand0m
Caught a missing 8 byte structure to switch it to 4 bytes in the payload
Revision 1.5 2003/08/01 20:46:32 jrand0m
Updated Payload structure to include AES IV and reduce the size # to 4 bytes
Revision 1.4 2003/08/01 13:29:06 jrand0m
s/recieve/receive/g
Revision 1.3 2003/07/31 15:07:54 jrand0m
Added MessagePayloadMessage
Updated the Changes section so the changelog isn't visible on the web (so hezekiah's browser at 800x600 doesn't puke)
Revision 1.2 2003/07/31 01:26:39 jrand0m
Added SignaturePublicKey, SignaturePrivateKey, and updated Signature to reflect DSA as opposed to ElGamal signatures
Also updated Payload data structure to reflect a new faster and smaller way of encrypting data
Revision 1.1.1.1 2003/07/29 02:34:32 jrand0m
initial import
-->
</td>
</tr>
</table>
</body>
</html>