{% trans naming=site_url('docs/naming') -%}
-This document specifies
-the I2P blockfile file format
-and the tables in the hostsdb.blockfile used by the Blockfile Naming Service.
-{%- endtrans %}
-
-
{% trans -%}
-The blockfile provides fast Destination lookup in a compact format. While the blockfile page overhead is substantial,
-the destinations are stored in binary rather than in Base 64 as in the hosts.txt format.
-In addition, the blockfile provides the capability of arbitrary metadata storage
-(such as added date, source, and comments) for each entry.
-The metadata may be used in the future to provide advanced addressbook features.
-The blockfile storage requirement is a modest increase over the hosts.txt format, and the blockfile provides
-approximately 10x reduction in lookup times.
-{%- endtrans %}
-
-
{% trans url='http://www.metanotion.net/software/sandbox/block.html' -%}
-A blockfile is simply on-disk storage of multiple sorted maps (key-value pairs),
-implemented as skiplists.
-The blockfile format is adopted from the
-Metanotion Blockfile Database.
-First we will define the file format, then the use of that format by the BlockfileNamingService.
-{%- endtrans %}
-
-
{% trans %}Blockfile Format{% endtrans %}
-
{% trans -%}
-The original blockfile spec was modified to add magic numbers to each page.
-The file is structured in 1024-byte pages. Pages are numbered starting from 1.
-The "superblock" is always at page 1, i.e. starting at byte 0 in the file.
-The metaindex skiplist is always at page 2, i.e. starting at byte 1024 in the file.
-{%- endtrans %}
-
-
{% trans -%}
-All 2-byte integer values are unsigned.
-All 4-byte integer values (page numbers) are signed and negative values are illegal.
-All integer values are stored in network byte order (big endian).
-{%- endtrans %}
-
-
{% trans -%}
-The database is designed to be opened and accessed by a single thread.
-The BlockfileNamingService provides synchronization.
-{%- endtrans %}
-
-
{% trans -%}
-Superblock format:
-{%- endtrans %}
-{% highlight %}
-Byte Contents
-0-5 Magic number 0x3141de493250 ("1A" 0xde "I2P")
-6 Major version 0x01
-7 Minor version 0x02
-8-15 File length Total length in bytes
-16-19 First free list page
-20-21 Mounted flag 0x01 = yes
-22-23 Span size Max number of key/value pairs per span (16 for hostsdb)
- Used for new skip lists.
-24-27 Page size As of version 1.2. Prior to 1.2, 1024 is assumed.
-28-1023 unused
-{% endhighlight %}
-
-
{% trans -%}
-Skip list block page format:
-{%- endtrans %}
-{% highlight %}
-Byte Contents
-0-7 Magic number 0x536b69704c697374 "SkipList"
-8-11 First span page
-12-15 First level page
-16-19 Size (total number of keys - may only be valid at startup)
-20-23 Spans (total number of spans - may only be valid at startup)
-24-27 Levels (total number of levels - may only be valid at startup)
-28-29 Span size - As of version 1.2. Max number of key/value pairs per span.
- Prior to that, specified for all skiplists in the superblock.
- Used for new spans in this skip list.
-30-1023 unused
-{% endhighlight %}
-
-
-
{% trans -%}
-Skip level block page format is as follows.
-All levels have a span. Not all spans have levels.
-{%- endtrans %}
-{% highlight %}
-Byte Contents
-0-7 Magic number 0x42534c6576656c73 "BSLevels"
-8-9 Max height
-10-11 Current height
-12-15 Span page
-16- Next level pages ('current height' entries, 4 bytes each, lowest first)
-remaining bytes unused
-{% endhighlight %}
-
-
-
{% trans -%}
-Skip span block page format is as follows.
-Key/value structures are sorted by key within each span and across all spans.
-Key/value structures are sorted by key within each span.
-Spans other than the first span may not be empty.
-{%- endtrans %}
-{% highlight %}
-Byte Contents
-0-3 Magic number 0x5370616e "Span"
-4-7 First continuation page or 0
-8-11 Previous span page or 0
-12-15 Next span page or 0
-16-17 Max keys (16 for hostsdb)
-18-19 Size (current number of keys)
-20-1023 key/value structures
-{% endhighlight %}
-
-
-{% highlight %}
-Byte Contents
-0-3 Magic number 0x434f4e54 "CONT"
-4-7 Next continuation page or 0
-8-1023 key/value structures
-{% endhighlight %}
-
-
-
{% trans -%}
-Key/value structure format is as follows.
-Key and value lengths must not be split across pages, i.e. all 4 bytes must be on the same page.
-If there is not enough room the last 1-3 bytes of a page are unused and the lengths will
-be at offset 8 in the continuation page.
-Key and value data may be split across pages.
-Max key and value lengths are 65535 bytes.
-{%- endtrans %}
-{% highlight %}
-Byte Contents
-0-1 key length in bytes
-2-3 value length in bytes
-4- key data
- value data
-{% endhighlight %}
-
-
{% trans -%}
-Free list block page format:
-{%- endtrans %}
-{% highlight %}
-Byte Contents
-0-7 Magic number 0x2366724c69737423 "#frList#"
-8-11 Next free list block or 0 if none
-12-15 Number of valid free pages in this block (0 - 252)
-16-1023 Free pages (4 bytes each), only the first (valid number) are valid
-{% endhighlight %}
-
-
-
{% trans -%}
-Free page block format:
-{%- endtrans %}
{% trans -%}
-The metaindex (located at page 2) is a mapping of US-ASCII strings to 4-byte integers.
-The key is the name of the skiplist and the value is the page index of the skiplist.
-{%- endtrans %}
-
-
{% trans %}Blockfile Naming Service Tables{% endtrans %}
-
{% trans -%}
-The tables created and used by the BlockfileNamingService are as follows.
-The maximum number of entries per span is 16.
-{%- endtrans %}
-
-
{% trans %}Properties Skiplist{% endtrans %}
-
{% trans INFO='"%%__INFO__%%"' -%}
-{{ INFO }} is the master database skiplist with String/Properties key/value entries containing only one entry:
-{%- endtrans %}
-
- "info": a Properties (UTF-8 String/String Map), serialized as a Mapping:
- "version": "3"
- "created": Java long time (ms)
- "upgraded": Java long time (ms) (as of database version 2)
- "lists": Comma-separated list of host databases, to be
- searched in-order for lookups. Almost always "privatehosts.txt,userhosts.txt,hosts.txt".
-
-
-
{% trans %}Reverse Lookup Skiplist{% endtrans %}
-
{% trans REVERSE='"%%__REVERSE__%%"' -%}
-{{ REVERSE }} is the reverse lookup skiplist with Integer/Properties key/value entries
- (as of database version 2):
-{%- endtrans %}
-
- The skiplist keys are 4-byte Integers, the first 4 bytes of the hash of the Destination.
- The skiplist values are each a Properties (a UTF-8 String/String Map) serialized as a Mapping
- There may be multiple entries in the properties, each one is a reverse mapping,
- as there may be more than one hostname for a given destination,
- or there could be collisions with the same first 4 bytes of the hash.
- Each property key is a hostname.
- Each property value is the empty string.
-
-
-
{% trans %}hosts.txt, userhosts.txt, and privatehosts.txt Skiplists{% endtrans %}
-
{% trans -%}
-For each host database, there is a skiplist containing
-the hosts for that database.
-The keys/values in these skiplists are as follows:
-{%- endtrans %}
-
- key: a UTF-8 String (the hostname)
- value: a DestEntry, which is a Properties (a UTF-8 String/String Map) serialized as a Mapping
- followed by a binary Destination (serialized as usual).
-
-
-
{% trans -%}
-The DestEntry Properties typically contains:
-{%- endtrans %}
-
- "a": The time added (Java long time in ms)
- "s": The original source of the entry (typically a file name or subscription URL)
- others: TBD
-
-
-
{% trans -%}
-Hostname keys are stored in lower-case and always end in ".i2p".
-{%- endtrans %}
-
-
-{% endblock %}
diff --git a/i2p2www/spec/blockfile.rst b/i2p2www/spec/blockfile.rst
new file mode 100644
index 00000000..ac1dc6ae
--- /dev/null
+++ b/i2p2www/spec/blockfile.rst
@@ -0,0 +1,247 @@
+==========================================
+Blockfile and Hosts Database Specification
+==========================================
+.. meta::
+ :lastupdated: November 2014
+ :accuratefor: 0.9.17
+
+
+Overview
+========
+
+This document specifies the I2P blockfile file format and the tables in the
+hostsdb.blockfile used by the Blockfile Naming Service [NAMING]_.
+
+The blockfile provides fast Destination lookup in a compact format. While the
+blockfile page overhead is substantial, the destinations are stored in binary
+rather than in Base 64 as in the hosts.txt format. In addition, the blockfile
+provides the capability of arbitrary metadata storage (such as added date,
+source, and comments) for each entry. The metadata may be used in the future
+to provide advanced addressbook features. The blockfile storage requirement is
+a modest increase over the hosts.txt format, and the blockfile provides
+approximately 10x reduction in lookup times.
+
+A blockfile is simply on-disk storage of multiple sorted maps (key-value
+pairs), implemented as skiplists. The blockfile format is adopted from the
+Metanotion Blockfile Database [METANOTION]_. First we will define the file
+format, then the use of that format by the BlockfileNamingService.
+
+
+Blockfile Format
+================
+
+The original blockfile spec was modified to add magic numbers to each page.
+The file is structured in 1024-byte pages. Pages are numbered starting from 1.
+The "superblock" is always at page 1, i.e. starting at byte 0 in the file. The
+metaindex skiplist is always at page 2, i.e. starting at byte 1024 in the file.
+
+All 2-byte integer values are unsigned. All 4-byte integer values (page
+numbers) are signed and negative values are illegal. All integer values are
+stored in network byte order (big endian).
+
+The database is designed to be opened and accessed by a single thread. The
+BlockfileNamingService provides synchronization.
+
+Superblock format:
+
+.. raw:: html
+
+ {% highlight %}Byte Contents
+ 0-5 Magic number 0x3141de493250 ("1A" 0xde "I2P")
+ 6 Major version 0x01
+ 7 Minor version 0x02
+ 8-15 File length Total length in bytes
+ 16-19 First free list page
+ 20-21 Mounted flag 0x01 = yes
+ 22-23 Span size Max number of key/value pairs per span (16 for hostsdb)
+ Used for new skip lists.
+ 24-27 Page size As of version 1.2. Prior to 1.2, 1024 is assumed.
+ 28-1023 unused
+{% endhighlight %}
+
+Skip list block page format:
+
+.. raw:: html
+
+ {% highlight %}Byte Contents
+ 0-7 Magic number 0x536b69704c697374 "SkipList"
+ 8-11 First span page
+ 12-15 First level page
+ 16-19 Size (total number of keys - may only be valid at startup)
+ 20-23 Spans (total number of spans - may only be valid at startup)
+ 24-27 Levels (total number of levels - may only be valid at startup)
+ 28-29 Span size - As of version 1.2. Max number of key/value pairs per span.
+ Prior to that, specified for all skiplists in the superblock.
+ Used for new spans in this skip list.
+ 30-1023 unused
+{% endhighlight %}
+
+Skip level block page format is as follows.
+All levels have a span. Not all spans have levels.
+
+.. raw:: html
+
+ {% highlight %}Byte Contents
+ 0-7 Magic number 0x42534c6576656c73 "BSLevels"
+ 8-9 Max height
+ 10-11 Current height
+ 12-15 Span page
+ 16- Next level pages ('current height' entries, 4 bytes each, lowest first)
+ remaining bytes unused
+{% endhighlight %}
+
+Skip span block page format is as follows.
+Key/value structures are sorted by key within each span and across all spans.
+Key/value structures are sorted by key within each span.
+Spans other than the first span may not be empty.
+
+.. raw:: html
+
+ {% highlight %}Byte Contents
+ 0-3 Magic number 0x5370616e "Span"
+ 4-7 First continuation page or 0
+ 8-11 Previous span page or 0
+ 12-15 Next span page or 0
+ 16-17 Max keys (16 for hostsdb)
+ 18-19 Size (current number of keys)
+ 20-1023 key/value structures
+{% endhighlight %}
+
+Span Continuation block page format:
+
+.. raw:: html
+
+ {% highlight %}Byte Contents
+ 0-3 Magic number 0x434f4e54 "CONT"
+ 4-7 Next continuation page or 0
+ 8-1023 key/value structures
+{% endhighlight %}
+
+Key/value structure format is as follows.
+Key and value lengths must not be split across pages, i.e. all 4 bytes must be on the same page.
+If there is not enough room the last 1-3 bytes of a page are unused and the lengths will
+be at offset 8 in the continuation page.
+Key and value data may be split across pages.
+Max key and value lengths are 65535 bytes.
+
+.. raw:: html
+
+ {% highlight %}Byte Contents
+ 0-1 key length in bytes
+ 2-3 value length in bytes
+ 4- key data
+ value data
+{% endhighlight %}
+
+Free list block page format:
+
+.. raw:: html
+
+ {% highlight %}Byte Contents
+ 0-7 Magic number 0x2366724c69737423 "#frList#"
+ 8-11 Next free list block or 0 if none
+ 12-15 Number of valid free pages in this block (0 - 252)
+ 16-1023 Free pages (4 bytes each), only the first (valid number) are valid
+{% endhighlight %}
+
+Free page block format:
+
+.. raw:: html
+
+ {% highlight %}Byte Contents
+ 0-7 Magic number 0x7e2146524545217e "~!FREE!~"
+ 8-1023 unused
+{% endhighlight %}
+
+The metaindex (located at page 2) is a mapping of US-ASCII strings to 4-byte integers.
+The key is the name of the skiplist and the value is the page index of the skiplist.
+
+
+Blockfile Naming Service Tables
+===============================
+
+The tables created and used by the BlockfileNamingService are as follows.
+The maximum number of entries per span is 16.
+
+Properties Skiplist
+-------------------
+
+"%%__INFO__%%" is the master database skiplist with String/Properties key/value
+entries containing only one entry:
+
+ info
+ a Properties (UTF-9 String/String Map), serialized as a [Mapping]_:
+
+ version
+ "3"
+
+ created
+ Java long time (ms)
+
+ upgraded
+ Java long time (ms) (as of database version 2)
+
+ lists
+ Comma-separated list of host databases, to be searched in-order for
+ lookups. Almost always "privatehosts.txt,userhosts.txt,hosts.txt".
+
+Reverse Lookup Skiplist
+-----------------------
+
+"%%__REVERSE__%%" is the reverse lookup skiplist with Integer/Properties
+key/value entries (as of database version 2):
+
+* The skiplist keys are 4-byte Integers, the first 4 bytes of the hash of the
+ [Destination]_.
+
+* The skiplist values are each a Properties (a UTF-8 String/String Map)
+ serialized as a [Mapping]_
+
+ * There may be multiple entries in the properties, each one is a reverse
+ mapping, as there may be more than one hostname for a given destination, or
+ there could be collisions with the same first 4 bytes of the hash.
+
+ * Each property key is a hostname.
+
+ * Each property value is the empty string.
+
+hosts.txt, userhosts.txt, and privatehosts.txt Skiplists
+--------------------------------------------------------
+
+For each host database, there is a skiplist containing the hosts for that
+database. The keys/values in these skiplists are as follows:
+
+ key
+ a UTF-8 String (the hostname)
+
+ value
+ a DestEntry, which is a Properties (a UTF-8 String/String Map)
+ serialized as a [Mapping]_ followed by a binary [Destination]_
+ (serialized as usual).
+
+The DestEntry Properties typically contains:
+
+ "a"
+ The time added (Java long time in ms)
+
+ "s"
+ The original source of the entry (typically a file name or subscription
+ URL)
+
+Hostname keys are stored in lower-case and always end in ".i2p".
+
+
+References
+==========
+
+.. [NAMING]
+ {{ site_url('docs/naming', True) }}
+
+.. [METANOTION]
+ http://www.metanotion.net/software/sandbox/block.html
+
+.. [Mapping]
+ {{ spec_url('common-structures') }}#type-mapping
+
+.. [Destination]
+ {{ spec_url('common-structures') }}#struct-destination
diff --git a/i2p2www/spec/common-structures.html b/i2p2www/spec/common-structures.html
deleted file mode 100644
index 4d52efac..00000000
--- a/i2p2www/spec/common-structures.html
+++ /dev/null
@@ -1,1017 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}{% trans %}Common structures Specification{% endtrans %}{% endblock %}
-{% block lastupdated %}{% trans %}April 2015{% endtrans %}{% endblock %}
-{% block accuratefor %}0.9.19{% endblock %}
-{% block content %}
-
{% trans i2np=site_url('docs/protocol/i2np'),
-i2cp=site_url('docs/protocol/i2cp'),
-ssu=site_url('docs/transport/ssu') -%}
-This document describes some data types common to all I2P protocols, like
-I2NP, I2CP,
-SSU, etc.
-{%- endtrans %}
{% trans -%}
-Represents a non-negative integer.
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-1 to 8 bytes in network byte order representing an unsigned integer
-{% endtrans %}
-
-
Date
-
{% trans %}Description{% endtrans %}
-
{% trans -%}
-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.
-{% endtrans %}
{% trans -%}
-Represents a UTF-8 encoded string.
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-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.
-Length limit is 255 bytes (not characters). Length may be 0.
-{% endtrans %}
-
-
Boolean
-
{% trans %}Description{% endtrans %}
-
{% trans -%}
-A boolean value, supporting null/unknown representation
-0=false, 1=true, 2=unknown/null
-{% endtrans %}
{% trans cryptography=site_url('docs/how/cryptography') -%}
-This structure is used in ElGamal encryption, representing only the exponent, not the primes, which are constant and defined in
-the cryptography specification.
-{% endtrans %}
{% trans cryptography=site_url('docs/how/cryptography') -%}
-This structure is used in ElGamal decryption, representing only the exponent, not the primes which are constant and defined in
-the cryptography specification.
-{% endtrans %}
{% trans cryptography=site_url('docs/how/cryptography') -%}
-This structure is used for verifying signatures.
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-Key type and length are inferred from context or are specified in the Key Certificate of a Destination.
-{% endtrans %}
-{% trans -%}
-The default type is DSA_SHA1.
-{% endtrans %}
-{% trans -%}
-As of release 0.9.12, other types may be supported, depending on context.
-{% endtrans %}
-
-
-
{% trans %}Type{% endtrans %}
{% trans %}Length (bytes){% endtrans %}
{% trans %}Since{% endtrans %}
-
DSA_SHA1
128
-
ECDSA_SHA256_P256
64
0.9.12
-
ECDSA_SHA384_P384
96
0.9.12
-
ECDSA_SHA512_P521
132
0.9.12
-
RSA_SHA256_2048
256
0.9.12
-
RSA_SHA384_3072
384
0.9.12
-
RSA_SHA512_4096
512
0.9.12
-
EdDSA_SHA512_Ed25519
32
0.9.15
-
-
-
{% trans %}Notes{% endtrans %}
-
-
{% trans -%}
-When a key is composed of two elements (for example points X,Y), it is serialized by
-padding each element to length/2 with leading zeros if necessary.
-{%- endtrans %}
-
{% trans -%}
-All types are Big Endian, except for
-EdDSA, which is stored and transmitted in a Little Endian format.
-{%- endtrans %}
{% trans cryptography=site_url('docs/how/cryptography') -%}
-This structure is used for creating signatures.
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-Key type and length are specified when created.
-{% endtrans %}
-{% trans -%}
-The default type is DSA_SHA1.
-{% endtrans %}
-{% trans -%}
-As of release 0.9.12, other types may be supported, depending on context.
-{% endtrans %}
-
-
-
{% trans %}Type{% endtrans %}
{% trans %}Length (bytes){% endtrans %}
{% trans %}Since{% endtrans %}
-
DSA_SHA1
20
-
ECDSA_SHA256_P256
32
0.9.12
-
ECDSA_SHA384_P384
48
0.9.12
-
ECDSA_SHA512_P521
66
0.9.12
-
RSA_SHA256_2048
512
0.9.12
-
RSA_SHA384_3072
768
0.9.12
-
RSA_SHA512_4096
1024
0.9.12
-
EdDSA_SHA512_Ed25519
32
0.9.15
-
-
-
{% trans %}Notes{% endtrans %}
-
-
{% trans -%}
-When a key is composed of two elements (for example points X,Y), it is serialized by
-padding each element to length/2 with leading zeros if necessary.
-{%- endtrans %}
-
{% trans -%}
-All types are Big Endian, except for
-EdDSA, which is stored and transmitted in a Little Endian format.
-{%- endtrans %}
{% trans cryptography=site_url('docs/how/cryptography') -%}
-This structure represents the signature of some data.
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-Signature type and length are inferred from the type of key used.
-{% endtrans %}
-{% trans -%}
-The default type is DSA_SHA1.
-{% endtrans %}
-{% trans -%}
-As of release 0.9.12, other types may be supported, depending on context.
-{% endtrans %}
-
-
-
{% trans %}Type{% endtrans %}
{% trans %}Length (bytes){% endtrans %}
{% trans %}Since{% endtrans %}
-
DSA_SHA1
40
-
ECDSA_SHA256_P256
64
0.9.12
-
ECDSA_SHA384_P384
96
0.9.12
-
ECDSA_SHA512_P521
132
0.9.12
-
RSA_SHA256_2048
256
0.9.12
-
RSA_SHA384_3072
384
0.9.12
-
RSA_SHA512_4096
512
0.9.12
-
EdDSA_SHA512_Ed25519
64
0.9.15
-
-
-
{% trans %}Notes{% endtrans %}
-
-
{% trans -%}
-When a signature is composed of two elements (for example values R,S), it is serialized by
-padding each element to length/2 with leading zeros if necessary.
-{%- endtrans %}
-
{% trans -%}
-All types are Big Endian, except for
-EdDSA, which is stored and transmitted in a Little Endian format.
-{%- endtrans %}
{% trans -%}
-Defines an identifier that is unique to each router in a tunnel.
-{% endtrans %}
-{% trans -%}
-A Tunnel ID is generally greater than zero; do not use a value of zero except in special cases.
-{% endtrans %}
{% trans -%}
-A certificate is a container for various receipts or proof of works used throughout the I2P network.
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-1 byte Integer specifying certificate type, followed by a 2 byte Integer specifying the size of the certificate payload, then that many bytes.
-{% endtrans %}
-{% highlight lang='dataspec' %}
-+----+----+----+----+----+-//
-|type| length | payload
-+----+----+----+----+----+-//
-
-type :: `Integer`
- length -> 1 byte
-
- case 0 -> NULL
- case 1 -> HASHCASH
- case 2 -> HIDDEN
- case 3 -> SIGNED
- case 4 -> MULTIPLE
- case 5 -> KEY
-
-length :: `Integer`
- length -> 2 bytes
-
-payload :: data
- length -> $length bytes
-{% endhighlight %}
-
-
{% trans %}Notes{% endtrans %}
-
-
{% trans -%}
-For Router Identities, the Certificate is always NULL through version 0.9.15.
-As of 0.9.16, a Key Certificate may be used to specify the signing public key type. See below.
-{%- endtrans %}
-
-
{% trans i2np=site_url('docs/spec/i2np') -%}
-For Garlic Cloves, the Certificate is always NULL, no others are currently implemented.
-{%- endtrans %}
-
-
{% trans i2np=site_url('docs/spec/i2np') -%}
-For Garlic Messages, the Certificate is always NULL, no others are currently implemented.
-{%- endtrans %}
-
-
{% trans -%}
-For Destinations, the Certificate may be non-NULL.
-As of 0.9.12, a Key Certificate may be used to specify the signing public key type. See below.
-{%- endtrans %}
-Key certificates are preliminary, and are scheduled to be introduced in release 0.9.12.
-Prior to that release, all PublicKeys were 256-byte ElGamal keys, and
-all SigningPublicKeys were 128-byte DSA-SHA1 keys.
-A key certificate provides a mechanism to indicate the type of the PublicKey and SigningPublicKey
-in the Destination or RouterIdentity, and to package any key data in excess of the
-standard lengths.
-
-By maintaining exactly 384 bytes before the certificate, and putting any excess key
-data inside the certificate, we maintain compatibility for any software that
-parses Destinations and RouterIdentities.
-
-
-When a Key Certificate is not present, the preceeding 384 bytes in the Destination or RouterIdentity
-are defined as the 256-byte ElGamal PublicKey followed by the 128-byte DSA-SHA1 SigningPublicKey.
-When a Key Certificate is present, the preceeding 384 bytes are redefined as follows:
-
-Complete or first portion of Crypto Public Key
-
-Random padding if the total lengths of the two keys are less than 384 bytes
-
-Complete or first portion of Signing Public Key
-
-
-The Crypto Public Key is aligned at the start and the Signing Public Key is aligned at the end.
-The padding (if any) is in the middle.
-The lengths and boundaries of the initial key data, the padding, and the excess key data portions
-in the certificates are not explicitly specified, but are derived from
-the lengths of the specified key types.
-If the total lengths of the Crypto and Signing Public Keys exceed 384 bytes,
-the remainder will be contained in the Key Certificate.
-If the Crypto Public Key length is not 256 bytes, the method for determining
-the boundary between the two keys is to be specified in a future revision of this document.
-
-
-
-Example layouts using an ElGamal Crypto Public Key and the Signing Public Key type indicated:
-
{% trans -%}
-A set of key/value mappings or properties
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-A 2-byte size Integer followed by a series of String=String; pairs
-{% endtrans %}
-{% highlight lang='dataspec' %}
-+----+----+----+----+----+----+----+----+
-| size |key_string (len + data) | = |
-+----+----+----+----+----+----+----+----+
-| val_string (len + data) | ; | ...
-+----+----+----+----+----+----+----+
-size :: `Integer`
- length -> 2 bytes
- Total number of bytes that follow
-
-key_string :: `String`
- A string (one byte length followed by UTF-8 encoded characters)
-
-= :: A single byte containing '='
-
-val_string :: `String`
- A string (one byte length followed by UTF-8 encoded characters)
-
-; :: A single byte containing ';'
-
-{% endhighlight %}
-
-
{% trans %}Notes{% endtrans %}
-
-
{% trans -%}
-The encoding isn't optimal - we either need the '=' and ';' characters, or the string lengths, but not both
-{%- endtrans %}
-
-
{% trans -%}
-Some documentation says that the strings may not include '=' or ';' but this encoding supports them
-{%- endtrans %}
-
-
{% trans -%}
-Strings are defined to be UTF-8 but in the current implementation, I2CP uses UTF-8 but I2NP does not.
-For example,
-UTF-8 strings in a RouterInfo options mapping in a I2NP Database Store Message will be corrupted.
-{%- endtrans %}
-
-
{% trans -%}
-The encoding allows duplicate keys, however in any usage where the mapping is signed,
-duplicates may cause a signature failure.
-{%- endtrans %}
-
-
{% trans -%}
-Mappings contained in I2NP messages (i.e. in a RouterAddress or RouterInfo)
-must be sorted by key so that the signature will be invariant.
-Duplicate keys are not allowed.
-{%- endtrans %}
-
-
{% trans i2cp=site_url('docs/spec/i2cp') -%}
-Mappings contained in an I2CP SessionConfig
-must be sorted by key so that the signature will be invariant.
-Duplicate keys are not allowed.
-{%- endtrans %}
-
-
{% trans -%}
-The sort method is defined as in Java String.compareTo(),
-using the Unicode value of the characters.
-{%- endtrans %}
-
-
{% trans -%}
-While it is application-dependent, keys and values are generally case-sensitive.
-{%- endtrans %}
-
-
{% trans -%}
-Key and value string length limits are 255 bytes (not characters) each, plus the length byte. Length byte may be 0.
-{%- endtrans %}
-
-
{% trans -%}
-Total length limit is 65535 bytes, plus the 2 byte size field, or 65537 total.
-{%- endtrans %}
-Do not assume that these are always 387 bytes!
-They are 387 bytes plus the certificate length specified at bytes 385-386, which may be non-zero.
-
-As of release 0.9.12, if the certificate is a Key Certificate, the boundaries of the
-key fields may vary. See the Key Certificate section above for details.
-
-The Crypto Public Key is aligned at the start and the Signing Public Key is aligned at the end.
-The padding (if any) is in the middle.
-
{% trans -%}
-Defines the way to uniquely identify a particular router
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-Identical to KeysAndCert.
-{% endtrans %}
-
-
{% trans %}Notes{% endtrans %}
-
{% trans -%}
-The certificate for a RouterIdentity was always NULL until release 0.9.12.
-{%- endtrans %}
-Do not assume that these are always 387 bytes!
-They are 387 bytes plus the certificate length specified at bytes 385-386, which may be non-zero.
-
-As of release 0.9.12, if the certificate is a Key Certificate, the boundaries of the
-key fields may vary. See the Key Certificate section above for details.
-
-The Crypto Public Key is aligned at the start and the Signing Public Key is aligned at the end.
-The padding (if any) is in the middle.
-
{% trans -%}
-A Destination defines a particular endpoint to which messages can be directed for secure delivery.
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-Identical to KeysAndCert.
-{% endtrans %}
-
-
Notes
-
-The public key of the destination was used for the old i2cp-to-i2cp encryption
-which was disabled in version 0.6, it is currently unused
-except for the IV for LeaseSet encryption,
-which is deprecated. The public key in the LeaseSet is used instead.
-
-Do not assume that these are always 387 bytes!
-They are 387 bytes plus the certificate length specified at bytes 385-386, which may be non-zero.
-
-As of release 0.9.12, if the certificate is a Key Certificate, the boundaries of the
-key fields may vary. See the Key Certificate section above for details.
-
-The Crypto Public Key is aligned at the start and the Signing Public Key is aligned at the end.
-The padding (if any) is in the middle.
-
{% trans -%}
-Contains all of the currently authorized Leases for a particular Destination, the PublicKey to which garlic messages can be encrypted,
-and then the public key that can be used to revoke this particular version of the structure. The LeaseSet is one of the two structures stored in the network database(
-the other being RouterInfo), and is keyed under the SHA256 of the contained Destination.
-{% endtrans %}
{% trans -%}
-The public key of the destination was used for the old i2cp-to-i2cp encryption
-which was disabled in version 0.6, it is currently unused.
-{%- endtrans %}
-
-
{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
-The encryption key is used for end-to-end ElGamal/AES+SessionTag encryption.
-It is currently generated anew at every router startup, it is not persistent.
-{%- endtrans %}
-
-
{% trans -%}
-The signature may be verified using the signing public key of the destination.
-{%- endtrans %}
-
-
{% trans -%}
-The signing_key is currently unused. It was intended for LeaseSet revocation, which is unimplemented.
-It is currently generated anew at every router startup, it is not persistent.
-The signing key type is always the same as the destination's signing key type.
-{%- endtrans %}
-
{% trans -%}
-The earliest expiration of all the Leases is treated as the timestamp or version of the LeaseSet.
-Routers will generally not accept a store of a LeaseSet unless it is "newer" than the current one.
-Take care when publishing a new LeaseSet where the oldest Lease is the same as the oldest Lease
-in the previous LeaseSet. The publishing router should generally increment the expiration
-of the oldest Lease by at least 1 ms in that case.
-{%- endtrans %}
-
{% trans -%}
-Prior to release 0.9.7, when included in a DatabaseStore Message sent by the originating router,
-the router set all the published leases' expirations to the same value, that of the
-earliest lease. As of release 0.9.7, the router publishes the actual lease expiration for each lease.
-This is an implementation detail and not part of the structures specification.
-{%- endtrans %}
{% trans -%}
-This structure defines the means to contact a router through a transport protocol.
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-1 byte Integer defining the relative cost of using the address, where 0 is free and 255 is expensive, followed by the expiration Date after which the address should not be used, or if null, the address never expires.
-After that comes a String defining the transport protocol this router address uses. Finally there is a Mapping containing all of the transport specific options necessary to establish the connection, such as
-IP address, port number, email address, URL, etc.
-{% endtrans %}
{% trans -%}
-Cost is typically 5 or 6 for SSU, and 10 or 11 for NTCP.
-{%- endtrans %}
-
-
{% trans -%}
-Expiration is currently unused, always null (all zeroes).
-As of release 0.9.3, the expiration is assumed zero and not stored, so any non-zero expiration
-will fail in the RouterInfo signature verification.
-Implementing expiration (or another use for these bytes) will be a backwards-incompatible change.
-Routers MUST set this field to all zeros.
-As of release 0.9.12, a non-zero expiration field is again recognized, however we must wait
-several releases to use this field, until the vast majority of the network recognizes it.
-{%- endtrans %}
-
-
{% trans -%}
-The following options, while not required, are standard and expected to be present in most router addresses:
-"host" (an IPv4 or IPv6 address or host name) and "port".
-{%- endtrans %}
{% trans -%}
-Defines all of the data that a router wants to publish for the network to see. The RouterInfo is one of two structures stored in the network database(the other being LeaseSet, and is keyed under the SHA256 of
-the contained RouterIdentity.
-{% endtrans %}
-
{% trans %}Contents{% endtrans %}
-
{% trans -%}
-RouterIdentity followed by the Date, when the entry was published
-{% endtrans %}
{% trans -%}
-The peer_size Integer may be followed by a list of that many router hashes.
-This is currently unused. It was intended for a form of restricted routes, which is unimplemented.
-{%- endtrans %}
-
-
{% trans -%}
-The signature may be verified using the signing public key of the router_ident.
-{%- endtrans %}
-
-
{% trans netdb=site_url('docs/how/network-database') -%}
-See the network database page
-for standard options that are expected to be present in all router infos.
-{%- endtrans %}
{% trans tunnelmessage=site_url('docs/spec/tunnel-message') -%}
-Tunnel Message Delivery Instructions are defined in the Tunnel Message Specification.
-{% endtrans %}
-
{% trans i2npmessage=site_url('docs/spec/i2np') -%}
-Garlic Message Delivery Instructions are defined in the I2NP Message Specification.
-{% endtrans %}
-{% endblock %}
diff --git a/i2p2www/spec/common-structures.rst b/i2p2www/spec/common-structures.rst
new file mode 100644
index 00000000..bd36dfa3
--- /dev/null
+++ b/i2p2www/spec/common-structures.rst
@@ -0,0 +1,1107 @@
+===============================
+Common structures Specification
+===============================
+.. meta::
+ :lastupdated: April 2015
+ :accuratefor: 0.9.19
+
+
+This document describes some data types common to all I2P protocols, like
+[I2NP]_, [I2CP]_, [SSU]_, etc.
+
+Index
+=====
+
++--------------------------+
+| Type |
++==========================+
+| Boolean_ |
++--------------------------+
+| Certificate_ |
++--------------------------+
+| Date_ |
++--------------------------+
+| `Delivery Instructions`_ |
++--------------------------+
+| Destination_ |
++--------------------------+
+| Hash_ |
++--------------------------+
+| Integer_ |
++--------------------------+
+| KeysAndCert_ |
++--------------------------+
+| Lease_ |
++--------------------------+
+| LeaseSet_ |
++--------------------------+
+| Mapping_ |
++--------------------------+
+| PrivateKey_ |
++--------------------------+
+| PublicKey_ |
++--------------------------+
+| RouterAddress_ |
++--------------------------+
+| RouterIdentity_ |
++--------------------------+
+| RouterInfo_ |
++--------------------------+
+| `Session Tag`_ |
++--------------------------+
+| Signature_ |
++--------------------------+
+| PrivateKey_ |
++--------------------------+
+| SigningPublicKey_ |
++--------------------------+
+| String_ |
++--------------------------+
+| TunnelId_ |
++--------------------------+
+
+
+Common type specification
+=========================
+
+.. _type-integer:
+
+Integer
+-------
+
+Description
+```````````
+Represents a non-negative integer.
+
+Contents
+````````
+1 to 8 bytes in network byte order representing an unsigned integer
+
+.. _type-date:
+
+Date
+----
+
+Description
+```````````
+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.
+
+Contents
+````````
+8 byte Integer_
+
+.. _type-string:
+
+String
+------
+
+Description
+```````````
+Represents a UTF-8 encoded string.
+
+Contents
+````````
+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. Length limit is 255 bytes (not characters). Length
+may be 0.
+
+.. _type-boolean:
+
+Boolean
+-------
+
+Description
+```````````
+A boolean value, supporting null/unknown representation
+0=false, 1=true, 2=unknown/null
+
+Contents
+````````
+1 byte Integer_
+
+Notes
+`````
+Deprecated - unused
+
+.. _type-publickey:
+
+PublicKey
+---------
+
+Description
+```````````
+This structure is used in ElGamal encryption, representing only the exponent,
+not the primes, which are constant and defined in the cryptography
+specification [ELGAMAL]_.
+
+Contents
+````````
+256 bytes
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/PublicKey.html
+
+.. _type-privatekey:
+
+PrivateKey
+----------
+
+Description
+```````````
+This structure is used in ElGamal decryption, representing only the exponent,
+not the primes which are constant and defined in the cryptography specification
+[ELGAMAL]_.
+
+Contents
+````````
+256 bytes
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/PrivateKey.html
+
+.. _type-sessionkey:
+
+SessionKey
+----------
+
+Description
+```````````
+This structure is used for AES256 encryption and decryption.
+
+Contents
+````````
+32 bytes
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/SessionKey.html
+
+.. _type-signingpublickey:
+
+SigningPublicKey
+----------------
+
+Description
+```````````
+This structure is used for verifying signatures.
+
+Contents
+````````
+Key type and length are inferred from context or are specified in the Key
+Certificate of a Destination. The default type is DSA_SHA1. As of release
+0.9.12, other types may be supported, depending on context.
+
+==================== ============== ======
+ Type Length (bytes) Since
+==================== ============== ======
+DSA_SHA1 128
+ECDSA_SHA256_P256 64 0.9.12
+ECDSA_SHA384_P384 96 0.9.12
+ECDSA_SHA512_P521 132 0.9.12
+RSA_SHA256_2048 256 0.9.12
+RSA_SHA384_3072 384 0.9.12
+RSA_SHA512_4096 512 0.9.12
+EdDSA_SHA512_Ed25519 32 0.9.15
+==================== ============== ======
+
+Notes
+`````
+* When a key is composed of two elements (for example points X,Y), it is
+ serialized by padding each element to length/2 with leading zeros if
+ necessary.
+
+* All types are Big Endian, except for EdDSA, which is stored and transmitted
+ in a Little Endian format.
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/SigningPublicKey.html
+
+.. _type-signingprivatekey:
+
+SigningPrivateKey
+-----------------
+
+Description
+```````````
+This structure is used for creating signatures.
+
+Contents
+````````
+Key type and length are specified when created. The default type is DSA_SHA1.
+As of release 0.9.12, other types may be supported, depending on context.
+
+==================== ============== ======
+ Type Length (bytes) Since
+==================== ============== ======
+DSA_SHA1 20
+ECDSA_SHA256_P256 32 0.9.12
+ECDSA_SHA384_P384 48 0.9.12
+ECDSA_SHA512_P521 66 0.9.12
+RSA_SHA256_2048 512 0.9.12
+RSA_SHA384_3072 768 0.9.12
+RSA_SHA512_4096 1024 0.9.12
+EdDSA_SHA512_Ed25519 32 0.9.15
+==================== ============== ======
+
+Notes
+`````
+* When a key is composed of two elements (for example points X,Y), it is
+ serialized by padding each element to length/2 with leading zeros if
+ necessary.
+
+* All types are Big Endian, except for EdDSA, which is stored and transmitted
+ in a Little Endian format.
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/SigningPrivateKey.html
+
+.. _type-signature:
+
+Signature
+---------
+
+Description
+```````````
+This structure represents the signature of some data.
+
+Contents
+````````
+Signature type and length are inferred from the type of key used. The default
+type is DSA_SHA1. As of release 0.9.12, other types may be supported,
+depending on context.
+
+==================== ============== ======
+ Type Length (bytes) Since
+==================== ============== ======
+DSA_SHA1 40
+ECDSA_SHA256_P256 64 0.9.12
+ECDSA_SHA384_P384 96 0.9.12
+ECDSA_SHA512_P521 132 0.9.12
+RSA_SHA256_2048 256 0.9.12
+RSA_SHA384_3072 384 0.9.12
+RSA_SHA512_4096 512 0.9.12
+EdDSA_SHA512_Ed25519 64 0.9.15
+==================== ============== ======
+
+Notes
+`````
+* When a signature is composed of two elements (for example values R,S), it is
+ serialized by padding each element to length/2 with leading zeros if
+ necessary.
+
+* All types are Big Endian, except for EdDSA, which is stored and transmitted
+ in a Little Endian format.
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/Signature.html
+
+.. _type-hash:
+
+Hash
+----
+
+Description
+```````````
+Represents the SHA256 of some data.
+
+Contents
+````````
+32 bytes
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/Hash.html
+
+.. _type-sessiontag:
+
+Session Tag
+-----------
+
+Description
+```````````
+A random number
+
+Contents
+````````
+32 bytes
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/SessionTag.html
+
+.. _type-tunnelid:
+
+TunnelId
+--------
+
+Description
+```````````
+Defines an identifier that is unique to each router in a tunnel. A Tunnel ID
+is generally greater than zero; do not use a value of zero except in special
+cases.
+
+Contents
+````````
+4 byte Integer_
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/TunnelId.html
+
+.. _type-certificate:
+
+Certificate
+-----------
+
+Description
+```````````
+A certificate is a container for various receipts or proof of works used
+throughout the I2P network.
+
+Contents
+````````
+1 byte Integer_ specifying certificate type, followed by a 2 byte Integer_
+specifying the size of the certificate payload, then that many bytes.
+
+.. raw:: html
+
+ {% highlight lang='dataspec' -%}
++----+----+----+----+----+-//
+ |type| length | payload
+ +----+----+----+----+----+-//
+
+ type :: `Integer`
+ length -> 1 byte
+
+ case 0 -> NULL
+ case 1 -> HASHCASH
+ case 2 -> HIDDEN
+ case 3 -> SIGNED
+ case 4 -> MULTIPLE
+ case 5 -> KEY
+
+ length :: `Integer`
+ length -> 2 bytes
+
+ payload :: data
+ length -> $length bytes
+{% endhighlight %}
+
+Notes
+`````
+* For `Router Identities`_, the Certificate is always NULL through version
+ 0.9.15. As of 0.9.16, a Key Certificate may be used to specify the signing
+ public key type. See below.
+
+* For `Garlic Cloves`_, the Certificate is always NULL, no others are currently
+ implemented.
+
+* For `Garlic Messages`_, the Certificate is always NULL, no others are
+ currently implemented.
+
+* For `Destinations`_, the Certificate may be non-NULL. As of 0.9.12, a Key
+ Certificate may be used to specify the signing public key type. See below.
+
+.. _Router Identities: #struct_RouterIdentity
+.. _Garlic Cloves: {{ site_url('docs/spec/i2np') }}#struct_GarlicClove
+.. _Garlic Messages: {{ site_url('docs/spec/i2np') }}#msg_Garlic
+.. _Destinations: #struct_Destination
+
+Certificate Types
+`````````````````
+The following certificate types are defined:
+
+======== ========= ============== ============ =====
+Type Type Code Payload Length Total Length Notes
+======== ========= ============== ============ =====
+Null 0 0 3
+HashCash 1 varies varies Experimental, unused. Payload contains an ASCII colon-separated hashcash string.
+Hidden 2 0 3 Experimental, unused. Hidden routers generally do not announce that they are hidden.
+Signed 3 40 or 72 43 or 75 Experimental, unused. Payload contains a 40-byte DSA signature,
+ optionally followed by the 32-byte Hash of the signing Destination.
+Multiple 4 varies varies Experimental, unused. Payload contains multiple certificates.
+Key 5 4+ 7+ Since 0.9.12. See below for details.
+======== ========= ============== ============ =====
+
+
+Key Certificates
+````````````````
+Key certificates are preliminary, and are scheduled to be introduced in release
+0.9.12. Prior to that release, all PublicKeys were 256-byte ElGamal keys, and
+all SigningPublicKeys were 128-byte DSA-SHA1 keys. A key certificate provides
+a mechanism to indicate the type of the PublicKey and SigningPublicKey in the
+Destination or RouterIdentity, and to package any key data in excess of the
+standard lengths.
+
+By maintaining exactly 384 bytes before the certificate, and putting any excess
+key data inside the certificate, we maintain compatibility for any software
+that parses Destinations and RouterIdentities.
+
+The key certificate payload contains:
+
+================================== ======
+ Data Length
+================================== ======
+Signing Public Key Type (Integer_) 2
+Crypto Public Key Type (Integer_) 2
+Excess Signing Public Key Data 0+
+Excess Crypto Public Key Data 0+
+================================== ======
+
+The defined Signing Public Key types are:
+
+==================== ========= ======================= ======
+ Type Type Code Total Public Key Length Since
+==================== ========= ======================= ======
+DSA_SHA1 0 128 0.9.12
+ECDSA_SHA256_P256 1 64 0.9.12
+ECDSA_SHA384_P384 2 96 0.9.12
+ECDSA_SHA512_P521 3 132 0.9.12
+RSA_SHA256_2048 4 256 0.9.12
+RSA_SHA384_3072 5 384 0.9.12
+RSA_SHA512_4096 6 512 0.9.12
+EdDSA_SHA512_Ed25519 7 32 0.9.15
+==================== ========= ======================= ======
+
+The defined Crypto Public Key types are:
+
+======= ========= =======================
+ Type Type Code Total Public Key Length
+======= ========= =======================
+ElGamal 0 256
+======= ========= =======================
+
+When a Key Certificate is not present, the preceeding 384 bytes in the
+Destination or RouterIdentity are defined as the 256-byte ElGamal PublicKey
+followed by the 128-byte DSA-SHA1 SigningPublicKey. When a Key Certificate is
+present, the preceeding 384 bytes are redefined as follows:
+
+* Complete or first portion of Crypto Public Key
+
+* Random padding if the total lengths of the two keys are less than 384 bytes
+
+* Complete or first portion of Signing Public Key
+
+The Crypto Public Key is aligned at the start and the Signing Public Key is
+aligned at the end. The padding (if any) is in the middle. The lengths and
+boundaries of the initial key data, the padding, and the excess key data
+portions in the certificates are not explicitly specified, but are derived from
+the lengths of the specified key types. If the total lengths of the Crypto and
+Signing Public Keys exceed 384 bytes, the remainder will be contained in the
+Key Certificate. If the Crypto Public Key length is not 256 bytes, the method
+for determining the boundary between the two keys is to be specified in a
+future revision of this document.
+
+Example layouts using an ElGamal Crypto Public Key and the Signing Public Key
+type indicated:
+
+==================== ============== ===============================
+ Signing Key Type Padding Length Excess Signing Key Data in Cert
+==================== ============== ===============================
+DSA_SHA1 0 0
+ECDSA_SHA256_P256 64 0
+ECDSA_SHA384_P384 32 0
+ECDSA_SHA512_P521 0 4
+RSA_SHA256_2048 0 128
+RSA_SHA384_3072 0 256
+RSA_SHA512_4096 0 384
+EdDSA_SHA512_Ed25519 96 0
+==================== ============== ===============================
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/Certificate.html
+
+.. _type-mapping:
+
+Mapping
+-------
+
+Description
+```````````
+A set of key/value mappings or properties
+
+Contents
+````````
+A 2-byte size Integer followed by a series of String=String; pairs
+
+.. raw:: html
+
+ {% highlight lang='dataspec' -%}
++----+----+----+----+----+----+----+----+
+ | size | key_string (len + data)| = |
+ +----+----+----+----+----+----+----+----+
+ | val_string (len + data) | ; | ...
+ +----+----+----+----+----+----+----+
+ size :: `Integer`
+ length -> 2 bytes
+ Total number of bytes that follow
+
+ key_string :: `String`
+ A string (one byte length followed by UTF-8 encoded characters)
+
+ = :: A single byte containing '='
+
+ val_string :: `String`
+ A string (one byte length followed by UTF-8 encoded characters)
+
+ ; :: A single byte containing ';'
+{% endhighlight %}
+
+Notes
+`````
+* The encoding isn't optimal - we either need the '=' and ';' characters, or
+ the string lengths, but not both
+
+* Some documentation says that the strings may not include '=' or ';' but this
+ encoding supports them
+
+* Strings are defined to be UTF-8 but in the current implementation, I2CP uses
+ UTF-8 but I2NP does not. For example, UTF-8 strings in a RouterInfo options
+ mapping in a I2NP Database Store Message will be corrupted.
+
+* The encoding allows duplicate keys, however in any usage where the mapping is
+ signed, duplicates may cause a signature failure.
+
+* Mappings contained in I2NP messages (i.e. in a RouterAddress or RouterInfo)
+ must be sorted by key so that the signature will be invariant. Duplicate keys
+ are not allowed.
+
+* Mappings contained in an `I2CP SessionConfig`_ must be sorted by key so that
+ the signature will be invariant. Duplicate keys are not allowed.
+
+* The sort method is defined as in Java String.compareTo(), using the Unicode
+ value of the characters.
+
+* While it is application-dependent, keys and values are generally
+ case-sensitive.
+
+* Key and value string length limits are 255 bytes (not characters) each, plus
+ the length byte. Length byte may be 0.
+
+* Total length limit is 65535 bytes, plus the 2 byte size field, or 65537
+ total.
+
+.. _I2CP SessionConfig: {{ site_url('docs/spec/i2cp') }}#struct_SessionConfig
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/DataHelper.html
+
+
+Common structure specification
+==============================
+
+.. _struct-keysandcert:
+
+KeysAndCert
+-----------
+
+Description
+```````````
+An encryption public key, a signing public key, and a certificate, used as
+either a RouterIdentity or a Destination.
+
+Contents
+````````
+A PublicKey_ followed by a SigningPublicKey_ and then a Certificate_.
+
+.. raw:: html
+
+ {% highlight lang='dataspec' -%}
++----+----+----+----+----+----+----+----+
+ | public_key |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | padding (optional) |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | signing_key |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | certificate |
+ +----+----+----+-//
+
+ public_key :: `PublicKey` (partial or full)
+ length -> 256 bytes or as specified in key certificate
+
+ padding :: random data
+ length -> 0 bytes or as specified in key certificate
+ padding length + signing_key length == 128 bytes
+
+ signing__key :: `SigningPublicKey` (partial or full)
+ length -> 128 bytes or as specified in key certificate
+ padding length + signing_key length == 128 bytes
+
+ certificate :: `Certificate`
+ length -> >= 3 bytes
+
+ total length: 387+ bytes
+{% endhighlight %}
+
+Notes
+`````
+* Do not assume that these are always 387 bytes! They are 387 bytes plus the
+ certificate length specified at bytes 385-386, which may be non-zero.
+
+* As of release 0.9.12, if the certificate is a Key Certificate, the boundaries
+ of the key fields may vary. See the Key Certificate section above for
+ details.
+
+* The Crypto Public Key is aligned at the start and the Signing Public Key is
+ aligned at the end. The padding (if any) is in the middle.
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/KeysAndCert.html
+
+.. _struct-routeridentity:
+
+RouterIdentity
+--------------
+
+Description
+```````````
+Defines the way to uniquely identify a particular router
+
+Contents
+````````
+Identical to KeysAndCert.
+
+Notes
+`````
+* The certificate for a RouterIdentity was always NULL until release 0.9.12.
+
+* Do not assume that these are always 387 bytes! They are 387 bytes plus the
+ certificate length specified at bytes 385-386, which may be non-zero.
+
+* As of release 0.9.12, if the certificate is a Key Certificate, the boundaries
+ of the key fields may vary. See the Key Certificate section above for
+ details.
+
+* The Crypto Public Key is aligned at the start and the Signing Public Key is
+ aligned at the end. The padding (if any) is in the middle.
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/router/RouterIdentity.html
+
+.. _struct-destination:
+
+Destination
+-----------
+
+Description
+```````````
+A Destination defines a particular endpoint to which messages can be directed
+for secure delivery.
+
+Contents
+````````
+Identical to KeysAndCert_.
+
+Notes
+`````
+* The public key of the destination was used for the old i2cp-to-i2cp
+ encryption which was disabled in version 0.6, it is currently unused except
+ for the IV for LeaseSet encryption, which is deprecated. The public key in
+ the LeaseSet is used instead.
+
+* Do not assume that these are always 387 bytes! They are 387 bytes plus the
+ certificate length specified at bytes 385-386, which may be non-zero.
+
+* As of release 0.9.12, if the certificate is a Key Certificate, the boundaries
+ of the key fields may vary. See the Key Certificate section above for
+ details.
+
+* The Crypto Public Key is aligned at the start and the Signing Public Key is
+ aligned at the end. The padding (if any) is in the middle.
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/Destination.html
+
+.. _struct-lease:
+
+Lease
+-----
+
+Description
+```````````
+Defines the authorization for a particular tunnel to receive messages targeting
+a Destination_.
+
+Contents
+````````
+SHA256 Hash_ of the RouterIdentity_ of the gateway router, then the TunnelId_,
+and finally an end Date_.
+
+.. raw:: html
+
+ {% highlight lang='dataspec' -%}
++----+----+----+----+----+----+----+----+
+ | tunnel_gw |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | tunnel_id | end_date
+ +----+----+----+----+----+----+----+----+
+ |
+ +----+----+----+----+
+
+ tunnel_gw :: Hash of the `RouterIdentity` of the tunnel gateway
+ length -> 32 bytes
+
+ tunnel_id :: `TunnelId`
+ length -> 4 bytes
+
+ end_date :: `Date`
+ length -> 8 bytes
+{% endhighlight %}
+
+Notes
+`````
+* Total size: 44 bytes
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/Lease.html
+
+.. _struct-leaseset:
+
+LeaseSet
+--------
+
+Description
+```````````
+Contains all of the currently authorized Leases_ for a particular Destination_,
+the PublicKey_ to which garlic messages can be encrypted, and then the
+SigningPublicKey_ that can be used to revoke this particular version of the
+structure. The LeaseSet is one of the two structures stored in the network
+database (the other being RouterInfo_), and is keyed under the SHA256 of the
+contained Destination_.
+
+.. _Leases: _Lease
+
+Contents
+````````
+Destination_, followed by a PublicKey_ for encryption, then a SigningPublicKey_
+which can be used to revoke this version of the LeaseSet, then a 1 byte
+Integer_ specifying how many Lease_ structures are in the set, followed by the
+actual Lease_ structures and finally a Signature_ of the previous bytes signed
+by the Destination_'s SigningPrivateKey_.
+
+.. raw:: html
+
+ {% highlight lang='dataspec' -%}
++----+----+----+----+----+----+----+----+
+ | destination |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | encryption_key |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | signing_key |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | num| Lease 0 |
+ +----+ +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | Lease 1 |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | Lease ($num-1) |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | signature |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+
+ destination :: `Destination`
+ length -> >= 387 bytes
+
+ encryption_key :: `PublicKey`
+ length -> 256 bytes
+
+ signing_key :: `SigningPublicKey`
+ length -> 128 bytes or as specified in destination's key
+ certificate
+
+ num :: `Integer`
+ length -> 1 byte
+ Number of leases to follow
+ value: 0 <= num <= 16
+
+ leases :: [`Lease`]
+ length -> $num*44 bytes
+
+ signature :: `Signature`
+ length -> 40 bytes or as specified in destination's key
+ certificate
+{% endhighlight %}
+
+Notes
+`````
+* The public key of the destination was used for the old I2CP-to-I2CP
+ encryption which was disabled in version 0.6, it is currently unused.
+
+* The encryption key is used for end-to-end ElGamal/AES+SessionTag encryption
+ [ELGAMAL-AES]_. It is currently generated anew at every router startup, it is
+ not persistent.
+
+* The signature may be verified using the signing public key of the
+ destination.
+
+* The signing_key is currently unused. It was intended for LeaseSet revocation,
+ which is unimplemented. It is currently generated anew at every router
+ startup, it is not persistent. The signing key type is always the same as the
+ destination's signing key type.
+
+* The earliest expiration of all the Leases is treated as the timestamp or
+ version of the LeaseSet. Routers will generally not accept a store of a
+ LeaseSet unless it is "newer" than the current one. Take care when publishing
+ a new LeaseSet where the oldest Lease is the same as the oldest Lease in the
+ previous LeaseSet. The publishing router should generally increment the
+ expiration of the oldest Lease by at least 1 ms in that case.
+
+* Prior to release 0.9.7, when included in a DatabaseStore Message sent by the
+ originating router, the router set all the published leases' expirations to
+ the same value, that of the earliest lease. As of release 0.9.7, the router
+ publishes the actual lease expiration for each lease. This is an
+ implementation detail and not part of the structures specification.
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/LeaseSet.html
+
+.. _struct-routeraddress:
+
+RouterAddress
+-------------
+
+Description
+```````````
+This structure defines the means to contact a router through a transport
+protocol.
+
+Contents
+````````
+1 byte Integer_ defining the relative cost of using the address, where 0 is
+free and 255 is expensive, followed by the expiration Date_ after which the
+address should not be used, or if null, the address never expires. After that
+comes a String_ defining the transport protocol this router address uses.
+Finally there is a Mapping_ containing all of the transport specific options
+necessary to establish the connection, such as IP address, port number, email
+address, URL, etc.
+
+.. raw:: html
+
+ {% highlight lang='dataspec' -%}
++----+----+----+----+----+----+----+----+
+ |cost| expiration
+ +----+----+----+----+----+----+----+----+
+ | transport_style |
+ +----+----+----+----+-//-+----+----+----+
+ | |
+ + +
+ | options |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+
+ cost :: `Integer`
+ length -> 1 byte
+
+ case 0 -> free
+ case 255 -> expensive
+
+ expiration :: `Date` (must be all zeros, see notes below)
+ length -> 8 bytes
+
+ case null -> never expires
+
+ transport_style :: `String`
+ length -> 1-256 bytes
+
+ options :: `Mapping`
+{% endhighlight %}
+
+Notes
+`````
+* Cost is typically 5 or 6 for SSU, and 10 or 11 for NTCP.
+
+* Expiration is currently unused, always null (all zeroes). As of release
+ 0.9.3, the expiration is assumed zero and not stored, so any non-zero
+ expiration will fail in the RouterInfo signature verification. Implementing
+ expiration (or another use for these bytes) will be a backwards-incompatible
+ change. Routers MUST set this field to all zeros. As of release 0.9.12, a
+ non-zero expiration field is again recognized, however we must wait several
+ releases to use this field, until the vast majority of the network recognizes
+ it.
+
+* The following options, while not required, are standard and expected to be
+ present in most router addresses: "host" (an IPv4 or IPv6 address or host
+ name) and "port".
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/router/RouterAddress.html
+
+.. _struct-routerinfo:
+
+RouterInfo
+----------
+
+Description
+```````````
+Defines all of the data that a router wants to publish for the network to see.
+The RouterInfo_ is one of two structures stored in the network database (the
+other being LeaseSet_), and is keyed under the SHA256 of the contained
+RouterIdentity_.
+
+Contents
+````````
+RouterIdentity_ followed by the Date_, when the entry was published
+
+.. raw:: html
+
+ {% highlight lang='dataspec' -%}
++----+----+----+----+----+----+----+----+
+ | router_ident |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | published |
+ +----+----+----+----+----+----+----+----+
+ |size| RouterAddress 0 |
+ +----+ +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | RouterAddress 1 |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | RouterAddress ($size-1) |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+-//-+----+----+----+
+ |psiz| options |
+ +----+----+----+----+-//-+----+----+----+
+ | signature |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+
+ router_ident :: `RouterIdentity`
+ length -> >= 387 bytes
+
+ published :: `Date`
+ length -> 8 bytes
+
+ size :: `Integer`
+ length -> 1 byte
+ The number of `RouterAddress`es to follow, 0-255
+
+ addresses :: [`RouterAddress`]
+ length -> varies
+
+ peer_size :: `Integer`
+ length -> 1 byte
+ The number of peer `Hash`es to follow, 0-255, unused, always zero
+ value -> 0
+
+ options :: `Mapping`
+
+ signature :: `Signature`
+ length -> 40 bytes
+{% endhighlight %}
+
+Notes
+`````
+* The peer_size Integer_ may be followed by a list of that many router hashes.
+ This is currently unused. It was intended for a form of restricted routes,
+ which is unimplemented.
+
+* The signature may be verified using the signing public key of the
+ router_ident.
+
+* See the network database page [NETDB-ROUTERINFO]_ for standard options that
+ are expected to be present in all router infos.
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/router/RouterInfo.html
+
+.. _struct-deliveryinstructions:
+
+Delivery Instructions
+---------------------
+
+Tunnel Message Delivery Instructions are defined in the Tunnel Message
+Specification [TUNNEL-DELIVERY]_.
+
+Garlic Message Delivery Instructions are defined in the I2NP Message
+Specification [GARLIC-DELIVERY]_.
+
+
+References
+==========
+
+.. [ELGAMAL]
+ {{ site_url('docs/how/cryptography', True) }}#elgamal
+
+.. [ELGAMAL-AES]
+ {{ site_url('docs/how/elgamal-aes', True) }}
+
+.. [GARLIC-DELIVERY]
+ {{ site_url('docs/protocol/i2np', True) }}#struct-garlicclovedeliveryinstructions
+
+.. [I2CP]
+ {{ site_url('docs/protocol/i2cp', True) }}
+
+.. [I2NP]
+ {{ site_url('docs/protocol/i2np', True) }}
+
+.. [NETDB-ROUTERINFO]
+ {{ site_url('docs/how/network-database', True) }}#routerInfo
+
+.. [SSU]
+ {{ site_url('docs/transport/ssu', True) }}
+
+.. [TUNNEL-DELIVERY]
+ {{ site_url('docs/spec/tunnel-message', True) }}#struct-tunnelmessagedeliveryinstructions
diff --git a/i2p2www/spec/configuration.html b/i2p2www/spec/configuration.html
deleted file mode 100644
index 54d39459..00000000
--- a/i2p2www/spec/configuration.html
+++ /dev/null
@@ -1,385 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}{% trans %}Configuration File Specification{% endtrans %}{% endblock %}
-{% block lastupdated %}{% trans %}November 2014{% endtrans %}{% endblock %}
-{% block accuratefor %}0.9.17{% endblock %}
-{% block content %}
-
{% trans %}Overview{% endtrans %}
-
{% trans -%}
-This page provides a general specification of I2P configuration files,
-used by the router and various applications.
-It also gives an overview of the information contained in the various files,
-and links to detailed documentation where available.
-{%- endtrans %}
-
-
-
{% trans %}General Format{% endtrans %}
-
{% trans url='http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Properties.html#load%28java.io.InputStream%29' -%}
-An I2P configuration file is formatted as specified in
-Java Properties
-with the following exceptions:
-{%- endtrans %}
-
-
{% trans %}Encoding must be UTF-8{% endtrans %}
-
{% trans %}Does not use or recognize any escapes, including '\', so lines may not be continued{% endtrans %}
-
{% trans %}'#' or ';' starts a comment, but '!' does not{% endtrans %}
-
{% trans %}'#' starts a comment in any position but ';' must be in column 1 to start a comment{% endtrans %}
-
{% trans %}Leading and trailing whitespace is not trimmed on keys{% endtrans %}
-
{% trans %}Leading and trailing whitespace is trimmed on values{% endtrans %}
-
{% trans %}'=' is the only key-termination character (not ':' or whitespace){% endtrans %}
-
{% trans %}Lines without '=' are ignored. As of release 0.9.10, keys with a value of "" are supported.{% endtrans %}
-
{% trans %}As there are no escapes, keys may not contain '#', '=', or '\n', or start with ';'{% endtrans %}
-
{% trans %}As there are no escapes, values may not contain '#' or '\n', or start or end with '\r' or whitespace{% endtrans %}
-
-
-
{% trans -%}
-The file need not be sorted, but most applications do sort by key when
-writing to the file, for ease of reading and manual editing.
-{%- endtrans %}
-
-
{% trans url='http://docs.i2p-projekt.de/javadoc/net/i2p/data/DataHelper.html',
-commonstructures=site_url('docs/spec/common-structures') -%}
-Reads and writes are implemented in
-DataHelper loadProps() and storeProps().
-Note that the file format is significantly different than the
-serialized format for I2P protocols specified in
-Mapping.
-{%- endtrans %}
-
-
{% trans %}Core library and router{% endtrans %}
-
-
{% trans %}Clients{% endtrans %} (clients.config)
-
{% trans -%}
-Configured via /configclients in the router console.
-{%- endtrans %}
-
-The format is as follows:
-
-Lines are of the form clientApp.x.prop=val, where x is the app number.
-App numbers MUST start with 0 and be consecutive.
-
-Properties are as follows:
-
- main: Full class name. Required. The constructor or main() method in this
- class will be run, depending on whether the client is managed or unmanaged.
- See below for details.
- name: Name to be displayed on console.
- args: Arguments to the main class, separated by spaces or tabs.
- Arguments containing spaces or tabs may be quoted with ' or "
- delay: Seconds before starting, default 120
- onBoot: {true|false}, default false, forces a delay of 0,
- overrides delay setting
- startOnLoad: {true|false} Is the client to be run at all?
- Default true
-
-
-The following additional properties are used only by plugins:
-
- stopargs: Arguments to stop the client.
- uninstallargs: Arguments to uninstall the client.
- classpath: Additional classpath elements for the client,
- separated by commas.
-
-
-The following substitutions are made in the args, stopargs,
-uninstallargs, and classpath lines, for plugins only:
-
- $I2P: The base I2P install directory
- $CONFIG: The user's configuration directory (e.g. ~/.i2p)
- $PLUGIN: This plugin's directory (e.g. ~/.i2p/plugins/foo)
-
-
-All properties except "main" are optional.
-Lines starting with "#" are comments.
-
-If the delay is less than zero, the client is run immediately,
-in the same thread, so that exceptions may be propagated to the console.
-In this case, the client should either throw an exception, return quickly,
-or spawn its own thread.
-If the delay is greater than or equal to zero, it will be run
-in a new thread, and exceptions will be logged but not propagated
-to the console.
-
-
-Clients may be "managed" or "unmanaged".
-
-
-
-
{% trans %}Logger{% endtrans %} (logger.config)
-
{% trans -%}
-Configured via /configlogging in the router console.
-{%- endtrans %}
-
-{% trans -%}
-Properties are as follows:
-{%- endtrans %}
-
- # Default 20
- logger.consoleBufferSize=n
- # Default from locale; format as specified by Java SimpleDateFormat
- logger.dateFormat=HH:mm:ss.SSS
- # Default ERROR
- logger.defaultLevel=CRIT|ERROR|WARN|INFO|DEBUG
- # Default true
- logger.displayOnScreen=true|false
- # Default true
- logger.dropDuplicates=true|false
- # Default false
- logger.dropOnOverflow=true|false
- # As of 0.9.18. Default 29 (seconds)
- logger.flushInterval=nnn
- # d = date, c = class, t = thread name, p = priority, m = message
- logger.format={dctpm}*
- # Max to buffer before flushing. Default 1024
- logger.logBufferSize=n
- # Default logs/log-@.txt; @ replaced with number
- logger.logFileName=name
- logger.logFilenameOverride=name
- # Default 10M
- logger.logFileSize=nnn[K|M|G]
- # Highest file number. Default 2
- logger.logRotationLimit=n
- # Default CRIT
- logger.minimumOnScreenLevel=CRIT|ERROR|WARN|INFO|DEBUG
- logger.record.{class}=CRIT|ERROR|WARN|INFO|DEBUG
-
-
-
-
{% trans %}Individual Plugin{% endtrans %} (xxx/plugin.config)
-
{% trans pluginspec=site_url('docs/spec/plugin') -%}
-See the plugin specification.
-{%- endtrans %}
-
-
{% trans %}Plugins{% endtrans %} (plugins.config)
-
{% trans -%}
-Enable/disable for each installed plugin.
-{%- endtrans %}
-{% trans -%}
-Properties are as follows:
-{%- endtrans %}
-
- plugin.{name}.startOnLoad=true|false
-
-
-
-
{% trans %}Webapps{% endtrans %} (webapps.config)
-
{% trans -%}
-Enable/disable for each installed webapp.
-{%- endtrans %}
-{% trans -%}
-Properties are as follows:
-{%- endtrans %}
-
- webapps.{name}.classpath=[space- or comma-separated paths]
- webapps.{name}.startOnLoad=true|false
-
-
-
-
{% trans %}Router{% endtrans %} (router.config)
-
{% trans -%}
-Configured via /configadvanced in the router console.
-{%- endtrans %}
-
-
{% trans %}Applications{% endtrans %}
-
-
{% trans %}Addressbook{% endtrans %} (addressbook/config.txt)
-
{% trans -%}
-See documentation in SusiDNS.
-{%- endtrans %}
-
-
I2PSnark (i2psnark.config)
-
{% trans -%}
-Configured via the application gui.
-{%- endtrans %}
-
-
I2PTunnel (i2ptunnel.config)
-
{% trans -%}
-Configured via the /i2ptunnel application in the router console.
-{%- endtrans %}
-{% trans -%}
-Properties are as follows:
-{%- endtrans %}
-
-# Display description for UI
-tunnel.N.description=
-
-# Router IP address or host name. Ignored if in router context.
-tunnel.N.i2cpHost=127.0.0.1
-
-# Router I2CP port. Ignored if in router context.
-tunnel.N.i2cpPort=nnnn
-
-# For clients only. Local listen IP address or host name.
-tunnel.N.interface=127.0.0.1
-
-# For clients only. Local listen port.
-tunnel.N.listenPort=nnnn
-
-# Display name for UI
-tunnel.N.name=
-
-# Servers only. Default false. Originate connections to local server with a unique IP per-remote-destination.
-tunnel.N.option.enableUniqueLocal=true|false
-
-# Servers only. The maximum size of the thread pool, default 65. Ignored for standard servers.
-tunnel.N.option.i2ptunnel.blockingHandlerCount=nnn
-
-# HTTP client only. Whether to use allow SSL connections to i2p addresses. Default false.
-tunnel.N.option.i2ptunnel.httpclient.allowInternalSSL=true|false
-
-# HTTP client only. Whether to disable address helper links. Default false.
-tunnel.N.option.i2ptunnel.httpclient.disableAddressHelper=true|false
-
-# HTTP client only. Comma- or space-separated list of jump server URLs.
-tunnel.N.option.i2ptunnel.httpclient.jumpServers=http://example.i2p/jump
-
-# HTTP client only. Whether to pass Accept* headers through. Default false.
-tunnel.N.option.i2ptunnel.httpclient.sendAccept=true|false
-
-# HTTP client only. Whether to pass Referer headers through. Default false.
-tunnel.N.option.i2ptunnel.httpclient.sendReferer=true|false
-
-# HTTP client only. Whether to pass User-Agent headers through. Default false.
-tunnel.N.option.i2ptunnel.httpclient.sendUserAgent=true|false
-
-# HTTP client only. Whether to pass Via headers through. Default false.
-tunnel.N.option.i2ptunnel.httpclient.sendVia=true|false
-
-# HTTP client only. Comma- or space-separated list of in-network SSL outproxies.
-tunnel.N.option.i2ptunnel.httpclient.SSLOutproxies=example.i2p
-
-# SOCKS client only. Comma- or space-separated list of in-network outproxies for any ports not specified.
-tunnel.N.option.i2ptunnel.socks.proxy.default=example.i2p
-
-# SOCKS client only. Comma- or space-separated list of in-network outproxies for port NNNN.
-tunnel.N.option.i2ptunnel.socks.proxy.NNNN=example.i2p
-
-# HTTP client only. Whether to use a registered local outproxy plugin. Default true.
-tunnel.N.option.i2ptunnel.useLocalOutproxy=true|false
-
-# Servers only. Whether to use a thread pool. Default true. Ignored for standard servers, always false.
-tunnel.N.option.i2ptunnel.usePool=true|false
-
-# IRC Server only. Only used if fakeHostname contains a %c.
-# If unset, cloak with a random value that is persistent for
-# the life of this tunnel. If set, cloak with the hash of this passphrase.
-# Use to have consistent mangling across restarts, or for multiple IRC servers cloak consistently to
-# be able to track users even when they switch servers.
-# Note: don't quote or put spaces in the passphrase, the i2ptunnel gui can't handle it.
-tunnel.N.option.ircserver.cloakKey=
-
-# IRC Server only. Set the fake hostname sent by I2PTunnel,
-# %f is the full B32 destination hash, %c is the cloaked hash.
-tunnel.N.option.ircserver.fakeHostname=%f.b32.i2p
-
-# IRC Server only. Default user.
-tunnel.N.option.ircserver.method=user|webirc
-
-# IRC Server only. The password to use for the webirc protocol.
-# Note: don't quote or put spaces in the passphrase, the i2ptunnel gui can't handle it.
-tunnel.N.option.ircserver.webircPassword=
-
-# IRC Server only.
-tunnel.N.option.ircserver.webircSpoofIP=
-
-# HTTP Server only. Max number of POSTs allowed for one destination per postCheckTime. Default 0 (unlimited)
-tunnel.N.option.maxPosts=nnn
-
-# HTTP Server only. Max number of POSTs allowed for all destinations per postCheckTime. Default 0 (unlimited)
-tunnel.N.option.maxTotalPosts=nnn
-
-# HTTP Clients only. Whether to send authorization to an outproxy. Default false.
-tunnel.N.option.outproxyAuth=true|false
-
-# HTTP Clients only. The password for the outproxy authorization.
-tunnel.N.option.outproxyPassword=
-
-# HTTP Clients only. The username for the outproxy authorization.
-tunnel.N.option.outproxyUsername=
-
-# HTTP Clients only. Whether to send authorization to an outproxy. Default false.
-tunnel.N.option.outproxyAuth=true|false
-
-# Clients only. Whether to store a destination in a private key file and reuse it. Default false.
-tunnel.N.option.persistentClientKey=true|false
-
-# HTTP Server only. Time period for banning POSTs from a single destination after maxPosts is exceeded, in seconds. Default 1800 seconds.
-tunnel.N.option.postBanTime=nnn
-
-# HTTP Server only. Time period for checking maxPosts and maxTotalPosts, in seconds. Default 300 seconds.
-tunnel.N.option.postCheckTime=nnn
-
-# HTTP Server only. Time period for banning all POSTs after maxTotalPosts is exceeded, in seconds. Default 600 seconds.
-tunnel.N.option.postTotalBanTime=nnn
-
-# HTTP Clients only. Whether to require local authorization for the proxy. Default false. "true" is the same as "basic".
-tunnel.N.option.proxyAuth=true|false|basic|digest
-
-# HTTP Clients only. The MD5 of the password for local authorization for user USER.
-tunnel.N.option.proxy.auth.USER.md5=
-
-# HTTP Servers only. Whether to reject incoming connections apparently via an inproxy. Default false.
-tunnel.N.option.rejectInproxy=true|false
-
-# Servers only. Overrides targetHost and targetPort for incoming port NNNN.
-tunnel.N.option.targetForPort.NNNN=hostnameOrIP:nnnn
-
-# Servers only. Default false. Use SSL for connections to local server.
-tunnel.N.option.useSSL=false
-
-# Each option is passed to I2CP and streaming with "tunnel.N.option." stripped off. See those docs.
-tunnel.N.option.*=
-
-# For servers and clients with persistent keys only. Absolute path or relative to config directory.
-tunnel.N.privKeyFile=filename
-
-# For proxies only. Comma- or space-separated host names.
-tunnel.N.proxyList=example.i2p[,example2.i2p]
-
-# For clients only. Default false.
-tunnel.N.sharedClient=true|false
-
-# For HTTP servers only. Host name to be passed to the local server in the HTTP headers.
-# Default is the base 32 hostname.
-tunnel.N.spoofedHost=example.i2p
-
-# For HTTP servers only. Host name to be passed to the local server in the HTTP headers.
-# Overrides above setting for incoming port NNNN, to allow virtual hosts.
-tunnel.N.spoofedHost.NNNN=example.i2p
-
-# Default true
-tunnel.N.startOnLoad=true|false
-
-# For clients only. Comma- or space-separated host names or host:port.
-tunnel.N.targetDestination=example.i2p[:nnnn][,example2.i2p[:nnnn]]
-
-# For servers only. Local IP address or host name to connect to.
-tunnel.N.targetHost=
-
-# For servers only. Port on targetHost to connect to.
-tunnel.N.targetPort=nnnn
-
-# The type of i2ptunnel
-tunnel.N.type=client|connectclient|httpbidirserver|httpclient|httpserver|ircclient|ircserver|
- server|socksirctunnel|sockstunnel|streamrclient|streamrserver
-
-
-Note: Each 'N' is a tunnel number starting with 0.
-There may not be any gaps in numbering.
-
-
-
{% trans %}Router Console{% endtrans %}
-
{% trans -%}
-The router console uses the router.config file.
-{%- endtrans %}
-
-
SusiMail (susimail.config)
-
{% trans -%}
-See post on zzz.i2p.
-{%- endtrans %}
-
-{% endblock %}
diff --git a/i2p2www/spec/configuration.rst b/i2p2www/spec/configuration.rst
new file mode 100644
index 00000000..8688999e
--- /dev/null
+++ b/i2p2www/spec/configuration.rst
@@ -0,0 +1,434 @@
+================================
+Configuration File Specification
+================================
+.. meta::
+ :lastupdated: November 2014
+ :accuratefor: 0.9.17
+
+
+Overview
+========
+
+This page provides a general specification of I2P configuration files, used by
+the router and various applications. It also gives an overview of the
+information contained in the various files, and links to detailed documentation
+where available.
+
+
+General Format
+==============
+
+An I2P configuration file is formatted as specified in Java [Properties]_ with
+the following exceptions:
+
+* Encoding must be UTF-8
+
+* Does not use or recognize any escapes, including '\', so lines may not be
+ continued
+
+* '#' or ';' starts a comment, but '!' does not
+
+* '#' starts a comment in any position but ';' must be in column 1 to start a
+ comment
+
+* Leading and trailing whitespace is not trimmed on keys
+
+* Leading and trailing whitespace is trimmed on values
+
+* '=' is the only key-termination character (not ':' or whitespace)
+
+* Lines without '=' are ignored. As of release 0.9.10, keys with a value of ""
+ are supported.
+
+* As there are no escapes, keys may not contain '#', '=', or '\n', or start with
+ ';'
+
+* As there are no escapes, values may not contain '#' or '\n', or start or end
+ with '\r' or whitespace
+
+The file need not be sorted, but most applications do sort by key when writing
+to the file, for ease of reading and manual editing.
+
+Reads and writes are implemented in DataHelper loadProps() and storeProps()
+[DATAHELPER]_. Note that the file format is significantly different than the
+serialized format for I2P protocols specified in [Mapping]_.
+
+
+Core library and router
+=======================
+
+Clients (clients.config)
+------------------------
+
+Configured via /configclients in the router console.
+
+The format is as follows:
+
+Lines are of the form clientApp.x.prop=val, where x is the app number. App
+numbers MUST start with 0 and be consecutive.
+
+Properties are as follows:
+
+ main
+ Full class name. Required.
+
+ The constructor or main() method in this class will be run, depending on
+ whether the client is managed or unmanaged. See below for details.
+
+ name
+ Name to be displayed on console.
+
+ args
+ Arguments to the main class, separated by spaces or tabs.
+ Arguments containing spaces or tabs may be quoted with ' or "
+
+ delay
+ Seconds before starting, default 120
+
+ onBoot
+ {true|false},
+
+ Default false, forces a delay of 0, overrides delay setting
+
+ startOnLoad:
+ {true|false}
+
+ Is the client to be run at all? Default true
+
+The following additional properties are used only by plugins:
+
+ stopargs
+ Arguments to stop the client.
+
+ uninstallargs
+ Arguments to uninstall the client.
+
+ classpath
+ Additional classpath elements for the client, separated by commas.
+
+The following substitutions are made in the args, stopargs,
+uninstallargs, and classpath lines, for plugins only:
+
+ $I2P
+ The base I2P install directory
+
+ $CONFIG
+ The user's configuration directory (e.g. ~/.i2p)
+
+ $PLUGIN
+ This plugin's directory (e.g. ~/.i2p/plugins/foo)
+
+All properties except "main" are optional. Lines starting with "#" are
+comments.
+
+If the delay is less than zero, the client is run immediately, in the same
+thread, so that exceptions may be propagated to the console. In this case, the
+client should either throw an exception, return quickly, or spawn its own
+thread.
+
+If the delay is greater than or equal to zero, it will be run in a new thread,
+and exceptions will be logged but not propagated to the console.
+
+Clients may be "managed" or "unmanaged".
+
+Logger (logger.config)
+----------------------
+
+Configured via /configlogging in the router console.
+
+Properties are as follows::
+
+ # Default 20
+ logger.consoleBufferSize=n
+ # Default from locale; format as specified by Java SimpleDateFormat
+ logger.dateFormat=HH:mm:ss.SSS
+ # Default ERROR
+ logger.defaultLevel=CRIT|ERROR|WARN|INFO|DEBUG
+ # Default true
+ logger.displayOnScreen=true|false
+ # Default true
+ logger.dropDuplicates=true|false
+ # Default false
+ logger.dropOnOverflow=true|false
+ # As of 0.9.18. Default 29 (seconds)
+ logger.flushInterval=nnn
+ # d = date, c = class, t = thread name, p = priority, m = message
+ logger.format={dctpm}*
+ # Max to buffer before flushing. Default 1024
+ logger.logBufferSize=n
+ # Default logs/log-@.txt; @ replaced with number
+ logger.logFileName=name
+ logger.logFilenameOverride=name
+ # Default 10M
+ logger.logFileSize=nnn[K|M|G]
+ # Highest file number. Default 2
+ logger.logRotationLimit=n
+ # Default CRIT
+ logger.minimumOnScreenLevel=CRIT|ERROR|WARN|INFO|DEBUG
+ logger.record.{class}=CRIT|ERROR|WARN|INFO|DEBUG
+
+Individual Plugin (xxx/plugin.config)
+-------------------------------------
+
+See the plugin specification [PLUGIN]_.
+
+Plugins (plugins.config)
+------------------------
+
+Enable/disable for each installed plugin.
+
+Properties are as follows::
+
+ plugin.{name}.startOnLoad=true|false
+
+Webapps (webapps.config)
+------------------------
+
+Enable/disable for each installed webapp.
+
+Properties are as follows::
+
+ webapps.{name}.classpath=[space- or comma-separated paths]
+ webapps.{name}.startOnLoad=true|false
+
+Router (router.config)
+----------------------
+
+Configured via /configadvanced in the router console.
+
+
+Applications
+============
+
+Addressbook (addressbook/config.txt)
+------------------------------------
+
+See documentation in SusiDNS.
+
+I2PSnark (i2psnark.config)
+--------------------------
+
+Configured via the application gui.
+
+I2PTunnel (i2ptunnel.config)
+----------------------------
+
+Configured via the /i2ptunnel application in the router console.
+
+Properties are as follows::
+
+ # Display description for UI
+ tunnel.N.description=
+
+ # Router IP address or host name. Ignored if in router context.
+ tunnel.N.i2cpHost=127.0.0.1
+
+ # Router I2CP port. Ignored if in router context.
+ tunnel.N.i2cpPort=nnnn
+
+ # For clients only. Local listen IP address or host name.
+ tunnel.N.interface=127.0.0.1
+
+ # For clients only. Local listen port.
+ tunnel.N.listenPort=nnnn
+
+ # Display name for UI
+ tunnel.N.name=
+
+ # Servers only. Default false. Originate connections to local server with a
+ # unique IP per-remote-destination.
+ tunnel.N.option.enableUniqueLocal=true|false
+
+ # Servers only. The maximum size of the thread pool, default 65. Ignored
+ # for standard servers.
+ tunnel.N.option.i2ptunnel.blockingHandlerCount=nnn
+
+ # HTTP client only. Whether to use allow SSL connections to i2p addresses.
+ # Default false.
+ tunnel.N.option.i2ptunnel.httpclient.allowInternalSSL=true|false
+
+ # HTTP client only. Whether to disable address helper links. Default false.
+ tunnel.N.option.i2ptunnel.httpclient.disableAddressHelper=true|false
+
+ # HTTP client only. Comma- or space-separated list of jump server URLs.
+ tunnel.N.option.i2ptunnel.httpclient.jumpServers=http://example.i2p/jump
+
+ # HTTP client only. Whether to pass Accept* headers through. Default false.
+ tunnel.N.option.i2ptunnel.httpclient.sendAccept=true|false
+
+ # HTTP client only. Whether to pass Referer headers through. Default false.
+ tunnel.N.option.i2ptunnel.httpclient.sendReferer=true|false
+
+ # HTTP client only. Whether to pass User-Agent headers through. Default
+ # false.
+ tunnel.N.option.i2ptunnel.httpclient.sendUserAgent=true|false
+
+ # HTTP client only. Whether to pass Via headers through. Default false.
+ tunnel.N.option.i2ptunnel.httpclient.sendVia=true|false
+
+ # HTTP client only. Comma- or space-separated list of in-network SSL
+ # outproxies.
+ tunnel.N.option.i2ptunnel.httpclient.SSLOutproxies=example.i2p
+
+ # SOCKS client only. Comma- or space-separated list of in-network
+ # outproxies for any ports not specified.
+ tunnel.N.option.i2ptunnel.socks.proxy.default=example.i2p
+
+ # SOCKS client only. Comma- or space-separated list of in-network
+ # outproxies for port NNNN.
+ tunnel.N.option.i2ptunnel.socks.proxy.NNNN=example.i2p
+
+ # HTTP client only. Whether to use a registered local outproxy plugin.
+ # Default true.
+ tunnel.N.option.i2ptunnel.useLocalOutproxy=true|false
+
+ # Servers only. Whether to use a thread pool. Default true. Ignored for
+ # standard servers, always false.
+ tunnel.N.option.i2ptunnel.usePool=true|false
+
+ # IRC Server only. Only used if fakeHostname contains a %c. If unset,
+ # cloak with a random value that is persistent for the life of this tunnel.
+ # If set, cloak with the hash of this passphrase. Use to have consistent
+ # mangling across restarts, or for multiple IRC servers cloak consistently
+ # to be able to track users even when they switch servers. Note: don't
+ # quote or put spaces in the passphrase, the i2ptunnel gui can't handle it.
+ tunnel.N.option.ircserver.cloakKey=
+
+ # IRC Server only. Set the fake hostname sent by I2PTunnel, %f is the full
+ # B32 destination hash, %c is the cloaked hash.
+ tunnel.N.option.ircserver.fakeHostname=%f.b32.i2p
+
+ # IRC Server only. Default user.
+ tunnel.N.option.ircserver.method=user|webirc
+
+ # IRC Server only. The password to use for the webirc protocol. Note:
+ # don't quote or put spaces in the passphrase, the i2ptunnel gui can't
+ # handle it.
+ tunnel.N.option.ircserver.webircPassword=
+
+ # IRC Server only.
+ tunnel.N.option.ircserver.webircSpoofIP=
+
+ # HTTP Server only. Max number of POSTs allowed for one destination per
+ # postCheckTime. Default 0 (unlimited)
+ tunnel.N.option.maxPosts=nnn
+
+ # HTTP Server only. Max number of POSTs allowed for all destinations per
+ # postCheckTime. Default 0 (unlimited)
+ tunnel.N.option.maxTotalPosts=nnn
+
+ # HTTP Clients only. Whether to send authorization to an outproxy. Default
+ # false.
+ tunnel.N.option.outproxyAuth=true|false
+
+ # HTTP Clients only. The password for the outproxy authorization.
+ tunnel.N.option.outproxyPassword=
+
+ # HTTP Clients only. The username for the outproxy authorization.
+ tunnel.N.option.outproxyUsername=
+
+ # HTTP Clients only. Whether to send authorization to an outproxy. Default
+ # false.
+ tunnel.N.option.outproxyAuth=true|false
+
+ # Clients only. Whether to store a destination in a private key file and
+ # reuse it. Default false.
+ tunnel.N.option.persistentClientKey=true|false
+
+ # HTTP Server only. Time period for banning POSTs from a single destination
+ # after maxPosts is exceeded, in seconds. Default 1800 seconds.
+ tunnel.N.option.postBanTime=nnn
+
+ # HTTP Server only. Time period for checking maxPosts and maxTotalPosts, in
+ # seconds. Default 300 seconds.
+ tunnel.N.option.postCheckTime=nnn
+
+ # HTTP Server only. Time period for banning all POSTs after maxTotalPosts
+ # is exceeded, in seconds. Default 600 seconds.
+ tunnel.N.option.postTotalBanTime=nnn
+
+ # HTTP Clients only. Whether to require local authorization for the proxy.
+ # Default false. "true" is the same as "basic".
+ tunnel.N.option.proxyAuth=true|false|basic|digest
+
+ # HTTP Clients only. The MD5 of the password for local authorization for
+ # user USER.
+ tunnel.N.option.proxy.auth.USER.md5=
+
+ # HTTP Servers only. Whether to reject incoming connections apparently via
+ # an inproxy. Default false.
+ tunnel.N.option.rejectInproxy=true|false
+
+ # Servers only. Overrides targetHost and targetPort for incoming port NNNN.
+ tunnel.N.option.targetForPort.NNNN=hostnameOrIP:nnnn
+
+ # Servers only. Default false. Use SSL for connections to local server.
+ tunnel.N.option.useSSL=false
+
+ # Each option is passed to I2CP and streaming with "tunnel.N.option."
+ # stripped off. See those docs.
+ tunnel.N.option.*=
+
+ # For servers and clients with persistent keys only. Absolute path or
+ # relative to config directory.
+ tunnel.N.privKeyFile=filename
+
+ # For proxies only. Comma- or space-separated host names.
+ tunnel.N.proxyList=example.i2p[,example2.i2p]
+
+ # For clients only. Default false.
+ tunnel.N.sharedClient=true|false
+
+ # For HTTP servers only. Host name to be passed to the local server in the
+ # HTTP headers. Default is the base 32 hostname.
+ tunnel.N.spoofedHost=example.i2p
+
+ # For HTTP servers only. Host name to be passed to the local server in the
+ # HTTP headers. Overrides above setting for incoming port NNNN, to allow
+ # virtual hosts.
+ tunnel.N.spoofedHost.NNNN=example.i2p
+
+ # Default true
+ tunnel.N.startOnLoad=true|false
+
+ # For clients only. Comma- or space-separated host names or host:port.
+ tunnel.N.targetDestination=example.i2p[:nnnn][,example2.i2p[:nnnn]]
+
+ # For servers only. Local IP address or host name to connect to.
+ tunnel.N.targetHost=
+
+ # For servers only. Port on targetHost to connect to.
+ tunnel.N.targetPort=nnnn
+
+ # The type of i2ptunnel
+ tunnel.N.type=client|connectclient|httpbidirserver|httpclient|httpserver|ircclient|ircserver|
+ server|socksirctunnel|sockstunnel|streamrclient|streamrserver
+
+Note: Each 'N' is a tunnel number starting with 0.
+There may not be any gaps in numbering.
+
+Router Console
+--------------
+
+The router console uses the router.config file.
+
+SusiMail (susimail.config)
+--------------------------
+
+See post on zzz.i2p.
+
+
+References
+==========
+
+.. [DATAHELPER]
+ http://docs.i2p-projekt.de/javadoc/net/i2p/data/DataHelper.html
+
+.. [Mapping]
+ {{ spec_url('common-structures') }}#type-mapping
+
+.. [PLUGIN]
+ {{ spec_url('plugin') }}
+
+.. [Properties]
+ http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Properties.html#load%28java.io.InputStream%29
diff --git a/i2p2www/spec/datagrams.html b/i2p2www/spec/datagrams.html
deleted file mode 100644
index 93c5d63c..00000000
--- a/i2p2www/spec/datagrams.html
+++ /dev/null
@@ -1,109 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}{% trans %}Datagram Specification{% endtrans %}{% endblock %}
-{% block lastupdated %}{% trans %}July 2014{% endtrans %}{% endblock %}
-{% block accuratefor %}0.9.14{% endblock %}
-{% block content %}
-
{% trans -%}
-Non-repliable datagrams have no 'from' address and are not authenticated.
-They are also called "raw" datagrams.
-Strictly speaking, they are not "datagrams" at all, they are just raw data.
-They are not handled by the datagram API.
-However, SAM and the I2PTunnel classes support "raw datagrams".
-{%- endtrans %}
{% trans tunnelmessage=site_url('docs/spec/tunnel-message'),
-transports=site_url('docs/transport') -%}
-The practical length is limited by lower layers of protocols - the
-tunnel message spec
-limits messages to about 61.2 KB and the
-transports
-currently limit messages to about 32 KB, although this may be raised in the future.
-{%- endtrans %}
-
-
{% trans %}Repliable Datagrams{% endtrans %}
-
{% trans -%}
-Repliable datagrams contain a 'from' address and a signature. These add at least 427 bytes of overhead.
-{%- endtrans %}
-
Format
-{% highlight lang='dataspec' %}
-+----+----+----+----+----+----+----+----+
-| from |
-+ +
-| |
-~ ~
-~ ~
-| |
-+ +
-| |
-| |
-+----+----+----+----+----+----+----+----+
-| signature |
-+ +
-| |
-+ +
-| |
-+ +
-| |
-+ +
-| |
-+----+----+----+----+----+----+----+----+
-| payload...
-+----+----+----+----//
-
-
-from :: a `Destination`
- length: 387+ bytes
- The originator and signer of the datagram
-
-signature :: a `Signature`
- Signature type must match the signing public key type of $from
- length: 40+ bytes, as implied by the Signature type.
- For the default DSA_SHA1 key type:
- The DSA `Signature` of the SHA-256 hash of the payload.
- For other key types:
- The `Signature` of the payload.
- The signature may be verified by the signing public key of $from
-
-payload :: The data
- Length: 0 to ~31.5 KB (see notes)
-
-Total length: Payload length + 427+
-{% endhighlight %}
-
-
{% trans %}Notes{% endtrans %}
-
-
{% trans transports=site_url('docs/transport') -%}
-The practical length is limited by lower layers of protocols - the
-transports
-currently limit messages to about 32 KB, so the data length here is limited to about
-31.5 KB.
-{%- endtrans %}
-
{% trans dgrams=site_url('docs/api/datagrams') -%}
-See important notes about the reliability of large datagrams.
-For best results, limit the payload to about 10 KB or less.
-{%- endtrans %}
-
{% trans -%}
-Signatures for types other than DSA_SHA1 were redefined in release 0.9.14.
-{%- endtrans %}
-
-
-
-
-{% endblock %}
diff --git a/i2p2www/spec/datagrams.rst b/i2p2www/spec/datagrams.rst
new file mode 100644
index 00000000..f45129e4
--- /dev/null
+++ b/i2p2www/spec/datagrams.rst
@@ -0,0 +1,128 @@
+======================
+Datagram Specification
+======================
+.. meta::
+ :lastupdated: July 2014
+ :accuratefor: 0.9.14
+
+
+Overview
+========
+
+See [DATAGRAMS]_ for an overview of the Datagrams API.
+
+
+.. _raw:
+
+Non-Repliable Datagrams
+=======================
+
+Non-repliable datagrams have no 'from' address and are not authenticated. They
+are also called "raw" datagrams. Strictly speaking, they are not "datagrams"
+at all, they are just raw data. They are not handled by the datagram API.
+However, SAM and the I2PTunnel classes support "raw datagrams".
+
+Format
+------
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----//
+ | payload...
+ +----+----+----+----+----//
+
+ length: 0 - unlimited (see notes)
+{% endhighlight %}
+
+Notes
+-----
+
+The practical length is limited by lower layers of protocols - the tunnel
+message spec [TUNMSG]_ limits messages to about 61.2 KB and the transports
+[TRANSPORT]_ currently limit messages to about 32 KB, although this may be
+raised in the future.
+
+
+.. _repliable:
+
+Repliable Datagrams
+===================
+
+Repliable datagrams contain a 'from' address and a signature. These add at
+least 427 bytes of overhead.
+
+Format
+------
+
+.. raw:: html
+
+ {% highlight lang='dataspec' -%}
++----+----+----+----+----+----+----+----+
+ | from |
+ + +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ + +
+ | |
+ | |
+ +----+----+----+----+----+----+----+----+
+ | signature |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | payload...
+ +----+----+----+----//
+
+
+ from :: a `Destination`
+ length: 387+ bytes
+ The originator and signer of the datagram
+
+ signature :: a `Signature`
+ Signature type must match the signing public key type of $from
+ length: 40+ bytes, as implied by the Signature type.
+ For the default DSA_SHA1 key type:
+ The DSA `Signature` of the SHA-256 hash of the payload.
+ For other key types:
+ The `Signature` of the payload.
+ The signature may be verified by the signing public key of $from
+
+ payload :: The data
+ Length: 0 to ~31.5 KB (see notes)
+
+ Total length: Payload length + 427+
+{% endhighlight %}
+
+Notes
+-----
+
+* The practical length is limited by lower layers of protocols - the transports
+ [TRANSPORT]_ currently limit messages to about 32 KB, so the data length here
+ is limited to about 31.5 KB.
+
+* See important notes about the reliability of large datagrams [DATAGRAMS]_. For
+ best results, limit the payload to about 10 KB or less.
+
+* Signatures for types other than DSA_SHA1 were redefined in release 0.9.14.
+
+
+References
+==========
+
+.. [DATAGRAMS]
+ {{ site_url('docs/api/datagrams', True) }}
+
+.. [TRANSPORT]
+ {{ site_url('docs/transport', True) }}
+
+.. [TUNMSG]
+ {{ site_url('docs/spec/tunnel-message', True) }}#notes
diff --git a/i2p2www/spec/geoip.html b/i2p2www/spec/geoip.html
deleted file mode 100644
index dc452f4a..00000000
--- a/i2p2www/spec/geoip.html
+++ /dev/null
@@ -1,81 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}{% trans %}GeoIP File Specification{% endtrans %}{% endblock %}
-{% block lastupdated %}{% trans %}December 2013{% endtrans %}{% endblock %}
-{% block accuratefor %}0.9.9{% endblock %}
-{% block content %}
-
-
{% trans %}Overview{% endtrans %}
-
{% trans -%}
-This page specifies the format of the various GeoIP files,
-used by the router to look up a country for an IP.
-{%- endtrans %}
-
-
-
{% trans %}Country Name (countries.txt) Format{% endtrans %}
-
{% trans -%}
-This format is easily generated from data files available from many public sources.
-For example:
-{%- endtrans %}
CountryCode is the ISO two-letter code, upper case
-
CountryName is in English
-
-
-
-
{% trans %}IPv4 (geoip.txt) Format{% endtrans %}
-
{% trans -%}
-This format is borrowed from Tor and is easily generated from data files available from many public sources.
-For example:
-{%- endtrans %}
FromIP and ToIP are unsigned integer representations of the 4-byte IP
-
CountryCode is the ISO two-letter code, upper case
-
Entry lines must be sorted by numeric FromIP
-
-
-
-
{% trans %}IPv6 (geoipv6.dat.gz) Format{% endtrans %}
-
{% trans -%}
-This is a compressed binary format designed for I2P.
-The file is gzipped. Ungzipped format:
-{%- endtrans %}
-{% highlight %}
- Bytes 0-9: Magic number "I2PGeoIPv6"
- Bytes 10-11: Version (0x0001)
- Bytes 12-15 Options (0x00000000) (future use)
- Bytes 16-23: Creation date (ms since 1970-01-01)
- Bytes 24-xx: Optional comment (UTF-8) terminated by zero byte
- Bytes xx-255: null padding
- Bytes 256-: 18 byte records:
- 8 byte from (/64)
- 8 byte to (/64)
- 2 byte ISO country code LOWER case (ASCII)
-{% endhighlight %}
-
{% trans %}NOTES:{% endtrans %}
-
-
Data must be sorted (SIGNED long twos complement), no overlap.
-So the order is 80000000 ... FFFFFFFF 00000000 ... 7FFFFFFF.
-
-The GeoIPv6.java class contains a program to generate this format from
-public sources such as the Maxmind GeoLite data.
-
-IPv6 GeoIP lookup is supported as of release 0.9.8.
-
-{% endblock %}
diff --git a/i2p2www/spec/geoip.rst b/i2p2www/spec/geoip.rst
new file mode 100644
index 00000000..c9536226
--- /dev/null
+++ b/i2p2www/spec/geoip.rst
@@ -0,0 +1,84 @@
+========================
+GeoIP File Specification
+========================
+.. meta::
+ :lastupdated: December 2013
+ :accuratefor: 0.9.9
+
+
+Overview
+========
+
+This page specifies the format of the various GeoIP files,
+used by the router to look up a country for an IP.
+
+
+Country Name (countries.txt) Format
+===================================
+
+This format is easily generated from data files available from many public sources.
+For example:
+
+.. raw:: html
+
+ {% highlight lang='bash' %}$ wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
+ $ unzip GeoIPCountryCSV.zip
+ $ cut -d, -f5,6 < GeoIPCountryWhois.csv | sed 's/"//g' | sort | uniq > countries.txt
+{% endhighlight %}
+
+* Encoding is UTF-8
+* '#' in column 1 specifies a comment line
+* Entry lines are CountryCode,CountryName
+* CountryCode is the ISO two-letter code, upper case
+* CountryName is in English
+
+
+IPv4 (geoip.txt) Format
+=======================
+
+This format is borrowed from Tor and is easily generated from data files available from many public sources.
+For example:
+
+.. raw:: html
+
+ {% highlight lang='bash' %}$ wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
+ $ unzip GeoIPCountryCSV.zip
+ $ cut -d, -f3-5 < GeoIPCountryWhois.csv | sed 's/"//g' > geoip.txt
+ $ cut -d, -f5,6 < GeoIPCountryWhois.csv | sed 's/"//g' | sort | uniq > countries.txt
+{% endhighlight %}
+
+* Encoding is ASCII
+* '#' in column 1 specifies a comment line
+* Entry lines are FromIP,ToIP,CountryCode
+* FromIP and ToIP are unsigned integer representations of the 4-byte IP
+* CountryCode is the ISO two-letter code, upper case
+* Entry lines must be sorted by numeric FromIP
+
+
+IPv6 (geoipv6.dat.gz) Format
+============================
+
+This is a compressed binary format designed for I2P.
+The file is gzipped. Ungzipped format:
+
+.. raw:: html
+
+ {% highlight %} Bytes 0-9: Magic number "I2PGeoIPv6"
+ Bytes 10-11: Version (0x0001)
+ Bytes 12-15 Options (0x00000000) (future use)
+ Bytes 16-23: Creation date (ms since 1970-01-01)
+ Bytes 24-xx: Optional comment (UTF-8) terminated by zero byte
+ Bytes xx-255: null padding
+ Bytes 256-: 18 byte records:
+ 8 byte from (/64)
+ 8 byte to (/64)
+ 2 byte ISO country code LOWER case (ASCII)
+{% endhighlight %}
+
+NOTES:
+
+* Data must be sorted (SIGNED long twos complement), no overlap.
+ So the order is 80000000 ... FFFFFFFF 00000000 ... 7FFFFFFF.
+* The GeoIPv6.java class contains a program to generate this format from
+ public sources such as the Maxmind GeoLite data.
+* IPv6 GeoIP lookup is supported as of release 0.9.8.
diff --git a/i2p2www/spec/i2cp.html b/i2p2www/spec/i2cp.html
deleted file mode 100644
index 095d8c2e..00000000
--- a/i2p2www/spec/i2cp.html
+++ /dev/null
@@ -1,1467 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}I2CP Specification{% endblock %}
-{% block lastupdated %}June 2015{% endblock %}
-{% block accuratefor %}0.9.21{% endblock %}
-{% block content %}
-
Overview
-
-This page specified the I2P Control Protocol (I2CP),
-which is the interface between clients and the router.
-Java clients will use the I2CP client API, which implements this protocol.
-Non-Java clients will most likely use a higher-layer protocol
-such as SAM or BOB.
-
-The protocol is only serialized if the client and router are not in the same JVM;
-otherwise, I2CP message objects are passed via an internal JVM interface.
-
-The protocol was designed to handle multiple "sessions", each with a 2-byte session ID,
-over a single TCP connection,
-however, Multiple sessions were not implemented until version 0.9.21.
-See the multisession section below.
-Do not attempt to use multiple sessions on a single I2CP connection
-with routers older than version 0.9.21.
-
-
-
-It also appears that there are some provisions for a single client to talk to multiple
-routers over separate connections. This is also untested,
-and probably not useful.
-
-
-
-It does not appear that there is currently a way for a session to be
-maintained after a disconnect, or to be
-recovered on a different
-I2CP connection.
-
-
-
-
-
-
Example Message Sequences
-
-Note: The examples below do not show the Protocol Byte (0x2a) that must be
-sent from the client to the router when first connecting.
-More information about connection initialization is
-on the I2CP Overview page.
-
-
-
-
Standard Session Establish
-{% highlight %}
- Client Router
-
- ---------------------> Get Date Message
- Set Date Message <---------------------
- ---------------------> Create Session Message
- Session Status Message <---------------------
-Request LeaseSet Message <---------------------
- ---------------------> Create LeaseSet Message
-{% endhighlight %}
-
-
-
-Multiple sessions on a single I2CP connection are supported as of router version 0.9.21.
-The first session that is created is the "primary session".
-Additional sessions are "subsessions".
-Subsessions are used to support multiple destinations sharing a common set of tunnels.
-The initial application is for the primary session to use ECDSA signing keys,
-while the subsession uses DSA signing keys for communication with old eepsites.
-
-Subsessions share the same inbound and outbound tunnel pools as the primary session.
-Subsessions must use the same encryption keys as the primary session.
-This applies both to the LeaseSet encryption keys and the (unused) Destination encryption keys.
-Subsessions must use different signing keys in the destination, so the destination hash is
-different from the primary session.
-As subsessions use the same encryption keys and tunnels as the primary session,
-it is apparent to all that the Destinations are running on the same router,
-so the usual anti-correlation anonymity guarantees do not apply.
-
-Subsessions are created by sending a CreateSession message and receiving a SessionStatus message
-in reply, as usual. Subsessions must be created after the primary session is created.
-The SessionStatus response will, on success, contain a unique Session ID, distinct from
-the ID for the primary session.
-While CreateSession messages should be processed in-order,
-there is no sure way to correlate a CreateSession message with the response, so a client
-should not have multiple CreateSession messages outstanding simultaneously.
-SessionConfig options for the subsession may not be honored where they
-are different from the primary session.
-In particular, since subsessions use the same tunnel pool as the primary session,
-tunnel options may be ignored.
-
-The router will send separate RequestVariableLeaseSet messages for each Destination to the client,
-and the client must reply with a CreateLeaseSet message for each.
-The leases for the two Destinations will not necessarily be identical,
-even though they are selected from the same tunnel pool.
-
-A subsession may be destroyed with the DestroySession message as usual.
-This will not destroy the primary session or stop the I2CP connection.
-Destroying the primary session will, however, destroy all subsessions and
-stop the I2CP connection.
-A Disconnect message destroys all sessions.
-
-Note that most, but not all, I2CP messages contain a Session ID.
-For the ones that do not, clients may need additional logic to
-properly handle router responses.
-DestLookup and DestReply do not contain Session IDs; use the newer HostLookup and HostReply instead.
-GetBandwidthLimts and BandwidthLimits do not contain session IDs, however the response
-is not session-specific.
-
-Support for multiple sessions is preliminary and subject to change.
-Support may not be complete in other parts of the API and user interface, particularly streaming and i2ptunnel.
-Current support is primarily for clients (i.e. Destinations that do not publish their leaseset
-or accept incoming connections), and is incomplete and untested for servers.
-Future releases may provide additional features and options.
-
-
-
-
-
-
Version Notes
-
-The initial protocol version byte (0x2a) sent by the client is not expected to change.
-Prior to release 0.8.7, the router's version information was not available to the client,
-thus preventing new clients from working with old routers.
-As of release 0.8.7, the two parties' protocol version strings are exchanged in the Get/Set Date Messages.
-Going forward, clients may use this information to communicate correctly with old routers.
-Clients and routers should not send messages that are unsupported by the other side,
-as they generally disconnect the session upon reception of an unsupported message.
-
-The exchanged version information is the "core" version or I2CP protocol version,
-and is not necessarily the router version.
-
-A basic summary of the I2CP protocol versions is as follows. For details, see below.
-
-
-
Version
-
Required I2CP Features
-
-
0.9.21
-
Multiple sessions on a single I2CP connection supported
-
-
-
0.9.20
-
Additional SetDate messages may be sent to the client at any time
-
-
-
0.9.16
-
Authentication, if enabled, is required via GetDate before all other messages
-
-
-
0.9.15
-
Dest/LS key certs w/ EdDSA Ed25519 sig type supported
-
-
0.9.14
-
Per-message override of messageReliability=none with nonzero nonce
-
-
0.9.12
-
Dest/LS key certs w/ ECDSA P-256, P-384, and P-521 sig types supported
- Note: RSA sig types also supported as of this version, but currently unused
-
-
-
0.9.11
-
Host Lookup and Host Reply messages supported
- Authentication mapping in Get Date message supported
-
-
-
0.9.7
-
Request Variable Lease Set message supported
-
-
0.9.5
-
Additional Message Status codes defined
-
-
0.9.4
-
Send Message nonce=0 allowed
- Fast receive mode is the default
-
-
-
0.9.2
-
Send Message Expires flag tag bits supported
-
-
0.9
-
Supports up to 16 leases in a lease set (6 previously)
-
-
0.8.7
-
Get Date and Set Date version strings included.
- If not present, the client or router is version 0.8.6 or older.
-
-
-
0.8.4
-
Send Message Expires flag bits supported
-
-
0.8.3
-
Dest Lookup and Get Bandwidth messages supported in standard session
- Concurrent Dest Lookup messages supported
-
-
-
0.8.1
-
i2cp.messageReliability=none supported
-
-
0.7.2
-
Get Bandwidth Limits and Bandwidth Limits messages supported
-Uniquely identifies a message waiting on a particular router at a
-point in time.
-This is always generated by the router and is NOT the same as the nonce generated by the client.
-
-Currently, the client limits are the only values set,
-and are actually the router limits. All the values labeled as router limits are always 0.
-As of release 0.7.2.
-
-The SigningPrivateKey matches the SigningPublicKey from within the
-LeaseSet, as does the PrivateKey with the PublicKey. The Signing key is
-necessary to allow the router to revoke the LeaseSet if the client goes offline,
-and the encryption key is necessary for decrypting garlic routed messages. The
-LeaseSet granted may include Lease structures for tunnels pointing at another
-router if the client is actively connected to multiple routers with Leases granted
-to each.
-Really?
-Revocation is unimplemented.
-Connection to multiple routers is untested.
-
-
-
-
-
Create Session
-
Description
-
-This message is sent from a client to initiate a session, where a session is defined
-as a single Destination's connection to the network, to which all messages for
-that Destination will be delivered and from which all messages that
-Destination sends to any other Destination will be sent through.
-Sent from Client to Router.
-The router responds with a Session Status Message.
-
-As of release 0.7.
-As of release 0.8.3, multiple outstanding lookups are supported,
-and lookups are supported in both I2PSimpleSession and in standard sessions.
-Host Lookup Message is preferred as of release 0.9.11.
-
-
-
-
-
Dest Reply
-
Description
-
-Sent from Router to Client in response to a Dest Lookup Message.
-
-As of release 0.7.
-As of release 0.8.3,
-the requested Hash is returned if the lookup failed,
-so that the client may have multiple lookups outstanding and correlate the replies to the lookups.
-To correlate a Destination response with a request, take the Hash of the Destination.
-Prior to release 0.8.3, the response was empty on failure.
-
-
-
-
-
Destroy Session
-
Description
-
-This message is sent from a client to destroy a session.
-Sent from Client to Router.
-The router responds with a Session Status Message.
-
-The router at this point should release all resources related to the session.
-
-
-
-
-
Disconnect
-
Description
-
-Tell the other party that there are problems and the current connection is about to
-be destroyed. This does not necessarily end a session.
-Sent either from router to client or from client to router.
-
-Only implemented in the router-to-client direction.
-Disconnecting probably does end a session, in practice.
-
-
-
-
-
Get Bandwidth Limits
-
Description
-
-Request that the router state what its current bandwidth limits are.
-Sent from Client to Router.
-The router responds with a Bandwidth Limits Message.
-
-
Contents
-None
-
-
Notes
-
-As of release 0.7.2.
-As of release 0.8.3,
-supported in both I2PSimpleSession and in standard sessions.
-
-
-
-
-
Get Date
-
Description
-
-Sent from Client to Router.
-The router responds with a Set Date Message.
-
-Authentication Mapping
-(optional, as of release 0.9.11)
-
-
-
Notes
-
-Generally the first message sent by the client after sending the protocol version byte.
-
-The version string is included as of release 0.8.7.
-This is only useful if the client and router are not in the same JVM.
-If it is not present, the client is version 0.8.6 or earlier.
-
-As of release 0.9.11, the authentication
-Mapping
-may be included, with the keys i2cp.username and i2cp.password.
-The Mapping need not be sorted as this message is not signed.
-Prior to and including 0.9.10, authentication is included in the
-Session Config Mapping, and
-no authentication is enforced for GetDate, GetBandwidthLimits, or DestLookup.
-When enabled, authentication via GetDate is required before any other messages as of release 0.9.16.
-This is only useful outside router context.
-This is an incompatible change, but will only affect sessions outside
-router context with authentication, which should be rare.
-
-
-
-
-
-
Host Lookup
-
Description
-
-Sent from Client to Router.
-The router responds with a Host Reply Message.
-This replaces the Dest Lookup Message
-and adds a request ID, a timeout, and host name lookup support.
-As it also supports Hash lookups, it may be used for all lookups if the router supports it.
-For host name lookups, the router will query its context's naming service.
-This is only useful if the client is outside the router's context.
-Inside router context, the client should query the naming service itself,
-which is much more efficient.
-
-The session ID and request ID will be returned in the Host Reply Message.
-Use 0xFFFF for the session ID if there is no session.
-
-Timeout is useful for Hash lookups. Recommended minimum 10,000 (10 sec.).
-In the future it may also be useful for remote naming service lookups.
-The value may be not be honored for local host name lookups, which should be fast.
-
-The request type is 0 for Hash and 1 for host name.
-
-Base 32 host name lookup is supported but it is preferred to convert
-it to a Hash first.
-
-Notify the client of the delivery status of an incoming or outgoing message.
-Sent from Router to Client.
-If this message indicates that an incoming message is available,
-the client responds with a Receive Message Begin Message.
-For an outgoing message, this is a response to a
-Send Message Message or
-Send Message Expires Message.
-
-4 byte Integer nonce previously generated by the client
-
-
-
Notes
-
-Through version 0.9.4,
-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. The size Integer specifies the size of the available
-message and is only relevant for status = 0.
-Even though guaranteed is unimplemented, (best effort is the only service), the current
-router implementation uses the guaranteed status codes, not the best effort codes.
-As of router version 0.9.5, additional status codes are defined,
-however they are not necessarily implemented.
-See the
-MessageStatusMessage Javadocs
-for details.
-All status codes:
-
-
Status Code
As Of Release
Name
Description
-
0
Available
For incoming messages only.
- The included size is the size in bytes of the available message.
- This is unused in "fast receive" mode, which is the default as of release 0.9.4.
- All other status codes below are for outgoing messages.
-
1
Accepted
Outgoing message accepted by the local router for delivery.
- The included nonce matches the nonce in the
- Send Message Message, and the included Message ID
- will be used for subsequent success or failure notification.
-
2
Best Effort Success
Probable success (unused)
-
3
Best Effort Failure
Probable failure
-
4
Guaranteed Success
Probable success
-
5
Guaranteed Failure
Generic failure, specific cause unknown.
- May not really be a guaranteed failure.
-
6
0.9.5
Local Success
Local delivery successful.
- The destination was another client on the same router.
-
7
0.9.5
Local Failure
Local delivery failure.
- The destination was another client on the same router.
-
8
0.9.5
Router Failure
The local router is not ready, has shut down,
- or has major problems.
- This is a guaranteed failure.
-
9
0.9.5
Network Failure
The local computer apparently has no network connectivity at all.
- This is a guaranteed failure.
-
10
0.9.5
Bad Session
The I2CP session is invalid or closed.
- This is a guaranteed failure.
-
11
0.9.5
Bad Message
The message payload is invalid or zero-length or too big.
- This is a guaranteed failure.
-
12
0.9.5
Bad Options
Something is invalid in the message options,
- or the expiration is in the past or too far in the future.
- This is a guaranteed failure.
-
13
0.9.5
Overflow Failure
Some queue or buffer in the router is full and the message was dropped.
- This is a guaranteed failure.
-
14
0.9.5
Message Expired
The message expired before it could be sent.
- This is a guaranteed failure.
-
15
0.9.5
Bad Local Leaseset
The client has not yet signed a leaseset, or the local keys
- are invalid, or it has expired, or it does not have any tunnels in it.
- This is a guaranteed failure.
-
16
0.9.5
No Local Tunnels
Local problems. No outbound tunnel to send through,
- or no inbound tunnel if a reply is required.
- This is a guaranteed failure.
-
17
0.9.5
Unsupported Encryption
The certs or options in the destination or its leaseset
- indicate that it uses an encryption format that we don't support, so we can't talk to it.
- This is a guaranteed failure.
-
18
0.9.5
Bad Destination
Something is wrong with the far-end destination.
- Bad format, unsupported options, certificates, etc.
- This is a guaranteed failure.
-
19
0.9.5
Bad Leaseset
We got the far-end leaseset but something strange is wrong with it.
- Unsupported options or certificates, no tunnels, etc.
- This is a guaranteed failure.
-
20
0.9.5
Expired Leaseset
We got the far-end leaseset but it's expired and we can't get a new one.
- This is a guaranteed failure.
-
21
0.9.5
No Leaseset
Could not find the far-end leaseset.
- This is a common failure, equivalent to a DNS lookup failure.
- This is a guaranteed failure.
-
-
-
-When status = 1 (accepted), the nonce matches the nonce in the
-Send Message Message, and the included Message ID
-will be used for subsequent success or failure notification.
-Otherwise, the nonce may be ignored.
-
-
-
-
-
Receive Message Begin
-
Description
-
-Request the router to deliver a message that it was previously notified of.
-Sent from Client to Router.
-The router responds with a Message Payload Message.
-
-The ReceiveMessageBeginMessage is sent as a response to a
-MessageStatusMessage stating that a new message is available for pickup. If the
-message id specified in the ReceiveMessageBeginMessage is invalid or
-incorrect, the router may simply not reply, or it may send back a
-DisconnectMessage.
-
-
-This is unused in "fast receive" mode, which is the default as of release 0.9.4.
-
-
-
-
-
-
Receive Message End
-
Description
-
-Tell the router that delivery of a message was completed successfully and that
-the router can discard the message.
-Sent from Client to Router.
-
-If the Date in the Session Config is too far (more than +/- 30 seconds) from the router's current time, the session will be rejected.
-
-The Mapping in the Session Config
-must be sorted by key so that the signature will be validated correctly in the router.
-
-Some configuration options may only be set in the Create Session message, and changes here will not be recognized by the router.
-Changes to tunnel options inbound.* and outbound.* are always recognized.
-
-
-
-
-
-
Report Abuse
-
Description
-
-Tell the other party (client or router) 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 banlist some of the peers that sent it messages delivering the attack.
-Sent either from router to client or from client to router.
-
-Unused.
-Not fully implemented. Both router and client can generate Report Abuse Messages,
-but neither has a handler for the message when received.
-
-
-
-
-
-
Request LeaseSet
-
Description
-
-Request that a client authorize the inclusion of a particular set of inbound tunnels.
-Sent from Router to Client.
-The client responds with a Create LeaseSet Message.
-
-This requests a LeaseSet with all Leases set to expire at the same time.
-For client versions 0.9.7 or higher, RequestVariableLeaseSet is preferred.
-
-
-
-
-
-
-
Request Variable LeaseSet
-
Description
-
-Request that a client authorize the inclusion of a particular set of inbound tunnels.
-Sent from Router to Client.
-The client responds with a Create LeaseSet Message.
-
-This requests a LeaseSet with an individual expiration time for each Lease.
-As of release 0.9.7.
-For clients before that release, use RequestLeaseSet.
-
-
-
-
-
-
-
Send Message
-
Description
-
-This is how a client sends a message (the payload) to the Destination.
-The router will use a default expiration.
-Sent from Client to Router.
-The router responds with a Message Status Message.
-
-As soon as the SendMessageMessage arrives fully intact, the router should return
-a MessageStatusMessage stating that it has been accepted for delivery.
-That message will contain the same nonce sent here.
-Later on,
-based on the delivery guarantees of the session configuration, the router may
-additionally send back another MessageStatusMessage updating the status.
-
-As of release 0.8.1, the router does not send either Message Status Message if
-i2cp.messageReliability=none.
-
-Prior to release 0.9.4, a nonce value of 0 was not allowed.
-As of release 0.9.4, a nonce value of 0 is allowed, and tells to the router
-that it should not send either Message Status Message, i.e. it acts as if
-i2cp.messageReliability=none for this message only.
-
-Prior to release 0.9.14, a session with i2cp.messageReliability=none could not be overridden on a per-message basis.
-As of release 0.9.14, in a session with i2cp.messageReliability=none,
-the client may request delivery of a Message Status Message with the delivery success or failure
-by setting the nonce to a nonzero value.
-The router will not send the "accepted" Message Status Message but it will later send the client
-a Message Status Message with the same nonce, and a success or failure value.
-
-
-
-
-
-
Send Message Expires
-
Description
-
-Sent from Client to Router. Same as Send Message Message, except includes an expiration and options.
-
-Expiration Date
-truncated from 8 bytes to 6 bytes
-
-
-
Notes
-
-As of release 0.7.1.
-
-In "best effort" mode,
-as soon as the SendMessageExpiresMessage arrives fully intact, the router should return
-a MessageStatusMessage stating that it has been accepted for delivery.
-That message will contain the same nonce sent here.
-Later on,
-based on the delivery guarantees of the session configuration, the router may
-additionally send back another MessageStatusMessage updating the status.
-
-As of release 0.8.1, the router does not send either Message Status Message if
-i2cp.messageReliability=none.
-
-Prior to release 0.9.4, a nonce value of 0 was not allowed.
-As of release 0.9.4, a nonce value of 0 is allowed, and tells the router
-that it should not send either Message Status Message, i.e. it acts as if
-i2cp.messageReliability=none for this message only.
-
-Prior to release 0.9.14, a session with i2cp.messageReliability=none could not be overridden on a per-message basis.
-As of release 0.9.14, in a session with i2cp.messageReliability=none,
-the client may request delivery of a Message Status Message with the delivery success or failure
-by setting the nonce to a nonzero value.
-The router will not send the "accepted" Message Status Message but it will later send the client
-a Message Status Message with the same nonce, and a success or failure value.
-
-
-
Flags Field
-
-As of release 0.8.4, the upper two bytes of the Date are redefined to contain
-flags. The flags must default to all zeros for backward compatibility.
-The Date will not encroach on the flags field until the year 10889.
-The flags may be used by the application to provide hints to the router
-as to whether a LeaseSet and/or ElGamal/AES Session Tags should be delivered
-with the message. The settings will significantly affect the amount of
-protocol overhead and the reliability of message delivery.
-The individual flag bits are defined as follows, as of release 0.9.2.
-Definitions are subject to change. Use the SendMessageOptions class to construct the flags.
-
-Bit order: 15...0
-
-Bits 15-11: Unused, must be zero
-
-Bits 10-9: Message Reliability Override (Unimplemented, to be removed).
-
-
-
Field value
Description
-
00
Use session setting i2cp.messageReliabiltiy (default)
-
01
Use "best effort" message reliabiltiy for this message,
- overriding the session setting. The router will send one or more MessageStatusMessages in response.
- Unused. Use a nonzero nonce value to override a session setting of "none".
-
10
Use "guaranteed" message reliabiltiy for this message,
- overriding the session setting. The router will send one or more MessageStatusMessages in response.
- Unused. Use a nonzero nonce value to override a session setting of "none".
-
11
Unused. Use a nonce value of 0 to force "none" and override a session setting
- of "best effort" or "guaranteed".
-
-
-Bit 8: If 1, don't bundle a lease set in the garlic with this message.
-If 0, the router may bundle a lease set at its discretion.
-
-Bits 7-4: Low tag threshold. If there are less than this many tags available, send more.
-This is advisory and does not force tags to be delivered.
-
-
Field value
Tag threshold
-
0000
Use session key manager settings
-
0001
2
-
0010
3
-
0011
6
-
0100
9
-
0101
14
-
0110
20
-
0111
27
-
1000
35
-
1001
45
-
1010
57
-
1011
72
-
1100
92
-
1101
117
-
1110
147
-
1111
192
-
-
-Bits 3-0: Number of tags to send if required.
-This is advisory and does not force tags to be delivered.
-
-
Field value
Tags to send
-
0000
Use session key manager settings
-
0001
2
-
0010
4
-
0011
6
-
0100
8
-
0101
12
-
0110
16
-
0111
24
-
1000
32
-
1001
40
-
1010
51
-
1011
64
-
1100
80
-
1101
100
-
1110
125
-
1111
160
-
-
-
-
-
-
-
Session Status
-
Description
-
-Instruct the client as to the status of its session.
-Sent from Router to Client, possibly in response to a Create Session or Reconfigure Session.
-
Destroyed: The session with the given ID is terminated.
-
1
Created: In response to a Create Session, a new session with the given ID is now active.
-
2
Updated: In response to a Reconfigure Session, an existing session with the given ID has been reconfigured.
-
3
Invalid:
-In response to a Create Session, the configuration is invalid. The included session ID should be ignored.
-In response to a Reconfigure Session, the new configuration is invalid for the session with the given ID.
-
4
Refused: In response to a Create Session, the router was unable to create the session,
-perhaps due to limits being exceeded. The included session ID should be ignored. Since 0.9.12.
-
-
-
Notes
-
-Status values include 0 for destroyed, 1 for created, 2 for updated, and
-3 for invalid session.
-If created, the Session ID is the identifier to be used for the rest of the session.
-
-
-
-
-
Set Date
-
Description
-
-The current date and time.
-Sent from Router to Client as a part of the initial handshake.
-As of release 0.9.20, may also be sent at any time after the handshake to notify the client of a clock shift.
-
-This is generally the first message sent by the router.
-The version string is included as of release 0.8.7.
-This is only useful if the client and router are not in the same JVM.
-If it is not present, the router is version 0.8.6 or earlier.
-
-Additional SetDate messages will not be sent to clients in the same JVM.
-
-
-
-
-
-
-
-
-{% endblock %}
diff --git a/i2p2www/spec/i2cp.rst b/i2p2www/spec/i2cp.rst
new file mode 100644
index 00000000..6df97266
--- /dev/null
+++ b/i2p2www/spec/i2cp.rst
@@ -0,0 +1,1377 @@
+==================
+I2CP Specification
+==================
+.. meta::
+ :lastupdated: June 2015
+ :accuratefor: 0.9.21
+
+
+Overview
+========
+
+This page specified the I2P Control Protocol (I2CP), which is the interface
+between clients and the router. Java clients will use the I2CP client API,
+which implements this protocol. Non-Java clients will most likely use a
+higher-layer protocol such as SAM or BOB.
+
+The protocol is only serialized if the client and router are not in the same
+JVM; otherwise, I2CP message objects are passed via an internal JVM interface.
+
+More information is on the I2CP Overview page [I2CP]_.
+
+
+Sessions
+========
+
+The protocol was designed to handle multiple "sessions", each with a 2-byte
+session ID, over a single TCP connection, however, Multiple sessions were not
+implemented until version 0.9.21. See the `multisession section below`_. Do
+not attempt to use multiple sessions on a single I2CP connection with routers
+older than version 0.9.21.
+
+.. _multisession section below: _multisession
+
+It also appears that there are some provisions for a single client to talk to
+multiple routers over separate connections. This is also untested, and probably
+not useful.
+
+It does not appear that there is currently a way for a session to be maintained
+after a disconnect, or to be recovered on a different I2CP connection.
+
+
+Example Message Sequences
+=========================
+
+Note: The examples below do not show the Protocol Byte (0x2a) that must be sent
+from the client to the router when first connecting. More information about
+connection initialization is on the I2CP Overview page [I2CP]_.
+
+Standard Session Establish
+--------------------------
+
+.. raw:: html
+
+ {% highlight %}
+ Client Router
+
+ ---------------------> Get Date Message
+ Set Date Message <---------------------
+ ---------------------> Create Session Message
+ Session Status Message <---------------------
+ Request LeaseSet Message <---------------------
+ ---------------------> Create LeaseSet Message
+{% endhighlight %}
+
+Get Bandwidth Limits (Simple Session)
+-------------------------------------
+
+.. raw:: html
+
+ {% highlight %}
+ Client Router
+
+ ---------------------> Get Bandwidth Limits Message
+ Bandwidth Limits Message <---------------------
+{% endhighlight %}
+
+Destination Lookup (Simple Session)
+-----------------------------------
+
+.. raw:: html
+
+ {% highlight %}
+ Client Router
+
+ ---------------------> Dest Lookup Message
+ Dest Reply Message <---------------------
+{% endhighlight %}
+
+Outgoing Message
+----------------
+
+Existing session, with i2cp.messageReliability=none
+
+.. raw:: html
+
+ {% highlight %}
+ Client Router
+
+ ---------------------> Send Message Message
+{% endhighlight %}
+
+Existing session, with i2cp.messageReliability=none and nonzero nonce
+
+.. raw:: html
+
+ {% highlight %}
+ Client Router
+
+ ---------------------> Send Message Message
+ Message Status Message <---------------------
+ (succeeded)
+{% endhighlight %}
+
+Existing session, with i2cp.messageReliability=BestEffort
+
+.. raw:: html
+
+ {% highlight %}
+ Client Router
+
+ ---------------------> Send Message Message
+ Message Status Message <---------------------
+ (accepted)
+ Message Status Message <---------------------
+ (succeeded)
+{% endhighlight %}
+
+Incoming Message
+----------------
+
+Existing session, with i2cp.fastReceive=true (as of 0.9.4)
+
+.. raw:: html
+
+ {% highlight %}
+ Client Router
+
+ Message Payload Message <---------------------
+{% endhighlight %}
+
+Existing session, with i2cp.fastReceive=false
+
+.. raw:: html
+
+ {% highlight %}
+ Client Router
+
+ Message Status Message <---------------------
+ (available)
+ ---------------------> Receive Message Begin Message
+ Message Payload Message <---------------------
+ ---------------------> Receive Message End Message
+{% endhighlight %}
+
+
+.. _multisession:
+
+Multisession Notes
+------------------
+
+Multiple sessions on a single I2CP connection are supported as of router
+version 0.9.21. The first session that is created is the "primary session".
+Additional sessions are "subsessions". Subsessions are used to support
+multiple destinations sharing a common set of tunnels. The initial application
+is for the primary session to use ECDSA signing keys, while the subsession uses
+DSA signing keys for communication with old eepsites.
+
+Subsessions share the same inbound and outbound tunnel pools as the primary
+session. Subsessions must use the same encryption keys as the primary session.
+This applies both to the LeaseSet encryption keys and the (unused) Destination
+encryption keys. Subsessions must use different signing keys in the
+destination, so the destination hash is different from the primary session. As
+subsessions use the same encryption keys and tunnels as the primary session, it
+is apparent to all that the Destinations are running on the same router, so the
+usual anti-correlation anonymity guarantees do not apply.
+
+Subsessions are created by sending a CreateSession message and receiving a
+SessionStatus message in reply, as usual. Subsessions must be created after the
+primary session is created. The SessionStatus response will, on success,
+contain a unique Session ID, distinct from the ID for the primary session.
+While CreateSession messages should be processed in-order, there is no sure way
+to correlate a CreateSession message with the response, so a client should not
+have multiple CreateSession messages outstanding simultaneously. SessionConfig
+options for the subsession may not be honored where they are different from the
+primary session. In particular, since subsessions use the same tunnel pool as
+the primary session, tunnel options may be ignored.
+
+The router will send separate RequestVariableLeaseSet messages for each
+Destination to the client, and the client must reply with a CreateLeaseSet
+message for each. The leases for the two Destinations will not necessarily be
+identical, even though they are selected from the same tunnel pool.
+
+A subsession may be destroyed with the DestroySession message as usual. This
+will not destroy the primary session or stop the I2CP connection. Destroying
+the primary session will, however, destroy all subsessions and stop the I2CP
+connection. A Disconnect message destroys all sessions.
+
+Note that most, but not all, I2CP messages contain a Session ID. For the ones
+that do not, clients may need additional logic to properly handle router
+responses. DestLookup and DestReply do not contain Session IDs; use the newer
+HostLookup and HostReply instead. GetBandwidthLimts and BandwidthLimits do not
+contain session IDs, however the response is not session-specific.
+
+Support for multiple sessions is preliminary and subject to change. Support
+may not be complete in other parts of the API and user interface, particularly
+streaming and i2ptunnel. Current support is primarily for clients (i.e.
+Destinations that do not publish their leaseset or accept incoming
+connections), and is incomplete and untested for servers. Future releases may
+provide additional features and options.
+
+
+.. _notes:
+
+Version Notes
+-------------
+
+The initial protocol version byte (0x2a) sent by the client is not expected to
+change. Prior to release 0.8.7, the router's version information was not
+available to the client, thus preventing new clients from working with old
+routers. As of release 0.8.7, the two parties' protocol version strings are
+exchanged in the Get/Set Date Messages. Going forward, clients may use this
+information to communicate correctly with old routers. Clients and routers
+should not send messages that are unsupported by the other side, as they
+generally disconnect the session upon reception of an unsupported message.
+
+The exchanged version information is the "core" version or I2CP protocol
+version, and is not necessarily the router version.
+
+A basic summary of the I2CP protocol versions is as follows. For details, see
+below.
+
+============== ======================
+ Version Required I2CP Features
+============== ======================
+ 0.9.21 Multiple sessions on a single I2CP connection supported
+
+ 0.9.20 Additional SetDate messages may be sent to the client at any
+ time
+
+ 0.9.16 Authentication, if enabled, is required via GetDate before all
+ other messages
+
+ 0.9.15 Dest/LS key certs w/ EdDSA Ed25519 sig type supported
+
+ 0.9.14 Per-message override of messageReliability=none with nonzero
+ nonce
+
+ 0.9.12 Dest/LS key certs w/ ECDSA P-256, P-384, and P-521 sig types
+ supported
+
+ Note: RSA sig types also supported as of this version, but
+ currently unused
+
+ 0.9.11 Host Lookup and Host Reply messages supported
+
+ Authentication mapping in Get Date message supported
+
+ 0.9.7 Request Variable Lease Set message supported
+
+ 0.9.5 Additional Message Status codes defined
+
+ 0.9.4 Send Message nonce=0 allowed
+
+ Fast receive mode is the default
+
+ 0.9.2 Send Message Expires flag tag bits supported
+
+ 0.9 Supports up to 16 leases in a lease set (6 previously)
+
+ 0.8.7 Get Date and Set Date version strings included.
+
+ If not present, the client or router is version 0.8.6 or older.
+
+ 0.8.4 Send Message Expires flag bits supported
+
+ 0.8.3 Dest Lookup and Get Bandwidth messages supported in standard
+ session
+
+ Concurrent Dest Lookup messages supported
+
+ 0.8.1 i2cp.messageReliability=none supported
+
+ 0.7.2 Get Bandwidth Limits and Bandwidth Limits messages supported
+
+ 0.7.1 Send Message Expires message supported
+ Reconfigure Session message supported
+
+ 0.7 Dest Lookup and Dest Reply messages supported
+
+0.6.5 or lower All messages and features not listed above
+============== ======================
+
+
+.. _structures:
+
+Common structures
+=================
+
+.. _struct-i2cpmessageheader:
+
+I2CP message header
+-------------------
+
+Description
+```````````
+Common header to all I2CP messages, containing the message length and message
+type.
+
+Contents
+````````
+1. 4 byte [Integer]_ specifying the length of the message body
+2. 1 byte [Integer]_ specifying the message type.
+3. The I2CP message body, 0 or more bytes
+
+Notes
+`````
+Actual message length limit is about 64 KB.
+
+.. _struct-messageid:
+
+Message ID
+----------
+
+Description
+```````````
+Uniquely identifies a message waiting on a particular router at a point in
+time. This is always generated by the router and is NOT the same as the nonce
+generated by the client.
+
+Contents
+````````
+1. 4 byte [Integer]_
+
+Notes
+`````
+Message IDs are unique within a session only; they are not globally unique.
+
+.. _struct-payload:
+
+Payload
+-------
+
+Description
+```````````
+This structure is the content of a message being delivered from one Destination
+to another.
+
+Contents
+````````
+1. 4 byte [Integer]_ length
+2. That many bytes
+
+Notes
+`````
+The payload is in a gzip format as specified on the I2CP Overview page
+[I2CP-FORMAT]_.
+
+.. _struct-sessionconfig:
+
+Session Config
+--------------
+
+Description
+```````````
+Defines the configuration options for a particular client session.
+
+Contents
+````````
+1. [Destination]_
+2. [Mapping]_ of options
+3. Creation [Date]_
+4. [Signature]_ of the previous 3 fields, signed by the [SigningPrivateKey]_
+
+Notes
+`````
+* The options are specified on the
+I2CP Overview page.
+
+* The [Mapping]_ must be sorted by key so that the signature will be validated
+ correctly in the router.
+
+* The creation date must be within +/- 30 seconds of the current time when
+ processed by the router, or the config will be rejected.
+
+.. _struct-sessionid:
+
+Session ID
+----------
+
+Description
+```````````
+Uniquely identifies a session on a particular router at a point in
+time.
+
+Contents
+````````
+1. 2 byte [Integer]_
+
+Notes
+`````
+
+
+Messages
+========
+
+See also the I2CP Javadocs [I2CP-JAVADOCS]_.
+
+.. _types:
+
+Message Types
+-------------
+
+=============================== ========= ==== =====
+ Message Direction Type Since
+=============================== ========= ==== =====
+BandwidthLimitsMessage_ R -> C 23 0.7.2
+CreateLeaseSetMessage_ C -> R 4
+CreateSessionMessage_ C -> R 1
+DestLookupMessage_ C -> R 34 0.7
+DestReplyMessage_ R -> C 35 0.7
+DestroySessionMessage_ C -> R 3
+DisconnectMessage_ bidir. 30
+GetBandwidthLimitsMessage_ C -> R 8 0.7.2
+GetDateMessage_ C -> R 32
+HostLookupMessage_ C -> R 38 0.9.11
+HostReplyMessage_ R -> C 39 0.9.11
+MessagePayloadMessage_ R -> C 31
+MessageStatusMessage_ R -> C 22
+ReceiveMessageBeginMessage_ C -> R 6
+ReceiveMessageEndMessage_ C -> R 7
+ReconfigureSessionMessage_ C -> R 2 0.7.1
+ReportAbuseMessage_ bidir. 29
+RequestLeaseSetMessage_ R -> C 21
+RequestVariableLeaseSetMessage_ R -> C 37 0.9.7
+SendMessageMessage_ C -> R 5
+SendMessageExpiresMessage_ C -> R 36 0.7.1
+SessionStatusMessage_ R -> C 20
+SetDateMessage_ R -> C 33
+=============================== ========= ==== =====
+
+.. _msg_bandwidthlimits:
+
+BandwidthLimitsMessage
+----------------------
+
+Description
+```````````
+Tell the client what the bandwidth limits are.
+
+Sent from Router to Client in response to a GetBandwidthLimitsMessage_.
+
+Contents
+````````
+1. 4 byte [Integer]_ Client inbound limit (KBps)
+2. 4 byte [Integer]_ Client outbound limit (KBps)
+3. 4 byte [Integer]_ Router inbound limit (KBps)
+4. 4 byte [Integer]_ Router inbound burst limit (KBps)
+5. 4 byte [Integer]_ Router outbound limit (KBps)
+6. 4 byte [Integer]_ Router outbound burst limit (KBps)
+7. 4 byte [Integer]_ Router burst time (seconds)
+8. Nine 4-byte [Integer]_ (undefined)
+
+Notes
+`````
+Currently, the client limits are the only values set, and are actually the
+router limits. All the values labeled as router limits are always 0. As of
+release 0.7.2.
+
+.. _msg-createleaseset:
+
+CreateLeaseSetMessage
+---------------------
+
+Description
+```````````
+This message is sent in response to a RequestLeaseSetMessage_ or
+RequestVariableLeaseSetMessage_ and contains all of the [Lease]_ structures that
+should be published to the I2NP Network Database.
+
+Sent from Client to Router.
+
+Contents
+````````
+1. `Session ID`_
+2. [SigningPrivateKey]_
+3. [PrivateKey]_
+4. [LeaseSet]_
+
+Notes
+`````
+The SigningPrivateKey matches the [SigningPublicKey]_ from within the LeaseSet,
+as does the PrivateKey with the [PublicKey]_. The signing key is necessary to
+allow the router to revoke the LeaseSet if the client goes offline, and the
+encryption key is necessary for decrypting garlic routed messages. The LeaseSet
+granted may include Lease structures for tunnels pointing at another router if
+the client is actively connected to multiple routers with Leases granted to
+each.
+
+**XXX** Really?
+Revocation is unimplemented.
+Connection to multiple routers is untested.
+
+.. _msg-CreateSession:
+
+CreateSessionMessage
+--------------------
+
+Description
+```````````
+This message is sent from a client to initiate a session, where a session is
+defined as a single Destination's connection to the network, to which all
+messages for that Destination will be delivered and from which all messages
+that Destination sends to any other Destination will be sent through.
+
+Sent from Client to Router. The router responds with a SessionStatusMessage_.
+
+Contents
+````````
+1. `Session Config`_
+
+Notes
+`````
+* This is the second message sent by the client. Previously the client sent a
+ GetDateMessage_ and received a SetDateMessage_ response.
+
+* If the Date in the Session Config is too far (more than +/- 30 seconds) from
+ the router's current time, the session will be rejected.
+
+* If there is already a session on the router for this Destination, the session
+ will be rejected.
+
+* The [Mapping]_ in the Session Config must be sorted by key so that the
+ signature will be validated correctly in the router.
+
+.. _msg-destlookup:
+
+DestLookupMessage
+-----------------
+
+Description
+```````````
+Sent from Client to Router. The router responds with a DestReplyMessage_.
+
+Contents
+````````
+1. SHA-256 [Hash]_
+
+Notes
+`````
+As of release 0.7.
+
+As of release 0.8.3, multiple outstanding lookups are supported, and lookups
+are supported in both I2PSimpleSession and in standard sessions.
+
+HostLookupMessage_ is preferred as of release 0.9.11.
+
+.. _msg-DestReply:
+
+DestReplyMessage
+----------------
+
+Description
+```````````
+Sent from Router to Client in response to a DestLookupMessage_.
+
+Contents
+````````
+1. [Destination]_ on success, or [Hash]_ on failure
+
+Notes
+`````
+As of release 0.7.
+
+As of release 0.8.3, the requested Hash is returned if the lookup failed, so
+that the client may have multiple lookups outstanding and correlate the replies
+to the lookups. To correlate a Destination response with a request, take the
+Hash of the Destination. Prior to release 0.8.3, the response was empty on
+failure.
+
+.. _msg-destroysession:
+
+DestroySessionMessage
+---------------------
+
+Description
+```````````
+This message is sent from a client to destroy a session.
+
+Sent from Client to Router. The router responds with a SessionStatusMessage_.
+
+Contents
+````````
+1. `Session ID`_
+
+Notes
+`````
+The router at this point should release all resources related to the session.
+
+.. _msg-disconnect:
+
+DisconnectMessage
+-----------------
+
+Description
+```````````
+Tell the other party that there are problems and the current connection is about to
+be destroyed. This does not necessarily end a session.
+Sent either from router to client or from client to router.
+
+Contents
+````````
+1. Reason [String]_
+
+Notes
+`````
+Only implemented in the router-to-client direction. Disconnecting probably
+does end a session, in practice.
+
+.. _msg-GetBandwidthLimits:
+
+GetBandwidthLimitsMessage
+-------------------------
+
+Description
+```````````
+Request that the router state what its current bandwidth limits are.
+
+Sent from Client to Router. The router responds with a
+BandwidthLimitsMessage_.
+
+Contents
+````````
+*None*
+
+Notes
+`````
+As of release 0.7.2.
+
+As of release 0.8.3, supported in both I2PSimpleSession and in standard
+sessions.
+
+.. _msg-GetDate:
+
+GetDateMessage
+--------------
+
+Description
+```````````
+Sent from Client to Router. The router responds with a SetDateMessage_.
+
+Contents
+````````
+1. I2CP Version [String]_
+2. Authentication [Mapping]_ (optional, as of release 0.9.11)
+
+Notes
+`````
+* Generally the first message sent by the client after sending the protocol
+ version byte.
+
+* The version string is included as of release 0.8.7. This is only useful if
+ the client and router are not in the same JVM. If it is not present, the
+ client is version 0.8.6 or earlier.
+
+* As of release 0.9.11, the authentication [Mapping]_ may be included, with the
+ keys i2cp.username and i2cp.password. The Mapping need not be sorted as this
+ message is not signed. Prior to and including 0.9.10, authentication is
+ included in the `Session Config`_ Mapping, and no authentication is enforced
+ for GetDateMessage_, GetBandwidthLimitsMessage_, or DestLookupMessage_. When
+ enabled, authentication via GetDateMessage_ is required before any other
+ messages as of release 0.9.16. This is only useful outside router context.
+ This is an incompatible change, but will only affect sessions outside router
+ context with authentication, which should be rare.
+
+.. _msg-HostLookup:
+
+HostLookupMessage
+-----------------
+
+Description
+```````````
+Sent from Client to Router. The router responds with a HostReplyMessage_.
+
+This replaces the DestLookupMessage_ and adds a request ID, a timeout, and host
+name lookup support. As it also supports Hash lookups, it may be used for all
+lookups if the router supports it. For host name lookups, the router will
+query its context's naming service. This is only useful if the client is
+outside the router's context. Inside router context, the client should query
+the naming service itself, which is much more efficient.
+
+Contents
+````````
+1. `Session ID`_
+2. 4 byte [Integer]_ request ID
+3. 4 byte [Integer]_ timeout (ms)
+4. 1 byte [Integer]_ request type
+5. SHA-256 [Hash]_ or host name [String]_
+
+Notes
+`````
+* As of release 0.9.11. Use DestLookupMessage_ for older routers.
+
+* The session ID and request ID will be returned in the HostReplyMessage_. Use
+ 0xFFFF for the session ID if there is no session.
+
+* Timeout is useful for Hash lookups. Recommended minimum 10,000 (10 sec.). In
+ the future it may also be useful for remote naming service lookups. The value
+ may be not be honored for local host name lookups, which should be fast.
+
+* The request type is 0 for Hash and 1 for host name.
+
+* Base 32 host name lookup is supported but it is preferred to convert it to a
+ Hash first.
+
+.. _msg-hostreply:
+
+HostReplyMessage
+----------------
+
+Description
+```````````
+Sent from Router to Client in response to a HostLookupMessage_.
+
+Contents
+````````
+1. `Session ID`_
+2. 4 byte [Integer]_ request ID
+3. 1 byte [Integer]_ result code
+4. [Destination]_, only present if result code is zero.
+
+Notes
+`````
+* As of release 0.9.11. See HostLookupMessage_ notes.
+
+* The session ID and request ID are those from the HostLookupMessage_.
+
+* The result code is 0 for success, 1-255 for failure. Only 1 is used for
+ failure now, more specific failure codes may be defined in the future.
+
+.. _msg-messagepayload:
+
+MessagePayloadMessage
+---------------------
+
+Description
+```````````
+Deliver the payload of a message to the client.
+
+Sent from Router to Client. The client responds with a
+ReceiveMessageEndMessage_.
+
+Contents
+````````
+1. `Session ID`_
+2. `Message ID`_
+3. Payload_
+
+Notes
+`````
+
+.. _msg-messagestatus:
+
+MessageStatusMessage
+--------------------
+
+Description
+```````````
+Notify the client of the delivery status of an incoming or outgoing message.
+Sent from Router to Client. If this message indicates that an incoming message
+is available, the client responds with a ReceiveMessageBeginMessage_. For an
+outgoing message, this is a response to a SendMessageMessage_ or
+SendMessageExpiresMessage_.
+
+Contents
+````````
+1. `Session ID`_
+2. `Message ID`_ generated by the router
+3. 1 byte [Integer]_ status
+4. 4 byte [Integer]_ size
+5. 4 byte [Integer]_ nonce previously generated by the client
+
+Notes
+`````
+Through version 0.9.4, 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. The size Integer specifies the
+size of the available message and is only relevant for status = 0. Even though
+guaranteed is unimplemented, (best effort is the only service), the current
+router implementation uses the guaranteed status codes, not the best effort
+codes.
+
+As of router version 0.9.5, additional status codes are defined, however they
+are not necessarily implemented. See [MSM-JAVADOCS]_ for details. All status
+codes:
+
+=========== ============= ====================== ==========================================================
+Status Code As Of Release Name Description
+=========== ============= ====================== ==========================================================
+ 0 Available For incoming messages only. All other status codes below
+ are for outgoing messages.
+
+ The included size is the size in bytes of the available
+ message.
+
+ This is unused in "fast receive" mode, which is the
+ default as of release 0.9.4.
+
+ 1 Accepted Outgoing message accepted by the local router for
+ delivery. The included nonce matches the nonce in the
+ SendMessageMessage_, and the included Message ID will be
+ used for subsequent success or failure notification.
+
+ 2 Best Effort Success Probable success (unused)
+
+ 3 Best Effort Failure Probable failure
+
+ 4 Guaranteed Success Probable success
+
+ 5 Guaranteed Failure Generic failure, specific cause unknown.
+ May not really be a guaranteed failure.
+
+ 6 0.9.5 Local Success Local delivery successful.
+ The destination was another client on the same router.
+
+ 7 0.9.5 Local Failure Local delivery failure.
+ The destination was another client on the same router.
+
+ 8 0.9.5 Router Failure The local router is not ready, has shut down, or has
+ major problems.
+
+ This is a guaranteed failure.
+
+ 9 0.9.5 Network Failure The local computer apparently has no network connectivity
+ at all.
+
+ This is a guaranteed failure.
+
+ 10 0.9.5 Bad Session The I2CP session is invalid or closed.
+
+ This is a guaranteed failure.
+
+ 11 0.9.5 Bad Message The message payload is invalid or zero-length or too big.
+
+ This is a guaranteed failure.
+
+ 12 0.9.5 Bad Options Something is invalid in the message options, or the
+ expiration is in the past or too far in the future.
+
+ This is a guaranteed failure.
+
+ 13 0.9.5 Overflow Failure Some queue or buffer in the router is full and the message
+ was dropped.
+
+ This is a guaranteed failure.
+
+ 14 0.9.5 Message Expired The message expired before it could be sent.
+
+ This is a guaranteed failure.
+
+ 15 0.9.5 Bad Local Leaseset The client has not yet signed a [LeaseSet]_, or the local
+ keys are invalid, or it has expired, or it does not have
+ any tunnels in it.
+
+ This is a guaranteed failure.
+
+ 16 0.9.5 No Local Tunnels Local problems. No outbound tunnel to send through, or no
+ inbound tunnel if a reply is required.
+
+ This is a guaranteed failure.
+
+ 17 0.9.5 Unsupported Encryption The certs or options in the [Destination]_ or its
+ [LeaseSet]_ indicate that it uses an encryption format
+ that we don't support, so we can't talk to it.
+
+ This is a guaranteed failure.
+
+ 18 0.9.5 Bad Destination Something is wrong with the far-end [Destination]_. Bad
+ format, unsupported options, certificates, etc.
+
+ This is a guaranteed failure.
+
+ 19 0.9.5 Bad Leaseset We got the far-end [LeaseSet]_ but something strange is
+ wrong with it. Unsupported options or certificates, no
+ tunnels, etc.
+
+ This is a guaranteed failure.
+
+ 20 0.9.5 Expired Leaseset We got the far-end [LeaseSet]_ but it's expired and we
+ can't get a new one.
+
+ This is a guaranteed failure.
+
+ 21 0.9.5 No Leaseset Could not find the far-end [LeaseSet]_. This is a common
+ failure, equivalent to a DNS lookup failure.
+
+ This is a guaranteed failure.
+=========== ============= ====================== ==========================================================
+
+When status = 1 (accepted), the nonce matches the nonce in the
+SendMessageMessage_, and the included Message ID will be used for subsequent
+success or failure notification. Otherwise, the nonce may be ignored.
+
+.. _msg-receivemessagebegin:
+
+ReceiveMessageBeginMessage
+--------------------------
+
+Description
+```````````
+Request the router to deliver a message that it was previously notified of.
+Sent from Client to Router. The router responds with a MessagePayloadMessage_.
+
+Contents
+````````
+1. `Session ID`_
+2. `Message ID`
+
+Notes
+`````
+The ReceiveMessageBeginMessage_ is sent as a response to a
+MessageStatusMessage_ stating that a new message is available for pickup. If
+the message id specified in the ReceiveMessageBeginMessage_ is invalid or
+incorrect, the router may simply not reply, or it may send back a
+DisconnectMessage_.
+
+This is unused in "fast receive" mode, which is the default as of release
+0.9.4.
+
+.. _msg-receivemessageend:
+
+ReceiveMessageEndMessage
+------------------------
+
+Description
+```````````
+Tell the router that delivery of a message was completed successfully and that
+the router can discard the message.
+
+Sent from Client to Router.
+
+Contents
+````````
+1. `Session ID`_
+2. `Message ID`
+
+Notes
+`````
+The ReceiveMessageEndMessage_ is sent after a MessagePayloadMessage_ fully
+delivers a message's payload.
+
+This is unused in "fast receive" mode, which is the default as of release
+0.9.4.
+
+.. _msg-reconfiguresession:
+
+ReconfigureSessionMessage
+-------------------------
+
+Description
+```````````
+
+Sent from Client to Router to update the session configuration. The router
+responds with a SessionStatusMessage_.
+
+Contents
+````````
+1. `Session ID`_
+2. `Session Config`_
+
+Notes
+`````
+* As of release 0.7.1.
+
+* If the Date in the Session Config is too far (more than +/- 30 seconds) from
+ the router's current time, the session will be rejected.
+
+* The [Mapping]_ in the Session Config must be sorted by key so that the
+ signature will be validated correctly in the router.
+
+* Some configuration options may only be set in the CreateSessionMessage_, and
+ changes here will not be recognized by the router. Changes to tunnel options
+ inbound.* and outbound.* are always recognized.
+
+.. _msg-reportabuse:
+
+ReportAbuseMessage
+------------------
+
+Description
+```````````
+Tell the other party (client or router) 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 banlist some of the peers that
+sent it messages delivering the attack.
+
+Sent either from router to client or from client to router.
+
+Contents
+````````
+1. `Session ID`_
+2. 1 byte [Integer]_ abuse severity (0 is minimally abusive, 255 being
+ extremely abusive)
+3. Reason [String]_
+4. `Message ID`_
+
+Notes
+`````
+Unused. Not fully implemented. Both router and client can generate a
+ReportAbuseMessage_, but neither has a handler for the message when received.
+
+.. _msg-requestleaseset:
+
+RequestLeaseSetMessage
+----------------------
+
+Description
+```````````
+Request that a client authorize the inclusion of a particular set of inbound
+tunnels. Sent from Router to Client. The client responds with a
+CreateLeaseSetMessage_.
+
+Contents
+````````
+1. `Session ID`_
+2. 1 byte [Integer]_ number of tunnels
+3. That many pairs of:
+
+ 1. [RouterIdentity]_
+ 2. [TunnelId]_
+
+4. End [Date]_
+
+Notes
+`````
+This requests a [LeaseSet]_ with all [Leases]_ set to expire at the same time.
+For client versions 0.9.7 or higher, RequestVariableLeaseSetMessage_ is
+preferred.
+
+.. _msg-requestvariableleaseset:
+
+RequestVariableLeaseSetMessage
+------------------------------
+
+Description
+```````````
+Request that a client authorize the inclusion of a particular set of inbound
+tunnels.
+
+Sent from Router to Client. The client responds with a CreateLeaseSetMessage_.
+
+Contents
+````````
+1. `Session ID`_
+2. 1 byte [Integer]_ number of tunnels
+3. That many [Leases]_
+
+Notes
+`````
+This requests a [LeaseSet]_ with an individual expiration time for each
+[Lease]_.
+
+As of release 0.9.7. For clients before that release, use
+RequestLeaseSetMessage_.
+
+.. _msg-sendmessage:
+
+SendMessageMessage
+------------------
+
+Description
+```````````
+This is how a client sends a message (the payload) to the [Destination]_. The
+router will use a default expiration.
+
+Sent from Client to Router. The router responds with a MessageStatusMessage_.
+
+Contents
+````````
+1. `Session ID`_
+2. [Destination]_
+3. Payload_
+4. 4 byte [Integer]_ nonce
+
+Notes
+`````
+As soon as the SendMessageMessage_ arrives fully intact, the router should
+return a MessageStatusMessage_ stating that it has been accepted for delivery.
+That message will contain the same nonce sent here. Later on, based on the
+delivery guarantees of the session configuration, the router may additionally
+send back another MessageStatusMessage_ updating the status.
+
+As of release 0.8.1, the router does not send either MessageStatusMessage_ if
+i2cp.messageReliability=none.
+
+Prior to release 0.9.4, a nonce value of 0 was not allowed. As of release
+0.9.4, a nonce value of 0 is allowed, and tells to the router that it should
+not send either MessageStatusMessage_, i.e. it acts as if
+i2cp.messageReliability=none for this message only.
+
+Prior to release 0.9.14, a session with i2cp.messageReliability=none could not
+be overridden on a per-message basis. As of release 0.9.14, in a session with
+i2cp.messageReliability=none, the client may request delivery of a
+MessageStatusMessage_ with the delivery success or failure by setting the nonce
+to a nonzero value. The router will not send the "accepted"
+MessageStatusMessage_ but it will later send the client a MessageStatusMessage_
+with the same nonce, and a success or failure value.
+
+.. _msg-sendmessageexpires:
+
+SendMessageExpiresMessage
+-------------------------
+
+Description
+```````````
+Sent from Client to Router. Same as SendMessageMessage_, except includes an
+expiration and options.
+
+Contents
+````````
+1. `Session ID`_
+2. [Destination]_
+3. Payload_
+4. 4 byte [Integer]_ nonce
+5. 2 bytes of flags (options)
+6. Expiration [Date]_ truncated from 8 bytes to 6 bytes
+
+Notes
+`````
+As of release 0.7.1.
+
+In "best effort" mode, as soon as the SendMessageExpiresMessage arrives fully
+intact, the router should return a MessageStatusMessage stating that it has
+been accepted for delivery. That message will contain the same nonce sent
+here. Later on, based on the delivery guarantees of the session configuration,
+the router may additionally send back another MessageStatusMessage updating the
+status.
+
+As of release 0.8.1, the router does not send either Message Status Message if
+i2cp.messageReliability=none.
+
+Prior to release 0.9.4, a nonce value of 0 was not allowed. As of release
+0.9.4, a nonce value of 0 is allowed, and tells the router that it should not
+send either Message Status Message, i.e. it acts as if
+i2cp.messageReliability=none for this message only.
+
+Prior to release 0.9.14, a session with i2cp.messageReliability=none could not
+be overridden on a per-message basis. As of release 0.9.14, in a session with
+i2cp.messageReliability=none, the client may request delivery of a Message
+Status Message with the delivery success or failure by setting the nonce to a
+nonzero value. The router will not send the "accepted" Message Status Message
+but it will later send the client a Message Status Message with the same nonce,
+and a success or failure value.
+
+Flags Field
+```````````
+As of release 0.8.4, the upper two bytes of the Date are redefined to contain
+flags. The flags must default to all zeros for backward compatibility. The
+Date will not encroach on the flags field until the year 10889. The flags may
+be used by the application to provide hints to the router as to whether a
+LeaseSet and/or ElGamal/AES Session Tags should be delivered with the message.
+The settings will significantly affect the amount of protocol overhead and the
+reliability of message delivery. The individual flag bits are defined as
+follows, as of release 0.9.2. Definitions are subject to change. Use the
+SendMessageOptions class to construct the flags.
+
+Bit order: 15...0
+
+Bits 15-11
+ Unused, must be zero
+
+Bits 10-9
+ Message Reliability Override (Unimplemented, to be removed).
+
+=========== ===========
+Field value Description
+=========== ===========
+ 00 Use session setting i2cp.messageReliability (default)
+
+ 01 Use "best effort" message reliability for this message, overriding
+ the session setting. The router will send one or more
+ MessageStatusMessages in response.
+
+ Unused. Use a nonzero nonce value to override a session setting of
+ "none".
+
+ 10 Use "guaranteed" message reliability for this message, overriding
+ the session setting. The router will send one or more
+ MessageStatusMessages in response.
+
+ Unused. Use a nonzero nonce value to override a session setting of
+ "none".
+
+ 11 Unused. Use a nonce value of 0 to force "none" and override a
+ session setting of "best effort" or "guaranteed".
+=========== ===========
+
+Bit 8
+ If 1, don't bundle a lease set in the garlic with this message. If 0, the
+ router may bundle a lease set at its discretion.
+
+Bits 7-4
+ Low tag threshold. If there are less than this many tags available, send
+ more. This is advisory and does not force tags to be delivered.
+
+=========== =============
+Field value Tag threshold
+=========== =============
+ 0000 Use session key manager settings
+ 0001 2
+ 0010 3
+ 0011 6
+ 0100 9
+ 0101 14
+ 0110 20
+ 0111 27
+ 1000 35
+ 1001 45
+ 1010 57
+ 1011 72
+ 1100 92
+ 1101 117
+ 1110 147
+ 1111 192
+=========== =============
+
+Bits 3-0
+ Number of tags to send if required. This is advisory and does not force
+ tags to be delivered.
+
+=========== ============
+Field value Tags to send
+=========== ============
+ 0000 Use session key manager settings
+ 0001 2
+ 0010 4
+ 0011 6
+ 0100 8
+ 0101 12
+ 0110 16
+ 0111 24
+ 1000 32
+ 1001 40
+ 1010 51
+ 1011 64
+ 1100 80
+ 1101 100
+ 1110 125
+ 1111 160
+=========== ============
+
+.. _msg-sessionstatus:
+
+SessionStatusMessage
+--------------------
+
+Description
+```````````
+Instruct the client as to the status of its session.
+
+Sent from Router to Client, possibly in response to a CreateSessionMessage_ or
+ReconfigureSessionMessage_.
+
+Contents
+````````
+1. `Session ID`_
+2. 1 byte [Integer]_ status
+
+====== ====== ========= =============================================================
+Status Since Name Definition
+====== ====== ========= =============================================================
+ 0 Destroyed The session with the given ID is terminated.
+
+ 1 Created In response to a CreateSessionMessage_, a new session with
+ the given ID is now active.
+
+ 2 Updated In response to a ReconfigureSessionMessage_, an existing
+ session with the given ID has been reconfigured.
+
+ 3 Invalid In response to a CreateSessionMessage_, the configuration is
+ invalid. The included session ID should be ignored.
+
+ In response to a ReconfigureSessionMessage_, the new
+ configuration is invalid for the session with the given ID.
+
+ 4 0.9.12 Refused In response to a CreateSessionMessage_, the router was unable
+ to create the session, perhaps due to limits being exceeded.
+ The included session ID should be ignored.
+====== ====== ========= =============================================================
+
+Notes
+`````
+Status values include 0 for destroyed, 1 for created, 2 for updated, and 3 for
+invalid session. If created, the Session ID is the identifier to be used for
+the rest of the session.
+
+.. _msg-setdate:
+.. _SetDateMessage:
+
+Set Date
+--------
+
+Description
+```````````
+The current date and time. Sent from Router to Client as a part of the initial
+handshake. As of release 0.9.20, may also be sent at any time after the
+handshake to notify the client of a clock shift.
+
+Contents
+````````
+1. [Date]_
+2. I2CP Version [String]_
+
+Notes
+`````
+This is generally the first message sent by the router. The version string is
+included as of release 0.8.7. This is only useful if the client and router are
+not in the same JVM. If it is not present, the router is version 0.8.6 or
+earlier.
+
+Additional SetDate messages will not be sent to clients in the same JVM.
+
+
+References
+==========
+
+.. [Date]
+ {{ spec_url('common-structures') }}#type-date
+
+.. [Destination]
+ {{ spec_url('common-structures') }}#struct-destination
+
+.. [Hash]
+ {{ spec_url('common-structures') }}#struct-hash
+
+.. [I2CP]
+ {{ site_url('docs/protocol/i2cp', True) }}
+
+.. [I2CP-FORMAT]
+ {{ site_url('docs/protocol/i2cp', True) }}#format
+
+.. [I2CP-JAVADOCS]
+ http://docs.i2p-projekt.de/javadoc/net/i2p/data/i2cp/package-summary.html
+
+.. [Integer]
+ {{ spec_url('common-structures') }}#type-integer
+
+.. [Leases]
+.. [Lease]
+ {{ spec_url('common-structures') }}#struct-lease
+
+.. [LeaseSet]
+ {{ spec_url('common-structures') }}#struct-leaseset
+
+.. [Mapping]
+ {{ spec_url('common-structures') }}#type-mapping
+
+.. [MSM-JAVADOCS]
+ http://docs.i2p-projekt.de/javadoc/net/i2p/data/i2cp/MessageStatusMessage.html
+
+.. [PrivateKey]
+ {{ spec_url('common-structures') }}#type-privatekey
+
+.. [RouterIdentity]
+ {{ spec_url('common-structures') }}#struct-routeridentity
+
+.. [Signature]
+ {{ spec_url('common-structures') }}#type-signature
+
+.. [SigningPrivateKey]
+ {{ spec_url('common-structures') }}#type-signingprivatekey
+
+.. [String]
+ {{ spec_url('common-structures') }}#struct-string
+
+.. [TunnelId]
+ {{ spec_url('common-structures') }}#tunnelid
diff --git a/i2p2www/spec/i2np.html b/i2p2www/spec/i2np.html
deleted file mode 100644
index cfce8ef1..00000000
--- a/i2p2www/spec/i2np.html
+++ /dev/null
@@ -1,1245 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}I2NP Specification{% endblock %}
-{% block lastupdated %}January 2015{% endblock %}
-{% block accuratefor %}0.9.17{% endblock %}
-{% block content %}
-
-The I2P Network Protocol (I2NP),
-which is sandwiched between I2CP and the various I2P transport protocols, manages the
-routing and mixing of messages between routers, as well as the selection of what
-transports to use when communicating with a peer for which there are multiple
-common transports supported.
-
-
-
Protocol Versions
-
-All routers must publish their I2NP protocol version in the "router.version" field in the RouterInfo properties.
-This version field indicates their level of support for various I2NP protocol features,
-and is not necessarily the actual router version.
-
-If alternative (non-Java) routers
-wish to publish any version information about the actual router implementation,
-they must do so in another property.
-Versions other than those listed below are allowed. Support will be
-determined through a numeric comparison; for example, 0.9.13 implies support for 0.9.12 features.
-Note that the "coreVersion" property is not used for determination of the I2NP protocol version.
-
-A basic summary of the I2NP protocol versions is as follows. For details, see below.
-
-
-
Version
-
Required I2NP Features
-
-
0.9.18
-
DSM type bits 7-1 ignored
-
-
-
0.9.16
-
RI key certs / ECDSA and EdDSA sig types
- Note: RSA sig types also supported as of this version, but currently unused
- DLM lookup types (DLM flag bits 3-2)
-
-
-
0.9.15
-
Dest/LS key certs w/ EdDSA Ed25519 sig type (if floodfill)
-
-
0.9.12
-
Dest/LS key certs w/ ECDSA P-256, P-384, and P-521 sig types (if floodfill)
- Note: RSA sig types also supported as of this version, but currently unused
- Nonzero expiration allowed in RouterAddress
-
-
-
0.9.7
-
Encrypted DSM/DSRM replies supported (DLM flag bit 1) (if floodfill)
-
-
0.9.6
-
Nonzero DLM flag bits 7-1 allowed
-
-
0.9.3
-
Requires zero expiration in RouterAddress
-
-
0.9
-
Supports up to 16 leases in a DSM LS store (6 previously)
-
-
0.7.12
-
VTBM and VTBRM message support
-
-
0.7.10
-
Floodfill supports encrypted DSM stores
-
-
0.7.9 or lower
-
All messages and features not listed above
-
-
0.6.1.10
-
TBM and TBRM messages introduced
- Minimum version compatible with current network
-
-
-
-
-
-Note that there are also transport-related features and compatibility issues;
-see the NTCP and SSU transport documentation for details.
-
-
-
-
-
-
-
Common structures
-The following structures are elements of multiple I2NP messages.
-They are not complete messages.
-
-
I2NP message header
-
Description
-
- Common header to all I2NP messages, which contains important information like a checksum, expiration date, etc.
-
-
Contents
-
- 1 byte Integer specifying the type of this message,
- followed by a 4 byte Integer specifying the message-id.
- After that there is an expiration Date,
- followed by a 2 byte Integer specifying
- the length of the message payload, followed by a Hash,
- which is truncated to the first byte. After that the actual message data follows.
-
-{% highlight lang='dataspec' %}
-type :: `Integer`
- length -> 1 byte
-
- purpose -> identifies the message type (see table below)
-
-msg_id :: `Integer`
- length -> 4 bytes
-
- purpose -> uniquely identifies this message (for some time at least)
- This is usually a locally-generated random number, but for
- outgoing tunnel build messages it may be derived from
- the incoming message. See below.
-
-expiration :: `Date`
- 8 bytes
- date this message will expire
-
-short_expiration :: `Integer`
- 4 bytes
- date this message will expire (seconds since the epoch)
-
-size :: `Integer`
- length -> 2 bytes
-
- purpose -> length of the payload
-
-chks :: `Integer`
- length -> 1 byte
-
- purpose -> checksum of the payload
- SHA256 hash truncated to the first byte
-
-data ::
- length -> $size bytes
-
- purpose -> actual message contents
-{% endhighlight %}
-
-
Notes
-
-When transmitted over SSU,
-the 16-byte standard header is not used.
-Only a 1-byte type and a 4-byte expiration in seconds is included.
-The message id and size are
-incorporated into various parts of the SSU data packet format.
-The checksum is not required since errors are caught in decryption.
-
-The standard header is also required for I2NP messages contained in other messages and structures
-(Data, TunnelData, TunnelGateway, and GarlicClove).
-As of release 0.8.12, to reduce overhead, checksum verification is disabled at
-some places in the protocol stack.
-However, for compatibility with older versions, checksum generation is still required.
-It is a topic for future research to determine points in the protocol stack
-where the far-end router's version is known and checksum generation can be disabled.
-
-In the 512-byte encrypted record,
-the ElGamal data contains bytes 1-256 and 258-513 of the
-514-byte ElGamal encrypted block.
-The two padding bytes from the block (the zero bytes at locations 0 and 257) are removed.
-
-{% highlight lang='dataspec' %}
-unencrypted:
-Delivery Instructions :: as defined below
- Length varies but is typically 1, 33, or 37 bytes
-
-I2NP Message :: Any I2NP Message
-
-Clove ID :: 4 byte `Integer`
-
-Expiration :: `Date` (8 bytes)
-
-Certificate :: Always NULL in the current implementation (3 bytes total, all zeroes)
-
-{% endhighlight %}
-
-
Notes
-
-
- Cloves are never fragmented.
- When used in a Garlic Clove, the first bit of the Delivery Instructions flag byte specifies encryption.
- If this bit is 0, the clove is not encrypted.
- If 1, the clove is encrypted, and a 32 byte Session Key immediately follows the flag byte.
- Clove encryption is not fully implemented.
-
- Maximum length is a function of the total length of all the cloves and the
- maximum length of the GarlicMessage.
-
- In the future, the certificate could possibly be used for a HashCash to "pay" for the routing.
-
- The message can be any I2NP message (including a GarlicMessage, although that is not used in practice).
- The messages used in practice are DataMessage, DeliveryStatusMessage, and DatabaseStoreMessage.
-
- The Clove ID is generally set to a random number on transmit and is checked for
- duplicates on receive (same message ID space as top-level Message IDs)
-
-
-
-
Garlic Clove Delivery Instructions
-
-
-This specification is for Delivery Instructions inside Garlic Cloves only.
-Note that "Delivery Instructions" are also used inside
-Tunnel Messages,
-where the format is significantly different.
-See the
-Tunnel Message documentation
-for details.
-Do NOT use the following specification for Tunnel Message Delivery Instructions!
-
-
-{% highlight lang='dataspec' %}
-+----+----+----+----+----+----+----+----+
-|flag| |
-+----+ +
-| |
-+ Session Key (optional) +
-| |
-+ +
-| |
-+ +----+----+----+----+--------------+
-| | |
-+----+ +
-| |
-+ To Hash (optional) +
-| |
-+ +
-| |
-+ +----+----+----+----+--------------+
-| | Tunnel ID (opt) | Delay (opt)
-+----+----+----+----+----+----+----+----+
- |
-+----+
-{% endhighlight %}
-
-
Definition
-{% highlight lang='dataspec' %}
-flag ::
- 1 byte
- Bit order: 76543210
- bit 7: encrypted? Unimplemented, always 0
- If 1, a 32-byte encryption session key is included
- bits 6-5: delivery type
- 0x0 = LOCAL, 0x01 = DESTINATION, 0x02 = ROUTER, 0x03 = TUNNEL
- bit 4: delay included? Not fully implemented, always 0
- If 1, four delay bytes are included
- bits 3-0: reserved, set to 0 for compatibility with future uses
-
-Session Key ::
- 32 bytes
- Optional, present if encrypt flag bit is set. Unimplemented, never set, never present.
-
-To Hash ::
- 32 bytes
- Optional, present if delivery type is DESTINATION, ROUTER, or TUNNEL
- If DESTINATION, the SHA256 Hash of the destination
- If ROUTER, the SHA256 Hash of the router
- If TUNNEL, the SHA256 Hash of the gateway router
-
-Tunnel ID :: `TunnelId`
- 4 bytes
- Optional, present if delivery type is TUNNEL
- The destination tunnel ID
-
-Delay :: `Integer`
- 4 bytes
- Optional, present if delay included flag is set
- Not fully implemented. Specifies the delay in seconds.
-
-Total length: Typical length is:
- 1 byte for LOCAL delivery;
- 33 bytes for ROUTER / DESTINATION delivery;
- 37 bytes for TUNNEL delivery
-
-{% endhighlight %}
-
-
-
-
-{% highlight lang='dataspec' %}
-key ::
- 32 bytes
- SHA256 hash
-
-type ::
- 1 byte
- type identifier
- bit 0:
- 0 `RouterInfo`
- 1 `LeaseSet`
- bits 7-1:
- Through release 0.9.17, must be 0
- As of release 0.9.18, ignored, reserved for future options, set to 0 for compatibility
-
-reply token ::
- 4 bytes
- If greater than zero, a `DeliveryStatusMessage`
- is requested with the Message ID set to the value of the Reply Token.
- A floodfill router is also expected to flood the data to the closest floodfill peers
- if the token is greater than zero.
-
-reply_tunnelId ::
- 4 byte `TunnelId`
- Only included if reply token > 0
- This is the `TunnelId` of the inbound gateway of the tunnel the response should be sent to
- If $reply_tunnelId is zero, the reply is sent directy to the reply gateway router.
-
-reply gateway ::
- 32 bytes
- Hash of the `RouterInfo` entry to reach the gateway
- Only included if reply token > 0
- If $reply_tunnelId is nonzero, this is the router hash of the inbound gateway
- of the tunnel the response should be sent to.
- If $reply_tunnelId is zero, this is the router hash the response should be sent to.
-
-data ::
- If type == 0, data is a 2-byte `Integer` specifying the number of bytes that follow,
- followed by a gzip-compressed `RouterInfo`.
- If type == 1, data is an uncompressed `LeaseSet`.
-{% endhighlight %}
-
-
Notes
-
-For security, the reply fields are ignored if the message is received down a tunnel.
-
-The key is the "real" hash of the RouterIdentity or Destination, NOT the routing key.
-
-
-
-
-
DatabaseLookup
-
Description
-
- A request to look up an item in the network database.
- The response is either a DatabaseStore or a DatabaseSearchReply.
-
-
Contents
-{% highlight lang='dataspec' %}
-+----+----+----+----+----+----+----+----+
-| SHA256 hash as the key to look up |
-+ +
-| |
-+ +
-| |
-+ +
-| |
-+----+----+----+----+----+----+----+----+
-| SHA256 hash of the routerInfo |
-+ who is asking, or the gateway to +
-| send the reply to |
-+ +
-| |
-+ +
-| |
-+----+----+----+----+----+----+----+----+
-|flag| reply_tunnelId |size | |
-+----+----+----+----+----+----+----+ +
-| SHA256 of $key1 to exclude |
-+ +
-| |
-+ +
-| |
-+ +----+
-| | |
-+----+----+----+----+----+----+----+ +
-| SHA256 of $key2 to exclude |
-+ +
-~ ~
-+ +----+
-| | |
-+----+----+----+----+----+----+----+ +
-| |
-+ +
-| Session key if reply encryption |
-+ was requested +
-| |
-+ +----+
-| |tags|
-+----+----+----+----+----+----+----+----+
-| |
-+ +
-| Session tags if reply encryption |
-+ was requested +
-| |
-+ +
-| |
-+----+----+----+----+----+----+----+----+
-{% endhighlight %}
-
-
Definition
-{% highlight lang='dataspec' %}
-key ::
- 32 bytes
- SHA256 hash of the object to lookup
-
-from ::
- 32 bytes
- if deliveryFlag == 0, the SHA256 hash of the routerInfo entry this request came from
- (to which the reply should be sent)
- if deliveryFlag == 1, the SHA256 hash of the reply tunnel gateway
- (to which the reply should be sent)
-
-flags ::
- 1 byte
- bit order: 76543210
- bit 0: deliveryFlag
- 0 => send reply directly
- 1 => send reply to some tunnel
- bit 1: encryptionFlag
- through release 0.9.5, must be set to 0
- as of release 0.9.6, ignored
- as of release 0.9.7:
- 0 => send unencrypted reply
- 1 => send AES encrypted reply using enclosed key and tag
- bits 3-2: lookup type flags
- through release 0.9.5, must be set to 00
- as of release 0.9.6, ignored
- as of release 0.9.16:
- 00 => normal lookup, return `RouterInfo` or `LeaseSet` or `DatabaseSearchReplyMessage`
- 01 => LS lookup, return `LeaseSet` or `DatabaseSearchReplyMessage`
- 10 => RI lookup, return `RouterInfo` or `DatabaseSearchReplyMessage`
- 11 => exploration lookup, return `DatabaseSearchReplyMessage` containing non-floodfill routers only
- (replaces an excludedPeer of all zeroes)
- bits 7-4:
- through release 0.9.5, must be set to 0
- as of release 0.9.6, ignored, set to 0 for compatibility with future uses and with older routers
-
-reply_tunnelId ::
- 4 byte `TunnelID`
- only included if deliveryFlag == 1
- tunnelId of the tunnel to send the reply to
-
-size ::
- 2 byte `Integer`
- valid range: 0-512
- number of peers to exclude from the `DatabaseSearchReplyMessage`
-
-excludedPeers ::
- $size SHA256 hashes of 32 bytes each (total $size*32 bytes)
- if the lookup fails, these peers are requested to be excluded from the list in
- the `DatabaseSearchReplyMessage`.
- if excludedPeers includes a hash of all zeroes, the request is exploratory, and
- the `DatabaseSearchReplyMessage` is requested to list non-floodfill routers only.
-
-reply_key ::
- 32 byte `SessionKey`
- only included if encryptionFlag == 1, only as of release 0.9.7
-
-tags ::
- 1 byte `Integer`
- valid range: 1-32 (typically 1)
- the number of reply tags that follow
- only included if encryptionFlag == 1, only as of release 0.9.7
-
-reply_tags ::
- one or more 32 byte `SessionTag`s (typically one)
- only included if encryptionFlag == 1, only as of release 0.9.7
-
-{% endhighlight %}
-
-
Notes
-
-Prior to 0.9.16,
-the key may be for a RouterInfo or LeaseSet, as they are in the same key space,
-and there was no flag to request only a particular type of data.
-
-Encryption flag, reply key, and reply tags as of release 0.9.7.
-
-Encrypted replies are only useful when the response is through a tunnel.
-
-The number of included tags could be greater than one if alternative DHT lookup strategies
-(for example, recursive lookups) are implemented.
-
-The lookup key and exclude keys are the "real" hashes, NOT routing keys.
-
-
-
-
DatabaseSearchReply
-
Description
-
- The response to a failed Database Lookup Message
-
-
Contents
-
- A list of router hashes closest to the requested key
-
-{% highlight lang='dataspec' %}
-key ::
- 32 bytes
- SHA256 of the object being searched
-
-num ::
- 1 byte `Integer`
- number of peer hashes that follow, 0-255
-
-peer_hashes ::
- $num SHA256 hashes of 32 bytes each (total $num*32 bytes)
- SHA256 of the `RouterIdentity` that the other router thinks is close to the key
-
-from ::
- 32 bytes
- SHA256 of the `RouterInfo` of the router this reply was sent from
-{% endhighlight %}
-
-
Notes
-
- The 'from' hash is unauthenticated and cannot be trusted.
-
- The returned peer hashes are not necessarily closer to the key
- than the router being queried.
-
- Typical number of hashes returned: 3
-
-The lookup key, peer hashes, and from hash are "real" hashes, NOT routing keys.
-
-
-
-
-
-
DeliveryStatus
-
Description
-
- A simple message acknowledgment. Generally created by the message originator, and wrapped
- in a Garlic Message with the message itself, to be returned by the destination.
-
-
Contents
-
- The ID of the delivered message, and the creation or arrival time.
-
-{% highlight lang='dataspec' %}
-msg_id :: `Integer`
- 4 bytes
- unique ID of the message we deliver the DeliveryStatus for (see `I2NPMessageHeader` for details)
-
-time_stamp :: `Date`
- 8 bytes
- time the message was successfully created or delivered
-{% endhighlight %}
-
-
Notes
-
- It appears that the time stamp is always set by the creator to the current time.
- However there are several uses of this in the code, and more may be added in the future.
-
- This message is also used as a session established confirmation in SSU.
- In this case, the message ID is set to a random number, and the
- "arrival time" is set to the current network-wide ID, which is 2
- (i.e. 0x0000000000000002).
-
-{% highlight lang='dataspec' %}
-Encrypted:
-
-length ::
- 4 byte `Integer`
- number of bytes that follow 0 - 64 KB
-
-data ::
- $length bytes
- ElGamal encrypted data
-
-
-Unencrypted data:
-
-num ::
- 1 byte `Integer` number of `GarlicClove`s to follow
-
-clove :: a `GarlicClove`
-
-Certificate :: always NULL in the current implementation (3 bytes total, all zeroes)
-
-Message_ID :: 4 byte `Integer`
-
-Expiration :: `Date` (8 bytes)
-
-{% endhighlight %}
-
-
Notes
-
-
- When unencrypted, data contains one or more Garlic Cloves.
-
- The AES encrypted block is padded to a minimum of 128 bytes; with the 32-byte Session Tag
- the minimum size of the encrypted message is 160 bytes; with the 4 length bytes
- the minimum size of the Garlic Message is 164 bytes.
-
- Actual max length is less than 64 KB; see the I2NP Overview.
-
- The 128 byte minimum size of the AES encrypted block is not currently configurable,
- however the minimum size of a DataMessage in a GarlicClove in a GarlicMessage, with
- overhead, is 128 bytes anyway. A configurable option to increase the minimum size
- may be added in the future.
-
- The message ID is generally set to a random number on transmit and
- appears to be ignored on receive.
-
- In the future, the certificate could possibly be used for a HashCash to "pay" for the routing.
-
-
-
-
TunnelData
-
Description
-
- A message sent from a tunnel's gateway or participant to the next participant or endpoint.
- The data is of fixed length, containing I2NP messages that are fragmented, batched, padded, and encrypted.
-
-{% highlight lang='dataspec' %}
-Same format as `TunnelBuildMessage`, except for the addition of a $num field in front
-and $num number of `BuildRequestRecord`s instead of 8
-
-num ::
- 1 byte `Integer`
- Valid values: 1-8
-
-record size: 528 bytes
-total size: 1+$num*528
-{% endhighlight %}
-
-
Notes
-
-
- This message was introduced in router version 0.7.12, and may not be sent to tunnel participants earlier than that version.
-
- The I2NP message ID for this message must be set according to the tunnel creation specification.
-
-
-
-
-{% endblock %}
diff --git a/i2p2www/spec/i2np.rst b/i2p2www/spec/i2np.rst
new file mode 100644
index 00000000..d00e6630
--- /dev/null
+++ b/i2p2www/spec/i2np.rst
@@ -0,0 +1,1285 @@
+==================
+I2NP Specification
+==================
+.. meta::
+ :lastupdated: January 2015
+ :accuratefor: 0.9.17
+
+
+Overview
+========
+
+The I2P Network Protocol (I2NP), which is sandwiched between I2CP and the
+various I2P transport protocols, manages the routing and mixing of messages
+between routers, as well as the selection of what transports to use when
+communicating with a peer for which there are multiple common transports
+supported.
+
+
+.. _versions:
+
+Protocol Versions
+=================
+
+All routers must publish their I2NP protocol version in the "router.version"
+field in the RouterInfo properties. This version field indicates their level
+of support for various I2NP protocol features, and is not necessarily the
+actual router version.
+
+If alternative (non-Java) routers wish to publish any version information about
+the actual router implementation, they must do so in another property.
+Versions other than those listed below are allowed. Support will be determined
+through a numeric comparison; for example, 0.9.13 implies support for 0.9.12
+features. Note that the "coreVersion" property is not used for determination
+of the I2NP protocol version.
+
+A basic summary of the I2NP protocol versions is as follows. For details, see
+below.
+
+============== ================================================================
+ Version Required I2NP Features
+============== ================================================================
+ 0.9.18 DSM type bits 7-1 ignored
+
+ 0.9.16 RI key certs / ECDSA and EdDSA sig types
+
+ Note: RSA sig types also supported as of this version, but
+ currently unused
+
+ DLM lookup types (DLM flag bits 3-2)
+
+ 0.9.15 Dest/LS key certs w/ EdDSA Ed25519 sig type (if floodfill)
+
+ 0.9.12 Dest/LS key certs w/ ECDSA P-256, P-384, and P-521 sig types (if
+ floodfill)
+
+ Note: RSA sig types also supported as of this version, but
+ currently unused
+
+ Nonzero expiration allowed in RouterAddress
+
+ 0.9.7 Encrypted DSM/DSRM replies supported (DLM flag bit 1) (if
+ floodfill)
+
+ 0.9.6 Nonzero DLM flag bits 7-1 allowed
+
+ 0.9.3 Requires zero expiration in RouterAddress
+
+ 0.9 Supports up to 16 leases in a DSM LS store (6 previously)
+
+ 0.7.12 VTBM and VTBRM message support
+
+ 0.7.10 Floodfill supports encrypted DSM stores
+
+0.7.9 or lower All messages and features not listed above
+
+ 0.6.1.10 TBM and TBRM messages introduced
+
+ Minimum version compatible with current network
+============== ================================================================
+
+Note that there are also transport-related features and compatibility issues;
+see the NTCP and SSU transport documentation for details.
+
+
+.. _structures:
+
+Common structures
+=================
+
+The following structures are elements of multiple I2NP messages.
+They are not complete messages.
+
+.. _struct-i2npmessageheader:
+
+I2NP message header
+-------------------
+
+Description
+```````````
+Common header to all I2NP messages, which contains important information like a checksum, expiration date, etc.
+
+Contents
+````````
+1 byte [Integer]_ specifying the type of this message, followed by a 4 byte
+[Integer]_ specifying the message-id. After that there is an expiration
+[Date]_, followed by a 2 byte [Integer]_ specifying the length of the message
+payload, followed by a [Hash]_, which is truncated to the first byte. After
+that the actual message data follows.
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
+Standard (16 bytes):
+
+ +----+----+----+----+----+----+----+----+
+ |type| msg_id | expiration
+ +----+----+----+----+----+----+----+----+
+ | size |chks|
+ +----+----+----+----+----+----+----+----+
+
+ Short (SSU, 5 bytes):
+
+ +----+----+----+----+----+
+ |type| short_expiration |
+ +----+----+----+----+----+
+
+ type :: `Integer`
+ length -> 1 byte
+ purpose -> identifies the message type (see table below)
+
+ msg_id :: `Integer`
+ length -> 4 bytes
+ purpose -> uniquely identifies this message (for some time at least)
+ This is usually a locally-generated random number, but
+ for outgoing tunnel build messages it may be derived from
+ the incoming message. See below.
+
+ expiration :: `Date`
+ 8 bytes
+ date this message will expire
+
+ short_expiration :: `Integer`
+ 4 bytes
+ date this message will expire (seconds since the epoch)
+
+ size :: `Integer`
+ length -> 2 bytes
+ purpose -> length of the payload
+
+ chks :: `Integer`
+ length -> 1 byte
+ purpose -> checksum of the payload
+ SHA256 hash truncated to the first byte
+
+ data ::
+ length -> $size bytes
+ purpose -> actual message contents
+{% endhighlight %}
+
+Notes
+`````
+* When transmitted over [SSU]_, the 16-byte standard header is not used. Only a
+ 1-byte type and a 4-byte expiration in seconds is included. The message id
+ and size are incorporated into various parts of the SSU data packet format.
+ The checksum is not required since errors are caught in decryption.
+
+* The standard header is also required for I2NP messages contained in other
+ messages and structures (Data, TunnelData, TunnelGateway, and GarlicClove).
+ As of release 0.8.12, to reduce overhead, checksum verification is disabled
+ at some places in the protocol stack. However, for compatibility with older
+ versions, checksum generation is still required. It is a topic for future
+ research to determine points in the protocol stack where the far-end router's
+ version is known and checksum generation can be disabled.
+
+.. _struct-buildrequestrecord:
+
+BuildRequestRecord
+------------------
+
+Description
+```````````
+One Record in a set of multiple records to request the creation of one hop in
+the tunnel. For more details see the tunnel overview [TUNNEL-IMPL]_ and the
+tunnel creation specification [TUNNEL-CREATION]_.
+
+Contents
+````````
+[TunnelId]_ to receive messages on, followed by the [Hash]_ of our
+[RouterIdentity]_. After that the [TunnelId]_ and the [Hash]_ of the next
+router's [RouterIdentity]_ follow.
+
+Definition
+``````````
+ElGamal and AES encrypted:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | encrypted data... |
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+
+ encrypted_data :: ElGamal and AES encrypted data
+ length -> 528
+
+ total length: 528
+{% endhighlight %}
+
+ElGamal encrypted:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | toPeer |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | encrypted data... |
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+
+ toPeer :: First 16 bytes of the SHA-256 Hash of the peer's `RouterIdentity`
+ length -> 16 bytes
+
+ encrypted_data :: ElGamal-2048 encrypted data (see notes)
+ length -> 512
+
+ total length: 528
+{% endhighlight %}
+
+Cleartext:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | receive_tunnel | our_ident |
+ +----+----+----+----+ +
+ | |
+ + +
+ | |
+ + +
+ | |
+ + +----+----+----+----+
+ | | next_tunnel |
+ +----+----+----+----+----+----+----+----+
+ | next_ident |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | layer_key |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | iv_key |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | reply_key |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | reply_iv |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ |flag| request_time | send_msg_id
+ +----+----+----+----+----+----+----+----+
+ | |
+ +----+ +
+ | 29 bytes padding |
+ + +
+ | |
+ + +----+----+
+ | |
+ +----+----+----+----+----+----+
+
+ receive_tunnel :: `TunnelId`
+ length -> 4 bytes
+
+ our_ident :: `Hash`
+ length -> 32 bytes
+
+ next_tunnel :: `TunnelId`
+ length -> 4 bytes
+
+ next_ident :: `Hash`
+ length -> 32 bytes
+
+ layer_key :: `SessionKey`
+ length -> 32 bytes
+
+ iv_key :: `SessionKey`
+ length -> 32 bytes
+
+ reply_key :: `SessionKey`
+ length -> 32 bytes
+
+ reply_iv :: data
+ length -> 16 bytes
+
+ flag :: `Integer`
+ length -> 1 byte
+
+ request_time :: `Integer`
+ length -> 4 bytes
+ Hours since the epoch, i.e. current time / 3600
+
+ send_message_id :: `Integer`
+ length -> 4 bytes
+
+ padding :: Data
+ length -> 29 bytes
+ source -> random
+
+ total length: 222
+{% endhighlight %}
+
+Notes
+`````
+* In the 512-byte encrypted record, the ElGamal data contains bytes 1-256 and
+ 258-513 of the 514-byte ElGamal encrypted block [CRYPTO-ELG]_. The two
+ padding bytes from the block (the zero bytes at locations 0 and 257) are
+ removed.
+
+* See the tunnel creation specification [TUNNEL-CREATION]_ for details on field
+ contents.
+
+.. _struct-buildresponserecord:
+
+BuildResponseRecord
+-------------------
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
+Encrypted:
+
+ bytes 0-527 :: AES-encrypted record (note: same size as `BuildRequestRecord`)
+
+ Unencrypted:
+
+ +----+----+----+----+----+----+----+----+
+ | |
+ + +
+ | |
+ + SHA-256 Hash of following bytes +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | random data... |
+ ~ ~
+ | |
+ + +----+
+ | | ret|
+ +----+----+----+----+----+----+----+----+
+
+ bytes 0-31 :: SHA-256 Hash of bytes 32-527
+ bytes 32-526 :: random data
+ byte 527 :: reply
+
+ total length: 528
+{% endhighlight %}
+
+Notes
+`````
+* The random data field could, in the future, be used to return congestion or
+ peer connectivity information back to the requestor.
+
+* See the tunnel creation specification [TUNNEL-CREATION]_ for details on the
+ reply field.
+
+.. _struct-garlicclove:
+.. _Garlic Cloves:
+
+GarlicClove
+-----------
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
+Unencrypted:
+
+ +----+----+----+----+----+----+----+----+
+ | Delivery Instructions |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | I2NP Message |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | Clove ID | Expiration
+ +----+----+----+----+----+----+----+----+
+ | Certificate |
+ +----+----+----+----+----+----+----+
+
+ Delivery Instructions :: as defined below
+ Length varies but is typically 1, 33, or 37 bytes
+
+ I2NP Message :: Any I2NP Message
+
+ Clove ID :: 4 byte `Integer`
+
+ Expiration :: `Date` (8 bytes)
+
+ Certificate :: Always NULL in the current implementation (3 bytes total, all zeroes)
+{% endhighlight %}
+
+Notes
+`````
+* Cloves are never fragmented. When used in a Garlic Clove, the first bit of
+ the Delivery Instructions flag byte specifies encryption. If this bit is 0,
+ the clove is not encrypted. If 1, the clove is encrypted, and a 32 byte
+ Session Key immediately follows the flag byte. Clove encryption is not fully
+ implemented.
+
+* See also the garlic routing specification [GARLIC]_.
+
+* Maximum length is a function of the total length of all the cloves and the
+ maximum length of the GarlicMessage.
+
+* In the future, the certificate could possibly be used for a HashCash to "pay"
+ for the routing.
+
+* The message can be any I2NP message (including a GarlicMessage, although that
+ is not used in practice). The messages used in practice are DataMessage,
+ DeliveryStatusMessage, and DatabaseStoreMessage.
+
+* The Clove ID is generally set to a random number on transmit and is checked
+ for duplicates on receive (same message ID space as top-level Message IDs)
+
+.. _struct-garlicclovedeliveryinstructions:
+
+Garlic Clove Delivery Instructions
+----------------------------------
+
+This specification is for Delivery Instructions inside Garlic Cloves only.
+Note that "Delivery Instructions" are also used inside Tunnel Messages, where
+the format is significantly different. See the Tunnel Message documentation
+[TMDI]_ for details. Do NOT use the following specification for Tunnel Message
+Delivery Instructions!
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ |flag| |
+ +----+ +
+ | |
+ + Session Key (optional) +
+ | |
+ + +
+ | |
+ + +----+----+----+----+--------------+
+ | | |
+ +----+ +
+ | |
+ + To Hash (optional) +
+ | |
+ + +
+ | |
+ + +----+----+----+----+--------------+
+ | | Tunnel ID (opt) | Delay (opt)
+ +----+----+----+----+----+----+----+----+
+ |
+ +----+
+
+ flag ::
+ 1 byte
+ Bit order: 76543210
+ bit 7: encrypted? Unimplemented, always 0
+ If 1, a 32-byte encryption session key is included
+ bits 6-5: delivery type
+ 0x0 = LOCAL, 0x01 = DESTINATION, 0x02 = ROUTER, 0x03 = TUNNEL
+ bit 4: delay included? Not fully implemented, always 0
+ If 1, four delay bytes are included
+ bits 3-0: reserved, set to 0 for compatibility with future uses
+
+ Session Key ::
+ 32 bytes
+ Optional, present if encrypt flag bit is set.
+ Unimplemented, never set, never present.
+
+ To Hash ::
+ 32 bytes
+ Optional, present if delivery type is DESTINATION, ROUTER, or TUNNEL
+ If DESTINATION, the SHA256 Hash of the destination
+ If ROUTER, the SHA256 Hash of the router
+ If TUNNEL, the SHA256 Hash of the gateway router
+
+ Tunnel ID :: `TunnelId`
+ 4 bytes
+ Optional, present if delivery type is TUNNEL
+ The destination tunnel ID
+
+ Delay :: `Integer`
+ 4 bytes
+ Optional, present if delay included flag is set
+ Not fully implemented. Specifies the delay in seconds.
+
+ Total length: Typical length is:
+ 1 byte for LOCAL delivery;
+ 33 bytes for ROUTER / DESTINATION delivery;
+ 37 bytes for TUNNEL delivery
+{% endhighlight %}
+
+
+Messages
+========
+
+========================= ====
+ Message Type
+========================= ====
+DatabaseStore_ 1
+DatabaseLookup_ 2
+DatabaseSearchReply_ 3
+DeliveryStatus_ 10
+Garlic_ 11
+TunnelData_ 18
+TunnelGateway_ 19
+Data_ 20
+TunnelBuild_ 21
+TunnelBuildReply_ 22
+VariableTunnelBuild_ 23
+VariableTunnelBuildReply_ 24
+========================= ====
+
+.. _msg-databasestore:
+
+DatabaseStore
+-------------
+
+Description
+```````````
+An unsolicited database store, or the response to a successful DatabaseLookup_ Message
+
+Contents
+````````
+An uncompressed LeaseSet or a compressed RouterInfo
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
+with reply token:
+ +----+----+----+----+----+----+----+----+
+ | SHA256 Hash as key |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ |type| reply token | reply_tunnelId
+ +----+----+----+----+----+----+----+----+
+ | SHA256 of the gateway RouterInfo |
+ +----+ +
+ | |
+ + +
+ | |
+ + +
+ | |
+ + +----+----+----+----+----+----+----+
+ | | data ...
+ +----+-//
+
+ with reply token == 0:
+ +----+----+----+----+----+----+----+----+
+ | SHA256 Hash as key |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ |type| 0 | data ...
+ +----+----+----+----+----+-//
+
+ key ::
+ 32 bytes
+ SHA256 hash
+
+ type ::
+ 1 byte
+ type identifier
+ bit 0:
+ 0 `RouterInfo`
+ 1 `LeaseSet`
+ bits 7-1:
+ Through release 0.9.17, must be 0
+ As of release 0.9.18, ignored, reserved for future options, set to 0 for compatibility
+
+ reply token ::
+ 4 bytes
+ If greater than zero, a `DeliveryStatusMessage`
+ is requested with the Message ID set to the value of the Reply Token.
+ A floodfill router is also expected to flood the data to the closest floodfill peers
+ if the token is greater than zero.
+
+ reply_tunnelId ::
+ 4 byte `TunnelId`
+ Only included if reply token > 0
+ This is the `TunnelId` of the inbound gateway of the tunnel the response should be sent to
+ If $reply_tunnelId is zero, the reply is sent directy to the reply gateway router.
+
+ reply gateway ::
+ 32 bytes
+ Hash of the `RouterInfo` entry to reach the gateway
+ Only included if reply token > 0
+ If $reply_tunnelId is nonzero, this is the router hash of the inbound gateway
+ of the tunnel the response should be sent to.
+ If $reply_tunnelId is zero, this is the router hash the response should be sent to.
+
+ data ::
+ If type == 0, data is a 2-byte `Integer` specifying the number of bytes that follow,
+ followed by a gzip-compressed `RouterInfo`.
+ If type == 1, data is an uncompressed `LeaseSet`.
+{% endhighlight %}
+
+Notes
+`````
+* For security, the reply fields are ignored if the message is received down a
+ tunnel.
+
+* The key is the "real" hash of the RouterIdentity or Destination, NOT the
+ routing key.
+
+.. _msg-databaselookup:
+
+DatabaseLookup
+--------------
+
+Description
+```````````
+A request to look up an item in the network database. The response is either a
+DatabaseStore_ or a DatabaseSearchReply_.
+
+Contents
+````````
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | SHA256 hash as the key to look up |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | SHA256 hash of the routerInfo |
+ + who is asking, or the gateway to +
+ | send the reply to |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ |flag| reply_tunnelId | size | |
+ +----+----+----+----+----+----+----+ +
+ | SHA256 of $key1 to exclude |
+ + +
+ | |
+ + +
+ | |
+ + +----+
+ | | |
+ +----+----+----+----+----+----+----+ +
+ | SHA256 of $key2 to exclude |
+ + +
+ ~ ~
+ + +----+
+ | | |
+ +----+----+----+----+----+----+----+ +
+ | |
+ + +
+ | Session key if reply encryption |
+ + was requested +
+ | |
+ + +----+
+ | |tags|
+ +----+----+----+----+----+----+----+----+
+ | |
+ + +
+ | Session tags if reply encryption |
+ + was requested +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+
+ key ::
+ 32 bytes
+ SHA256 hash of the object to lookup
+
+ from ::
+ 32 bytes
+ if deliveryFlag == 0, the SHA256 hash of the routerInfo entry this
+ request came from (to which the reply should be
+ sent)
+ if deliveryFlag == 1, the SHA256 hash of the reply tunnel gateway (to
+ which the reply should be sent)
+
+ flags ::
+ 1 byte
+ bit order: 76543210
+ bit 0: deliveryFlag
+ 0 => send reply directly
+ 1 => send reply to some tunnel
+ bit 1: encryptionFlag
+ through release 0.9.5, must be set to 0
+ as of release 0.9.6, ignored
+ as of release 0.9.7:
+ 0 => send unencrypted reply
+ 1 => send AES encrypted reply using enclosed key and tag
+ bits 3-2: lookup type flags
+ through release 0.9.5, must be set to 00
+ as of release 0.9.6, ignored
+ as of release 0.9.16:
+ 00 => normal lookup, return `RouterInfo` or `LeaseSet` or
+ `DatabaseSearchReplyMessage`
+ 01 => LS lookup, return `LeaseSet` or
+ `DatabaseSearchReplyMessage`
+ 10 => RI lookup, return `RouterInfo` or
+ `DatabaseSearchReplyMessage`
+ 11 => exploration lookup, return `DatabaseSearchReplyMessage`
+ containing non-floodfill routers only (replaces an
+ excludedPeer of all zeroes)
+ bits 7-4:
+ through release 0.9.5, must be set to 0
+ as of release 0.9.6, ignored, set to 0 for compatibility with
+ future uses and with older routers
+
+ reply_tunnelId ::
+ 4 byte `TunnelID`
+ only included if deliveryFlag == 1
+ tunnelId of the tunnel to send the reply to
+
+ size ::
+ 2 byte `Integer`
+ valid range: 0-512
+ number of peers to exclude from the `DatabaseSearchReplyMessage`
+
+ excludedPeers ::
+ $size SHA256 hashes of 32 bytes each (total $size*32 bytes)
+ if the lookup fails, these peers are requested to be excluded
+ from the list in the `DatabaseSearchReplyMessage`.
+ if excludedPeers includes a hash of all zeroes, the request is
+ exploratory, and the `DatabaseSearchReplyMessage` is requested
+ to list non-floodfill routers only.
+
+ reply_key ::
+ 32 byte `SessionKey`
+ only included if encryptionFlag == 1, only as of release 0.9.7
+
+ tags ::
+ 1 byte `Integer`
+ valid range: 1-32 (typically 1)
+ the number of reply tags that follow
+ only included if encryptionFlag == 1, only as of release 0.9.7
+
+ reply_tags ::
+ one or more 32 byte `SessionTag`s (typically one)
+ only included if encryptionFlag == 1, only as of release 0.9.7
+{% endhighlight %}
+
+Notes
+`````
+* Prior to 0.9.16, the key may be for a RouterInfo or LeaseSet, as they are in
+ the same key space, and there was no flag to request only a particular type
+ of data.
+
+* Encryption flag, reply key, and reply tags as of release 0.9.7.
+
+* Encrypted replies are only useful when the response is through a tunnel.
+
+* The number of included tags could be greater than one if alternative DHT
+ lookup strategies (for example, recursive lookups) are implemented.
+
+* The lookup key and exclude keys are the "real" hashes, NOT routing keys.
+
+.. _msg-databasesearchreply:
+
+DatabaseSearchReply
+-------------------
+
+Description
+```````````
+The response to a failed DatabaseLookup_ Message
+
+Contents
+````````
+A list of router hashes closest to the requested key
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | SHA256 hash as query key |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | num| peer_hashes |
+ +----+ +
+ | |
+ + +
+ | |
+ + +
+ | |
+ + +----+----+----+----+----+----+----+
+ | | from |
+ +----+ +
+ | |
+ + +
+ | |
+ + +
+ | |
+ + +----+----+----+----+----+----+----+
+ | |
+ +----+
+
+ key ::
+ 32 bytes
+ SHA256 of the object being searched
+
+ num ::
+ 1 byte `Integer`
+ number of peer hashes that follow, 0-255
+
+ peer_hashes ::
+ $num SHA256 hashes of 32 bytes each (total $num*32 bytes)
+ SHA256 of the `RouterIdentity` that the other router thinks is close
+ to the key
+
+ from ::
+ 32 bytes
+ SHA256 of the `RouterInfo` of the router this reply was sent from
+{% endhighlight %}
+
+Notes
+`````
+* The 'from' hash is unauthenticated and cannot be trusted.
+
+* The returned peer hashes are not necessarily closer to the key than the
+ router being queried.
+
+* Typical number of hashes returned: 3
+
+* The lookup key, peer hashes, and from hash are "real" hashes, NOT routing
+ keys.
+
+.. _msg-deliverystatus:
+
+DeliveryStatus
+--------------
+
+Description
+```````````
+A simple message acknowledgment. Generally created by the message originator,
+and wrapped in a Garlic Message with the message itself, to be returned by the
+destination.
+
+Contents
+````````
+The ID of the delivered message, and the creation or arrival time.
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+----+----+----+----+
+ | msg_id | time_stamp |
+ +----+----+----+----+----+----+----+----+----+----+----+----+
+
+ msg_id :: `Integer`
+ 4 bytes
+ unique ID of the message we deliver the DeliveryStatus for (see
+ `I2NPMessageHeader` for details)
+
+ time_stamp :: `Date`
+ 8 bytes
+ time the message was successfully created or delivered
+{% endhighlight %}
+
+Notes
+`````
+* It appears that the time stamp is always set by the creator to the current
+ time. However there are several uses of this in the code, and more may be
+ added in the future.
+
+* This message is also used as a session established confirmation in SSU
+ [SSU-ED]_. In this case, the message ID is set to a random number, and the
+ "arrival time" is set to the current network-wide ID, which is 2 (i.e.
+ 0x0000000000000002).
+
+.. _msg-garlic:
+
+Garlic
+------
+
+Description
+```````````
+Used to wrap multiple encrypted I2NP Messages
+
+Contents
+````````
+When decrypted, a series of `Garlic Cloves`_.
+
+Encrypted:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | length | data |
+ +----+----+----+----+ +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+
+ length ::
+ 4 byte `Integer`
+ number of bytes that follow 0 - 64 KB
+
+ data ::
+ $length bytes
+ ElGamal encrypted data
+{% endhighlight %}
+Unencrypted data:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | num| clove 1 |
+ +----+ +
+ | |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | clove 2 ... |
+ ~ ~
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | Certificate | Message_ID |
+ +----+----+----+----+----+----+----+----+
+ Expiration |
+ +----+----+----+----+----+----+----+
+
+ num ::
+ 1 byte `Integer` number of `GarlicClove`s to follow
+
+ clove :: a `GarlicClove`
+
+ Certificate :: always NULL in the current implementation (3 bytes total, all zeroes)
+
+ Message_ID :: 4 byte `Integer`
+
+ Expiration :: `Date` (8 bytes)
+{% endhighlight %}
+
+Notes
+`````
+* When unencrypted, data contains one or more `Garlic Cloves`_.
+
+* The AES encrypted block is padded to a minimum of 128 bytes; with the 32-byte
+ Session Tag the minimum size of the encrypted message is 160 bytes; with the
+ 4 length bytes the minimum size of the Garlic Message is 164 bytes.
+
+* Actual max length is less than 64 KB; see [I2NP]_.
+
+* See also the ElGamal/AES specification [ELG-AES]_.
+
+* See also the garlic routing specification [GARLIC]_.
+
+* The 128 byte minimum size of the AES encrypted block is not currently
+ configurable, however the minimum size of a DataMessage in a GarlicClove in a
+ GarlicMessage, with overhead, is 128 bytes anyway. A configurable option to
+ increase the minimum size may be added in the future.
+
+* The message ID is generally set to a random number on transmit and appears to
+ be ignored on receive.
+
+* In the future, the certificate could possibly be used for a HashCash to "pay"
+ for the routing.
+
+.. _msg-tunneldata:
+
+TunnelData
+----------
+
+Description
+```````````
+A message sent from a tunnel's gateway or participant to the next participant
+or endpoint. The data is of fixed length, containing I2NP messages that are
+fragmented, batched, padded, and encrypted.
+
+Contents
+````````
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | tunnnelID | data |
+ +----+----+----+----+ |
+ | |
+ ~ ~
+ ~ ~
+ | |
+ + +----+----+----+----+
+ | |
+ +----+----+----+----+
+
+ tunnelId ::
+ 4 byte `TunnelId`
+ identifies the tunnel this message is directed at
+
+ data ::
+ 1024 bytes
+ payload data.. fixed to 1024 bytes
+{% endhighlight %}
+
+Notes
+`````
+* The I2NP message ID for this message is set to a new random number at each
+ hop.
+
+* See also the Tunnel Message Specification [TUNNEL-MSG]_
+
+.. _msg-tunnelgateway:
+
+TunnelGateway
+-------------
+
+Description
+```````````
+Wraps another I2NP message to be sent into a tunnel at the tunnel's inbound gateway.
+
+Contents
+````````
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+-//
+ | tunnelId | length | data...
+ +----+----+----+----+----+----+----+-//
+
+ tunnelId ::
+ 4 byte `TunnelId`
+ identifies the tunnel this message is directed at
+
+ length ::
+ 2 byte `Integer`
+ length of the payload
+
+ data ::
+ $length bytes
+ actual payload of this message
+{% endhighlight %}
+
+Notes
+`````
+* The payload is an I2NP message with a standard 16-byte header.
+
+.. _msg-data:
+
+Data
+----
+
+Description
+```````````
+Used by Garlic Messages and Garlic Cloves to wrap arbitrary data.
+
+Contents
+````````
+A length Integer, followed by opaque data.
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+-//-+
+ | length | data... |
+ +----+----+----+----+----+-//-+
+
+ length ::
+ 4 bytes
+ length of the payload
+
+ data ::
+ $length bytes
+ actual payload of this message
+{% endhighlight %}
+
+.. _msg_TunnelBuild:
+
+TunnelBuild
+-----------
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | Record 0 ... |
+
+ | |
+ +----+----+----+----+----+----+----+----+
+ | Record 1 ... |
+
+ ~ ..... ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | Record 7 ... |
+
+ | |
+ +----+----+----+----+----+----+----+----+
+
+ Just 8 `BuildRequestRecord`s attached together
+ record size: 528 bytes
+ total size: 8*528 = 4224 bytes
+{% endhighlight %}
+
+Notes
+`````
+* See also the tunnel creation specification [TUNNEL-CREATION]_.
+
+* The I2NP message ID for this message must be set according to the tunnel
+ creation specification.
+
+.. _msg-tunnelbuildreply:
+
+TunnelBuildReply
+----------------
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
+Same format as `TunnelBuildMessage`, with `BuildResponseRecord`s
+{% endhighlight %}
+
+Notes
+`````
+* See also the tunnel creation specification [TUNNEL-CREATION]_.
+
+* The I2NP message ID for this message must be set according to the tunnel
+ creation specification.
+
+.. _msg-variabletunnelbuild:
+
+VariableTunnelBuild
+-------------------
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | num| BuildRequestRecords...
+ +----+----+----+----+----+----+----+----+
+
+ Same format as `TunnelBuildMessage`, except for the addition of a $num field
+ in front and $num number of `BuildRequestRecord`s instead of 8
+
+ num ::
+ 1 byte `Integer`
+ Valid values: 1-8
+
+ record size: 528 bytes
+ total size: 1+$num*528
+{% endhighlight %}
+
+Notes
+`````
+* This message was introduced in router version 0.7.12, and may not be sent to
+ tunnel participants earlier than that version.
+
+* See also the tunnel creation specification [TUNNEL-CREATION]_.
+
+* The I2NP message ID for this message must be set according to the tunnel
+ creation specification.
+
+msg_VariableTunnelBuildReply:
+
+VariableTunnelBuildReply
+------------------------
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | num| BuildResponseRecords...
+ +----+----+----+----+----+----+----+----+
+
+ Same format as `VariableTunnelBuildMessage`, with `BuildResponseRecord`s.
+{% endhighlight %}
+
+Notes
+`````
+* This message was introduced in router version 0.7.12, and may not be sent to
+ tunnel participants earlier than that version.
+
+* See also the tunnel creation specification [TUNNEL-CREATION]_.
+
+* The I2NP message ID for this message must be set according to the tunnel
+ creation specification.
+
+
+References
+==========
+
+.. [CRYPTO-ELG]
+ {{ site_url('docs/how/cryptography', True) }}#elgamal
+
+.. [Date]
+ {{ spec_url('common-structures') }}#type-date
+
+.. [ElG-AES]
+ {{ site_url('docs/how/elgamal-aes', True) }}
+
+.. [GARLIC]
+ {{ site_url('docs/how/garlic-routing', True) }}
+
+.. [Hash]
+ {{ spec_url('common-structures') }}#struct-hash
+
+.. [I2NP]
+ {{ site_url('docs/protocol/i2np', True) }}
+
+.. [Integer]
+ {{ spec_url('common-structures') }}#type-integer
+
+.. [RouterIdentity]
+ {{ spec_url('common-structures') }}#struct-routeridentity
+
+.. [SSU]
+ {{ site_url('docs/transport/ssu', True) }}
+
+.. [SSU-ED]
+ {{ site_url('docs/transport/ssu', True) }}#establishDirect
+
+.. [TMDI]
+ {{ spec_url('tunnel-message') }}#struct-tunnelmessagedeliveryinstructions
+
+.. [TUNNEL-CREATION]
+ {{ spec_url('tunnel-creation') }}
+
+.. [TUNNEL-MSG]
+ {{ spec_url('tunnel-message') }}
+
+.. [TUNNEL-IMPL]
+ {{ site_url('docs/tunnels/implementation', True) }}
+
+.. [TunnelId]
+ {{ spec_url('common-structures') }}#tunnelid
diff --git a/i2p2www/spec/plugin.html b/i2p2www/spec/plugin.html
deleted file mode 100644
index 1cf789a9..00000000
--- a/i2p2www/spec/plugin.html
+++ /dev/null
@@ -1,539 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}I2P Plugin Specification{% endblock %}
-{% block lastupdated %}May 2015{% endblock %}
-{% block accuratefor %}0.9.20{% endblock %}
-{% block content %}
-
Overview
-
-This document specifies
-a .xpi2p file format (like the Firefox .xpi), but with a simple
-plugin.config description file instead of an XML install.rdf file.
-This file format is used for both initial plugin installs and plugin updates.
-
-In addition, this document provides a brief overview of how the router installs plugins,
-and policies and guidelines for plugin developers.
-
-The basic .xpi2p file format is the same as a i2pupdate.sud file
-(the format used for router updates),
-but the installer will let the user install the
-addon even if it doesn't know the signer's key yet.
-
-As of release 0.9.15, the su3 file format is supported and is preferred.
-This format enables stronger signing keys.
-
-
-
-The standard directory structure will let users install the following types of addons:
-
-
- console webapps
-
- new eepsite with cgi-bin, webapps
-
- console themes
-
- console translations
-
- Java programs
-
- Java programs in a separate JVM
-
- Any shell script or program
-
-
-
-A plugin installs all its files in ~/.i2p/plugins/name/ (%APPDIR%\I2P\plugins\name\ on Windows). The installer will prevent
-installation anywhere else, although the plugin can access libraries elsewhere when running.
-
-
-This should be viewed only as a way to make installation, uninstallation, and upgrading easier,
-and to lessen basic inter-plugin conflicts.
-
-
-There is essentially no security model once the plugin is running, however. The plugin runs
-in the same JVM and with the same permissions as the router, and has full access to the file
-system, the router, executing external programs, etc.
-
-
-The following four are required properties.
-The first three must be identical to those in the installed plugin for an update plugin.
-
-
- name (will be installed in this directory name)
- For native plugins, you may want separate names in different packages -
- foo-windows and foo-linux, for example
-
- key (DSA public key as 172 B64 chars ending with '=')
- Omit for SU3 format.
-
- signer (yourname@mail.i2p recommended)
-
- version (must be in a format VersionComparator can parse, e.g. 1.2.3-4)
- 16 bytes max (must match sud version)
- Valid number separators are '.', '-', and '_'
- This must be greater than the one in the installed plugin for an update plugin.
-
-
-
- Values for the following properties are displayed on /configclients in the router console if present:
-
- date (Java time - long int)
- author (yourname@mail.i2p recommended)
- websiteURL (http://foo.i2p/)
- updateURL (http://foo.i2p/foo.xpi2p)
- The update checker will check bytes 41-56 at this URL
- to determine whether a newer version is available
- ( Should the checker fetch with ?currentVersion=1.2.3?...
- No. If the dev wants to have the URL contain the current version, just
- set it in the config file, and remember to change it every release)
- updateURL.su3 (http://foo.i2p/foo.su3)
- The location of the su3-format update file, as of 0.9.15
- description
- description_xx (for language xx)
- license
- disableStop=true
- Default false.
- If true, the stop button will not be shown. Use this if there are no
- webapps and no clients with stopargs.
-
-
- The following properties are used to add a link on the console summary bar:
-
-
- consoleLinkName (will be added to summary bar)
- consoleLinkName_xx (for language xx)
- consoleLinkURL (/appname/index.jsp)
- consoleLinkTooltip (supported as of 0.7.12-6)
- consoleLinkTooltip_xx (lang xx as of 0.7.12-6)
-
-
-
- The following optional property may be used to add a custom icon on the console:
-
-
- console-icon (supported as of 0.9.20) Only for webapps.
- A path within the webapp to a 32x32 image, e.g. /icon.png
- Applies to all webapps in the plugin.
-
-
-
- The following properties are used by the plugin installer:
-
-
- type (app/theme/locale/webapp/...) (unimplemented, probably not necessary)
- min-i2p-version
- max-i2p-version
- min-java-version
- min-jetty-version (supported as of 0.8.13, use 6 for Jetty 6 webapps)
- max-jetty-version (supported as of 0.8.13, use 5.99999 for Jetty 5 webapps)
- required-platform-OS (unimplemented - perhaps will be displayed only, not verified)
- other-requirements (unimplemented e.g. python x.y - not verified by the installer, just displayed to the user)
- dont-start-at-install=true
- Default false.
- Won't start the plugin when it is installed or updated. On initial installation,
- configures the plugin so the user must manually start it. An update will not change
- the user's preference to start it if they choose to do so.
- router-restart-required=true
- Default false.
- This does not restart the router or the plugin on an update, it just informs the user that a restart is required.
- It has no effect on initial plugin installation.
- update-only=true
- Default false.
- If true, will fail if an installation does not exist.
- install-only=true
- Default false.
- If true, will fail if an installation exists.
- min-installed-version (to update over, if an installation exists)
- max-installed-version (to update over, if an installation exists)
- depends=plugin1,plugin2,plugin3 (unimplemented - is this too hard? proposed by sponge)
- depends-version=0.3.4,,5.6.7 (unimplemented)
-
-
- The following property is used for translation plugins:
-
- langs=xx,yy,Klingon,... (unimplemented) (yy is the country flag)
-
-
-
-Application Directories and Files
-
-
-Each of the following directories or files is optional, but something must be there or it won't do anything:
-
-
-console/
- locale/
- Only jars containing new resource bundles (translations) for apps in the base I2P installation.
- Bundles for this plugin should go inside console/webapp/foo.war or lib/foo.jar
-
- themes/
- New themes for the router console
- Place each theme in a subdirectory.
-
- webapps/
- (See important notes below about webapps)
- .wars
- These will be run at install time unless disabled in webapps.config
- The war name does not have to be the same as the plugin name.
- Do not duplicate war names in the base I2P installation.
-
- webapps.config
- Same format as router's webapps.config
- Also used to specify additional jars in $PLUGIN/lib/ or $I2P/lib for the webapp classpath,
- with webapps.warname.classpath=$PLUGIN/lib/foo.jar,$I2P/lib/bar.jar
- NOTE: Currently, the classpath line is only loaded if the warname is
- the same as the plugin name.
- NOTE: Prior to router version 0.7.12-9, the router looked for plugin.warname.startOnLoad instead
- of webapps.warname.startOnLoad. For compatibility with older router versions, a plugin
- wishing to disable a war should include both lines.
-
-eepsite/
- (See important notes below about eepsites)
- cgi-bin/
- docroot/
- logs/
- webapps/
- jetty.xml
- The installer will have to do variable substitution in here to set the path
- The location and name of this file doesn't really matter, as long as it is set in
- clients.config - it may be more convenient to be up one level from here
- (that's what the zzzot plugin does)
-
-lib/
- Put any jars here, and specify them in a classpath line in console/webapps.config and/or clients.config
-
-
-clients.config file
-
-
-This file is optional,
-and specifies clients that will be run when a plugin is started.
-It uses the same format as the router's clients.config file.
-See the clients.config configuration file specification
-for more information about the format and important details
-about how clients are started and stopped.
-
-
- property clientApp.0.stopargs=foo bar stop baz
- If present, the class will be called with these args to stop the client
- All stop tasks are called with zero delay
- Note: The router can't tell if your unmanaged clients are running or not.
- Each should handle stopping an app that isn't running without complaint.
- That probably goes for starting a client that is already started too.
- property clientApp.0.uninstallargs=foo bar uninstall baz
- If present, the class will be called with these args just before deleting $PLUGIN
- All uninstall tasks are called with zero delay
- property clientApp.0.classpath=$I2P/lib/foo.bar,$PLUGIN/lib/bar.jar
- The plugin runner will do variable substitution in the args and stopargs lines as follows:
- $I2P => i2p base installation dir;
- $CONFIG => i2p config dir (typically ~/.i2p)
- $PLUGIN => this plugin's installation dir (typically ~/.i2p/plugins/appname)
- (See important notes below about running shell scripts or external programs)
-
-
-
-
Plugin installer tasks
-This lists what happens when a plugin is installed by I2P.
-
-
-
The .xpi2p file is downloaded.
-
The .sud signature is verified against stored keys.
- As of release 0.9.14.1,
- if there is no matching key, the installation fails, unless an advanced router property is set to allow all keys.
-
Verify the integrity of the zip file.
-
Extract the plugin.config file.
-
Verify the I2P version, to make sure the plugin will work.
-
Check that webapps don't duplicate the existing $I2P applications.
-
Stop the existing plugin (if present).
-
Verify that the install directory does not exist yet if update=false, or ask to overwrite.
-
Verify that the install directory does exist if update=true, or ask to create.
-
Unzip the plugin in to appDir/plugins/name/
-
Add the plugin to plugins.config
-
-
-
-Plugin starter tasks
-
-This lists what happens when plugins are started.
-First, plugins.config is checked to see which plugins need to be started.
-For each plugin:
-
-
Check clients.config, and load and start each item (add the configured jars to the classpath).
-
Check console/webapp and console/webapp.config. Load and start required items (add the configured jars to the classpath).
-
Add console/locale/foo.jar to the translation classpath if present.
-
Add console/theme to the theme search path if present.
-
Add the summary bar link.
-
-
-
-Console webapp notes
-
-
-Console webapps with background tasks should implement a ServletContextListener
-(see seedless or i2pbote for examples), or override destroy() in the servlet,
-so that they can be stopped.
-As of router version 0.7.12-3, console webapps will always be stopped before they
-are restarted, so you do not need to worry about multiple instances,
-as long as you do this.
-Also as of router version 0.7.12-3, console webapps will be stopped at router shutdown.
-
-Don't bundle library jars in the webapp; put them in lib/ and put a classpath in webapps.config.
-Then you can make separate install and update plugins, where the update plugin does not
-contain the library jars.
-
-Don't include .java or .jsp files; otherwise jetty will recompile them at installation.
-
-For now, a webapp needing to add classpath files in $PLUGIN must be the same name as the plugin.
-For example, a webapp in plugin foo must be named foo.war.
-
-
-
-Eepsite notes
-
-
-It isn't clear how to have a plugin install to an existing eepsite.
-The router has no hook to the eepsite, and it may or may not be running,
-and there may be more than one.
-Better is to start your own Jetty instance and I2PTunnel instance,
-for a brand new eepsite.
-
- It can instantiate a new I2PTunnel (somewhat like the i2ptunnel CLI does),
- but it won't appear in the i2ptunnel gui of course, that's a different instance.
-But that's ok. Then you can start and stop i2ptunnel and jetty together.
-
-So don't count on the router to automatically merge this with some existing eepsite. It probably won't happen.
-Start a new I2PTunnel and Jetty from clients.config.
-The best examples of this are the zzzot and pebble plugins,
-available at zzz's plugins page.
-
-How to get path substitution into jetty.xml?
-See zzzot and pebble plugins for examples.
-
-
-
-Client start/stop notes
-
-
-As of release 0.9.4, the router supports "managed" plugin clients.
-Managed plugin clients are instantiated and started by the ClientAppManager.
-The ClientAppManager maintains a reference to the client and receives updates on the client's state.
-Managed plugin client are preferred, as it is much easier to implement state tracking
-and to start and stop a client. It also is much easier to avoid static references in the client code
-which could lead to excessive memory usage after a client is stopped.
-See the clients.config configuration file specification
-for more information on writing a managed client.
-
-For "unmanaged" plugin clients,
-The router has no way to monitor the state of clients started via clients.config.
-The plugin author should handle multiple start or stop calls gracefully, if at all possible,
-by keeping a static state table, or using PID files, etc.
-Avoid logging or exceptions on multiple starts or stops.
-This also goes for a stop call without a previous start.
-As of router version 0.7.12-3, plugins will be stopped at router shutdown,
-which means that all clients with stopargs in clients.config will be called,
-whether or not they were previously started.
-
-
-
-To work on both Windows and Linux, write a small Java class that checks the OS type, then
-runs ShellCommand on either the .bat or a .sh file you provide.
-
-External programs won't be stopped when the router stops, and a second copy will
-fire up when the router starts. To work around this, you could
-write a wrapper class or shell script that does the usual storage of the PID
-in a PID file, and check for it on start.
-
-
-
-
-
-Other plugin guidelines
-
-
-
-See i2p.scripts branch or any of the sample plugins on zzz's page for a xpi2p file generator to make it easy.
-
-Pack200 of jars and wars is strongly recommended for plugins, it generally shrinks plugins by 60-65%.
-See any of the sample plugins on zzz's page for an example.
-Pack200 unpacking is supported on routers 0.7.11-5 or higher, which is essentially all routers that
-support plugins at all.
-
-
- Plugins should not attempt to write anywhere in $I2P as it may be readonly, and that isn't good policy anyway.
-
- Plugins may write to $CONFIG but keeping files in $PLUGIN only is recommended.
-All files in $PLUGIN will be deleted at uninstall.
-Files elsewhere will not be deleted at uninstall unless the plugin does it explicitly
-with a client in clients.config run with uninstallargs.
-If the user may want to save data after uninstallation, the uninstallargs hook
-could ask.
-
-
- $CWD may be anywhere; do not assume it is in a particular place, do not attempt to read or write files relative to $CWD.
-
- Java programs should find out where they are with the directory getters in I2PAppContext.
-
- Plugin directory is I2PAppContext.getGlobalContext().getAppDir().getAbsolutePath() + "/plugins/" + appname,
- or put a $PLUGIN argument in the args line in clients.config.
-There is no reliable way to find the i2p install or config or plugin directory without using the
-context API in i2p.jar.
-
- See Howto for info on generating signing keys and generating/verifying keys and sud files
-
- All config files must be UTF-8.
-
- To run in a separate JVM, use ShellCommand with java -cp foo:bar:baz my.main.class arg1 arg2 arg3.
-Of course, it will be a lot harder to stop the plugin then...
-But with some trickery with PID files it should be possible.
-
- As an alternative to stopargs in clients.config,
- a Java client may register a shutdown hook with I2PAppContext.addShutdownTask().
- But this wouldn't shut down a plugin when upgrading, so stopargs is recommended.
- Also, set all created threads to daemon mode.
-
- Do not include classes duplicating those in the standard installation. Extend the classes if necessary.
-
- Beware of the different classpath definitions in wrapper.config between old and new installations -
- see classpath section below.
-
- Clients will reject duplicate keys with different keynames, and duplicate keynames with different keys,
- and different keys or keynames in upgrade packages. Safeguard your keys. Only generate them once.
-
- Do not modify the plugin.config file at runtime as it will be overwritten on upgrade.
- Use a different config file in the directory for storing runtime configuration.
-
- In general, plugins should not require access to $I2P/lib/router.jar. Do not access router classes,
-unless you are doing something special.
-The router may in the future implement a restricted classpath for plugins that prevents
-access to router classes.
-
-Since each version must be higher than the one before, you could enhance your build
-script to add a build number to the end of the version.
-This helps for testing. Most of zzz's plugins have that feature, check build.xml for an example.
-
-Plugins must never call System.exit().
-
-Please respect licenses by meeting license requirements for any software you bundle.
-
-The router sets the JVM time zone to UTC. If a plugin needs to know the user's actual time zone,
-it is stored by the router in the I2PAppContext property "i2p.systemTimeZone".
-
-
-
-Classpaths
-
-
-The following jars in $I2P/lib can be assumed to be in the standard classpath for all I2P installations,
-no matter how old or how new the original installation:
-
-
-The following jars in $I2P/lib can be assumed to be present for all I2P installations,
-no matter how old or how new the original installation,
-but are not necessarily in the classpath:
-
- jstl.jar, standard.jar
-
-
- Anything not listed above may not be present in everybody's classpath, even if you
- have it in the classpath in YOUR version of i2p.
- If you need any jar not listed above, add $I2P/lib/foo.jar to the classpath specified
- in clients.config or webapps.config in your plugin.
-
-Previously, a classpath entry specified in clients.config was added to the classpath for
-the entire JVM.
-However, as of 0.7.13-3, this was fixed using class loaders, and now, as originally intended,
-the specified classpath in clients.config is only for the particular thread.
-See the section on JVM crashes below, and
-this thread on zzz.i2p for background.
-Therefore, specify the full required classpath for each client.
-
-
-
-Java Version Notes
-
-While most I2P users are running a 1.6 (6.0) JVM, we support 1.5 (5.0) and higher JVMs.
-Unless you require 1.6 features, you should create your plugin so it works on 1.5.
-
-If your plugin does not require 1.6:
-
-
-Ensure that all java and jsp files are compiled with source="1.5" target="1.5".
-
-Ensure that all bundled library jars are also for 1.5 or lower.
-
-If you are using pack200, any 1.6 classes in a jar will
-cause pack200 to create a 1.6 pack format, and
-plugin installation will fail on a 1.5 system
-with the misleading message "plugin is corrupt".
-
-
-
-If your plugin requires 1.6:
-
-
-Note that on your download page.
-
-Add min-java-version=1.6 to your plugin.config
-
-If you are using pack200, plugin installation will fail on a 1.5 system
-with the misleading message "plugin is corrupt".
-
-
-
-
-JVM Crashes When Updating
-
-Note - this should all be fixed now.
-
-The JVM has a tendency to crash when updating jars in a plugin if that plugin was running
-since i2p was started (even if the plugin was later stopped).
-This may have been fixed with the class loader implementation in 0.7.13-3, but it may not.
-For further testing.
-
-The safest is to design your plugin with the jar inside the war (for a webapp), or to require a restart
-after update, or don't update the jars in your plugin.
-
-Due to the way class loaders work inside a webapp, it _may_ be safe to have external jars if
-you specify the classpath in webapps.config.
-More testing is required to verify this.
-Don't specify the classpath with a 'fake' client in clients.config if it's only
-needed for a webapp - use webapps.config instead.
-
-The least safe, and apparently the source of most crashes, is clients with plugin jars specified
-in the classpath in clients.config.
-
-
-None of this should be a problem on initial install - you should not ever have to require a restart
-for an initial install of a plugin.
-
-{% endblock %}
diff --git a/i2p2www/spec/plugin.rst b/i2p2www/spec/plugin.rst
new file mode 100644
index 00000000..3b3ff204
--- /dev/null
+++ b/i2p2www/spec/plugin.rst
@@ -0,0 +1,650 @@
+====================
+Plugin Specification
+====================
+.. meta::
+ :lastupdated: May 2015
+ :accuratefor: 0.9.20
+
+
+Overview
+========
+
+This document specifies a .xpi2p file format (like the Firefox .xpi), but with
+a simple plugin.config description file instead of an XML install.rdf file.
+This file format is used for both initial plugin installs and plugin updates.
+
+In addition, this document provides a brief overview of how the router installs
+plugins, and policies and guidelines for plugin developers.
+
+The basic .xpi2p file format is the same as a i2pupdate.sud file (the format
+used for router updates), but the installer will let the user install the addon
+even if it doesn't know the signer's key yet.
+
+As of release 0.9.15, the SU3 file format [UPDATES]_ is supported and is
+preferred. This format enables stronger signing keys.
+
+The standard directory structure will let users install the following types of
+addons:
+
+* console webapps
+
+* new eepsite with cgi-bin, webapps
+
+* console themes
+
+* console translations
+
+* Java programs
+
+* Java programs in a separate JVM
+
+* Any shell script or program
+
+A plugin installs all its files in ~/.i2p/plugins/name/
+(%APPDIR%\I2P\plugins\name\ on Windows). The installer will prevent
+installation anywhere else, although the plugin can access libraries elsewhere
+when running.
+
+This should be viewed only as a way to make installation, uninstallation, and
+upgrading easier, and to lessen basic inter-plugin conflicts.
+
+There is essentially no security model once the plugin is running, however. The
+plugin runs in the same JVM and with the same permissions as the router, and
+has full access to the file system, the router, executing external programs,
+etc.
+
+Details
+=======
+
+foo.xpi2p is a signed update (sud) file [UPDATES]_ containing the following:
+
+Standard .sud header prepended to the zip file, containing the following::
+
+ 40-byte DSA signature [CRYPTO-DSA]_
+ 16-byte plugin version in UTF-8, padded with trailing zeroes if necessary
+
+Zip file containing the following:
+
+plugin.config file
+``````````````````
+This file is required. It is a standard I2P configuration file [CONFIG]_,
+containing the following properties:
+
+The following four are required properties. The first three must be identical
+to those in the installed plugin for an update plugin.
+
+ name
+ Will be installed in this directory name
+
+ For native plugins, you may want separate names in different packages -
+ foo-windows and foo-linux, for example
+
+ key
+ DSA public key [CRYPTO-DSA]_ as 172 B64 chars ending with '='
+
+ Omit for SU3 format.
+
+ signer
+ yourname@mail.i2p recommended)
+
+ version
+ Must be in a format VersionComparator can parse, e.g. 1.2.3-4
+
+ 16 bytes max (must match sud version)
+
+ Valid number separators are '.', '-', and '_'
+
+ This must be greater than the one in the installed plugin for an update plugin.
+
+Values for the following properties are displayed on /configclients in the
+router console if present:
+
+ date
+ Java time - long int
+
+ author
+ yourname@mail.i2p recommended
+
+ websiteURL
+ http://foo.i2p/
+
+ updateURL
+ http://foo.i2p/foo.xpi2p
+
+ The update checker will check bytes 41-56 at this URL
+ to determine whether a newer version is available
+
+ (Should the checker fetch with ?currentVersion=1.2.3?...
+ No. If the dev wants to have the URL contain the current version, just
+ set it in the config file, and remember to change it every release)
+
+ updateURL.su3
+ http://foo.i2p/foo.su3
+
+ The location of the su3-format update file, as of 0.9.15
+
+ description
+ in English
+
+ description_xx
+ for language xx
+
+ license
+ The plugin license
+
+ disableStop=true
+ Default false.
+ If true, the stop button will not be shown. Use this if there are no
+ webapps and no clients with stopargs.
+
+The following properties are used to add a link on the console summary bar:
+
+ consoleLinkName
+ will be added to summary bar
+
+ consoleLinkName_xx
+ for language xx
+
+ consoleLinkURL
+ /appname/index.jsp
+
+ consoleLinkTooltip
+ supported as of 0.7.12-6
+
+ consoleLinkTooltip_xx
+ lang xx as of 0.7.12-6
+
+The following optional property may be used to add a custom icon on the
+console:
+
+ console-icon
+ supported as of 0.9.20
+
+ Only for webapps.
+
+ A path within the webapp to a 32x32 image, e.g. /icon.png
+ Applies to all webapps in the plugin.
+
+The following properties are used by the plugin installer:
+
+ type
+ app/theme/locale/webapp/...
+
+ (unimplemented, probably not necessary)
+
+ min-i2p-version
+ The minimum version of I2P this plugin requires
+
+ max-i2p-version
+ The maximum version of I2P this plugin will run on
+
+ min-java-version
+ The minimum version of Java this plugin requires
+
+ min-jetty-version
+ supported as of 0.8.13, use 6 for Jetty 6 webapps
+
+ max-jetty-version
+ supported as of 0.8.13, use 5.99999 for Jetty 5 webapps
+
+ required-platform-OS
+ unimplemented - perhaps will be displayed only, not verified
+
+ other-requirements
+ unimplemented
+
+ e.g. python x.y - not verified by the installer, just displayed to the
+ user
+
+ dont-start-at-install=true
+ Default false.
+
+ Won't start the plugin when it is installed or updated. On initial
+ installation, configures the plugin so the user must manually start it.
+ An update will not change the user's preference to start it if they
+ choose to do so.
+
+ router-restart-required=true
+ Default false.
+
+ This does not restart the router or the plugin on an update, it just
+ informs the user that a restart is required. It has no effect on initial
+ plugin installation.
+
+ update-only=true
+ Default false.
+
+ If true, will fail if an installation does not exist.
+
+ install-only=true
+ Default false.
+ If true, will fail if an installation exists.
+
+ min-installed-version
+ to update over, if an installation exists
+
+ max-installed-version
+ to update over, if an installation exists
+
+ depends=plugin1,plugin2,plugin3
+ unimplemented - is this too hard? proposed by sponge
+
+ depends-version=0.3.4,,5.6.7
+ unimplemented
+
+The following property is used for translation plugins:
+
+ langs=xx,yy,Klingon,...
+ (unimplemented)
+ (yy is the country flag)
+
+Application Directories and Files
+`````````````````````````````````
+Each of the following directories or files is optional, but something must be
+there or it won't do anything:
+
+console/
+ locale/
+ Only jars containing new resource bundles (translations) for apps in the
+ base I2P installation. Bundles for this plugin should go inside
+ console/webapp/foo.war or lib/foo.jar
+
+ themes/
+ New themes for the router console
+ Place each theme in a subdirectory.
+
+ webapps/
+ (See important notes below about webapps)
+
+ .wars
+ These will be run at install time unless disabled in webapps.config
+ The war name does not have to be the same as the plugin name.
+ Do not duplicate war names in the base I2P installation.
+
+ webapps.config
+ Same format as router's webapps.config. Also used to specify additional
+ jars in $PLUGIN/lib/ or $I2P/lib for the webapp classpath, with
+ ``webapps.warname.classpath=$PLUGIN/lib/foo.jar,$I2P/lib/bar.jar``
+
+ NOTE: Currently, the classpath line is only loaded if the warname is the
+ same as the plugin name.
+
+ NOTE: Prior to router version 0.7.12-9, the router looked for
+ ``plugin.warname.startOnLoad`` instead of
+ ``webapps.warname.startOnLoad``. For compatibility with older router
+ versions, a plugin wishing to disable a war should include both lines.
+
+eepsite/
+ (See important notes below about eepsites)
+
+ cgi-bin/
+
+ docroot/
+
+ logs/
+
+ webapps/
+
+ jetty.xml
+ The installer will have to do variable substitution in here to set the
+ path. The location and name of this file doesn't really matter, as long
+ as it is set in clients.config - it may be more convenient to be up one
+ level from here (that's what the zzzot plugin does)
+
+lib/
+ Put any jars here, and specify them in a classpath line in
+ console/webapps.config and/or clients.config
+
+clients.config file
+```````````````````
+This file is optional, and specifies clients that will be run when a plugin is
+started. It uses the same format as the router's clients.config file. See the
+clients.config configuration file specification [CONFIG]_ for more information
+about the format and important details about how clients are started and
+stopped.
+
+ property clientApp.0.stopargs=foo bar stop baz
+ If present, the class will be called with these args to stop the client
+ All stop tasks are called with zero delay
+ Note: The router can't tell if your unmanaged clients are running or not.
+ Each should handle stopping an app that isn't running without complaint.
+ That probably goes for starting a client that is already started too.
+
+ property clientApp.0.uninstallargs=foo bar uninstall baz
+ If present, the class will be called with these args just before
+ deleting $PLUGIN. All uninstall tasks are called with zero delay
+
+ property clientApp.0.classpath=$I2P/lib/foo.bar,$PLUGIN/lib/bar.jar
+ The plugin runner will do variable substitution in the args and stopargs
+ lines as follows:
+
+ $I2P
+ I2P base installation dir
+
+ $CONFIG
+ I2P config dir (typically ~/.i2p)
+
+ $PLUGIN
+ this plugin's installation dir (typically ~/.i2p/plugins/appname)
+
+ (See important notes below about running shell scripts or external
+ programs)
+
+
+Plugin installer tasks
+======================
+
+This lists what happens when a plugin is installed by I2P.
+
+* The .xpi2p file is downloaded.
+
+* The .sud signature is verified against stored keys. As of release 0.9.14.1,
+ if there is no matching key, the installation fails, unless an advanced
+ router property is set to allow all keys.
+
+* Verify the integrity of the zip file.
+
+* Extract the plugin.config file.
+
+* Verify the I2P version, to make sure the plugin will work.
+
+* Check that webapps don't duplicate the existing $I2P applications.
+
+* Stop the existing plugin (if present).
+
+* Verify that the install directory does not exist yet if update=false, or ask
+ to overwrite.
+
+* Verify that the install directory does exist if update=true, or ask to
+ create.
+
+* Unzip the plugin in to appDir/plugins/name/
+
+* Add the plugin to plugins.config
+
+
+Plugin starter tasks
+====================
+
+This lists what happens when plugins are started.
+First, plugins.config is checked to see which plugins need to be started.
+For each plugin:
+
+* Check clients.config, and load and start each item (add the configured jars
+ to the classpath).
+
+* Check console/webapp and console/webapp.config. Load and start required items
+ (add the configured jars to the classpath).
+
+* Add console/locale/foo.jar to the translation classpath if present.
+
+* Add console/theme to the theme search path if present.
+
+* Add the summary bar link.
+
+
+Console webapp notes
+====================
+
+Console webapps with background tasks should implement a ServletContextListener
+(see seedless or i2pbote for examples), or override destroy() in the servlet,
+so that they can be stopped. As of router version 0.7.12-3, console webapps
+will always be stopped before they are restarted, so you do not need to worry
+about multiple instances, as long as you do this. Also as of router version
+0.7.12-3, console webapps will be stopped at router shutdown.
+
+Don't bundle library jars in the webapp; put them in lib/ and put a classpath
+in webapps.config. Then you can make separate install and update plugins,
+where the update plugin does not contain the library jars.
+
+Don't include .java or .jsp files; otherwise jetty will recompile them at
+installation.
+
+For now, a webapp needing to add classpath files in $PLUGIN must be the same
+name as the plugin. For example, a webapp in plugin foo must be named foo.war.
+
+
+Eepsite notes
+=============
+
+It isn't clear how to have a plugin install to an existing eepsite. The router
+has no hook to the eepsite, and it may or may not be running, and there may be
+more than one. Better is to start your own Jetty instance and I2PTunnel
+instance, for a brand new eepsite.
+
+It can instantiate a new I2PTunnel (somewhat like the i2ptunnel CLI does), but
+it won't appear in the i2ptunnel gui of course, that's a different instance.
+But that's ok. Then you can start and stop i2ptunnel and jetty together.
+
+So don't count on the router to automatically merge this with some existing
+eepsite. It probably won't happen. Start a new I2PTunnel and Jetty from
+clients.config. The best examples of this are the zzzot and pebble plugins,
+available at zzz's plugins page [STATS-PLUGINS]_.
+
+How to get path substitution into jetty.xml? See zzzot and pebble plugins for
+examples.
+
+
+Client start/stop notes
+=======================
+
+As of release 0.9.4, the router supports "managed" plugin clients. Managed
+plugin clients are instantiated and started by the ``ClientAppManager``. The
+ClientAppManager maintains a reference to the client and receives updates on
+the client's state. Managed plugin client are preferred, as it is much easier
+to implement state tracking and to start and stop a client. It also is much
+easier to avoid static references in the client code which could lead to
+excessive memory usage after a client is stopped. See the clients.config
+configuration file specification [CONFIG]_ for more information on writing a
+managed client.
+
+For "unmanaged" plugin clients, The router has no way to monitor the state of
+clients started via clients.config. The plugin author should handle multiple
+start or stop calls gracefully, if at all possible, by keeping a static state
+table, or using PID files, etc. Avoid logging or exceptions on multiple starts
+or stops. This also goes for a stop call without a previous start. As of
+router version 0.7.12-3, plugins will be stopped at router shutdown, which
+means that all clients with stopargs in clients.config will be called, whether
+or not they were previously started.
+
+
+Shell script and external program notes
+=======================================
+
+To run shell scripts or other external programs, see [ZZZ-141]_.
+
+To work on both Windows and Linux, write a small Java class that checks the OS
+type, then runs ShellCommand on either the .bat or a .sh file you provide.
+
+External programs won't be stopped when the router stops, and a second copy
+will fire up when the router starts. To work around this, you could write a
+wrapper class or shell script that does the usual storage of the PID in a PID
+file, and check for it on start.
+
+
+Other plugin guidelines
+=======================
+
+* See i2p.scripts branch or any of the sample plugins on zzz's page for a xpi2p
+ file generator to make it easy.
+
+* Pack200 of jars and wars is strongly recommended for plugins, it generally
+ shrinks plugins by 60-65%. See any of the sample plugins on zzz's page for
+ an example. Pack200 unpacking is supported on routers 0.7.11-5 or higher,
+ which is essentially all routers that support plugins at all.
+
+* Plugins should not attempt to write anywhere in $I2P as it may be readonly,
+ and that isn't good policy anyway.
+
+* Plugins may write to $CONFIG but keeping files in $PLUGIN only is recommended.
+ All files in $PLUGIN will be deleted at uninstall. Files elsewhere will not be
+ deleted at uninstall unless the plugin does it explicitly with a client in
+ clients.config run with uninstallargs. If the user may want to save data after
+ uninstallation, the uninstallargs hook could ask.
+
+* $CWD may be anywhere; do not assume it is in a particular place, do not
+ attempt to read or write files relative to $CWD.
+
+* Java programs should find out where they are with the directory getters in
+ I2PAppContext.
+
+* Plugin directory is
+ ``I2PAppContext.getGlobalContext().getAppDir().getAbsolutePath() + "/plugins/" + appname``,
+ or put a $PLUGIN argument in the args line in clients.config. There is no
+ reliable way to find the i2p install or config or plugin directory without
+ using the context API in i2p.jar.
+
+* See [ZZZ-16]_ for info on generating signing keys and generating/verifying
+ keys and sud files.
+
+* All config files must be UTF-8.
+
+* To run in a separate JVM, use ShellCommand with
+ ``java -cp foo:bar:baz my.main.class arg1 arg2 arg3``. Of course, it will be a
+ lot harder to stop the plugin then... But with some trickery with PID files it
+ should be possible.
+
+* As an alternative to stopargs in clients.config, a Java client may register a
+ shutdown hook with I2PAppContext.addShutdownTask(). But this wouldn't shut
+ down a plugin when upgrading, so stopargs is recommended. Also, set all
+ created threads to daemon mode.
+
+* Do not include classes duplicating those in the standard installation. Extend
+ the classes if necessary.
+
+* Beware of the different classpath definitions in wrapper.config between old
+ and new installations - see classpath section below.
+
+* Clients will reject duplicate keys with different keynames, and duplicate
+ keynames with different keys, and different keys or keynames in upgrade
+ packages. Safeguard your keys. Only generate them once.
+
+* Do not modify the plugin.config file at runtime as it will be overwritten on
+ upgrade. Use a different config file in the directory for storing runtime
+ configuration.
+
+* In general, plugins should not require access to $I2P/lib/router.jar. Do not
+ access router classes, unless you are doing something special. The router may
+ in the future implement a restricted classpath for plugins that prevents
+ access to router classes.
+
+* Since each version must be higher than the one before, you could enhance your
+ build script to add a build number to the end of the version. This helps for
+ testing. Most of zzz's plugins have that feature, check build.xml for an example.
+
+* Plugins must never call ``System.exit()``.
+
+* Please respect licenses by meeting license requirements for any software you
+ bundle.
+
+* The router sets the JVM time zone to UTC. If a plugin needs to know the user's
+ actual time zone, it is stored by the router in the I2PAppContext property
+ ``i2p.systemTimeZone``.
+
+
+Classpaths
+==========
+
+The following jars in $I2P/lib can be assumed to be in the standard classpath
+for all I2P installations, no matter how old or how new the original
+installation::
+
+ i2p.jar, router.jar, jbigi.jar, sam.jar, mstreaming.jar, streaming.jar, i2ptunnel.jar,
+ org.mortbay.jetty.jar, javax.servlet.jar, jasper-compiler.jar, jasper-runtime.jar,
+ commons-logging.jar, commons-el.jar, wrapper.jar, systray.jar, systray4j.jar
+
+The following jars in $I2P/lib can be assumed to be present for all I2P
+installations, no matter how old or how new the original installation, but are
+not necessarily in the classpath::
+
+ jstl.jar, standard.jar
+
+Anything not listed above may not be present in everybody's classpath, even if
+you have it in the classpath in YOUR version of i2p. If you need any jar not
+listed above, add $I2P/lib/foo.jar to the classpath specified in clients.config
+or webapps.config in your plugin.
+
+Previously, a classpath entry specified in clients.config was added to the
+classpath for the entire JVM. However, as of 0.7.13-3, this was fixed using
+class loaders, and now, as originally intended, the specified classpath in
+clients.config is only for the particular thread. See the section on JVM
+crashes below, and [ZZZ-633]_ for background. Therefore, specify the full
+required classpath for each client.
+
+
+Java Version Notes
+==================
+
+While most I2P users are running a 1.6 (6.0) JVM, we support 1.5 (5.0) and
+higher JVMs. Unless you require 1.6 features, you should create your plugin so
+it works on 1.5.
+
+If your plugin **does not require 1.6**:
+
+* Ensure that all java and jsp files are compiled with source="1.5"
+ target="1.5".
+
+* Ensure that all bundled library jars are also for 1.5 or lower.
+
+* If you are using pack200, any 1.6 classes in a jar will cause pack200 to
+ create a 1.6 pack format, and plugin installation will fail on a 1.5 system
+ with the misleading message "plugin is corrupt".
+
+If your plugin **requires 1.6**:
+
+* Note that on your download page.
+
+* Add min-java-version=1.6 to your plugin.config
+
+* If you are using pack200, plugin installation will fail on a 1.5 system with
+ the misleading message "plugin is corrupt".
+
+
+JVM Crashes When Updating
+=========================
+
+Note - this should all be fixed now.
+
+The JVM has a tendency to crash when updating jars in a plugin if that plugin
+was running since I2P was started (even if the plugin was later stopped). This
+may have been fixed with the class loader implementation in 0.7.13-3, but it
+may not. For further testing.
+
+The safest is to design your plugin with the jar inside the war (for a webapp),
+or to require a restart after update, or don't update the jars in your plugin.
+
+Due to the way class loaders work inside a webapp, it _may_ be safe to have
+external jars if you specify the classpath in webapps.config. More testing is
+required to verify this. Don't specify the classpath with a 'fake' client in
+clients.config if it's only needed for a webapp - use webapps.config instead.
+
+The least safe, and apparently the source of most crashes, is clients with
+plugin jars specified in the classpath in clients.config.
+
+None of this should be a problem on initial install - you should not ever have
+to require a restart for an initial install of a plugin.
+
+
+References
+==========
+
+.. [CONFIG]
+ {{ spec_url('configuration') }}
+
+.. [CRYPTO-DSA]
+ {{ site_url('docs/how/cryptography', True) }}#DSA
+
+.. [STATS-PLUGINS]
+ http://{{ i2pconv('stats.i2p') }}/i2p/plugins/
+
+.. [UPDATES]
+ {{ spec_url('updates') }}
+
+.. [ZZZ-16]
+ http://{{ i2pconv('zzz.i2p') }}/topics/16
+
+.. [ZZZ-141]
+ http://{{ i2pconv('zzz.i2p') }}/topics/141
+
+.. [ZZZ-633]
+ http://{{ i2pconv('zzz.i2p') }}/topics/633
diff --git a/i2p2www/spec/ssu.html b/i2p2www/spec/ssu.html
deleted file mode 100644
index bc2ee62c..00000000
--- a/i2p2www/spec/ssu.html
+++ /dev/null
@@ -1,1107 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}SSU Protocol Specification{% endblock %}
-{% block lastupdated %}February 2015{% endblock %}
-{% block accuratefor %}0.9.18{% endblock %}
-{% block content %}
-
-
-The initial 2048-bit DH key exchange is described on the
-SSU page.
-This exchange uses the same shared prime as that used for I2P's
-ElGamal encryption.
-
-
-
-
Message Header
-
-
-All UDP datagrams begin with a 16 byte MAC (Message Authentication Code)
-and a 16 byte IV (Initialization Vector)
-followed by a variable-size
-payload encrypted with the appropriate key. The MAC used is
-HMAC-MD5, truncated to 16 bytes, while the key is a full 32 byte AES256
-key. The specific construct of the MAC is the first 16 bytes from:
-
- HMAC-MD5(encryptedPayload + IV + (payloadLength ^ protocolVersion), macKey)
-
-where '+' means append and '^' means exclusive-or.
-
-The IV is generated randomly for each packet.
-The encryptedPayload is the encrypted version of the message starting with the flag byte (encrypt-then-MAC).
-The payloadLength used in the MAC is a 2 byte unsigned integer.
-Note that protocolVersion is 0, so the exclusive-or is a no-op.
-The macKey is either the introduction key or is constructed from the
-exchanged DH key (see details below), as specified for each message below.
-WARNING - the HMAC-MD5-128 used here is non-standard,
-see the cryptography page for details.
-
-
-
The payload itself (that is, the message starting with the flag byte)
-is AES256/CBC encrypted with the IV and the
-sessionKey, with replay prevention addressed within its body,
-explained below.
-
-
-
The protocolVersion is a 2 byte unsigned integer
-and is currently set to 0. Peers using a different protocol version will
-not be able to communicate with this peer, though earlier versions not
-using this flag are.
-
-
HMAC Specification
-
-Inner padding: 0x36...
-
-Outer padding: 0x5C...
-
-Key: 32 bytes
-
-Hash digest function: MD5, 16 bytes
-
-Block size: 64 bytes
-
-MAC size: 16 bytes
-
-Example C implementations:
-hmac.h in i2pd
-and
-I2PHMAC.cpp in i2pcpp.
-
-Example Java implementation:
-I2PHMac.java in i2p
-
-
-
-
Session Key Details
-The 32-byte session key is created as follows:
-
-Take the exchanged DH key, represented as a positive minimal-length BigInteger byte array (two's complement big-endian)
-
-If the most significant bit is 1 (i.e. array[0] & 0x80 != 0),
-prepend a 0x00 byte, as in Java's BigInteger.toByteArray() representation
-
-If the byte array is greater than or equal to 32 bytes, use the first (most significant) 32 bytes
-
-If the byte array is less than 32 bytes, append 0x00 bytes to extend to 32 bytes.
-Very unlikely - See note below.
-
-
-
MAC Key Details
-The 32-byte MAC key is created as follows:
-
-Take the exchanged DH key byte array, prepended with a 0x00 byte if necessary,
-from step 2 in the Session Key Details above.
-
-If that byte array is greater than or equal to 64 bytes, the MAC key is
-bytes 33-64 from that byte array.
-
-If that byte array is less than 64 bytes, the MAC key is the SHA-256 Hash of that byte array.
-As of release 0.9.8. See note below.
-
-Important note: Code before release 0.9.8 was broken and did not correctly handle DH key byte arrays
-between 32 and 63 bytes (steps 3 and 4 above) and the connection will fail.
-As these cases didn't ever work, they were redefined as described above for release 0.9.8,
-and the 0-32 byte case was redefined as well.
-Since the nominal exchanged DH key is 256 bytes, the chances of the mininimal representation
-being less than 64 bytes is vanishingly small.
-
-
-
Header Format
-
Within the AES encrypted payload, there is a minimal common structure
-to the various messages - a one byte flag and a four byte sending
-timestamp (seconds since the unix epoch). The flag byte contains
-the following bitfields:
-{% highlight %}
- Bit order: 76543210 (bit 7 is MSB)
-
- bits 7-4: payload type
- bit 3: rekey, always 0, unimplemented
- bit 2: extended options included, always 0, unimplemented
- bits 1-0: reserved, set to 0 for compatibility with future uses
-{% endhighlight %}
-
-
-Note that rekeying and extended options are unimplemented, so the
-current header size is exactly 37 bytes.
-
-
-
-
Rekeying
-
If the rekey flag is set, 64 bytes of keying material follow the
-timestamp.
-
-
When rekeying, the first 32 bytes of the keying material is fed
-into a SHA256 to produce the new MAC key, and the next 32 bytes are
-fed into a SHA256 to produce the new session key, though the keys are
-not immediately used. The other side should also reply with the
-rekey flag set and that same keying material. Once both sides have
-sent and received those values, the new keys should be used and the
-previous keys discarded. It may be useful to keep the old keys
-around briefly, to address packet loss and reordering.
-
-
NOTE: Rekeying is currently unimplemented.
-
-
Extended Options
-
-If the extended options flag is set, a one byte option
-size value is appended, followed by that many extended option
-bytes.
-
-
NOTE: Extended options is currently unimplemented.
-
-
Padding
-
-All messages contain 0 or more bytes of padding.
-Each message must be padded to a 16 byte boundary, as required by the AES256 encryption layer.
-Through release 0.9.7, messages were only padded to the next 16 byte boundary,
-and messages not a multiple of 16 bytes could possibly be invalid.
-As of release 0.9.7, messages may be padded to any length as long as the current MTU is honored.
-Any extra 1-15 padding bytes beyond the last block of 16 bytes cannot be encrypted or decrypted and will be ignored.
-However, the full length and all padding is included in the MAC calculation.
-As of release 0.9.8, transmitted messages are not necessarily a multiple of 16 bytes.
-The SessionConfirmed message is an exception, see below.
-
-
-
-
Keys
-
-Signatures in the SessionCreated and SessionConfirmed messages are generated using
-the
-Signing Public Key
-from the
-Router Identity
-which is distributed out-of-band by publishing in the network database, and the associated
-Signing Private Key.
-Through release 0.9.15, the signature algorithm was always DSA, with a 40 byte signature.
-As of release 0.9.16, the signature algorithm may be specified by a
-a Key Certificate
-in Bob's Router Identity.
-
-Both introduction keys and session keys are 32 bytes,
-and are defined by the
-Common structures specification.
-The key used for the MAC and encryption is specified for each message below.
-
-
Introduction keys are delivered through an external channel
-(the network database, where they are identical to the router Hash for now).
-
-
-
-
Notes
-
-
IPv6 Notes
-The protocol specification allows both 4-byte IPv4 and 16-byte IPv6 addresses.
-SSU-over-IPv6 is supported as of version 0.9.8.
-See the documentation of individual messages below for details on IPv6 support.
-
-
Timestamps
-While most of I2P uses 8-byte Date timestamps with
-millisecond resolution, SSU uses a 4-byte timestamp with one-second resolution.
-
-
-
-
-
Messages
-
-There are 10 messages (payload types) defined:
-
-
-
Type
Message
Notes
-
0
SessionRequest
-
1
SessionCreated
-
2
SessionConfirmed
-
3
RelayRequest
-
4
RelayResponse
-
5
RelayIntro
-
6
Data
-
7
PeerTest
-
8
SessionDestroyed
Implemented as of 0.8.9
-
n/a
HolePunch
-
-
-
-
SessionRequest (type 0)
-
-This is the first message sent to establish a session.
-
-
-
-
Peer:
-
Alice to Bob
-
Data:
-
-
256 byte X, to begin the DH agreement
-
1 byte IP address size
-
that many byte representation of Bob's IP address
-
N bytes, currently uninterpreted
-
-
Crypto Key used:
-
Bob's introKey, as retrieved from the network database
-
MAC Key used:
-
Bob's introKey, as retrieved from the network database
-
-
-
Message format:
-
-{% highlight lang='dataspec' %}
- +----+----+----+----+----+----+----+----+
- | X, as calculated from DH |
- ~ . . . ~
- | |
- +----+----+----+----+----+----+----+----+
- |size| that many byte IP address (4-16) |
- +----+----+----+----+----+----+----+----+
- | arbitrary amount of uninterpreted data|
- ~ . . . ~
-{% endhighlight %}
-
-
-Typical size including header, in current implementation: 304 (IPv4) or 320 (IPv6) bytes
-(before non-mod-16 padding)
-
-
-
Notes
-
-IPv4 and IPv6 addresses are supported.
-
-The uninterpreted data could possibly be used in the future for challenges.
-
-
-
-
-
SessionCreated (type 1)
-
-This is the response to a Session Request.
-
-
-
-
Peer:
-
Bob to Alice
-
Data:
-
-
256 byte Y, to complete the DH agreement
-
1 byte IP address size
-
that many byte representation of Alice's IP address
-
2 byte Alice's port number
-
4 byte relay (introduction) tag which Alice can publish (else 0x00000000)
-
4 byte timestamp (seconds from the epoch) for use in the DSA
- signature
-
Bob's Signature of the critical exchanged data
- (X + Y + Alice's IP + Alice's port + Bob's IP + Bob's port + Alice's
- new relay tag + Bob's signed on time), encrypted with another
- layer of encryption using the negotiated sessionKey. The IV
- is reused here.
- See notes for length information.
-
-
0-15 bytes of padding of the signature, using random data,
- to a multiple of 16 bytes, so that the signature + padding may be
- encrypted with an additional layer of encryption
- using the negotiated session key as part of the DSA block.
-
-
N bytes, currently uninterpreted
-
-
Crypto Key used:
-
Bob's introKey, with an additional layer of encryption over the 40 byte
- signature and the following 8 bytes padding.
-
MAC Key used:
-
Bob's introKey
-
-
-
Message format:
-
-{% highlight lang='dataspec' %}
- +----+----+----+----+----+----+----+----+
- | Y, as calculated from DH |
- ~ . . . ~
- | |
- +----+----+----+----+----+----+----+----+
- |size| that many byte IP address (4-16) |
- +----+----+----+----+----+----+----+----+
- | Port (A)| public relay tag | signed
- +----+----+----+----+----+----+----+----+
- on time | |
- +----+----+ +
- | |
- + +
- | signature |
- + +
- | |
- + +
- | |
- + +----+----+----+----+----+----+
- | | (0-15 bytes of padding)
- +----+----+----+----+----+----+----+----+
- | |
- +----+----+ +
- | arbitrary amount |
- ~ of uninterpreted data ~
- ~ . . . ~
-{% endhighlight %}
-
-
-Typical size including header, in current implementation: 368 bytes (IPv4 or IPv6)
-(before non-mod-16 padding)
-
-
-
Notes
-
-IPv4 and IPv6 addresses are supported.
-
-If the relay tag is nonzero, Bob is offering to act as an introducer for Alice.
-Alice may subsequently publish Bob's address and the relay tag in the network database.
-
-For the signature, Bob must use his external port, as that what Alice will use to verify.
-If Bob's NAT/firewall has mapped his internal port to a different external port,
-and Bob is unaware of it, the verification by Alice will fail.
-
-See the Keys section above for details on signatures.
-Alice already has Bob's public signing key, from the network database.
-
-Through release 0.9.15, the signature was always a 40 byte DSA signature and the
-padding was always 8 bytes. As of release 0.9.16, the signature type and length
-are implied by the type of the Signing Public Key
-in Bob's Router Identity.
-The padding is as necessary to a multiple of 16 bytes.
-
-This is the only message that uses the sender's intro key.
-All others use the receiver's intro key or the established session key.
-
-Signed-on time appears to be unused or unverified in the current implementation.
-
-The uninterpreted data could possibly be used in the future for challenges.
-
-
-
-
-
SessionConfirmed (type 2)
-
-This is the response to a Session Created message and the last step in establishing a session.
-There may be multiple Session Confirmed messages required if the Router Identity must be fragmented.
-
-
-
-
Peer:
-
Alice to Bob
-
Data:
-
-
1 byte identity fragment info:
-Bit order: 76543210 (bit 7 is MSB)
-bits 7-4: current identity fragment # 0-14
-bits 3-0: total identity fragments (F) 1-15
The remaining bytes contain
- Alice's Signature of the critical exchanged
- data (X + Y + Alice's IP + Alice's port + Bob's IP + Bob's port
- + Alice's new relay tag + Alice's signed on time)
- See notes for length information.
-
-
-
-
Crypto Key used:
-
Alice/Bob sessionKey, as generated from the DH exchange
-
MAC Key used:
-
Alice/Bob MAC Key, as generated from the DH exchange
-
-
-
- Fragment 0 through F-2
-(only if F > 1; currently unused, see notes below) :
-
-{% highlight lang='dataspec' %}
- +----+----+----+----+----+----+----+----+
- |info| cursize | |
- +----+----+----+ +
- | last fragment of Alice's full |
- ~ Router Identity ~
- ~ . . . ~
- | |
- +----+----+----+----+----+----+----+----+
- | signed on time | |
- +----+----+----+----+ +
- | arbitrary amount of uninterpreted |
- ~ data, until the signature at ~
- ~ end of the current packet ~
- | Packet length must be mult. of 16 |
- +----+----+----+----+----+----+----+----+
- + +
- | |
- + +
- | signature |
- + +
- | |
- + +
- | |
- +----+----+----+----+----+----+----+----+
-{% endhighlight %}
-
-
-Typical size including header, in current implementation: 480 bytes
-(before non-mod-16 padding)
-
-
-
Notes
-
-In the current implementation, the maximum fragment size is 512 bytes.
-This should be extended so that longer signatures will work without fragmentation.
-The current implementation does not correctly process signatures split across two fragments.
-
-The typical Router Identity
-is 387 bytes, so no fragmentation is ever necessary.
-If new crypto extends the size of the RouterIdentity, the fragmentation scheme
-must be tested carefully.
-
-There is no mechanism for requesting or redelivering missing fragments.
-
-The total fragments field F must be set identically in all fragments.
-
-Signed-on time appears to be unused or unverified in the current implementation.
-
-Since the signature is at the end, the padding in the last or only packet must pad the total packet to
-a multiple of 16 bytes, or the signature will not get decrypted correctly.
-This is different from all the other message types, where the padding is at the end.
-
-Through release 0.9.15, the signature was always a 40 byte DSA signature.
-As of release 0.9.16, the signature type and length
-are implied by the type of the Signing Public Key
-in Alice's Router Identity.
-The padding is as necessary to a multiple of 16 bytes.
-
-
-
-
-
-
SessionDestroyed (type 8)
-
-The Session Destroyed message was implemented (reception only) in release 0.8.1,
-and is sent as of release 0.8.9.
-
-
-
-
Peer:
-
Alice to Bob or Bob to Alice
-
Data:
-
none
-
-
Crypto Key used:
-
Alice/Bob sessionKey
-
MAC Key used:
-
Alice/Bob MAC Key
-
-
-
-
-This message does not contain any data.
-Typical size including header, in current implementation: 48 bytes
-(before non-mod-16 padding)
-
-
-
Notes
-
-Destroy messages received with the sender's or receiver's intro key will be ignored.
-
-
-
-
RelayRequest (type 3)
-
-This is the first message sent from Alice to Bob to request an introduction to Charlie.
-
-
-
-
Peer:
-
Alice to Bob
-
Data:
-
-
4 byte relay (introduction) tag, nonzero, as received by Alice in the Session Created message from Bob
-
1 byte IP address size
-
that many byte representation of Alice's IP address
-
2 byte port number (of Alice)
-
1 byte challenge size
-
that many bytes to be relayed to Charlie in the intro
-
Alice's 32-byte introduction key (so Bob can reply with Charlie's info)
-
4 byte nonce of Alice's relay request
-
N bytes, currently uninterpreted
-
-
Crypto Key used:
-
Bob's introKey, as retrieved from the network database (or Alice/Bob sessionKey, if established)
-
MAC Key used:
-
Bob's introKey, as retrieved from the network database (or Alice/Bob MAC Key, if established)
-
-
-
Message format:
-
-{% highlight lang='dataspec' %}
- +----+----+----+----+----+----+----+----+
- | relay tag |size| Alice IP addr
- +----+----+----+----+----+----+----+----+
- | Port (A)|size| challenge bytes |
- +----+----+----+----+ +
- | to be delivered to Charlie |
- +----+----+----+----+----+----+----+----+
- | Alice's intro key |
- + +
- | |
- + +
- | |
- + +
- | |
- +----+----+----+----+----+----+----+----+
- | nonce | |
- +----+----+----+----+ +
- | arbitrary amount of uninterpreted data|
- ~ . . . ~
-{% endhighlight %}
-
-
-Typical size including header, in current implementation: 96 bytes (no Alice IP included) or 112 bytes (4-byte Alice IP included)
-(before non-mod-16 padding)
-
-
-
Notes
-
-The IP address is only included if it is be different than the
-packet's source address and port. In the current implementation, the
-IP length is always 0 and the port is always 0, and the receiver should
-use the packet's source address and port.
-
-This message may be sent via IPv4 or IPv6. If IPv6, Alice must include her IPv4 address and port.
-
-If Alice includes her address/port, Bob may perform additional validation before continuing.
-
-Challenge is unimplemented, challenge size is always zero
-
-There are no plans to implement relaying for IPv6.
-
-Prior to release 0.9.12, Bob's intro key was always used.
-As of release 0.9.12, the session key is used if there is an established session
-between Alice and Bob.
-In practice, there must be an established session, as Alice will only get the
-nonce (introduction tag) from the session created message, and
-Bob will mark the introduction tag invalid once the session is destroyed.
-
-
-
-
RelayResponse (type 4)
-
-This is the response to a Relay Request and is sent from Bob to Alice.
-
-
-
-
Peer:
-
Bob to Alice
-
Data:
-
-
1 byte IP address size
-
that many byte representation of Charlie's IP address
-
2 byte Charlie's port number
-
1 byte IP address size
-
that many byte representation of Alice's IP address
-
2 byte Alice's port number
-
4 byte nonce sent by Alice
-
N bytes, currently uninterpreted
-
-
Crypto Key used:
-
Alice's introKey, as received in the Relay Request (or Alice/Bob sessionKey, if established)
-
MAC Key used:
-
Alice's introKey, as received in the Relay Request (or Alice/Bob MAC Key, if established)
-
-
-
Message format:
-
-{% highlight lang='dataspec' %}
- +----+----+----+----+----+----+----+----+
- |size| Charlie IP | Port (C)|size|
- +----+----+----+----+----+----+----+----+
- | Alice IP | Port (A)| nonce
- +----+----+----+----+----+----+----+----+
- | arbitrary amount of |
- +----+----+ +
- | uninterpreted data |
- ~ . . . ~
-{% endhighlight %}
-
-
-Typical size including header, in current implementation: 64 (Alice IPv4) or 80 (Alice IPv6) bytes
-(before non-mod-16 padding)
-
-
-
Notes
-
-This message may be sent via IPv4 or IPv6.
-
-Alice's IP address/port are the apparent IP/port that Bob received the RelayRequest on
-(not necessarily the IP Alice included in the RelayRequest),
-and may be IPv4 or IPv6. Alice currently ignores these on receive.
-
-Charlie's IP address must be IPv4, as that is the address that Alice will send
-the SessionRequest to after the Hole Punch.
-
-There are no plans to implement relaying for IPv6.
-
-Prior to release 0.9.12, Alice's intro key was always used.
-As of release 0.9.12, the session key is used if there is an established session
-between Alice and Bob.
-
-
-
-
-
RelayIntro (type 5)
-
-This is the introduction for Alice, which is sent from Bob to Charlie.
-
-
-
-
Peer:
-
Bob to Charlie
-
Data:
-
-
1 byte IP address size
-
that many byte representation of Alice's IP address
-
2 byte port number (of Alice)
-
1 byte challenge size
-
that many bytes relayed from Alice
-
N bytes, currently uninterpreted
-
-
Crypto Key used:
-
Bob/Charlie sessionKey
-
MAC Key used:
-
Bob/Charlie MAC Key
-
-
-
Message format:
-
-{% highlight lang='dataspec' %}
- +----+----+----+----+----+----+----+----+
- |size| Alice IP | Port (A)|size|
- +----+----+----+----+----+----+----+----+
- | that many bytes of challenge |
- + +
- | data relayed from Alice |
- +----+----+----+----+----+----+----+----+
- | arbitrary amount of uninterpreted data|
- ~ . . . ~
-{% endhighlight %}
-
-
-Typical size including header, in current implementation: 48 bytes
-(before non-mod-16 padding)
-
-
-
Notes
-
-Alice's IP address is always 4 bytes in the current implementation, because Alice is trying to connect
-to Charlie via IPv4.
-
-This message must be sent via an established IPv4 connection, as that's the only way that
-Bob knows Charlie's IPv4 address to return to Alice in the RelayResponse.
-
-Challenge is unimplemented, challenge size is always zero
-
-
-
-
-
-
Data (type 6)
-
-This message is used for data transport and acknowledgment.
-
-
-
-
Peer:
-
Any
-
Data:
-
-
1 byte flags:
- Bit order: 76543210 (bit 7 is MSB)
- bit 7: explicit ACKs included
- bit 6: ACK bitfields included
- bit 5: reserved
- bit 4: explicit congestion notification (ECN)
- bit 3: request previous ACKs
- bit 2: want reply
- bit 1: extended data included (unused, never set)
- bit 0: reserved
-
if explicit ACKs are included:
-
a 1 byte number of ACKs
-
that many 4 byte MessageIds being fully ACKed
-
-
if ACK bitfields are included:
-
a 1 byte number of ACK bitfields
-
that many 4 byte MessageIds + a 1 or more byte ACK bitfield.
- The bitfield uses the 7 low bits of each byte, with the high
- bit specifying whether an additional bitfield byte follows it
- (1 = true, 0 = the current bitfield byte is the last). These
- sequence of 7 bit arrays represent whether a fragment has been
- received - if a bit is 1, the fragment has been received. To
- clarify, assuming fragments 0, 2, 5, and 9 have been received,
- the bitfield bytes would be as follows:
-
-byte 0:
- Bit order: 76543210 (bit 7 is MSB)
- bit 7: 1 (further bitfield bytes follow)
- bit 6: 0 (fragment 6 not received)
- bit 5: 1 (fragment 5 received)
- bit 4: 0 (fragment 4 not received)
- bit 3: 0 (fragment 3 not received)
- bit 2: 1 (fragment 2 received)
- bit 1: 0 (fragment 1 not received)
- bit 0: 1 (fragment 0 received)
-byte 1:
- Bit order: 76543210 (bit 7 is MSB)
- bit 7: 0 (no further bitfield bytes)
- bit 6: 0 (fragment 13 not received)
- bit 5: 0 (fragment 12 not received)
- bit 4: 0 (fragment 11 not received)
- bit 3: 0 (fragment 10 not received)
- bit 2: 1 (fragment 9 received)
- bit 1: 0 (fragment 8 not received)
- bit 0: 0 (fragment 7 not received)
-
-
-
If extended data included:
-
1 byte data size
-
that many bytes of extended data (currently uninterpreted)
-
1 byte number of fragments (can be zero)
-
If nonzero, that many message fragments. Each fragment contains:
-
4 byte messageId
-
3 byte fragment info:
- Bit order: 76543210 (bit 7 is MSB)
- bits 23-17: fragment # 0 - 127
- bit 16: isLast (1 = true)
- bits 15-14: unused, set to 0 for compatibility with future uses
- bits 13-0: fragment size 0 - 16383
-
that many bytes
-
N bytes padding, uninterpreted
-
-
Crypto Key used:
-
Alice/Bob sessionKey
-
MAC Key used:
-
Alice/Bob MAC Key
-
-
-
Message format:
-
-{% highlight lang='dataspec' %}
- +----+----+----+----+----+----+----+----+
- |flag| (additional headers, determined |
- +----+ +
- ~ by the flags, such as ACKs or ~
- | bitfields |
- +----+----+----+----+----+----+----+----+
- |#frg| messageId | frag info |
- +----+----+----+----+----+----+----+----+
- | that many bytes of fragment data |
- ~ . . . ~
- | |
- +----+----+----+----+----+----+----+----+
- | messageId | frag info | |
- +----+----+----+----+----+----+----+ +
- | that many bytes of fragment data |
- ~ . . . ~
- | |
- +----+----+----+----+----+----+----+----+
- | messageId | frag info | |
- +----+----+----+----+----+----+----+ +
- | that many bytes of fragment data |
- ~ . . . ~
- | |
- +----+----+----+----+----+----+----+----+
- | arbitrary amount of uninterpreted data|
- ~ . . . ~
-{% endhighlight %}
-
-
Notes
-
-The current implementation adds a limited number of duplicate acks for
-messages previously acked, if space is available.
-
-If the number of fragments is zero, this is an ack-only or keepalive message.
-
-The ECN feature is unimplemented, and the bit is never set.
-
-In the current implementation, the want reply bit is set when the number of
-fragments is greater then zero, and not set when there are no fragments.
-
-Extended data is unimplemented and never present.
-
-Reception of multiple fragments is supported in all releases.
-Transmission of multiple fragments is implemented in release 0.9.16.
-
-As currently implemented, maximum fragments is 64
-(maximum fragment number = 63).
-
-As currently implemented, maximum fragment size is of course
-less than the MTU.
-
-Take care not to exceed the maximum MTU even if there is a large number of
-ACKs to send.
-
-The protocol allows zero-length fragments but there's no reason to send them.
-
-In SSU, the data uses a short 5-byte I2NP header followed by the payload
-of the I2NP message instead of the standard 16-byte I2NP header.
-The short I2NP header consists only of
-the one-byte I2NP type and 4-byte expiration in seconds.
-The I2NP message ID is used as the message ID for the fragment.
-The I2NP size is assembled from the fragment sizes.
-The I2NP checksum is not required as UDP message integrity is ensured by decryption.
-
-Message IDs are not sequence numbers and are not consecutive.
-SSU does not guarantee in-order delivery.
-While we use the I2NP message ID as the SSU message ID, from the SSU
-protocol view, they are random numbers.
-In fact, since the router uses a single Bloom filter for all peers,
-the message ID must be an actual random number.
-
-Because there are no sequence numbers, there is no way to be sure an ACK was received.
-The current implementation routinely sends a large amount of duplicate ACKs.
-Duplicate ACKs should not be taken as an indication of congestion.
-
-ACK Bitfield notes:
-The receiver of a data packet does not know how many fragments are in the message unless it has
-received the last fragment. Therefore, the number of bitfield bytes sent in response may be less or
-more than the number of fragments divided by 7.
-For example, if the highest fragment the receiver has seen is number 4, only
-one byte is required to be sent, even if there may be 13 fragments total.
-Up to 10 bytes (i.e. (64 / 7) + 1) may be included for each message ID acked.
-
that many byte representation of Alice's IP address, if size > 0
-
2 byte Alice's port number
-
Alice's or Charlie's 32-byte introduction key
-
N bytes, currently uninterpreted
-
-
Crypto Key used:
-
-Listed in order of occurrence:
-
-When sent from Alice to Bob:
-Alice/Bob sessionKey
-(The protocol also permits Bob's introKey if Alice and Bob do not have an established session,
- but in the current implementation Alice always selects a Bob that is established.
- As of release 0.9.15, Bob will reject PeerTests from peers without an established session.)
-
-When sent from Bob to Charlie:
-Bob/Charlie sessionKey
-
-When sent from Charlie to Bob:
-Bob/Charlie sessionKey
-
-When sent from Bob to Alice:
-Alice's introKey, as received in the Peer Test message from Alice
-
-When sent from Charlie to Alice:
-Alice's introKey, as received in the Peer Test message from Bob
-
-When sent from Alice to Charlie:
-Charlie's introKey, as received in the Peer Test message from Charlie
-
-
-
MAC Key used:
-
-Listed in order of occurrence:
-
-When sent from Alice to Bob:
-Alice/Bob MAC Key
-(The protocol also permits Bob's introKey if Alice and Bob do not have an established session,
- but in the current implementation Alice always selects a Bob that is established.
- As of release 0.9.15, Bob will reject PeerTests from peers without an established session.)
-
-When sent from Bob to Charlie:
-Bob/Charlie MAC Key
-
-When sent from Charlie to Bob:
-Bob/Charlie MAC Key
-
-When sent from Bob to Alice:
-Alice's introKey, as received in the Peer Test message from Alice
-
-When sent from Charlie to Alice:
-Alice's introKey, as received in the Peer Test message from Bob
-
-When sent from Alice to Charlie:
-Charlie's introKey, as received in the Peer Test message from Charlie
-
-
-
-
-
Message format:
-
-{% highlight lang='dataspec' %}
- +----+----+----+----+----+----+----+----+
- | test nonce |size| Alice IP addr
- +----+----+----+----+----+----+----+----+
- | Port (A)| |
- +----+----+----+ +
- | Alice or Charlie's |
- + introduction key (Alice's is sent to +
- | Bob and Charlie, while Charlie's is |
- + sent to Alice) +
- | |
- + +----+----+----+----+----+
- | | arbitrary amount of |
- +----+----+----+ |
- | uninterpreted data |
- ~ . . . ~
-{% endhighlight %}
-
-
-Typical size including header, in current implementation: 80 bytes
-(before non-mod-16 padding)
-
-
-
Notes
-
-When sent by Alice, IP address size is 0, IP address is not present, and port is 0,
-as Bob and Charlie do not use the data;
-the point is to determine Alice's true IP address/port and tell Alice;
-Bob and Charlie don't care what Alice thinks her address is.
-
-When sent by Bob or Charlie, IP and port are present, and
-IP address is always 4 bytes in the current implementation.
-IPv6 testing is not currently supported.
-
-IPv6 Notes:
-Only testing of IPv4 addresses is supported.
-Therefore, all Alice-Bob and Alice-Charlie communication must be via IPv4.
-Bob-Charlie communication, however, may be via IPv4 or IPv6.
-Alice's address, when specified in the PeerTest message, must be 4 bytes.
-
-A peer must maintain a table of active test states (nonces).
-On reception of a Peer Test message, look up the nonce in the table.
-If found, it's an existing test and you know your role (Alice, Bob, or Charlie).
-Otherwise, if the IP is not present and the port is 0, this is a new test and you are Bob.
-Otherwise, this is a new test and you are Charlie.
-
-As of release 0.9.15, Alice must have an established session with Bob and use the session key.
-
-
-
HolePunch
-
-A HolePunch is simply a UDP packet with no data.
-It is unauthenticated and unencrypted.
-It does not contain a SSU header, so it does not have a message type number.
-It is sent from Charlie to Alice as a part of the Introduction sequence.
-
-
-Minimal data message (no fragments, no ACKs, no NACKs, etc)
-(Size: 39 bytes)
-
-{% highlight lang='dataspec' %}
- +----+----+----+----+----+----+----+----+
- | MAC |
- + +
- | |
- +----+----+----+----+----+----+----+----+
- | IV |
- + +
- | |
- +----+----+----+----+----+----+----+----+
- |flag| time |flag|#frg| |
- +----+----+----+----+----+----+----+ +
- | padding to fit a full AES256 block |
- +----+----+----+----+----+----+----+----+
-{% endhighlight %}
-
-Minimal data message with payload
-(Size: 46+fragmentSize bytes)
-
-{% highlight lang='dataspec' %}
- +----+----+----+----+----+----+----+----+
- | MAC |
- + +
- | |
- +----+----+----+----+----+----+----+----+
- | IV |
- + +
- | |
- +----+----+----+----+----+----+----+----+
- |flag| time |flag|#frg|
- +----+----+----+----+----+----+----+----+
- messageId | frag info | |
- +----+----+----+----+----+----+ +
- | that many bytes of fragment data |
- ~ . . . ~
- | |
- +----+----+----+----+----+----+----+----+
-{% endhighlight %}
-
-
-{% endblock %}
diff --git a/i2p2www/spec/ssu.rst b/i2p2www/spec/ssu.rst
new file mode 100644
index 00000000..c5ad10a9
--- /dev/null
+++ b/i2p2www/spec/ssu.rst
@@ -0,0 +1,1150 @@
+==========================
+SSU Protocol Specification
+==========================
+.. meta::
+ :lastupdated: February 2015
+ :accuratefor: 0.9.18
+
+
+Overview
+========
+
+See [SSU]_ for an overview of the SSU transport.
+
+
+.. _dh:
+
+DH Key Exchange
+===============
+
+The initial 2048-bit DH key exchange is described on the SSU page [SSU-KEYS]_.
+This exchange uses the same shared prime as that used for I2P's ElGamal
+encryption [CRYPTO-ELG]_.
+
+
+.. _header:
+
+Message Header
+==============
+
+All UDP datagrams begin with a 16 byte MAC (Message Authentication Code) and a
+16 byte IV (Initialization Vector) followed by a variable-size payload
+encrypted with the appropriate key. The MAC used is HMAC-MD5, truncated to 16
+bytes, while the key is a full 32 byte AES256 key. The specific construct of
+the MAC is the first 16 bytes from::
+
+ HMAC-MD5(encryptedPayload + IV + (payloadLength ^ protocolVersion), macKey)
+
+where '+' means append and '^' means exclusive-or.
+
+The IV is generated randomly for each packet. The encryptedPayload is the
+encrypted version of the message starting with the flag byte
+(encrypt-then-MAC). The payloadLength used in the MAC is a 2 byte unsigned
+integer. Note that protocolVersion is 0, so the exclusive-or is a no-op. The
+macKey is either the introduction key or is constructed from the exchanged DH
+key (see details below), as specified for each message below.
+
+**WARNING** - the HMAC-MD5-128 used here is non-standard, see [CRYPTO-HMAC]_
+for details.
+
+The payload itself (that is, the message starting with the flag byte) is
+AES256/CBC encrypted with the IV and the sessionKey, with replay prevention
+addressed within its body, explained below.
+
+The protocolVersion is a 2 byte unsigned integer and is currently set to 0.
+Peers using a different protocol version will not be able to communicate with
+this peer, though earlier versions not using this flag are.
+
+HMAC Specification
+------------------
+
+* Inner padding: 0x36...
+* Outer padding: 0x5C...
+* Key: 32 bytes
+* Hash digest function: MD5, 16 bytes
+* Block size: 64 bytes
+* MAC size: 16 bytes
+* Example C implementations:
+
+ * hmac.h in i2pd [I2PD-SRC]_
+ * I2PHMAC.cpp in i2pcpp [I2PCPP-SRC]_.
+
+* Example Java implementation:
+
+ * I2PHMac.java in I2P [I2P-SRC]_
+
+Session Key Details
+-------------------
+
+The 32-byte session key is created as follows:
+
+1. Take the exchanged DH key, represented as a positive minimal-length
+ BigInteger byte array (two's complement big-endian)
+
+2. If the most significant bit is 1 (i.e. array[0] & 0x80 != 0), prepend a 0x00
+ byte, as in Java's BigInteger.toByteArray() representation
+
+3. If the byte array is greater than or equal to 32 bytes, use the first (most
+ significant) 32 bytes
+
+4. If the byte array is less than 32 bytes, append 0x00 bytes to extend to 32
+ bytes. *Very unlikely - See note below.*
+
+MAC Key Details
+---------------
+
+The 32-byte MAC key is created as follows:
+
+1. Take the exchanged DH key byte array, prepended with a 0x00 byte if
+ necessary, from step 2 in the Session Key Details above.
+
+2. If that byte array is greater than or equal to 64 bytes, the MAC key is
+ bytes 33-64 from that byte array.
+
+3. If that byte array is less than 64 bytes, the MAC key is the SHA-256 Hash of
+ that byte array. *As of release 0.9.8. See note below.*
+
+Important note
+``````````````
+Code before release 0.9.8 was broken and did not correctly handle DH key byte
+arrays between 32 and 63 bytes (steps 3 and 4 above) and the connection will
+fail. As these cases didn't ever work, they were redefined as described above
+for release 0.9.8, and the 0-32 byte case was redefined as well. Since the
+nominal exchanged DH key is 256 bytes, the chances of the mininimal
+representation being less than 64 bytes is vanishingly small.
+
+Header Format
+-------------
+
+Within the AES encrypted payload, there is a minimal common structure to the
+various messages - a one byte flag and a four byte sending timestamp (seconds
+since the unix epoch). The flag byte contains the following bitfields:
+
+.. raw:: html
+
+ {% highlight %}
+ Bit order: 76543210 (bit 7 is MSB)
+
+ bits 7-4: payload type
+ bit 3: rekey, always 0, unimplemented
+ bit 2: extended options included, always 0, unimplemented
+ bits 1-0: reserved, set to 0 for compatibility with future uses
+{% endhighlight %}
+
+The header format is:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
+Header: 37+ bytes
+ Encryption starts with the flag byte.
+ +----+----+----+----+----+----+----+----+
+ | MAC |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | IV |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ |flag| time | |
+ +----+----+----+----+----+ +
+ | keying material (optional) |
+ + +
+ | |
+ ~ ~
+ | |
+ + +----+----+----+
+ | |#opt| |
+ +----+----+----+----+----+----+ +
+ | #opt extended option bytes (optional) |
+ ~ ~
+ ~ ~
+ +----+----+----+----+----+----+----+----+
+{% endhighlight %}
+
+Note that rekeying and extended options are unimplemented, so the current
+header size is exactly 37 bytes.
+
+.. _rekey:
+
+Rekeying
+--------
+
+If the rekey flag is set, 64 bytes of keying material follow the timestamp.
+
+When rekeying, the first 32 bytes of the keying material is fed into a SHA256
+to produce the new MAC key, and the next 32 bytes are fed into a SHA256 to
+produce the new session key, though the keys are not immediately used. The
+other side should also reply with the rekey flag set and that same keying
+material. Once both sides have sent and received those values, the new keys
+should be used and the previous keys discarded. It may be useful to keep the
+old keys around briefly, to address packet loss and reordering.
+
+NOTE: Rekeying is currently unimplemented.
+
+.. _extend:
+
+Extended Options
+----------------
+
+If the extended options flag is set, a one byte option size value is appended,
+followed by that many extended option bytes.
+
+NOTE: Extended options is currently unimplemented.
+
+
+Padding
+=======
+
+All messages contain 0 or more bytes of padding. Each message must be padded
+to a 16 byte boundary, as required by the AES256 encryption layer
+[CRYPTO-AES]_.
+
+Through release 0.9.7, messages were only padded to the next 16 byte boundary,
+and messages not a multiple of 16 bytes could possibly be invalid.
+
+As of release 0.9.7, messages may be padded to any length as long as the
+current MTU is honored. Any extra 1-15 padding bytes beyond the last block of
+16 bytes cannot be encrypted or decrypted and will be ignored. However, the
+full length and all padding is included in the MAC calculation.
+
+As of release 0.9.8, transmitted messages are not necessarily a multiple of 16
+bytes. The SessionConfirmed message is an exception, see below.
+
+
+Keys
+====
+
+Signatures in the SessionCreated and SessionConfirmed messages are generated
+using the [SigningPublicKey]_ from the [RouterIdentity]_ which is distributed
+out-of-band by publishing in the network database, and the associated
+[SigningPrivateKey]_.
+
+Through release 0.9.15, the signature algorithm was always DSA, with a 40 byte
+signature.
+
+As of release 0.9.16, the signature algorithm may be specified by a a
+[KeyCertificate]_ in Bob's [RouterIdentity]_.
+
+Both introduction keys and session keys are 32 bytes, and are defined by the
+Common structures specification [SESSIONKEY]_. The key used for the MAC and
+encryption is specified for each message below.
+
+Introduction keys are delivered through an external channel (the network
+database, where they are identical to the router Hash for now).
+
+
+Notes
+=====
+
+IPv6
+----
+
+The protocol specification allows both 4-byte IPv4 and 16-byte IPv6 addresses.
+SSU-over-IPv6 is supported as of version 0.9.8. See the documentation of
+individual messages below for details on IPv6 support.
+
+.. _time:
+
+Timestamps
+----------
+
+While most of I2P uses 8-byte [Date]_ timestamps with millisecond resolution,
+SSU uses a 4-byte timestamp with one-second resolution.
+
+
+Messages
+========
+
+There are 10 messages (payload types) defined:
+
+==== ================ =====
+Type Message Notes
+==== ================ =====
+ 0 SessionRequest
+ 1 SessionCreated
+ 2 SessionConfirmed
+ 3 RelayRequest
+ 4 RelayResponse
+ 5 RelayIntro
+ 6 Data
+ 7 PeerTest
+ 8 SessionDestroyed Implemented as of 0.8.9
+ n/a HolePunch
+==== ================ =====
+
+.. _sessionRequest:
+
+SessionRequest (type 0)
+-----------------------
+
+This is the first message sent to establish a session.
+
+==================== ======================================================
+**Peer:** Alice to Bob
+**Data:** * 256 byte X, to begin the DH agreement
+ * 1 byte IP address size
+ * that many byte representation of Bob's IP address
+ * N bytes, currently uninterpreted
+**Crypto Key used:** Bob's introKey, as retrieved from the network database
+**MAC Key used:** Bob's introKey, as retrieved from the network database
+==================== ======================================================
+
+Message format:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | X, as calculated from DH |
+ ~ . . . ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ |size| that many byte IP address (4-16) |
+ +----+----+----+----+----+----+----+----+
+ | arbitrary amount of uninterpreted data|
+ ~ . . . ~
+{% endhighlight %}
+
+Typical size including header, in current implementation: 304 (IPv4) or 320
+(IPv6) bytes (before non-mod-16 padding)
+
+Notes
+`````
+* IPv4 and IPv6 addresses are supported.
+
+* The uninterpreted data could possibly be used in the future for challenges.
+
+.. _sessioncreated:
+
+SessionCreated (type 1)
+-----------------------
+
+This is the response to a SessionRequest_.
+
+==================== ==========================================================
+**Peer:** Bob to Alice
+**Data:** * 256 byte Y, to complete the DH agreement
+ * 1 byte IP address size
+ * that many byte representation of Alice's IP address
+ * 2 byte Alice's port number
+ * 4 byte relay (introduction) tag which Alice can publish
+ (else 0x00000000)
+ * 4 byte timestamp (seconds from the epoch) for use in the
+ DSA signature
+ * Bob's [Signature]_ of the critical exchanged data (X +
+ Y + Alice's IP + Alice's port + Bob's IP + Bob's port +
+ Alice's new relay tag + Bob's signed on time), encrypted
+ with another layer of encryption using the negotiated
+ sessionKey. The IV is reused here. See notes for length
+ information.
+ * 0-15 bytes of padding of the signature, using random
+ data, to a multiple of 16 bytes, so that the signature +
+ padding may be encrypted with an additional layer of
+ encryption using the negotiated session key as part of
+ the DSA block.
+ * N bytes, currently uninterpreted
+**Crypto Key used:** Bob's introKey, with an additional layer of encryption
+ over the 40 byte signature and the following 8 bytes
+ padding.
+**MAC Key used:** Bob's introKey
+==================== ==========================================================
+
+Message format:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | Y, as calculated from DH |
+ ~ . . . ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ |size| that many byte IP address (4-16) |
+ +----+----+----+----+----+----+----+----+
+ | Port (A)| public relay tag | signed
+ +----+----+----+----+----+----+----+----+
+ on time | |
+ +----+----+ +
+ | |
+ + +
+ | signature |
+ + +
+ | |
+ + +
+ | |
+ + +----+----+----+----+----+----+
+ | | (0-15 bytes of padding)
+ +----+----+----+----+----+----+----+----+
+ | |
+ +----+----+ +
+ | arbitrary amount |
+ ~ of uninterpreted data ~
+ ~ . . . ~
+{% endhighlight %}
+
+Typical size including header, in current implementation: 368 bytes (IPv4 or
+IPv6) (before non-mod-16 padding)
+
+Notes
+`````
+* IPv4 and IPv6 addresses are supported.
+
+* If the relay tag is nonzero, Bob is offering to act as an introducer for
+ Alice. Alice may subsequently publish Bob's address and the relay tag in the
+ network database.
+
+* For the signature, Bob must use his external port, as that what Alice will
+ use to verify. If Bob's NAT/firewall has mapped his internal port to a
+ different external port, and Bob is unaware of it, the verification by Alice
+ will fail.
+
+* See the Keys_ section above for details on signatures. Alice already has
+ Bob's public signing key, from the network database.
+
+* Through release 0.9.15, the signature was always a 40 byte DSA signature and
+ the padding was always 8 bytes. As of release 0.9.16, the signature type and
+ length are implied by the type of the [SigningPublicKey]_ in Bob's
+ [RouterIdentity]_. The padding is as necessary to a multiple of 16 bytes.
+
+* This is the only message that uses the sender's intro key. All others use the
+ receiver's intro key or the established session key.
+
+* Signed-on time appears to be unused or unverified in the current
+ implementation.
+
+* The uninterpreted data could possibly be used in the future for challenges.
+
+.. _sessionconfirmed:
+
+SessionConfirmed (type 2)
+-------------------------
+
+This is the response to a SessionCreated_ message and the last step in
+establishing a session. There may be multiple SessionConfirmed messages
+required if the Router Identity must be fragmented.
+
+==================== ==========================================================
+**Peer:** Alice to Bob
+**Data:** * 1 byte identity fragment info::
+
+ Bit order: 76543210 (bit 7 is MSB)
+ bits 7-4: current identity fragment # 0-14
+ bits 3-0: total identity fragments (F) 1-15
+
+ * 2 byte size of the current identity fragment
+ * that many byte fragment of Alice's [RouterIdentity]_
+ * After the last identity fragment only:
+
+ * 4 byte signed-on time
+
+ * N bytes padding, currently uninterpreted
+ * After the last identity fragment only:
+
+ * The remaining bytes contain Alice's [Signature]_ of
+ the critical exchanged data (X + Y + Alice's IP +
+ Alice's port + Bob's IP + Bob's port + Alice's new
+ relay tag + Alice's signed on time). See notes for
+ length information.
+**Crypto Key used:** Alice/Bob sessionKey, as generated from the DH exchange
+**MAC Key used:** Alice/Bob MAC Key, as generated from the DH exchange
+==================== ==========================================================
+
+**Fragment 0 through F-2** (only if F > 1; currently unused, see notes below):
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ |info| cursize | |
+ +----+----+----+ +
+ | fragment of Alice's full |
+ ~ Router Identity ~
+ ~ . . . ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | arbitrary amount of uninterpreted data|
+ ~ . . . ~
+{% endhighlight %}
+
+**Fragment F-1 (last or only fragment):**
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ |info| cursize | |
+ +----+----+----+ +
+ | last fragment of Alice's full |
+ ~ Router Identity ~
+ ~ . . . ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | signed on time | |
+ +----+----+----+----+ +
+ | arbitrary amount of uninterpreted |
+ ~ data, until the signature at ~
+ ~ end of the current packet ~
+ | Packet length must be mult. of 16 |
+ +----+----+----+----+----+----+----+----+
+ + +
+ | |
+ + +
+ | signature |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+{% endhighlight %}
+
+Typical size including header, in current implementation: 480 bytes (before
+non-mod-16 padding)
+
+Notes
+`````
+* In the current implementation, the maximum fragment size is 512 bytes. This
+ should be extended so that longer signatures will work without fragmentation.
+ The current implementation does not correctly process signatures split across
+ two fragments.
+
+* The typical [RouterIdentity]_ is 387 bytes, so no fragmentation is ever
+ necessary. If new crypto extends the size of the RouterIdentity, the
+ fragmentation scheme must be tested carefully.
+
+* There is no mechanism for requesting or redelivering missing fragments.
+
+* The total fragments field F must be set identically in all fragments.
+
+* See the Keys_ section above for details on DSA signatures.
+
+* Signed-on time appears to be unused or unverified in the current
+ implementation.
+
+* Since the signature is at the end, the padding in the last or only packet
+ must pad the total packet to a multiple of 16 bytes, or the signature will
+ not get decrypted correctly. This is different from all the other message
+ types, where the padding is at the end.
+
+* Through release 0.9.15, the signature was always a 40 byte DSA signature. As
+ of release 0.9.16, the signature type and length are implied by the type of
+ the [SigningPublicKey]_ in Alice's [RouterIdentity]_. The padding is as
+ necessary to a multiple of 16 bytes.
+
+.. _sessiondestroyed:
+
+SessionDestroyed (type 8)
+-------------------------
+
+The SessionDestroyed message was implemented (reception only) in release 0.8.1,
+and is sent as of release 0.8.9.
+
+==================== ============================
+**Peer:** Alice to Bob or Bob to Alice
+**Data:** none
+**Crypto Key used:** Alice/Bob sessionKey
+**MAC Key used:** Alice/Bob MAC Key
+==================== ============================
+
+This message does not contain any data. Typical size including header, in
+current implementation: 48 bytes (before non-mod-16 padding)
+
+Notes
+`````
+* Destroy messages received with the sender's or receiver's intro key will be
+ ignored.
+
+
+.. _relayrequest:
+
+RelayRequest (type 3)
+---------------------
+
+This is the first message sent from Alice to Bob to request an introduction to
+Charlie.
+
+==================== ==========================================================
+**Peer:** Alice to Bob
+**Data:** * 4 byte relay (introduction) tag, nonzero, as received by
+ Alice in the SessionCreated_ message from Bob
+ * 1 byte IP address size
+ * that many byte representation of Alice's IP address
+ * 2 byte port number (of Alice)
+ * 1 byte challenge size
+ * that many bytes to be relayed to Charlie in the intro
+ * Alice's 32-byte introduction key (so Bob can reply with
+ Charlie's info)
+ * 4 byte nonce of Alice's relay request
+ * N bytes, currently uninterpreted
+**Crypto Key used:** Bob's introKey, as retrieved from the network database (or
+ Alice/Bob sessionKey, if established)
+**MAC Key used:** Bob's introKey, as retrieved from the network database (or
+ Alice/Bob MAC Key, if established)
+==================== ==========================================================
+
+Message format:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | relay tag |size| Alice IP addr
+ +----+----+----+----+----+----+----+----+
+ | Port (A)|size| challenge bytes |
+ +----+----+----+----+ +
+ | to be delivered to Charlie |
+ +----+----+----+----+----+----+----+----+
+ | Alice's intro key |
+ + +
+ | |
+ + +
+ | |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | nonce | |
+ +----+----+----+----+ +
+ | arbitrary amount of uninterpreted data|
+ ~ . . . ~
+{% endhighlight %}
+
+Typical size including header, in current implementation: 96 bytes (no Alice IP
+included) or 112 bytes (4-byte Alice IP included) (before non-mod-16 padding)
+
+Notes
+`````
+* The IP address is only included if it is be different than the packet's
+ source address and port. In the current implementation, the IP length is
+ always 0 and the port is always 0, and the receiver should use the packet's
+ source address and port.
+
+* This message may be sent via IPv4 or IPv6. If IPv6, Alice must include her
+ IPv4 address and port.
+
+* If Alice includes her address/port, Bob may perform additional validation
+ before continuing.
+
+* Challenge is unimplemented, challenge size is always zero
+
+* There are no plans to implement relaying for IPv6.
+
+* Prior to release 0.9.12, Bob's intro key was always used. As of release
+ 0.9.12, the session key is used if there is an established session between
+ Alice and Bob. In practice, there must be an established session, as Alice
+ will only get the nonce (introduction tag) from the session created message,
+ and Bob will mark the introduction tag invalid once the session is destroyed.
+
+.. _relayresponse:
+
+RelayResponse (type 4)
+----------------------
+
+This is the response to a RelayRequest_ and is sent from Bob to Alice.
+
+==================== ==========================================================
+**Peer:** Bob to Alice
+**Data:** * 1 byte IP address size
+ * that many byte representation of Charlie's IP address
+ * 2 byte Charlie's port number
+ * 1 byte IP address size
+ * that many byte representation of Alice's IP address
+ * 2 byte Alice's port number
+ * 4 byte nonce sent by Alice
+ * N bytes, currently uninterpreted
+**Crypto Key used:** Alice's introKey, as received in the Relay Request (or
+ Alice/Bob sessionKey, if established)
+**MAC Key used:** Alice's introKey, as received in the Relay Request (or
+ Alice/Bob MAC Key, if established)
+==================== ==========================================================
+
+Message format:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ |size| Charlie IP | Port (C)|size|
+ +----+----+----+----+----+----+----+----+
+ | Alice IP | Port (A)| nonce
+ +----+----+----+----+----+----+----+----+
+ | arbitrary amount of |
+ +----+----+ +
+ | uninterpreted data |
+ ~ . . . ~
+{% endhighlight %}
+
+Typical size including header, in current implementation: 64 (Alice IPv4) or 80
+(Alice IPv6) bytes (before non-mod-16 padding)
+
+Notes
+`````
+* This message may be sent via IPv4 or IPv6.
+
+* Alice's IP address/port are the apparent IP/port that Bob received the
+ RelayRequest on (not necessarily the IP Alice included in the RelayRequest),
+ and may be IPv4 or IPv6. Alice currently ignores these on receive.
+
+* Charlie's IP address must be IPv4, as that is the address that Alice will
+ send the SessionRequest to after the Hole Punch.
+
+* There are no plans to implement relaying for IPv6.
+
+* Prior to release 0.9.12, Alice's intro key was always used. As of release
+ 0.9.12, the session key is used if there is an established session between
+ Alice and Bob.
+
+.. _relayintro:
+
+RelayIntro (type 5)
+-------------------
+
+This is the introduction for Alice, which is sent from Bob to Charlie.
+
+==================== =====================================================
+**Peer:** Bob to Charlie
+**Data:** * 1 byte IP address size
+ * that many byte representation of Alice's IP address
+ * 2 byte port number (of Alice)
+ * 1 byte challenge size
+ * that many bytes relayed from Alice
+ * N bytes, currently uninterpreted
+**Crypto Key used:** Bob/Charlie sessionKey
+**MAC Key used:** Bob/Charlie MAC Key
+==================== =====================================================
+
+Message format:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ |size| Alice IP | Port (A)|size|
+ +----+----+----+----+----+----+----+----+
+ | that many bytes of challenge |
+ + +
+ | data relayed from Alice |
+ +----+----+----+----+----+----+----+----+
+ | arbitrary amount of uninterpreted data|
+ ~ . . . ~
+{% endhighlight %}
+
+Typical size including header, in current implementation: 48 bytes (before
+non-mod-16 padding)
+
+Notes
+`````
+* Alice's IP address is always 4 bytes in the current implementation, because
+ Alice is trying to connect to Charlie via IPv4.
+
+* This message must be sent via an established IPv4 connection, as that's the
+ only way that Bob knows Charlie's IPv4 address to return to Alice in the
+ RelayResponse_.
+
+* Challenge is unimplemented, challenge size is always zero
+
+.. _data:
+
+Data (type 6)
+-------------
+
+This message is used for data transport and acknowledgment.
+
+==================== ==========================================================
+**Peer:** Any
+**Data:** * 1 byte flags::
+
+ Bit order: 76543210 (bit 7 is MSB)
+ bit 7: explicit ACKs included
+ bit 6: ACK bitfields included
+ bit 5: reserved
+ bit 4: explicit congestion notification (ECN)
+ bit 3: request previous ACKs
+ bit 2: want reply
+ bit 1: extended data included (unused, never set)
+ bit 0: reserved
+
+ * if explicit ACKs are included:
+
+ * a 1 byte number of ACKs
+ * that many 4 byte MessageIds being fully ACKed
+
+ * if ACK bitfields are included:
+
+ * a 1 byte number of ACK bitfields
+ * that many 4 byte MessageIds + a 1 or more byte ACK
+ bitfield. The bitfield uses the 7 low bits of each
+ byte, with the high bit specifying whether an
+ additional bitfield byte follows it (1 = true, 0 = the
+ current bitfield byte is the last). These sequence of
+ 7 bit arrays represent whether a fragment has been
+ received - if a bit is 1, the fragment has been
+ received. To clarify, assuming fragments 0, 2, 5, and
+ 9 have been received, the bitfield bytes would be as
+ follows::
+
+ byte 0:
+ Bit order: 76543210 (bit 7 is MSB)
+ bit 7: 1 (further bitfield bytes follow)
+ bit 6: 0 (fragment 6 not received)
+ bit 5: 1 (fragment 5 received)
+ bit 4: 0 (fragment 4 not received)
+ bit 3: 0 (fragment 3 not received)
+ bit 2: 1 (fragment 2 received)
+ bit 1: 0 (fragment 1 not received)
+ bit 0: 1 (fragment 0 received)
+ byte 1:
+ Bit order: 76543210 (bit 7 is MSB)
+ bit 7: 0 (no further bitfield bytes)
+ bit 6: 0 (fragment 13 not received)
+ bit 5: 0 (fragment 12 not received)
+ bit 4: 0 (fragment 11 not received)
+ bit 3: 0 (fragment 10 not received)
+ bit 2: 1 (fragment 9 received)
+ bit 1: 0 (fragment 8 not received)
+ bit 0: 0 (fragment 7 not received)
+
+ * If extended data included:
+
+ * 1 byte data size
+ * that many bytes of extended data (currently
+ uninterpreted)
+
+ * 1 byte number of fragments (can be zero)
+ * If nonzero, that many message fragments. Each fragment
+ contains:
+
+ * 4 byte messageId
+ * 3 byte fragment info::
+
+ Bit order: 76543210 (bit 7 is MSB)
+ bits 23-17: fragment # 0 - 127
+ bit 16: isLast (1 = true)
+ bits 15-14: unused, set to 0 for compatibility with
+ future uses
+ bits 13-0: fragment size 0 - 16383
+
+ * that many bytes
+
+ * N bytes padding, uninterpreted
+**Crypto Key used:** Alice/Bob sessionKey
+**MAC Key used:** Alice/Bob MAC Key
+==================== ==========================================================
+
+Message format:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ |flag| (additional headers, determined |
+ +----+ +
+ ~ by the flags, such as ACKs or ~
+ | bitfields |
+ +----+----+----+----+----+----+----+----+
+ |#frg| messageId | frag info |
+ +----+----+----+----+----+----+----+----+
+ | that many bytes of fragment data |
+ ~ . . . ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | messageId | frag info | |
+ +----+----+----+----+----+----+----+ +
+ | that many bytes of fragment data |
+ ~ . . . ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | messageId | frag info | |
+ +----+----+----+----+----+----+----+ +
+ | that many bytes of fragment data |
+ ~ . . . ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | arbitrary amount of uninterpreted data|
+ ~ . . . ~
+{% endhighlight %}
+
+Notes
+`````
+* The current implementation adds a limited number of duplicate acks for
+ messages previously acked, if space is available.
+
+* If the number of fragments is zero, this is an ack-only or keepalive message.
+
+* The ECN feature is unimplemented, and the bit is never set.
+
+* In the current implementation, the want reply bit is set when the number of
+ fragments is greater then zero, and not set when there are no fragments.
+
+* Extended data is unimplemented and never present.
+
+* Reception of multiple fragments is supported in all releases. Transmission of
+ multiple fragments is implemented in release 0.9.16.
+
+* As currently implemented, maximum fragments is 64 (maximum fragment number =
+ 63).
+
+* As currently implemented, maximum fragment size is of course less than the
+ MTU.
+
+* Take care not to exceed the maximum MTU even if there is a large number of
+ ACKs to send.
+
+* The protocol allows zero-length fragments but there's no reason to send them.
+
+* In SSU, the data uses a short 5-byte I2NP header followed by the payload of
+ the I2NP message instead of the standard 16-byte I2NP header. The short I2NP
+ header consists only of the one-byte I2NP type and 4-byte expiration in
+ seconds. The I2NP message ID is used as the message ID for the fragment. The
+ I2NP size is assembled from the fragment sizes. The I2NP checksum is not
+ required as UDP message integrity is ensured by decryption.
+
+* Message IDs are not sequence numbers and are not consecutive. SSU does not
+ guarantee in-order delivery. While we use the I2NP message ID as the SSU
+ message ID, from the SSU protocol view, they are random numbers. In fact,
+ since the router uses a single Bloom filter for all peers, the message ID
+ must be an actual random number.
+
+* Because there are no sequence numbers, there is no way to be sure an ACK was
+ received. The current implementation routinely sends a large amount of
+ duplicate ACKs. Duplicate ACKs should not be taken as an indication of
+ congestion.
+
+* ACK Bitfield notes: The receiver of a data packet does not know how many
+ fragments are in the message unless it has received the last fragment.
+ Therefore, the number of bitfield bytes sent in response may be less or more
+ than the number of fragments divided by 7. For example, if the highest
+ fragment the receiver has seen is number 4, only one byte is required to be
+ sent, even if there may be 13 fragments total. Up to 10 bytes (i.e. (64 / 7)
+ + 1) may be included for each message ID acked.
+
+.. _peertest:
+
+PeerTest (type 7)
+-----------------
+
+See [SSU-PEERTEST]_ for details.
+
+==================== ==========================================================
+**Peer:** Any
+**Data:** * 4 byte nonce
+ * 1 byte IP address size (may be zero)
+ * that many byte representation of Alice's IP address, if
+ size > 0
+ * 2 byte Alice's port number
+ * Alice's or Charlie's 32-byte introduction key
+ * N bytes, currently uninterpreted
+
+**Crypto Key used:** Listed in order of occurrence:
+
+ 1. When sent from Alice to Bob: Alice/Bob sessionKey
+
+ (The protocol also permits Bob's introKey if Alice and
+ Bob do not have an established session, but in the
+ current implementation Alice always selects a Bob that
+ is established. As of release 0.9.15, Bob will reject
+ PeerTests from peers without an established session.)
+
+ 2. When sent from Bob to Charlie: Bob/Charlie sessionKey
+
+ 3. When sent from Charlie to Bob: Bob/Charlie sessionKey
+
+ 4. When sent from Bob to Alice: Alice's introKey, as
+ received in the PeerTest message from Alice
+
+ 5. When sent from Charlie to Alice: Alice's introKey, as
+ received in the PeerTest message from Bob
+
+ 6. When sent from Alice to Charlie: Charlie's introKey, as
+ received in the PeerTest message from Charlie
+
+**MAC Key used:** Listed in order of occurrence:
+
+ 1. When sent from Alice to Bob: Alice/Bob MAC Key
+
+ (The protocol also permits Bob's introKey if Alice and
+ Bob do not have an established session, but in the
+ current implementation Alice always selects a Bob that
+ is established. As of release 0.9.15, Bob will reject
+ PeerTests from peers without an established session.)
+
+ 2. When sent from Bob to Charlie: Bob/Charlie MAC Key
+
+ 3. When sent from Charlie to Bob: Bob/Charlie MAC Key
+
+ 4. When sent from Bob to Alice: Alice's introKey, as
+ received in the PeerTest message from Alice
+
+ 5. When sent from Charlie to Alice: Alice's introKey, as
+ received in the PeerTest message from Bob
+
+ 6. When sent from Alice to Charlie: Charlie's introKey, as
+ received in the PeerTest message from Charlie
+==================== ==========================================================
+
+Message format:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | test nonce |size| Alice IP addr
+ +----+----+----+----+----+----+----+----+
+ | Port (A)| |
+ +----+----+----+ +
+ | Alice or Charlie's |
+ + introduction key (Alice's is sent to +
+ | Bob and Charlie, while Charlie's is |
+ + sent to Alice) +
+ | |
+ + +----+----+----+----+----+
+ | | arbitrary amount of |
+ +----+----+----+ |
+ | uninterpreted data |
+ ~ . . . ~
+{% endhighlight %}
+
+Typical size including header, in current implementation: 80 bytes (before
+non-mod-16 padding)
+
+Notes
+`````
+* When sent by Alice, IP address size is 0, IP address is not present, and port
+ is 0, as Bob and Charlie do not use the data; the point is to determine
+ Alice's true IP address/port and tell Alice; Bob and Charlie don't care what
+ Alice thinks her address is.
+
+* When sent by Bob or Charlie, IP and port are present, and IP address is
+ always 4 bytes in the current implementation. IPv6 testing is not currently
+ supported.
+
+* IPv6 Notes: Only testing of IPv4 addresses is supported. Therefore, all
+ Alice-Bob and Alice-Charlie communication must be via IPv4. Bob-Charlie
+ communication, however, may be via IPv4 or IPv6. Alice's address, when
+ specified in the PeerTest message, must be 4 bytes.
+
+* A peer must maintain a table of active test states (nonces). On reception of
+ a PeerTest message, look up the nonce in the table. If found, it's an
+ existing test and you know your role (Alice, Bob, or Charlie). Otherwise, if
+ the IP is not present and the port is 0, this is a new test and you are Bob.
+ Otherwise, this is a new test and you are Charlie.
+
+* As of release 0.9.15, Alice must have an established session with Bob and use
+ the session key.
+
+HolePunch
+---------
+
+A HolePunch is simply a UDP packet with no data. It is unauthenticated and
+unencrypted. It does not contain a SSU header, so it does not have a message
+type number. It is sent from Charlie to Alice as a part of the Introduction
+sequence.
+
+
+.. _sampledatagrams:
+
+Sample datagrams
+================
+
+Minimal data message
+--------------------
+
+* no fragments, no ACKs, no NACKs, etc
+* Size: 39 bytes
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | MAC |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | IV |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ |flag| time |flag|#frg| |
+ +----+----+----+----+----+----+----+ +
+ | padding to fit a full AES256 block |
+ +----+----+----+----+----+----+----+----+
+{% endhighlight %}
+
+Minimal data message with payload
+---------------------------------
+
+* Size: 46+fragmentSize bytes
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | MAC |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ | IV |
+ + +
+ | |
+ +----+----+----+----+----+----+----+----+
+ |flag| time |flag|#frg|
+ +----+----+----+----+----+----+----+----+
+ messageId | frag info | |
+ ----+----+----+----+----+----+ +
+ | that many bytes of fragment data |
+ ~ . . . ~
+ | |
+ +----+----+----+----+----+----+----+----+
+{% endhighlight %}
+
+
+References
+==========
+
+.. [CRYPTO-AES]
+ {{ site_url('docs/how/cryptography', True) }}#AES
+
+.. [CRYPTO-ELG]
+ {{ site_url('docs/how/cryptography', True) }}#elgamal
+
+.. [CRYPTO-HMAC]
+ {{ site_url('docs/how/cryptography', True) }}#udp
+
+.. [Date]
+ {{ spec_url('common-structures') }}#type-date
+
+.. [I2P-SRC]
+ https://github.com/i2p/i2p.i2p
+
+.. [I2PCPP-SRC]
+ http://{{ i2pconv('git.repo.i2p') }}/w/i2pcpp.git
+
+.. [I2PD-SRC]
+ https://github.com/PurpleI2P/i2pd
+
+.. [KeyCertificate]
+ {{ spec_url('common-structures') }}#key-certificates
+
+.. [RouterIdentity]
+ {{ spec_url('common-structures') }}#struct-routeridentity
+
+.. [SESSIONKEY]
+ {{ spec_url('common-structures') }}#type-sessionkey
+
+.. [Signature]
+ {{ spec_url('common-structures') }}#type-signature
+
+.. [SigningPrivateKey]
+ {{ spec_url('common-structures') }}#type-signingprivatekey
+
+.. [SigningPublicKey]
+ {{ spec_url('common-structures') }}#type-signingpublickey
+
+.. [SSU]
+ {{ site_url('docs/transport/ssu', True) }}
+
+.. [SSU-KEYS]
+ {{ site_url('docs/transport/ssu', True) }}#keys
+
+.. [SSU-PEERTEST]
+ {{ site_url('docs/transport/ssu', True) }}#peerTesting
diff --git a/i2p2www/spec/streaming.html b/i2p2www/spec/streaming.html
deleted file mode 100644
index 9925a405..00000000
--- a/i2p2www/spec/streaming.html
+++ /dev/null
@@ -1,169 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}{% trans %}Streaming Library Specification{% endtrans %}{% endblock %}
-{% block lastupdated %}{% trans %}June 2015{% endtrans %}{% endblock %}
-{% block accuratefor %}0.9.20{% endblock %}
-{% block content %}
-
Random number selected by the packet recipient before sending the first SYN reply packet
-and constant for the life of the connection.
-0 in the SYN message sent by the connection originator, and in subsequent messages, until a SYN reply is received,
-containing the peer's stream ID.
-
-
Random number selected by the packet originator before sending the first SYN packet
-and constant for the life of the connection. May be 0 if unknown, for example in a RESET packet.
-
-
-The sequence for this message, starting at 0 in the SYN message,
-and incremented by 1 in each message except for plain ACKs and retransmissions.
-If the sequenceNum is 0 and the SYN flag is not set, this is a plain ACK
-packet that should not be ACKed.
-
-
-The highest packet sequence number that was received
-on the receiveStreamId. This field is ignored on the initial
-connection packet (where receiveStreamId is the unknown id) or
-if the NO_ACK flag set.
-All packets up to and including this sequence number are ACKed,
-EXCEPT for those listed in NACKs below.
-
-
-How long is the creator of this packet going to wait before
-resending this packet (if it hasn't yet been ACKed). The
-value is seconds since the packet was created.
-Currently ignored on receive.
-
-
{% trans %}Flags and Option Data Fields{% endtrans %}
-
{% trans -%}
-The flags field above specifies some metadata about the packet, and in
-turn may require certain additional data to be included. The flags are
-as follows. Any data structures specified must be added to the options area
-in the given order.
-{%- endtrans %}
-
-
-Bit order: 15....0 (15 is MSB)
-
-
-
Bit
Flag
Option Order
Option Data
Function
-
0
SYNCHRONIZE
--
--
-Similar to TCP SYN. Set in the initial packet and in the first response.
-FROM_INCLUDED and SIGNATURE_INCLUDED must be set also.
-
1
CLOSE
--
--
-Similar to TCP FIN. If the response to a SYNCHRONIZE fits in a single message, the response
-will contain both SYNCHRONIZE and CLOSE.
-SIGNATURE_INCLUDED must be set also.
-
2
RESET
--
--
-Abnormal close.
-SIGNATURE_INCLUDED must be set also.
-Prior to release 0.9.20, due to a bug, FROM_INCLUDED must also be set.
-
-Currently sent only with SYNCHRONIZE, CLOSE, and RESET, where it is required,
-and with ECHO, where it is required for a ping.
-The signature uses the Destination's signing keys
-to sign the entire header and payload with the space in the option data field
-for the signature being set to all zeroes.
-
-Prior to release 0.9.11, the signature was always 40 bytes.
-As of release 0.9.11, the signature may be variable-length, see below for details.
-
4
SIGNATURE_REQUESTED
--
--
-Unused. Requests every packet in the other direction to have SIGNATURE_INCLUDED
-
-Currently sent only with SYNCHRONIZE, where it is required,
-and with ECHO, where it is required for a ping.
-Prior to release 0.9.20, due to a bug, must also be sent with RESET.
-
-Optional delay.
-How many milliseconds the sender of this packet wants the recipient
-to wait before sending any more data.
-A value greater than 60000 indicates choking.
-
-Currently sent with SYNCHRONIZE only.
-Was also sent in retransmitted packets until release 0.9.1.
-
8
PROFILE_INTERACTIVE
--
--
-Unused or ignored; the interactive profile is unimplemented.
-
9
ECHO
--
--
-Unused except by ping programs.
-If set, most other options are ignored. See
-the streaming docs.
-
10
NO_ACK
--
--
-This flag simply tells the recipient to ignore the ackThrough field in the header.
-Currently set in the inital SYN packet, otherwise the ackThrough field is always valid.
-Note that this does not save any space, the ackThrough field is before the flags
-and is always present.
-
11-15
unused
-Set to zero for compatibility with future uses.
-
-
-
Variable Length Signature Notes
-
-Prior to release 0.9.11, the signature in the option field was always 40 bytes.
-As of release 0.9.11, the signature is variable length.
-The Signature type and length are inferred from the type of key used in the FROM_INCLUDED option
-and the Signature documentation.
-
-When a packet contains both FROM_INCLUDED and SIGNATURE_INCLUDED (as in SYNCHRONIZE), the inference may be made directly.
-
-When a packet does not contain FROM_INCLUDED, the inference must be made from a previous SYNCHRONIZE packet.
-
-When a packet does not contain FROM_INCLUDED, and there was no previous SYNCHRONIZE packet
-(for example a stray CLOSE or RESET packet), the inference can be made from the length of the remaining options
-(since SIGNATURE_INCLUDED is the last option), but the packet will probably be discarded anyway, since there is no FROM available
-to validate the signature.
-If more option fields are defined in the future, they must be accounted for.
-
-
-
-
-{% endblock %}
diff --git a/i2p2www/spec/streaming.rst b/i2p2www/spec/streaming.rst
new file mode 100644
index 00000000..f68dbed7
--- /dev/null
+++ b/i2p2www/spec/streaming.rst
@@ -0,0 +1,191 @@
+===============================
+Streaming Library Specification
+===============================
+.. meta::
+ :lastupdated: June 2015
+ :accuratefor: 0.9.20
+
+
+Overview
+========
+
+See [STREAMING]_ for an overview of the Streaming Library.
+
+
+Protocol Specification
+======================
+
+Packet Format
+-------------
+
+The format of a single packet in the streaming protocol is:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | send Stream ID | rcv Stream ID |
+ +----+----+----+----+----+----+----+----+
+ | sequence Num | ack Through |
+ +----+----+----+----+----+----+----+----+
+ | nc | NACKs ...
+ +----+----+----+----+----+----+----+----+
+ | rd | flags | opt size| opt data
+ +----+----+----+----+----+----+----+----+
+ ... |
+ +----+----+----+----+----+----+----+----+
+ | payload ...
+ +----+----+----+-//
+
+ sendStreamId :: 4 byte `Integer`
+ Random number selected by the packet recipient before sending
+ the first SYN reply packet and constant for the life of the
+ connection. 0 in the SYN message sent by the connection
+ originator, and in subsequent messages, until a SYN reply is
+ received, containing the peer's stream ID.
+
+ receiveStreamId :: 4 byte `Integer`
+ Random number selected by the packet originator before
+ sending the first SYN packet and constant for the life of
+ the connection. May be 0 if unknown, for example in a RESET
+ packet.
+
+ sequenceNum :: 4 byte `Integer`
+ The sequence for this message, starting at 0 in the SYN
+ message, and incremented by 1 in each message except for plain
+ ACKs and retransmissions. If the sequenceNum is 0 and the SYN
+ flag is not set, this is a plain ACK packet that should not be
+ ACKed.
+
+ ackThrough :: 4 byte `Integer`
+ The highest packet sequence number that was received on the
+ $receiveStreamId. This field is ignored on the initial
+ connection packet (where $receiveStreamId is the unknown id) or
+ if the NO_ACK flag set. All packets up to and including this
+ sequence number are ACKed, EXCEPT for those listed in NACKs
+ below.
+
+ NACK count :: 1 byte `Integer`
+ The number of 4-byte NACKs in the next field
+
+ NACKs :: $nc * 4 byte `Integer`s
+ Sequence numbers less than ackThrough that are not yet received. Two
+ NACKs of a packet is a request for a 'fast retransmit' of that packet.
+
+ resendDelay :: 1 byte `Integer`
+ How long is the creator of this packet going to wait before
+ resending this packet (if it hasn't yet been ACKed). The value
+ is seconds since the packet was created. Currently ignored on
+ receive.
+
+ flags :: 2 byte value
+ See below.
+
+ option size :: 2 byte `Integer`
+ The number of bytes in the next field
+
+ option data :: 0 or more bytes
+ As specified by the flags. See below.
+
+ payload :: remaining packet size
+{% endhighlight %}
+
+Flags and Option Data Fields
+----------------------------
+
+The flags field above specifies some metadata about the packet, and in turn may
+require certain additional data to be included. The flags are as follows. Any
+data structures specified must be added to the options area in the given order.
+
+Bit order: 15....0 (15 is MSB)
+
+===== ======================== ============ =============== ===============================================================
+ Bit Flag Option Order Option Data Function
+===== ======================== ============ =============== ===============================================================
+ 0 SYNCHRONIZE -- -- Similar to TCP SYN. Set in the initial packet and in the first
+ response. FROM_INCLUDED and SIGNATURE_INCLUDED must also be
+ set.
+
+ 1 CLOSE -- -- Similar to TCP FIN. If the response to a SYNCHRONIZE fits in a
+ single message, the response will contain both SYNCHRONIZE and
+ CLOSE. SIGNATURE_INCLUDED must also be set.
+
+ 2 RESET -- -- Abnormal close. SIGNATURE_INCLUDED must also be set. Prior to
+ release 0.9.20, due to a bug, FROM_INCLUDED must also be set.
+
+ 3 SIGNATURE_INCLUDED 4 variable length Currently sent only with SYNCHRONIZE, CLOSE, and RESET, where
+ [Signature]_ it is required, and with ECHO, where it is required for a
+ ping. The signature uses the Destination's [SigningPrivateKey]_
+ to sign the entire header and payload with the space in the
+ option data field for the signature being set to all zeroes.
+
+ Prior to release 0.9.11, the signature was always 40 bytes. As
+ of release 0.9.11, the signature may be variable-length, see
+ below for details.
+
+ 4 SIGNATURE_REQUESTED -- -- Unused. Requests every packet in the other direction to have
+ SIGNATURE_INCLUDED
+
+ 5 FROM_INCLUDED 2 387+ byte Currently sent only with SYNCHRONIZE, where it is required, and
+ [Destination]_ with ECHO, where it is required for a ping. Prior to release
+ 0.9.20, due to a bug, must also be sent with RESET.
+
+ 6 DELAY_REQUESTED 1 2 byte Optional delay. How many milliseconds the sender of this packet
+ [Integer]_ wants the recipient to wait before sending any more data. A
+ value greater than 60000 indicates choking.
+
+ 7 MAX_PACKET_SIZE_INCLUDED 3 2 byte Currently sent with SYNCHRONIZE only. Was also sent in
+ [Integer]_ retransmitted packets until release 0.9.1.
+
+ 8 PROFILE_INTERACTIVE -- -- Unused or ignored; the interactive profile is unimplemented.
+
+ 9 ECHO -- -- Unused except by ping programs. If set, most other options are
+ ignored. See the streaming docs [STREAMING]_.
+
+ 10 NO_ACK -- -- This flag simply tells the recipient to ignore the ackThrough
+ field in the header. Currently set in the inital SYN packet,
+ otherwise the ackThrough field is always valid. Note that this
+ does not save any space, the ackThrough field is before the
+ flags and is always present.
+
+11-15 unused Set to zero for compatibility with future uses.
+===== ======================== ============ =============== ===============================================================
+
+Variable Length Signature Notes
+```````````````````````````````
+Prior to release 0.9.11, the signature in the option field was always 40 bytes.
+As of release 0.9.11, the signature is variable length. The Signature type and
+length are inferred from the type of key used in the FROM_INCLUDED option and
+the [Signature]_ documentation.
+
+* When a packet contains both FROM_INCLUDED and SIGNATURE_INCLUDED (as in
+ SYNCHRONIZE), the inference may be made directly.
+
+* When a packet does not contain FROM_INCLUDED, the inference must be made from
+ a previous SYNCHRONIZE packet.
+
+* When a packet does not contain FROM_INCLUDED, and there was no previous
+ SYNCHRONIZE packet (for example a stray CLOSE or RESET packet), the inference
+ can be made from the length of the remaining options (since
+ SIGNATURE_INCLUDED is the last option), but the packet will probably be
+ discarded anyway, since there is no FROM available to validate the signature.
+ If more option fields are defined in the future, they must be accounted for.
+
+
+References
+==========
+
+.. [Destination]
+ {{ spec_url('common-structures') }}#struct-destination
+
+.. [Integer]
+ {{ spec_url('common-structures') }}#type-integer
+
+.. [Signature]
+ {{ spec_url('common-structures') }}#type-signature
+
+.. [SigningPrivateKey]
+ {{ spec_url('common-structures') }}#type-signingprivatekey
+
+.. [STREAMING]
+ {{ site_url('docs/api/streaming', True) }}
diff --git a/i2p2www/spec/tunnel-creation.html b/i2p2www/spec/tunnel-creation.html
deleted file mode 100644
index 53c86d90..00000000
--- a/i2p2www/spec/tunnel-creation.html
+++ /dev/null
@@ -1,347 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}Tunnel Creation{% endblock %}
-{% block lastupdated %}September 2014{% endblock %}
-{% block accuratefor %}0.9.15{% endblock %}
-{% block content %}
-
-This page documents the current tunnel build implementation.
-
-
Tunnel Creation Specification
-
-
-This document specifies the details of the encrypted tunnel build messages
-used to create tunnels using a "non-interactive telescoping" method.
-See the tunnel build document
-for an overview of the process, including peer selection and ordering methods.
-
-
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 variable number of records (up to 8) - one for each potential peer in
-the tunnel. Individual records are asymmetrically
-(ElGamal)
-encrypted to be
-read only by a specific peer along the path, while an additional
-symmetric layer of encryption
-(AES)
-is added at each hop so as to expose
-the asymmetrically encrypted record only at the appropriate time.
-
-
Number of Records
-Not all records must contain valid data.
-The build message for a 3-hop tunnel, for example, may contain more records
-to hide the actual length of the tunnel from the participants.
-There are two build message types. The original
-Tunnel Build Message (TBM)
-contains 8 records, which is more than enough for any practical tunnel length.
-The newer
-Variable Tunnel Build Message (VTBM)
-contains 1 to 8 records. The originator may trade off the size of the message
-with the desired amount of tunnel length obfuscation.
-
-In the current network, most tunnels are 2 or 3 hops long.
-The current implementation uses a 5-record VTBM to build tunnels of 4 hops or less,
-and the 8-record TBM for longer tunnels.
-The 5-record VTBM (which, when fragmented, fits in three 1KB tunnel messaages) reduces network traffic
-and increases build sucess rate, because smaller messages are less likely to be dropped.
-
-The reply message must be the same type and length as the build message.
-
-
-
Cleartext of the record, visible only to the hop being asked:
- 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: AES-256 reply IV
- byte 184: flags
- bytes 185-188: request time (in hours since the epoch, rounded down)
- bytes 189-192: next message ID
- bytes 193-221: uninterpreted / random padding
-
-
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. In addition, the next message ID specifies the
-message ID that the message (or reply) should use.
-
-
-The tunnel layer key, tunnel IV key, reply key, and reply IV
-are each random 32-byte values generated by the creator,
-for use in this build request record only.
-
-
-
The flags field contains the following:
-
- Bit order: 76543210 (bit 7 is MSB)
- bit 7: if set, allow messages from anyone
- bit 6: if set, allow messages to anyone, and send the reply to the
- specified next hop in a Tunnel Build Reply Message
- bits 5-0: Undefined, must set to 0 for compatibility with future options
-
-
-Bit 7 indicates that the hop will be an inbound gateway (IBGW).
-Bit 6 indicates that the hop will be an outbound endpoint (OBEP).
-If neither bit is set, the hop will be an intermediate participant.
-Both cannot be set at once.
-
-
-
Request Record Creation
-
-Every hop gets a random Tunnel ID.
-The current and next-hop Tunnel IDs are filled in.
-Every record gets a random tunnel IV key, reply IV, layer key, and reply key.
-
-
-
-
Request Record Encryption
-
-
That cleartext record is ElGamal 2048 encrypted with the hop's
-public encryption key and formatted into a 528 byte record:
- bytes 0-15: First 16 bytes of the SHA-256 of the current hop's router identity
- bytes 16-527: ElGamal-2048 encrypted request record
-
-In the 512-byte encrypted record,
-the ElGamal data contains bytes 1-256 and 258-513 of the
-514-byte ElGamal encrypted block.
-The two padding bytes from the block (the zero bytes at locations 0 and 257) are removed.
-
-
Since the cleartext uses the full field, there is no need for
-additional padding beyond SHA256(cleartext) + cleartext.
-
-
-Each 528-byte record is then iteratively encrypted
-(using AES decryption, with the reply key and reply IV for each hop) so that the router identity will only be in cleartext
-for the hop in question.
-
-
-
Hop Processing and Encryption
-
-
When a hop receives a TunnelBuildMessage, it looks through the
-records contained within it for one starting with their own identity
-hash (trimmed to 16 bytes). It then decrypts 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.
-Duplicates or invalid requests
-are dropped.
-
-
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
-encrypted with the included reply key and IV. Each is
-AES/CBC encrypted separately with the same reply key and reply IV.
-The CBC mode is not continued (chained) across records.
-
-
-Each hop knows only its own response.
-If it agrees, it will maintain the tunnel until expiration,
-even if it will not be used,
-as it cannot know whether all other hops agreed.
-
-
-
-
Reply Record Specification
-
-
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 following rejection codes are defined:
-
-
-TUNNEL_REJECT_PROBABALISTIC_REJECT = 10
-
-TUNNEL_REJECT_TRANSIENT_OVERLOAD = 20
-
-TUNNEL_REJECT_BANDWIDTH = 30
-
-TUNNEL_REJECT_CRIT = 50
-
-To hide other causes, such as router shutdown, from peers, the current implementation
-uses TUNNEL_REJECT_BANDWIDTH for almost all rejections.
-
-
- The reply is encrypted with the AES session
-key delivered to it in the encrypted block, padded with 495 bytes of random data
-to reach the full record size.
-The padding is placed before the status byte:
-
- AES-256-CBC(SHA-256(padding+status) + padding + status, key, IV)
-
- bytes 0-31 : SHA-256 of bytes 32-527
- bytes 32-526 : Random padding
- byte 527 : Reply value
-
When building a new Tunnel Build Message, all of the Build Request Records must first be
-built and asymmetrically encrypted using
-ElGamal.
-Each record is then
-premptively decrypted with the reply keys and IVs of the hops earlier in the
-path, using
-AES.
-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.
-
-
The excess records not needed for individual requests are simply
-filled with random data by the creator.
-
-
Tunnel Build Message Delivery
-
-
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.
-The outbound tunnel is generally from the same pool as the new tunnel being built.
-If no outbound tunnel is available in that pool, an outbound exploratory tunnel is used.
-At startup, when no outbound exploratory tunnel exists yet, a fake 0-hop
-outbound tunnel is used.
-
-
Tunnel Build Message Endpoint Handling
-
-
-For creation of an outbound tunnel,
-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
-or
-VariableTunnelBuildReplyMessage
-(the type of message and number of records must match that of the request)
-and delivers it to the
-reply tunnel specified within the request record. That reply tunnel
-forwards the Tunnel Build Reply Message back to the tunnel creator,
-just as for any other message.
-The tunnel creator then
-processes it, as described below.
-
-
The reply tunnel was selected by the creator as follows:
-Generally it is an inbound tunnel from the same pool as the new outbound tunnel being built.
-If no inbound tunnel is available in that pool, an inbound exploratory tunnel is used.
-At startup, when no inbound exploratory tunnel exists yet, a fake 0-hop
-inbound tunnel is used.
-
-
-For creation of an inbound tunnel,
-when the request reaches the inbound endpoint (also known as the
-tunnel creator), there is no need to generate an explicit Tunnel Build Reply Message, and
-the router processes each of the replies, as below.
-
-
Tunnel Build Reply Message Processing
-
-
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.
-
-
-The agreements and rejections are noted in each peer's
-profile, to be used in future assessments
-of peer tunnel capacity.
-
-
-
History and Notes
-
-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:
-It was introduced in release 0.6.1.10 on 2006-02-16, which was the last time
-a non-backward-compatible change was made in I2P.
-
-
-
-Notes:
-
-
This design 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.
-
This design 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 latter replaced by a hashcash function of up to 2^64
-cost.
-
This design 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?
-
Are there any nonfatal methods of tagging the request?
-
-The timestamp with a one-hour resolution is used for replay prevention.
-The constraint was not enforced until release 0.9.16.
-
-In the current implementation, the originator leaves one record empty
-for itself. Thus a message of n records can only build a
-tunnel of n-1 hops.
-This appears to be necessary for inbound tunnels (where the next-to-last hop
-can see the hash prefix for the next hop), but not for outbound tunnels.
-This is to be researched and verified.
-If it is possible to use the remaining record without compromising anonymity,
-we should do so.
-
-Further analysis of possible tagging and timing attacks described in the above notes.
-
-The Bloom filter rotation time should be evaluated.
-
-Use only VTBM; do not select old peers that don't support it.
-
-The Build Request Record does not specify a tunnel lifetime or expiration;
-each hop expires the tunnel after 10 minutes, which is a network-wide hardcoded constant.
-We could use a bit in the flag field
-and take 4 (or 8) bytes out of the padding to specify a lifetime or expiration.
-The requestor would only specify this option if all participants supported it.
-
-
-
-{% endblock %}
diff --git a/i2p2www/spec/tunnel-creation.rst b/i2p2www/spec/tunnel-creation.rst
new file mode 100644
index 00000000..e2f8161a
--- /dev/null
+++ b/i2p2www/spec/tunnel-creation.rst
@@ -0,0 +1,358 @@
+=============================
+Tunnel Creation Specification
+=============================
+.. meta::
+ :lastupdated: September 2014
+ :accuratefor: 0.9.15
+
+
+.. _tunnelCreate.overview:
+
+Overview
+========
+
+This document specifies the details of the encrypted tunnel build messages used
+to create tunnels using a "non-interactive telescoping" method. See the tunnel
+build document [TUNNEL-IMPL]_ for an overview of the process, including peer
+selection and ordering methods.
+
+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 variable number of records
+(up to 8) - one for each potential peer in the tunnel. Individual records are
+asymmetrically (ElGamal [CRYPTO-ELG]_) encrypted to be read only by a specific
+peer along the path, while an additional symmetric layer of encryption (AES
+[CRYPTO-AES]_) is added at each hop so as to expose the asymmetrically
+encrypted record only at the appropriate time.
+
+.. _number:
+
+Number of Records
+-----------------
+
+Not all records must contain valid data. The build message for a 3-hop tunnel,
+for example, may contain more records to hide the actual length of the tunnel
+from the participants. There are two build message types. The original Tunnel
+Build Message ([TBM]_) contains 8 records, which is more than enough for any
+practical tunnel length. The newer Variable Tunnel Build Message ([VTBM]_)
+contains 1 to 8 records. The originator may trade off the size of the message
+with the desired amount of tunnel length obfuscation.
+
+In the current network, most tunnels are 2 or 3 hops long. The current
+implementation uses a 5-record VTBM to build tunnels of 4 hops or less, and the
+8-record TBM for longer tunnels. The 5-record VTBM (which, when fragmented,
+fits in three 1KB tunnel messaages) reduces network traffic and increases
+build sucess rate, because smaller messages are less likely to be dropped.
+
+The reply message must be the same type and length as the build message.
+
+.. _tunnelCreate.requestRecord:
+
+Request Record Specification
+----------------------------
+
+Also specified in the I2NP Specification [BRR]_.
+
+Cleartext of the record, visible only to the hop being asked::
+
+ 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: AES-256 reply IV
+ byte 184: flags
+ bytes 185-188: request time (in hours since the epoch, rounded down)
+ bytes 189-192: next message ID
+ bytes 193-221: uninterpreted / random padding
+
+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. In addition,
+the next message ID specifies the message ID that the message (or reply) should
+use.
+
+The tunnel layer key, tunnel IV key, reply key, and reply IV are each random
+32-byte values generated by the creator, for use in this build request record
+only.
+
+The flags field contains the following::
+
+ Bit order: 76543210 (bit 7 is MSB)
+ bit 7: if set, allow messages from anyone
+ bit 6: if set, allow messages to anyone, and send the reply to the
+ specified next hop in a Tunnel Build Reply Message
+ bits 5-0: Undefined, must set to 0 for compatibility with future options
+
+Bit 7 indicates that the hop will be an inbound gateway (IBGW). Bit 6
+indicates that the hop will be an outbound endpoint (OBEP). If neither bit is
+set, the hop will be an intermediate participant. Both cannot be set at once.
+
+Request Record Creation
+```````````````````````
+Every hop gets a random Tunnel ID.
+The current and next-hop Tunnel IDs are filled in.
+Every record gets a random tunnel IV key, reply IV, layer key, and reply key.
+
+.. _encryption:
+
+Request Record Encryption
+`````````````````````````
+That cleartext record is ElGamal 2048 encrypted [CRYPTO-ELG]_ with the hop's
+public encryption key and formatted into a 528 byte record::
+
+ bytes 0-15: First 16 bytes of the SHA-256 of the current hop's router identity
+ bytes 16-527: ElGamal-2048 encrypted request record
+
+In the 512-byte encrypted record, the ElGamal data contains bytes 1-256 and
+258-513 of the 514-byte ElGamal encrypted block [CRYPTO-ELG]_. The two padding
+bytes from the block (the zero bytes at locations 0 and 257) are removed.
+
+Since the cleartext uses the full field, there is no need for additional
+padding beyond ``SHA256(cleartext) + cleartext``.
+
+Each 528-byte record is then iteratively encrypted (using AES decryption, with
+the reply key and reply IV for each hop) so that the router identity will only
+be in cleartext for the hop in question.
+
+.. _tunnelCreate.hopProcessing:
+
+Hop Processing and Encryption
+-----------------------------
+
+When a hop receives a TunnelBuildMessage, it looks through the records
+contained within it for one starting with their own identity hash (trimmed to
+16 bytes). It then decrypts 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.
+Duplicates or invalid requests are dropped.
+
+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 encrypted [CRYPTO-AES]_ with the included
+reply key and IV. Each is AES/CBC encrypted separately with the same reply key
+and reply IV. The CBC mode is not continued (chained) across records.
+
+Each hop knows only its own response. If it agrees, it will maintain the
+tunnel until expiration, even if it will not be used, as it cannot know whether
+all other hops agreed.
+
+.. _tunnelCreate.replyRecord:
+
+Reply Record Specification
+``````````````````````````
+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 following rejection codes are defined:
+
+* TUNNEL_REJECT_PROBABALISTIC_REJECT = 10
+* TUNNEL_REJECT_TRANSIENT_OVERLOAD = 20
+* TUNNEL_REJECT_BANDWIDTH = 30
+* TUNNEL_REJECT_CRIT = 50
+
+To hide other causes, such as router shutdown, from peers, the current
+implementation uses TUNNEL_REJECT_BANDWIDTH for almost all rejections.
+
+The reply is encrypted with the AES session key delivered to it in the
+encrypted block, padded with 495 bytes of random data to reach the full record
+size. The padding is placed before the status byte::
+
+ AES-256-CBC(SHA-256(padding+status) + padding + status, key, IV)
+
+ bytes 0-31 : SHA-256 of bytes 32-527
+ bytes 32-526 : Random padding
+ byte 527 : Reply value
+
+This is also described in the I2NP spec [BRR]_.
+
+.. _tunnelCreate.requestPreparation:
+
+Tunnel Build Message Preparation
+--------------------------------
+
+When building a new Tunnel Build Message, all of the Build Request Records must
+first be built and asymmetrically encrypted using ElGamal [CRYPTO-ELG]_. Each
+record is then premptively decrypted with the reply keys and IVs of the hops
+earlier in the path, using AES [CRYPTO-AES]_. 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.
+
+The excess records not needed for individual requests are simply filled with
+random data by the creator.
+
+.. _tunnelCreate.requestDelivery:
+
+Tunnel Build Message Delivery
+-----------------------------
+
+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. The outbound tunnel is generally from the same
+pool as the new tunnel being built. If no outbound tunnel is available in that
+pool, an outbound exploratory tunnel is used. At startup, when no outbound
+exploratory tunnel exists yet, a fake 0-hop outbound tunnel is used.
+
+.. _tunnelCreate.endpointHandling:
+
+Tunnel Build Message Endpoint Handling
+--------------------------------------
+
+For creation of an outbound tunnel, 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 ([TBRM]_) or VariableTunnelBuildReplyMessage ([VTBRM]_)
+(the type of message and number of records must match that of the request) and
+delivers it to the reply tunnel specified within the request record. That
+reply tunnel forwards the Tunnel Build Reply Message back to the tunnel
+creator, just as for any other message [TUNNEL-OP]_. The tunnel creator then
+processes it, as described below.
+
+The reply tunnel was selected by the creator as follows: Generally it is an
+inbound tunnel from the same pool as the new outbound tunnel being built. If
+no inbound tunnel is available in that pool, an inbound exploratory tunnel is
+used. At startup, when no inbound exploratory tunnel exists yet, a fake 0-hop
+inbound tunnel is used.
+
+For creation of an inbound tunnel, when the request reaches the inbound
+endpoint (also known as the tunnel creator), there is no need to generate an
+explicit Tunnel Build Reply Message, and the router processes each of the
+replies, as below.
+
+.. _tunnelCreate.replyProcessing:
+
+Tunnel Build Reply Message Processing
+-------------------------------------
+
+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.
+
+The agreements and rejections are noted in each peer's profile
+[PEER-SELECTION]_, to be used in future assessments of peer tunnel capacity.
+
+
+.. _tunnelCreate.notes:
+
+History and Notes
+=================
+
+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 [TUNBUILD-SUMMARY]_, [TUNBUILD-REASONING]_. It was introduced in
+release 0.6.1.10 on 2006-02-16, which was the last time a
+non-backward-compatible change was made in I2P.
+
+Notes:
+
+* This design 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.
+
+* This design 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 latter replaced by a hashcash function of up to 2^64 cost.
+
+* This design 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?
+
+* Are there any nonfatal methods of tagging the request?
+
+* The timestamp with a one-hour resolution is used for replay prevention. The
+ constraint was not enforced until release 0.9.16.
+
+
+.. _future:
+
+Future Work
+===========
+
+* In the current implementation, the originator leaves one record empty
+ for itself. Thus a message of n records can only build a tunnel of n-1 hops.
+ This appears to be necessary for inbound tunnels (where the next-to-last hop
+ can see the hash prefix for the next hop), but not for outbound tunnels.
+ This is to be researched and verified. If it is possible to use the
+ remaining record without compromising anonymity, we should do so.
+
+* Further analysis of possible tagging and timing attacks described in the
+ above notes.
+
+* The Bloom filter rotation time should be evaluated.
+
+* Use only VTBM; do not select old peers that don't support it.
+
+* The Build Request Record does not specify a tunnel lifetime or expiration;
+ each hop expires the tunnel after 10 minutes, which is a network-wide
+ hardcoded constant. We could use a bit in the flag field and take 4 (or 8)
+ bytes out of the padding to specify a lifetime or expiration. The requestor
+ would only specify this option if all participants supported it.
+
+
+.. _ref:
+
+References
+==========
+
+.. [BRR]
+ {{ spec_url('i2np') }}#struct_BuildRequestRecord
+
+.. [CRYPTO-AES]
+ {{ site_url('docs/how/cryptography', True) }}#AES
+
+.. [CRYPTO-ELG]
+ {{ site_url('docs/how/cryptography', True) }}#elgamal
+
+.. [HASHING-IT-OUT]
+ http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf
+
+.. [PEER-SELECTION]
+ {{ site_url('docs/how/peer-selection', True) }}
+
+.. [PREDECESSOR]
+ http://forensics.umass.edu/pubs/wright-tissec.pdf
+
+.. [PREDECESSOR-2008]
+ http://forensics.umass.edu/pubs/wright.tissec.2008.pdf
+
+.. [TBM]
+ {{ spec_url('i2np') }}#msg_TunnelBuild
+
+.. [TBRM]
+ {{ spec_url('i2np') }}#msg_TunnelBuildReply
+
+.. [TUNBUILD-REASONING]
+ http://osdir.com/ml/network.i2p/2005-10/msg00129.html
+
+.. [TUNBUILD-SUMMARY]
+ http://osdir.com/ml/network.i2p/2005-10/msg00138.html
+
+.. [TUNNEL-IMPL]
+ {{ site_url('docs/tunnels/implementation', True) }}
+
+.. [TUNNEL-OP]
+ {{ site_url('docs/tunnels/implementation', True) }}#tunnel.operation
+
+.. [VTBM]
+ {{ spec_url('i2np') }}#msg_VariableTunnelBuild
+
+.. [VTBRM]
+ {{ spec_url('i2np') }}#msg_VariableTunnelBuildReply
diff --git a/i2p2www/spec/tunnel-message.html b/i2p2www/spec/tunnel-message.html
deleted file mode 100644
index b48956f5..00000000
--- a/i2p2www/spec/tunnel-message.html
+++ /dev/null
@@ -1,318 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}Tunnel Message Specification{% endblock %}
-{% block lastupdated %}February 2014{% endblock %}
-{% block accuratefor %}0.9.11{% endblock %}
-{% block content %}
-
-This document specifies the format of tunnel messages.
-For general information about tunnels see
-the tunnel documentation.
-
-
-
Message preprocessing
-
-
-A tunnel gateway is the entrance, or first hop, of a tunnel.
-For an outbound tunnel, the gateway is the creator of the tunnel.
-For an inbound tunnel, the gateway is at the opposite end from the creator of the tunnel.
-
-
-A gateway preprocessesI2NP messages
-by fragmenting and combining them into tunnel messages.
-
-
-While I2NP messages are variable size from 0 to almost 64 KB,
-tunnel messages are fixed-size, approximately 1 KB.
-Fixed message size
-restricts several types of attacks that are possible from
-observing message size.
-
-
-After the tunnel messages are created, they are encrypted as described in
-the tunnel documentation.
-
-
Tunnel Message (Encrypted)
-These are the contents of a tunnel data message after encryption.
-{% highlight lang='dataspec' %}
-+----+----+----+----+----+----+----+----+
-| Tunnel ID | IV |
-+----+----+----+----+ +
-| |
-+ +----+----+----+----+
-| | |
-+----+----+----+----+ +
-| |
-+ Encrypted Data +
-~ ~
-| |
-+ +-------------------+
-| |
-+----+----+----+----+
-{% endhighlight %}
-
-
Definition
-{% highlight lang='dataspec' %}
-Tunnel ID :: `TunnelId`
- 4 bytes
- the ID of the next hop
-
-IV ::
- 16 bytes
- the initialization vector
-
-Encrypted Data ::
- 1008 bytes
- the encrypted tunnel message
-
-total size: 1028 Bytes
-
-{% endhighlight %}
-
-
-
-{% highlight lang='dataspec' %}
-Tunnel ID :: `TunnelId`
- 4 bytes
- the ID of the next hop
-
-IV ::
- 16 bytes
- the initialization vector
-
-Checksum ::
- 4 bytes
- the first 4 bytes of the SHA256 hash of (the contents of the message (after the zero byte) + IV)
-
-Nonzero padding ::
- 0 or more bytes
- random nonzero data for padding
-
-Zero ::
- 1 byte
- the value 0x00
-
-Delivery Instructions :: `TunnelMessageDeliveryInstructions`
- length varies but is typically 7, 39, 43, or 47 bytes
- Indicates the fragment and the routing for the fragment
-
-Message Fragment ::
- 1 to 996 bytes, actual maximum depends on delivery instruction size
- A partial or full I2NP Message
-
-total size: 1028 Bytes
-
-{% endhighlight %}
-
-
Notes
-
-The padding, if any, must be before the instruction/message pairs.
-There is no provision for padding at the end.
-
-The checksum does NOT cover the padding or the zero byte.
-Take the message starting at the first delivery instructions, concatenate the IV,
-and take the Hash of that.
-
-
-
-
Tunnel Message Delivery Instructions
-
-
The instructions are encoded with a single control byte, followed by any
-necessary additional information. The first bit (MSB) in that control byte determines
-how the remainder of the header is interpreted - if it is not set, the message
-is either not fragmented or this is the first fragment in the message. If it is
-set, this is a follow on fragment.
-
-
-This specification is for Delivery Instructions inside Tunnel Messages only.
-Note that "Delivery Instructions" are also used inside
-Garlic Cloves,
-where the format is significantly different.
-See the
-I2NP documentation
-for details.
-Do NOT use the following specification for Garlic Clove Delivery Instructions!
-
-
-
First Fragment Delivery Instructions
-
If the MSB of the first byte is 0, this is an initial I2NP message fragment,
-or a complete (unfragmented) I2NP message, and the instructions are:
-{% highlight lang='dataspec' %}
-flag ::
- 1 byte
- Bit order: 76543210
- bit 7: 0 to specify an initial fragment or an unfragmented message
- bits 6-5: delivery type
- 0x0 = LOCAL, 0x01 = TUNNEL, 0x02 = ROUTER, 0x03 = unused, invalid
- Note: LOCAL is used for inbound tunnels only, unimplemented for outbound tunnels
- bit 4: delay included? Unimplemented, always 0
- If 1, a delay byte is included
- bit 3: fragmented? If 0, the message is not fragmented, what follows is the entire message
- If 1, the message is fragmented, and the instructions contain a Message ID
- bit 2: extended options? Unimplemented, always 0
- If 1, extended options are included
- bits 1-0: reserved, set to 0 for compatibility with future uses
-
-Tunnel ID :: `TunnelId`
- 4 bytes
- Optional, present if delivery type is TUNNEL
- The destination tunnel ID
-
-To Hash ::
- 32 bytes
- Optional, present if delivery type is DESTINATION, ROUTER, or TUNNEL
- If DESTINATION, the SHA256 Hash of the destination
- If ROUTER, the SHA256 Hash of the router
- If TUNNEL, the SHA256 Hash of the gateway router
-
-Delay ::
- 1 byte
- Optional, present if delay included flag is set
- In tunnel messages: Unimplemented, never present; original specification:
- bit 7: type (0 = strict, 1 = randomized)
- bits 6-0: delay exponent (2^value minutes)
-
-Message ID ::
- 4 bytes
- Optional, present if this message is the first of 2 or more fragments
- (i.e. if the fragmented bit is 1)
- An ID that uniquely identifies all fragments as belonging to a single message
- (the current implementation uses `I2NPMessageHeader.msg_id`)
-
-Extended Options ::
- 2 or more bytes
- Optional, present if extend options flag is set
- Unimplemented, never present; original specification:
- One byte length and then that many bytes
-
-size ::
- 2 bytes
- The length of the fragment that follows
- Valid values: 1 to approx. 960 in a tunnel message
-
-Total length: Typical length is:
- 3 bytes for LOCAL delivery (tunnel message);
- 35 bytes for ROUTER / DESTINATION delivery or 39 bytes for TUNNEL delivery (unfragmented tunnel message);
- 39 bytes for ROUTER delivery or 43 bytes for TUNNEL delivery (first fragment)
-
-{% endhighlight %}
-
-
Follow-on Fragment Delivery Instructions
-
If the MSB of the first byte is 1, this is a follow-on fragment, and the instructions are:
-{% highlight lang='dataspec' %}
-frag ::
- 1 byte
- Bit order: 76543210
- binary 1nnnnnnd
- bit 7: 1 to indicate this is a follow-on fragment
- bits 6-1: nnnnnn is the 6 bit fragment number from 1 to 63
- bit 0: d is 1 to indicate the last fragment, 0 otherwise
-
-Message ID ::
- 4 bytes
- Identifies the fragment sequence that this fragment belongs to.
- This will match the message ID of an initial fragment (a fragment
- with flag bit 7 set to 0 and flag bit 3 set to 1).
-
-size ::
- 2 bytes
- the length of the fragment that follows
- valid values: 1 to 996
-
-total length: 7 bytes
-{% endhighlight %}
-
-
-While the maximum I2NP message size is nominally 64 KB, the size is further constrained by the
-method of fragmenting I2NP messages into multiple 1 KB tunnel messages.
-The maximum number of fragments is 64, and the initial fragment may not
-be perfectly aligned at the start of a tunnel message.
-So the message must nominally fit in 63 fragments.
-
-The maximum size of an initial fragment is 956 bytes (assuming TUNNEL delivery mode);
-the maximum size of a follow-on fragment is 996 bytes.
-Therefore the maximum size is approximately 956 + (62 * 996) = 62708 bytes, or 61.2 KB.
-
-
-
Ordering, Batching, Packing
-Tunnel messages may be dropped or reordered.
-The tunnel gateway, who creates tunnel messages, is free to implement any
-batching, mixing, or reordering strategy to fragment I2NP messages and
-efficiently pack fragments into tunnel messages.
-In general, an optimal packing is not possible (the "packing problem").
-The gateways may implement various delay and reordering strategies.
-
-
Cover Traffic
-Tunnel messages may contain only padding (i.e. no delivery instructions or message fragments at all)
-for cover traffic. This is unimplemented.
-
-{% endblock %}
diff --git a/i2p2www/spec/tunnel-message.rst b/i2p2www/spec/tunnel-message.rst
new file mode 100644
index 00000000..2a6fa745
--- /dev/null
+++ b/i2p2www/spec/tunnel-message.rst
@@ -0,0 +1,351 @@
+============================
+Tunnel Message Specification
+============================
+.. meta::
+ :lastupdated: February 2014
+ :accuratefor: 0.9.11
+
+
+Overview
+========
+
+This document specifies the format of tunnel messages. For general information
+about tunnels see the tunnel documentation [TUNNEL-IMPL]_.
+
+
+Message preprocessing
+=====================
+
+A *tunnel gateway* is the entrance, or first hop, of a tunnel. For an outbound
+tunnel, the gateway is the creator of the tunnel. For an inbound tunnel, the
+gateway is at the opposite end from the creator of the tunnel.
+
+A gateway *preprocesses* [I2NP]_ messages by fragmenting and combining them
+into tunnel messages.
+
+While I2NP messages are variable size from 0 to almost 64 KB, tunnel messages
+are fixed-size, approximately 1 KB. Fixed message size restricts several types
+of attacks that are possible from observing message size.
+
+After the tunnel messages are created, they are encrypted as described in the
+tunnel documentation [TUNNEL-IMPL]_.
+
+.. _msg-tunnel:
+
+Tunnel Message (Encrypted)
+--------------------------
+
+These are the contents of a tunnel data message after encryption.
+
+.. raw:: html
+
+ {% highlight lang='dataspec' -%}
++----+----+----+----+----+----+----+----+
+ | Tunnel ID | IV |
+ +----+----+----+----+ +
+ | |
+ + +----+----+----+----+
+ | | |
+ +----+----+----+----+ +
+ | |
+ + Encrypted Data +
+ ~ ~
+ | |
+ + +-------------------+
+ | |
+ +----+----+----+----+
+
+ Tunnel ID :: `TunnelId`
+ 4 bytes
+ the ID of the next hop
+
+ IV ::
+ 16 bytes
+ the initialization vector
+
+ Encrypted Data ::
+ 1008 bytes
+ the encrypted tunnel message
+
+ total size: 1028 Bytes
+{% endhighlight %}
+
+Tunnel Message (Decrypted)
+--------------------------
+
+These are the contents of a tunnel data message when decrypted.
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ | Tunnel ID | IV |
+ +----+----+----+----+ +
+ | |
+ + +----+----+----+----+
+ | | Checksum |
+ +----+----+----+----+----+----+----+----+
+ | nonzero padding... |
+ ~ ~
+ | |
+ + +----+
+ | |zero|
+ +----+----+----+----+----+----+----+----+
+ | |
+ | Delivery Instructions 1 |
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | |
+ + I2NP Message Fragment 1 +
+ | |
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | |
+ | Delivery Instructions 2... |
+ ~ ~
+ | |
+ +----+----+----+----+----+----+----+----+
+ | |
+ + I2NP Message Fragment 2... +
+ | |
+ ~ ~
+ | |
+ + +-------------------+
+ | |
+ +----+----+----+----+
+
+ Tunnel ID :: `TunnelId`
+ 4 bytes
+ the ID of the next hop
+
+ IV ::
+ 16 bytes
+ the initialization vector
+
+ Checksum ::
+ 4 bytes
+ the first 4 bytes of the SHA256 hash of (the contents of the message
+ (after the zero byte) + IV)
+
+ Nonzero padding ::
+ 0 or more bytes
+ random nonzero data for padding
+
+ Zero ::
+ 1 byte
+ the value 0x00
+
+ Delivery Instructions :: `TunnelMessageDeliveryInstructions`
+ length varies but is typically 7, 39, 43, or 47 bytes
+ Indicates the fragment and the routing for the fragment
+
+ Message Fragment ::
+ 1 to 996 bytes, actual maximum depends on delivery instruction size
+ A partial or full I2NP Message
+
+ total size: 1028 Bytes
+{% endhighlight %}
+
+Notes
+`````
+* The padding, if any, must be before the instruction/message pairs.
+ There is no provision for padding at the end.
+
+* The checksum does NOT cover the padding or the zero byte.
+ Take the message starting at the first delivery instructions, concatenate the
+ IV, and take the Hash of that.
+
+
+.. _struct-tunnelmessagedeliveryinstructions:
+
+Tunnel Message Delivery Instructions
+====================================
+
+The instructions are encoded with a single control byte, followed by any
+necessary additional information. The first bit (MSB) in that control byte
+determines how the remainder of the header is interpreted - if it is not set,
+the message is either not fragmented or this is the first fragment in the
+message. If it is set, this is a follow on fragment.
+
+This specification is for Delivery Instructions inside Tunnel Messages only.
+Note that "Delivery Instructions" are also used inside Garlic Cloves
+[I2NP-GC]_, where the format is significantly different. See the I2NP
+documentation [I2NP-GCDI]_ for details. Do NOT use the following specification
+for Garlic Clove Delivery Instructions!
+
+First Fragment Delivery Instructions
+------------------------------------
+
+If the MSB of the first byte is 0, this is an initial I2NP message fragment,
+or a complete (unfragmented) I2NP message, and the instructions are:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+----+
+ |flag| Tunnel ID (opt) | |
+ +----+----+----+----+----+ +
+ | |
+ + +
+ | To Hash (optional) |
+ + +
+ | |
+ + +--------------+
+ | |dly | Message
+ +----+----+----+----+----+----+----+----+
+ ID (opt) |extended opts (opt)| size |
+ +----+----+----+----+----+----+----+----+
+
+ flag ::
+ 1 byte
+ Bit order: 76543210
+ bit 7: 0 to specify an initial fragment or an unfragmented message
+ bits 6-5: delivery type
+ 0x0 = LOCAL
+ 0x01 = TUNNEL
+ 0x02 = ROUTER
+ 0x03 = unused, invalid
+ Note: LOCAL is used for inbound tunnels only, unimplemented
+ for outbound tunnels
+ bit 4: delay included? Unimplemented, always 0
+ If 1, a delay byte is included
+ bit 3: fragmented? If 0, the message is not fragmented, what follows
+ is the entire message
+ If 1, the message is fragmented, and the
+ instructions contain a Message ID
+ bit 2: extended options? Unimplemented, always 0
+ If 1, extended options are included
+ bits 1-0: reserved, set to 0 for compatibility with future uses
+
+ Tunnel ID :: `TunnelId`
+ 4 bytes
+ Optional, present if delivery type is TUNNEL
+ The destination tunnel ID
+
+ To Hash ::
+ 32 bytes
+ Optional, present if delivery type is DESTINATION, ROUTER, or TUNNEL
+ If DESTINATION, the SHA256 Hash of the destination
+ If ROUTER, the SHA256 Hash of the router
+ If TUNNEL, the SHA256 Hash of the gateway router
+
+ Delay ::
+ 1 byte
+ Optional, present if delay included flag is set
+ In tunnel messages: Unimplemented, never present; original
+ specification:
+ bit 7: type (0 = strict, 1 = randomized)
+ bits 6-0: delay exponent (2^value minutes)
+
+ Message ID ::
+ 4 bytes
+ Optional, present if this message is the first of 2 or more fragments
+ (i.e. if the fragmented bit is 1)
+ An ID that uniquely identifies all fragments as belonging to a single
+ message (the current implementation uses `I2NPMessageHeader.msg_id`)
+
+ Extended Options ::
+ 2 or more bytes
+ Optional, present if extend options flag is set
+ Unimplemented, never present; original specification:
+ One byte length and then that many bytes
+
+ size ::
+ 2 bytes
+ The length of the fragment that follows
+ Valid values: 1 to approx. 960 in a tunnel message
+
+ Total length: Typical length is:
+ 3 bytes for LOCAL delivery (tunnel message);
+ 35 bytes for ROUTER / DESTINATION delivery or 39 bytes for TUNNEL
+ delivery (unfragmented tunnel message);
+ 39 bytes for ROUTER delivery or 43 bytes for TUNNEL delivery (first
+ fragment)
+{% endhighlight %}
+
+Follow-on Fragment Delivery Instructions
+----------------------------------------
+
+If the MSB of the first byte is 1, this is a follow-on fragment, and the
+instructions are:
+
+.. raw:: html
+
+ {% highlight lang='dataspec' %}
++----+----+----+----+----+----+----+
+ |frag| Message ID | size |
+ +----+----+----+----+----+----+----+
+
+ frag ::
+ 1 byte
+ Bit order: 76543210
+ binary 1nnnnnnd
+ bit 7: 1 to indicate this is a follow-on fragment
+ bits 6-1: nnnnnn is the 6 bit fragment number from 1 to 63
+ bit 0: d is 1 to indicate the last fragment, 0 otherwise
+
+ Message ID ::
+ 4 bytes
+ Identifies the fragment sequence that this fragment belongs to.
+ This will match the message ID of an initial fragment (a fragment
+ with flag bit 7 set to 0 and flag bit 3 set to 1).
+
+ size ::
+ 2 bytes
+ the length of the fragment that follows
+ valid values: 1 to 996
+
+ total length: 7 bytes
+{% endhighlight %}
+
+JavaDoc: http://docs.i2p-projekt.de/javadoc/net/i2p/data/i2np/DeliveryInstructions.html
+
+
+Notes
+=====
+
+I2NP Message Maximum Size
+-------------------------
+
+While the maximum I2NP message size is nominally 64 KB, the size is further
+constrained by the method of fragmenting I2NP messages into multiple 1 KB
+tunnel messages. The maximum number of fragments is 64, and the initial
+fragment may not be perfectly aligned at the start of a tunnel message. So the
+message must nominally fit in 63 fragments.
+
+The maximum size of an initial fragment is 956 bytes (assuming TUNNEL delivery
+mode); the maximum size of a follow-on fragment is 996 bytes. Therefore the
+maximum size is approximately 956 + (62 * 996) = 62708 bytes, or 61.2 KB.
+
+Ordering, Batching, Packing
+---------------------------
+
+Tunnel messages may be dropped or reordered. The tunnel gateway, who creates
+tunnel messages, is free to implement any batching, mixing, or reordering
+strategy to fragment I2NP messages and efficiently pack fragments into tunnel
+messages. In general, an optimal packing is not possible (the "packing
+problem"). The gateways may implement various delay and reordering strategies.
+
+Cover Traffic
+-------------
+
+Tunnel messages may contain only padding (i.e. no delivery instructions or
+message fragments at all) for cover traffic. This is unimplemented.
+
+
+References
+==========
+
+.. [I2NP]
+ {{ site_url('docs/protocol/i2np', True) }}
+
+.. [I2NP-GC]
+ {{ spec_url('i2np') }}#struct-garlicclove
+
+.. [I2NP-GCDI]
+ {{ spec_url('i2np') }}#struct-garlicclovedeliveryinstructions
+
+.. [TUNNEL-IMPL]
+ {{ site_url('docs/tunnels/implementation', True) }}
diff --git a/i2p2www/spec/updates.html b/i2p2www/spec/updates.html
deleted file mode 100644
index bde99bf3..00000000
--- a/i2p2www/spec/updates.html
+++ /dev/null
@@ -1,572 +0,0 @@
-{% extends "global/layout.html" %}
-{% block title %}{% trans %}I2P Software Update Specification{% endtrans %}{% endblock %}
-{% block lastupdated %}{% trans %}May 2015{% endtrans %}{% endblock %}
-{% block accuratefor %}0.9.20{% endblock %}
-{% block content %}
-
{% trans %}Overview{% endtrans %}
-
{% trans -%}
-I2P uses a simple, yet secure, system for automated software update.
-The router console periodically pulls a news file from a configurable I2P URL.
-There is a hardcoded backup URL pointing to the project website, in case
-the default project news host goes down.
-{%- endtrans %}
-
-
{% trans -%}
-The contents of the news file are displayed on the home page of the router console.
-In addition, the news file contains the most recent version number of the software.
-If the version is higher than the router's version number, it will
-display an indication to the user that an update is available.
-{%- endtrans %}
-
-
{% trans -%}
-The router may optionally download, or download and install, the new version
-if configured to do so.
-{%- endtrans %}
-
-
{% trans %}Old News File Specification{% endtrans %}
-
{% trans -%}
-This format is replaced by the su3 news format as of release 0.9.17.
-{%- endtrans %}
-
{% trans -%}
-The news.xml file may contain the following elements:
-{%- endtrans %}
{% trans -%}
-Parameters in the i2p.release entry are as follows.
-All keys are case-insensitive. All values must be enclosed in double quotes.
-{%- endtrans %}
-
-
-
-date: The release date of the router version. Unused. Format not specified.
-
-minJavaVersion: The minimum version of Java required to run the current version.
-As of release 0.9.9.
-
-minVersion: The minimum version of the router required to update to the current version.
-If a router is older than this, the user must (manually?) update to an intermediate version first.
-As of release 0.9.9.
-
-su3Clearnet: One or more HTTP URLs where the .su3 update file may
-be found on the clearnet (non-I2P).
-Multiple URLs must be separated by a space or comma.
-As of release 0.9.9.
-
-su3SSL: One or more HTTPS URLs where the .su3 update file may
-be found on the clearnet (non-I2P).
-Multiple URLs must be separated by a space or comma.
-As of release 0.9.9.
-
-sudTorrent: The magnet link for the .sud (non-pack200) torrent of the update.
-As of release 0.9.4.
-
-su2Torrent: The magnet link for the .su2 (pack200) torrent of the update.
-As of release 0.9.4.
-
-su3Torrent: The magnet link for the .su3 (new format) torrent of the update.
-As of release 0.9.9.
-
-version: Required. The latest current router version available.
-
-
-
{% trans -%}
-The elements may be included inside XML comments to prevent interpretation by browsers.
-The i2p.release element and version are required. All others are optional.
-NOTE: Due to parser limitations an entire element must be on a single line.
-{%- endtrans %}
-
-
-
{% trans %}Update File Specification{% endtrans %}
-
{% trans -%}
-As of release 0.9.9, the signed update file, named i2pupdate.su3, will
-use the "su3" file format specified below.
-Approved release signers will use 4096-bit RSA keys.
-The X.509 public key certificates for these signers are distributed in the router installation packages.
-The updates may contain certificates for new, approved signers, and/or contain
-a list of certificates to delete for revocation.
-{%- endtrans %}
-
-
-
{% trans %}Old Update File Specification{% endtrans %}
-
{% trans -%}
-This format is obsolete as of release 0.9.9.
-{%- endtrans %}
-
{% trans -%}
-The signed update file, traditionally named i2pupdate.sud,
-is simply a zip file with a prepended 56 byte header.
-The header contains:
-{%- endtrans %}
-
-
{% trans commonstructures=site_url('docs/spec/common-structures') -%}
-A 40-byte DSA signature
-{%- endtrans %}
-
{% trans -%}
-A 16-byte I2P version in UTF-8, padded with trailing zeroes if necessary
-{%- endtrans %}
-
-
-
{% trans commonstructures=site_url('docs/spec/common-structures') -%}
-The signature covers only the zip archive - not the prepended version.
-The signature must match one of the DSA public keys configured into the router,
-which has a hardcoded default list of keys of the current project release managers.
-{%- endtrans %}
-
-
{% trans -%}
-For version comparison purposes, version fields contain [0-9]*, field separators are
-'-', '_', and '.', and all other characters are ignored.
-{%- endtrans %}
-
-
{% trans -%}
-As of version 0.8.8, the version must also be specified as a zip file comment in UTF-8,
-without the trailing zeroes.
-The updating router verifes that the version in the header (not covered by the signature)
-matches the version in the zip file comment, which is covered by the signature.
-This prevents spoofing of the version number in the header.
-{%- endtrans %}
-
-
{% trans %}Download and Installation{% endtrans %}
-
{% trans -%}
-The router first downloads the header of the update file from one in a configurable list of I2P URLs,
-using the built-in HTTP client and proxy,
-and checks that the version is newer.
-This prevents the problem of update hosts that do not have the latest file.
-The router then downloads the full update file.
-The router verifies that the update file version is newer before installation.
-It also, of course, verifies the signature, and
-verifes that the zip file comment matches the header version, as explained above.
-{%- endtrans %}
-
-
{% trans -%}
-The zip file is extracted and copied to "i2pupdate.zip" in the I2P configuration directory (~/.i2p on Linux).
-{%- endtrans %}
-
-
{% trans -%}
-As of release 0.7.12, the router supports Pack200 decompression.
-Files inside the zip archive with a .jar.pack or .war.pack suffix
-are transparently decompressed to a .jar or .war file.
-Update files containing .pack files are traditionally named with a '.su2' suffix.
-Pack200 shrinks the update files by about 60%.
-{%- endtrans %}
-
-
{% trans -%}
-As of release 0.8.7, the router will delete the libjbigi.so and libjcpuid.so files
-if the zip archive contains a lib/jbigi.jar file, so that the new files will
-be extracted from jbigi.jar.
-{%- endtrans %}
-
-
{% trans -%}
-As of release 0.8.12, if the zip archive contains a file deletelist.txt, the router will
-delete the files listed there. The format is:
-{%- endtrans %}
-
-
{% trans %}One file name per line{% endtrans %}
-
{% trans %}All file names are relative to the installation directory; no absolute file names allowed, no files starting with ".."{% endtrans %}
-
{% trans %}Comments start with '#'{% endtrans %}
-
-
-
{% trans -%}
-The router will then delete the deletelist.txt file.
-{%- endtrans %}
-
-
-
-
{% trans %}SU3 File Specification{% endtrans %}
-
-
{% trans -%}
-This specification is used for router updates as of release 0.9.9, reseed data as of release 0.9.14,
-plugins as of release 0.9.15, and the news file as of release 0.9.17.
-{%- endtrans %}
-
-
{% trans %}Issues with the previous .sud/.su2 format:{% endtrans %}
-
-
{% trans -%}
-No magic number or flags
-{%- endtrans %}
-
{% trans -%}
-No way to specify compression, pack200 or not, or signing algo
-{%- endtrans %}
-
{% trans -%}
-Version is not covered by signature, so it is enforced by requiring it
-to be in the zip file comment (for router files) or in the plugin.config
-file (for plugins)
-{%- endtrans %}
-
{% trans -%}
-Signer not specified so verifier must try all known keys
-{%- endtrans %}
-
{% trans -%}
-Signature-before-data format requires two passes to generate file
-{%- endtrans %}
-
-
-
-
{% trans %}Goals:{% endtrans %}
-
-
-
{% trans -%}
-Fix above problems
-{%- endtrans %}
-
{% trans -%}
-Migrate to more secure signature algorithm
-{%- endtrans %}
-
{% trans -%}
-Keep version info in same format and offset for compatibility with
-existing version checkers
-{%- endtrans %}
-
{% trans -%}
-One-pass signature verification and file extraction
-{%- endtrans %}
-
-
-
{% trans %}Specification:{% endtrans %}
-
-
-
Bytes
Contents
-
-0-5
Magic number "I2Psu3"
-
-6
unused = 0
-
-7
su3 file format version = 0
-
-8-9
Signature type
-
0x0000 = DSA-SHA1
-
0x0001 = ECDSA-SHA256-P256
-
0x0002 = ECDSA-SHA384-P384
-
0x0003 = ECDSA-SHA512-P521
-
0x0004 = RSA-SHA256-2048
-
0x0005 = RSA-SHA384-3072
-
0x0006 = RSA-SHA512-4096
-
-
-10-11
Signature length, e.g. 40 (0x0028) for DSA-SHA1.
- Must match that specified for the signature type on the
- common structures page.
-
-12
unused = 0
-
-13
Version length (in bytes not chars, including padding)
- must be at least 16 (0x10) for compatibility
-
-14
unused = 0
-
-15
Signer ID length (in bytes not chars)
-
-16-23
Content length (not including header or sig)
-
-24
unused = 0
-
-25
File type
-
0x00 = zip file
-
0x01 = xml file (as of 0.9.15)
-
0x02 = html file (as of 0.9.17)
-
0x03 = xml.gz file (as of 0.9.17)
-
-
-26
unused = 0
-
-27
Content type
-
0x00 = unknown
-
0x01 = router update
-
0x02 = plugin or plugin update
-
0x03 = reseed data
-
0x04 = news feed (as of 0.9.15)
-
-
-28-39
unused = 0
-
-40-55+
Version, UTF-8 padded with trailing 0x00, 16 bytes minimum, length specified at byte 13.
- Do not append 0x00 bytes if the length is 16 or more.
-
-xx+
ID of signer, (e.g. "zzz@mail.i2p") UTF-8, not padded, length specified at byte 15
-
-xx+
Content: Length specified in header at bytes 16-23,
- format specified in header at byte 25,
- content specified in header at byte 27
-
-xx+
Signature: Length is specified in header at bytes 10-11, covers everything starting at byte 0
-
-
-
{% trans -%}
-All unused fields must be set to 0 for compatibility with future versions.
-{%- endtrans %}
-
-
-
{% trans %}Signature Details{% endtrans %}
-
-The signature covers the entire header starting at byte 0,
-through the end of the content.
-We use raw signatures. Take the hash of the data (using the hash type
-implied by the signature type at bytes 8-9) and pass that
-to a "raw" sign or verify function (e.g. "NONEwithRSA" in Java).
-
-While signature verification and content extraction may be implemented in one pass,
-an implementation must read and buffer the first 10 bytes to determine the hash type
-before starting to verify.
-
-Signature lengths for the various signature types are specified on the
-common structures page.
-Pad the signature with leading zeros if necessary.
-See the cryptography details page
-for parameters of the various signature types.
-
-
-
-
-
{% trans %}Notes{% endtrans %}
-
-The content type specifies the trust domain.
-For each content type, clients maintain a set of X.509 public key certificates for
-parties trusted to sign that content.
-Only certificates for the specified content type may be used.
-The certificate is looked up by the ID of the signer.
-Clients must verify that the content type is that expected for the application.
-
-All values are in network byte order (big endian).
-
-
-
-
-
-
{% trans %}SU3 Router Update File Specification{% endtrans %}
-
-
SU3 Details:
-
-SU3 Content Type: 1 (ROUTER UPDATE)
-
-SU3 File Type: 0 (ZIP)
-
-SU3 Version: The router version
-
-Jar and war files in the zip are compressed with pack200 as documented above for "su2" files.
-If the client does not support pack200, it must download the update in a "sud" format.
-
-
-
Notes:
-
-For releases, the SU3 version is the "base" router version, e.g. "0.9.20".
-
-For development builds, which are supported as of release 0.9.20,
-the SU3 version is the "full" router version, e.g. "0.9.20-5" or "0.9.20-5-rc".
-See RouterVersion.java.
-
-
-
-
-
{% trans %}SU3 Reseed File Specification{% endtrans %}
-
{% trans -%}
-As of 0.9.14, reseed data is delivered in an "su3" file format.
-{%- endtrans %}
-
-
{% trans %}Goals:{% endtrans %}
-
-
-
{% trans -%}
-Signed files with strong signatures and trusted certificates
-to prevent man-in-the-middle attacks that could boot victims into a separate, untrusted network.
-{%- endtrans %}
-
{% trans -%}
-Use su3 file format already used for updates, reseeding, and plugins
-{%- endtrans %}
-
{% trans -%}
-Single compressed file to speed up reseeding, which was slow to fetch 200 files
-{%- endtrans %}
-
-
-
{% trans %}Specification:{% endtrans %}
-
-
-
{% trans -%}
-The file must be named "i2pseeds.su3".
-{%- endtrans %}
-
{% trans -%}
-The file must be in the same directory as the router infos on the web server.
-{%- endtrans %}
-
{% trans -%}
-A router will first try to fetch (index URL)/i2pseeds.su3; if that fails it will fetch the index URL
-and then fetch the individual router info files found in the links.
-{%- endtrans %}
-
-
-
SU3 Details:
-
-SU3 Content Type: 3 (RESEED)
-
-SU3 File Type: 0 (ZIP)
-
-SU3 Version: Seconds since the epoch, in ASCII (date +%s)
-
-Router info files in the zip file must be at the "top level". No directories are in the zip file.
-
-Router info files must be named "routerInfo-(44 character base 64 router hash).dat", as in the old reseed mechanism.
-The I2P base 64 alphabet must be used.
-
-
-
-
-
-
{% trans %}SU3 Plugin File Specification{% endtrans %}
-
-
{% trans -%}
-As of 0.9.15, plugins may be packaged in an "su3" file format.
-{%- endtrans %}
-Each Atom <entry> in the news feed may be parsed and displayed in the router console.
-The following elements are used:
-
-<author> (optional) containing:
-
- <name> The name of the entry author
-
-
-<content> Content, must be type="xhtml".
-The XHTML will be sanitized with a whitelist of allowed elements
-and a blacklist of disallowed attributes.
-Clients may ignore an element, or the enclosing entry, or the entire feed
-when a non-whitelisted element is encountered. (required)
-
-<link> Link for further information (optional)
-
-<summary> Short summary, suitable for a tooltip (optional)
-
-There must be at least one <i2p:release> entity in the feed. Each contains the following attributes and entities:
-
-date (attribute): Timestamp for this entry (conforming to
-RFC 4287 (Atom) section 3.3 and
-RFC 3339. (required)
-The date also may be in truncated format yyyy-mm-dd (without the 'T'); this is the "full-date" format in RFC 3339.
-In this format the time is assumed to be 00:00:00 UTC for any processing.
-
-minJavaVersion (attribute): If present, the minimum version of Java required to run the current version.
-
-minVersion (attribute):
-If present, the minimum version of the router required to update to the current version.
-If a router is older than this, the user must (manually?) update to an intermediate version first.
-
-<i2p:version> Required. The latest current router version available.
-
-<i2p:update> An update file (one or more). It must contain at least one child.
-
- type (attribute): "sud", "su2", or "su3". Must be unique across all <i2p:update> elements.
-
- <i2p:clearnet> Out-of-network direct download links (zero or more)
-
- href (attribute): a standard clearnet http link
-
-
- <i2p:clearnetssl> Out-of-network direct download links (zero or more)
-
- href (attribute): a standard clearnet https link
-
-
- <i2p:torrent> In-network magnet link
-
- href (attribute): a magnet link
-
-
- <i2p:url> In-network direct download links (zero or more)
-
- href (attribute): an in-network http .i2p link
-
-
-
-
-
-
-
{% trans %}Future Work{% endtrans %}
-
-
{% trans -%}
-The router update mechanism is part of the web router console.
-There is currently no provision for updates of an embedded router lacking the router console.
-{%- endtrans %}
-
-
-
-
-{% endblock %}
diff --git a/i2p2www/spec/updates.rst b/i2p2www/spec/updates.rst
new file mode 100644
index 00000000..0af85186
--- /dev/null
+++ b/i2p2www/spec/updates.rst
@@ -0,0 +1,561 @@
+=============================
+Software Update Specification
+=============================
+.. meta::
+ :lastupdated: May 2015
+ :accuratefor: 0.9.20
+
+
+Overview
+========
+
+I2P uses a simple, yet secure, system for automated software update. The
+router console periodically pulls a news file from a configurable I2P URL.
+There is a hardcoded backup URL pointing to the project website, in case the
+default project news host goes down.
+
+The contents of the news file are displayed on the home page of the router
+console. In addition, the news file contains the most recent version number of
+the software. If the version is higher than the router's version number, it
+will display an indication to the user that an update is available.
+
+The router may optionally download, or download and install, the new version if
+configured to do so.
+
+Old News File Specification
+---------------------------
+
+This format is replaced by the su3 news format as of release 0.9.17.
+
+The news.xml file may contain the following elements::
+
+
+
+
+Parameters in the i2p.release entry are as follows. All keys are
+case-insensitive. All values must be enclosed in double quotes.
+
+ date
+ The release date of the router version.
+
+ Unused. Format not specified.
+
+ minJavaVersion
+ The minimum version of Java required to run the current version.
+
+ As of release 0.9.9.
+
+ minVersion
+ The minimum version of the router required to update to the current
+ version. If a router is older than this, the user must (manually?)
+ update to an intermediate version first.
+
+ As of release 0.9.9.
+
+ su3Clearnet
+ One or more HTTP URLs where the .su3 update file may be found on the
+ clearnet (non-I2P). Multiple URLs must be separated by a space or comma.
+
+ As of release 0.9.9.
+
+ su3SSL
+ One or more HTTPS URLs where the .su3 update file may be found on the
+ clearnet (non-I2P). Multiple URLs must be separated by a space or comma.
+
+ As of release 0.9.9.
+
+ sudTorrent
+ The magnet link for the .sud (non-pack200) torrent of the update.
+
+ As of release 0.9.4.
+
+ su2Torrent
+ The magnet link for the .su2 (pack200) torrent of the update.
+
+ As of release 0.9.4.
+
+ su3Torrent
+ The magnet link for the .su3 (new format) torrent of the update.
+
+ As of release 0.9.9.
+
+ version
+ Required.
+
+ The latest current router version available.
+
+The elements may be included inside XML comments to prevent interpretation by
+browsers. The i2p.release element and version are required. All others are
+optional. NOTE: Due to parser limitations an entire element must be on a
+single line.
+
+Update File Specification
+-------------------------
+
+As of release 0.9.9, the signed update file, named i2pupdate.su3, will use the
+"su3" file format specified below. Approved release signers will use 4096-bit
+RSA keys. The X.509 public key certificates for these signers are distributed
+in the router installation packages. The updates may contain certificates for
+new, approved signers, and/or contain a list of certificates to delete for
+revocation.
+
+
+Old Update File Specification
+-----------------------------
+
+This format is obsolete as of release 0.9.9.
+
+The signed update file, traditionally named i2pupdate.sud, is simply a zip file
+with a prepended 56 byte header. The header contains:
+
+* A 40-byte DSA [Signature]_
+* A 16-byte I2P version in UTF-8, padded with trailing zeroes if necessary
+
+The signature covers only the zip archive - not the prepended version. The
+signature must match one of the DSA [SigningPublicKey]_ configured into the
+router, which has a hardcoded default list of keys of the current project
+release managers.
+
+For version comparison purposes, version fields contain [0-9]*, field
+separators are '-', '_', and '.', and all other characters are ignored.
+
+As of version 0.8.8, the version must also be specified as a zip file comment
+in UTF-8, without the trailing zeroes. The updating router verifes that the
+version in the header (not covered by the signature) matches the version in the
+zip file comment, which is covered by the signature. This prevents spoofing of
+the version number in the header.
+
+Download and Installation
+-------------------------
+
+The router first downloads the header of the update file from one in a
+configurable list of I2P URLs, using the built-in HTTP client and proxy, and
+checks that the version is newer. This prevents the problem of update hosts
+that do not have the latest file. The router then downloads the full update
+file. The router verifies that the update file version is newer before
+installation. It also, of course, verifies the signature, and verifes that the
+zip file comment matches the header version, as explained above.
+
+The zip file is extracted and copied to "i2pupdate.zip" in the I2P
+configuration directory (~/.i2p on Linux).
+
+As of release 0.7.12, the router supports Pack200 decompression. Files inside
+the zip archive with a .jar.pack or .war.pack suffix are transparently
+decompressed to a .jar or .war file. Update files containing .pack files are
+traditionally named with a '.su2' suffix. Pack200 shrinks the update files by
+about 60%.
+
+As of release 0.8.7, the router will delete the libjbigi.so and libjcpuid.so
+files if the zip archive contains a lib/jbigi.jar file, so that the new files
+will be extracted from jbigi.jar.
+
+As of release 0.8.12, if the zip archive contains a file deletelist.txt, the
+router will delete the files listed there. The format is:
+
+* One file name per line
+
+* All file names are relative to the installation directory; no absolute file
+ names allowed, no files starting with ".."
+
+* Comments start with '#'
+
+The router will then delete the deletelist.txt file.
+
+.. _su3:
+
+SU3 File Specification
+----------------------
+
+This specification is used for router updates as of release 0.9.9, reseed data
+as of release 0.9.14, plugins as of release 0.9.15, and the news file as of
+release 0.9.17.
+
+Issues with the previous .sud/.su2 format
+`````````````````````````````````````````
+* No magic number or flags
+
+* No way to specify compression, pack200 or not, or signing algo
+
+* Version is not covered by signature, so it is enforced by requiring it to be
+ in the zip file comment (for router files) or in the plugin.config file (for
+ plugins)
+
+* Signer not specified so verifier must try all known keys
+
+* Signature-before-data format requires two passes to generate file
+
+Goals
+`````
+* Fix above problems
+
+* Migrate to more secure signature algorithm
+
+* Keep version info in same format and offset for compatibility with existing
+ version checkers
+
+* One-pass signature verification and file extraction
+
+Specification
+`````````````
+
+====== ========================================================================
+Bytes Contents
+====== ========================================================================
+ 0-5 Magic number "I2Psu3"
+ 6 unused = 0
+ 7 su3 file format version = 0
+
+ 8-9 Signature type
+
+ * 0x0000 = DSA-SHA1
+ * 0x0001 = ECDSA-SHA256-P256
+ * 0x0002 = ECDSA-SHA384-P384
+ * 0x0003 = ECDSA-SHA512-P521
+ * 0x0004 = RSA-SHA256-2048
+ * 0x0005 = RSA-SHA384-3072
+ * 0x0006 = RSA-SHA512-4096
+
+10-11 Signature length, e.g. 40 (0x0028) for DSA-SHA1. Must match that
+ specified for the [Signature]_ type.
+ 12 unused = 0
+
+ 13 Version length (in bytes not chars, including padding)
+
+ must be at least 16 (0x10) for compatibility
+
+ 14 unused = 0
+ 15 Signer ID length (in bytes not chars)
+16-23 Content length (not including header or sig)
+ 24 unused = 0
+
+ 25 File type
+
+ * 0x00 = zip file
+ * 0x01 = xml file (as of 0.9.15)
+ * 0x02 = html file (as of 0.9.17)
+ * 0x03 = xml.gz file (as of 0.9.17)
+
+ 26 unused = 0
+
+ 27 Content type
+
+ * 0x00 = unknown
+ * 0x01 = router update
+ * 0x02 = plugin or plugin update
+ * 0x03 = reseed data
+ * 0x04 = news feed (as of 0.9.15)
+
+28-39 unused = 0
+
+40-55+ Version, UTF-8 padded with trailing 0x00, 16 bytes minimum, length
+ specified at byte 13. Do not append 0x00 bytes if the length is 16 or
+ more.
+
+ xx+ ID of signer, (e.g. "zzz@mail.i2p") UTF-8, not padded, length specified
+ at byte 15
+
+ xx+ Content:
+
+ * Length specified in header at bytes 16-23
+ * Format specified in header at byte 25
+ * Content specified in header at byte 27
+
+ xx+ Signature: Length is specified in header at bytes 10-11, covers
+ everything starting at byte 0
+====== ========================================================================
+
+All unused fields must be set to 0 for compatibility with future versions.
+
+Signature Details
+`````````````````
+The signature covers the entire header starting at byte 0, through the end of
+the content. We use raw signatures. Take the hash of the data (using the hash
+type implied by the signature type at bytes 8-9) and pass that to a "raw" sign
+or verify function (e.g. "NONEwithRSA" in Java).
+
+While signature verification and content extraction may be implemented in one
+pass, an implementation must read and buffer the first 10 bytes to determine
+the hash type before starting to verify.
+
+Signature lengths for the various signature types are given in the [Signature]_
+specification. Pad the signature with leading zeros if necessary. See the
+cryptography details page [CRYPTO-SIG]_ for parameters of the various signature
+types.
+
+Notes
+`````
+The content type specifies the trust domain. For each content type, clients
+maintain a set of X.509 public key certificates for parties trusted to sign
+that content. Only certificates for the specified content type may be used.
+The certificate is looked up by the ID of the signer. Clients must verify that
+the content type is that expected for the application.
+
+All values are in network byte order (big endian).
+
+SU3 Router Update File Specification
+------------------------------------
+
+SU3 Details
+```````````
+* SU3 Content Type: 1 (ROUTER UPDATE)
+
+* SU3 File Type: 0 (ZIP)
+
+* SU3 Version: The router version
+
+* Jar and war files in the zip are compressed with pack200 as documented above
+ for "su2" files. If the client does not support pack200, it must download the
+ update in a "sud" format.
+
+Notes
+`````
+* For releases, the SU3 version is the "base" router version, e.g. "0.9.20".
+
+* For development builds, which are supported as of release 0.9.20, the SU3
+ version is the "full" router version, e.g. "0.9.20-5" or "0.9.20-5-rc". See
+ RouterVersion.java [I2P-SRC]_.
+
+SU3 Reseed File Specification
+-----------------------------
+
+As of 0.9.14, reseed data is delivered in an "su3" file format.
+
+Goals
+`````
+* Signed files with strong signatures and trusted certificates to prevent
+ man-in-the-middle attacks that could boot victims into a separate, untrusted
+ network.
+
+* Use su3 file format already used for updates, reseeding, and plugins
+
+* Single compressed file to speed up reseeding, which was slow to fetch 200 files
+
+Specification
+`````````````
+1. The file must be named "i2pseeds.su3".
+
+2. The file must be in the same directory as the router infos on the web server.
+
+3. A router will first try to fetch (index URL)/i2pseeds.su3; if that fails it
+ will fetch the index URL and then fetch the individual router info files
+ found in the links.
+
+SU3 Details
+```````````
+* SU3 Content Type: 3 (RESEED)
+
+* SU3 File Type: 0 (ZIP)
+
+* SU3 Version: Seconds since the epoch, in ASCII (date +%s)
+
+* Router info files in the zip file must be at the "top level". No directories
+ are in the zip file.
+
+* Router info files must be named "routerInfo-(44 character base 64 router
+ hash).dat", as in the old reseed mechanism. The I2P base 64 alphabet must be
+ used.
+
+SU3 Plugin File Specification
+-----------------------------
+
+As of 0.9.15, plugins may be packaged in an "su3" file format.
+
+SU3 Details
+```````````
+* SU3 Content Type: 2 (PLUGIN)
+
+* SU3 File Type: 0 (ZIP)
+
+ * See the plugin specification [PLUGIN]_ for details.
+
+* SU3 Version: The plugin version, must match that in plugin.config.
+
+* Jar and war files in the zip are compressed with pack200 as documented above
+ for "su2" files.
+
+SU3 News File Specification
+---------------------------
+
+As of 0.9.17, the news is delivered in an "su3" file format.
+
+Goals
+`````
+* Signed news with strong signatures and trusted certificates
+
+* Use su3 file format already used for updates, reseeding, and plugins
+
+* Standard XML format for use with standard parsers
+
+* Standard Atom format for use with standard feed readers and generators
+
+* Sanitization and verification of HTML before displaying on console
+
+* Suitable for easy implementation on Android and other platforms without an
+ HTML console
+
+SU3 Details
+```````````
+* SU3 Content Type: 4 (NEWS)
+
+* SU3 File Type: 1 (XML) or 3 (XML.GZ)
+
+* SU3 Version: Seconds since the epoch, in ASCII (date +%s)
+
+* File Format: XML or gzipped XML, containing an [RFC-4287]_ (Atom) XML Feed.
+ Charset must be UTF-8.
+
+Specification
+`````````````
+**Atom Details:**
+
+The following elements are used:
+
+
+ A news item. See below.
+
+
+ I2P update metadata. See below.
+
+
+ Required
+
+ Timestamp for the feed (conforming to [RFC-4287]_ (Atom) section 3.3 and
+ [RFC-3339]_.
+
+**Atom Details:**
+
+Each Atom in the news feed may be parsed and displayed in the router console.
+The following elements are used:
+
+
+ Optional
+
+ Containing:
+
+
+ The name of the entry author
+
+
+ Required
+
+ Content, must be type="xhtml".
+
+ The XHTML will be sanitized with a whitelist of allowed elements and a
+ blacklist of disallowed attributes. Clients may ignore an element, or
+ the enclosing entry, or the entire feed when a non-whitelisted element
+ is encountered.
+
+
+ Optional
+
+ Link for further information
+
+
+ Optional
+
+ Short summary, suitable for a tooltip
+
+
+ Required
+
+ Title of the news entry
+
+
+ Required
+
+ Timestamp for this entry (conforming to [RFC-4287]_ (Atom) section 3.3
+ and [RFC-3339]_).
+
+**Atom Details:**
+
+There must be at least one entity in the feed. Each contains the
+following attributes and entities:
+
+ date (attribute)
+ Required
+
+ Timestamp for this entry (conforming to [RFC-4287]_ (Atom) section 3.3
+ and [RFC-3339]_.
+
+ The date also may be in truncated format yyyy-mm-dd (without the 'T');
+ this is the "full-date" format in [RFC-3339]_. In this format the time
+ is assumed to be 00:00:00 UTC for any processing.
+
+ minJavaVersion (attribute)
+ If present, the minimum version of Java required to run the current
+ version.
+
+ minVersion (attribute)
+ If present, the minimum version of the router required to update to the
+ current version. If a router is older than this, the user must
+ (manually?) update to an intermediate version first.
+
+
+ Required
+
+ The latest current router version available.
+
+
+ An update file (one or more). It must contain at least one child.
+
+ type (attribute)
+ "sud", "su2", or "su3".
+
+ Must be unique across all elements.
+
+
+ Out-of-network direct download links (zero or more)
+
+ href (attribute)
+ A standard clearnet http link
+
+
+ Out-of-network direct download links (zero or more)
+
+ href (attribute)
+ A standard clearnet https link
+
+
+ In-network magnet link
+
+ href (attribute)
+ A magnet link
+
+
+ In-network direct download links (zero or more)
+
+ href (attribute)
+ An in-network http .i2p link
+
+
+Future Work
+===========
+
+* The router update mechanism is part of the web router console. There is
+ currently no provision for updates of an embedded router lacking the router
+ console.
+
+
+References
+==========
+
+.. [CRYPTO-SIG]
+ {{ site_url('docs/how/cryptography', True) }}#sig
+
+.. [I2P-SRC]
+ https://github.com/i2p/i2p.i2p
+
+.. [PLUGIN]
+ {{ spec_url('plugin') }}
+
+.. [RFC-3339]
+ http://tools.ietf.org/html/rfc3339
+
+.. [RFC-4287]
+ http://tools.ietf.org/html/rfc4287
+
+.. [Signature]
+ {{ spec_url('common-structures') }}#type-signature
+
+.. [SigningPublicKey]
+ {{ spec_url('common-structures') }}#type-signingpublickey