diff --git a/i2p2www/__init__.py b/i2p2www/__init__.py index ce91718f08d5be8897b80d7777e5d98b1748fadb..af3d944015f04c8f5d9aa95f5d59b60eec42243c 100644 --- a/i2p2www/__init__.py +++ b/i2p2www/__init__.py @@ -105,6 +105,7 @@ GETTEXT_DOMAIN_MAPPING = { TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'pages') STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static') +SPEC_DIR = os.path.join(os.path.dirname(__file__), 'spec') BLOG_DIR = os.path.join(os.path.dirname(__file__), 'blog') MEETINGS_DIR = os.path.join(os.path.dirname(__file__), 'meetings/logs') SITE_DIR = os.path.join(TEMPLATE_DIR, 'site') @@ -178,9 +179,12 @@ def pull_lang(endpoint, values): def set_lang(endpoint, values): if not values: return - if endpoint == 'static': + if endpoint == 'static' or \ + endpoint.startswith('spec_'): # Static urls shouldn't have a lang flag # (causes complete reload on lang change) + # Spec urls shouldn't have a lang flag + # (adds a spurious ?lang=xx to the url) return if 'lang' in values: return diff --git a/i2p2www/blog/helpers.py b/i2p2www/blog/helpers.py index a2fdff74ec3fb9e6a48ddd913abdba84b07bcc0e..42ee5859dcc39af217e80abba0163002f3545405 100644 --- a/i2p2www/blog/helpers.py +++ b/i2p2www/blog/helpers.py @@ -6,16 +6,17 @@ import os import os.path from i2p2www import BLOG_DIR +from i2p2www import helpers -SUPPORTED_METATAGS = { +BLOG_METATAGS = { 'author': u'I2P devs', 'category': None, 'date': None, 'excerpt': u'', } -LIST_METATAGS = [ +BLOG_LIST_METATAGS = [ 'category', ] @@ -108,11 +109,4 @@ def render_blog_post(slug): return publish_parts(source=rendered_content, source_path=BLOG_DIR, writer_name="html") def get_metadata_from_meta(meta): - metaLines = meta.split('\n') - ret = {} - for metaTag in SUPPORTED_METATAGS: - metaLine = [s for s in metaLines if 'name="%s"' % metaTag in s] - ret[metaTag] = metaLine[0].split('content="')[1].split('"')[0] if len(metaLine) > 0 else SUPPORTED_METATAGS[metaTag] - if metaTag in LIST_METATAGS and ret[metaTag]: - ret[metaTag] = [s.strip() for s in ret[metaTag].split(',')] - return ret + return helpers.get_metadata_from_meta(meta, BLOG_METATAGS, BLOG_LIST_METATAGS) diff --git a/i2p2www/extensions.py b/i2p2www/extensions.py index 51d8f727efb133ee1fe18fe6557ea6aca116bbb9..27d6f677903e5dca90d5785c8ca77ee5d046a0bb 100644 --- a/i2p2www/extensions.py +++ b/i2p2www/extensions.py @@ -17,7 +17,7 @@ except ImportError: from flask import g -from i2p2www.formatters import I2PHtmlFormatter +from i2p2www.formatters import I2PHtmlFormatter, TextSpecFormatter from i2p2www.lexers import DataSpecLexer @@ -55,13 +55,14 @@ class HighlightExtension(Extension): # extract the language if available # Any additional parameters are passed to HtmlFormatter lang = None + formatter = None parameters = [] while parser.stream.current.type != 'block_end': if lang or parameters: parser.stream.expect('comma') name = parser.stream.expect('name') - if name.value in parameters or (name.value == 'lang' and lang): + if name.value in parameters or (name.value == 'lang' and lang) or (name.value == 'formatter' and formatter): parser.fail('parameter %r defined twice.' % name.value, name.lineno, exc=TemplateAssertionError) @@ -70,20 +71,24 @@ class HighlightExtension(Extension): next(parser.stream) if name.value == 'lang': lang = parser.parse_expression() + elif name.value == 'formatter': + formatter = parser.parse_expression() else: parameters.append(nodes.Pair(nodes.Const(name.value), parser.parse_expression())) if lang == None: lang = nodes.Const(None) + if formatter == None: + formatter = nodes.Const('html') parameters = nodes.Dict(parameters) # body of the block body = parser.parse_statements(['name:endhighlight'], drop_needle=True) - return nodes.CallBlock(self.call_method('_highlight', [lang, parameters]), + return nodes.CallBlock(self.call_method('_highlight', [lang, formatter, parameters]), [], [], body).set_lineno(lineno) - def _highlight(self, lang, parameters, caller=None): + def _highlight(self, lang, formatter, parameters, caller=None): # highlight code using Pygments body = caller() try: @@ -100,14 +105,17 @@ class HighlightExtension(Extension): if ctags: if 'tagsfile' not in parameters: - parameters['tagsfile'] = module_path() + '/pages/site/spectags' + parameters['tagsfile'] = module_path() + '/spec/spectags' if 'tagurlformat' not in parameters: lang = 'en' if hasattr(g, 'lang') and g.lang: lang = g.lang - parameters['tagurlformat'] = '/' + lang + '/%(path)s%(fname)s' + parameters['tagurlformat'] = '/spec/%(path)s%(fname)s' - formatter = I2PHtmlFormatter(**parameters) + if formatter == 'textspec': + formatter = TextSpecFormatter(**parameters) + else: + formatter = I2PHtmlFormatter(**parameters) code = highlight(Markup(body).unescape(), lexer, formatter) return code diff --git a/i2p2www/formatters.py b/i2p2www/formatters.py index 2f03f5b57d401cf329a62868c7aa310d1fd248ba..8cd36825da48aacd057d0031985e4ccf89b2535d 100644 --- a/i2p2www/formatters.py +++ b/i2p2www/formatters.py @@ -23,7 +23,7 @@ try: except ImportError: ctags = None -__all__ = ['I2PHtmlFormatter'] +__all__ = ['I2PHtmlFormatter', 'TextSpecFormatter'] _escape_html_table = { @@ -727,8 +727,8 @@ class I2PHtmlFormatter(Formatter): filename, extension = os.path.splitext(filename) url = self.tagurlformat % {'path': base, 'fname': filename, 'fext': extension} - parts[0] = "<a href=\"%s#%s_%s\">%s" % \ - (url, kinds[kind], value, parts[0]) + parts[0] = "<a href=\"%s#%s-%s\">%s" % \ + (url, kinds[kind], value.lower(), parts[0]) parts[-1] = parts[-1] + "</a>" # for all but the last line @@ -829,3 +829,70 @@ class I2PHtmlFormatter(Formatter): for t, piece in source: outfile.write(piece) + + +class TextSpecFormatter(Formatter): + """ + Output the text unchanged without any formatting. + """ + name = 'Text spec' + aliases = ['textspec'] + filenames = ['*.txt'] + + def __init__(self, **options): + Formatter.__init__(self, **options) + self.tagsfile = self._decodeifneeded(options.get('tagsfile', '')) + self.tagurlformat = self._decodeifneeded(options.get('tagurlformat', '')) + + if self.tagsfile: + if not ctags: + raise RuntimeError('The "ctags" package must to be installed ' + 'to be able to use the "tagsfile" feature.') + self._ctags = ctags.CTags(self.tagsfile) + + def _decodeifneeded(self, value): + if isinstance(value, bytes): + if self.encoding: + return value.decode(self.encoding) + return value.decode() + return value + + def format(self, tokensource, outfile): + enc = self.encoding + tagsfile = self.tagsfile + refs = {} + + for ttype, value in tokensource: + if tagsfile and ttype in Token.Name.Class: + filename, kind = self._lookup_ctag(value) + # Handle message types + if not kind and value.endswith('Message'): + value = value[:-7] + filename, kind = self._lookup_ctag(value) + if kind: + base, filename = os.path.split(filename) + if base: + base += '/' + filename, extension = os.path.splitext(filename) + url = self.tagurlformat % {'path': base, 'fname': filename, + 'fext': extension} + refs[value] = '\n[%s]: %s#%s-%s' % (value, url, kinds[kind], value.lower()) + value = '[%s]' % value + + if enc: + outfile.write(value.encode(enc)) + else: + outfile.write(value) + + for ref in refs.values(): + if enc: + outfile.write(ref.encode(enc)) + else: + outfile.write(ref) + + def _lookup_ctag(self, token): + entry = ctags.TagEntry() + if self._ctags.find(entry, token, 0): + return entry['file'], entry['kind'] + else: + return None, None diff --git a/i2p2www/helpers.py b/i2p2www/helpers.py index 04bd49ee6f77021bdadd21078aa0a964e6683fad..41e6c6a85c30b6df06b84cff781c075c2a76eb94 100644 --- a/i2p2www/helpers.py +++ b/i2p2www/helpers.py @@ -9,6 +9,16 @@ def get_for_page(items, page, per_page): to_item = page*per_page return items[from_item:to_item] +def get_metadata_from_meta(meta, supported_metatags, list_metatags): + metaLines = meta.split('\n') + ret = {} + for metaTag in supported_metatags: + metaLine = [s for s in metaLines if 'name="%s"' % metaTag in s] + ret[metaTag] = metaLine[0].split('content="')[1].split('"')[0] if len(metaLine) > 0 else supported_metatags[metaTag] + if metaTag in list_metatags and ret[metaTag]: + ret[metaTag] = [s.strip() for s in ret[metaTag].split(',')] + return ret + ######################## # General helper classes diff --git a/i2p2www/pages/global/macros b/i2p2www/pages/global/macros index 4c470c8850442f8b4e21d61c106939a5f11ae714..b50e5541054610b63608608f69612ad7b74f7caa 100644 --- a/i2p2www/pages/global/macros +++ b/i2p2www/pages/global/macros @@ -1,5 +1,6 @@ {%- macro change_lang(lang) -%} {%- if request.endpoint == 'site_show' -%}{{ url_for('site_show', lang=lang, page=page) }} +{%- elif request.endpoint == 'spec_show' -%}{{ url_for('spec_show', name=name) }} {%- elif request.endpoint == 'blog_index' -%} {%- if category -%}{{ url_for('blog_index', lang=lang, category=category) }} {%- else -%}{{ url_for('blog_index', lang=lang) }} diff --git a/i2p2www/pages/global/nav.html b/i2p2www/pages/global/nav.html index f3a3893448ed3282d3185e2705a9bed5df596f8b..14d3f0cee98e24cbeed1572794d5872d4be11f15 100644 --- a/i2p2www/pages/global/nav.html +++ b/i2p2www/pages/global/nav.html @@ -29,23 +29,7 @@ <li><a href="{{ site_url('docs/how/elgamal-aes') }}"><div class="menuitem"><span>{{ _('ElGamal/AES+SessionTags') }}</span></div></a></li> </ul> </li> - <li class="has-sub"><div class="menuitem"><span>{{ _('Specifications') }}</span></div> - <ul> - <li><a href="{{ site_url('docs/spec/blockfile') }}"><div class="menuitem"><span>{{ _('Blockfile') }}</span></div></a></li> - <li><a href="{{ site_url('docs/spec/common-structures') }}"><div class="menuitem"><span>{{ _('Common structures') }}</span></div></a></li> - <li><a href="{{ site_url('docs/spec/configuration') }}"><div class="menuitem"><span>{{ _('Configuration files') }}</span></div></a></li> - <li><a href="{{ site_url('docs/spec/datagrams') }}"><div class="menuitem"><span>{{ _('Datagrams') }}</span></div></a></li> - <li><a href="{{ site_url('docs/spec/geoip') }}"><div class="menuitem"><span>{{ _('GeoIP files') }}</span></div></a></li> - <li><a href="{{ site_url('docs/spec/i2cp') }}"><div class="menuitem"><span>I2CP</span></div></a></li> - <li><a href="{{ site_url('docs/spec/i2np') }}"><div class="menuitem"><span>I2NP</span></div></a></li> - <li><a href="{{ site_url('docs/spec/plugin') }}"><div class="menuitem"><span>{{ _('Plugins') }}</span></div></a></li> - <li><a href="{{ site_url('docs/spec/ssu') }}"><div class="menuitem"><span>SSU</span></div></a></li> - <li><a href="{{ site_url('docs/spec/streaming') }}"><div class="menuitem"><span>{{ _('Streaming library') }}</span></div></a></li> - <li><a href="{{ site_url('docs/spec/tunnel-creation') }}"><div class="menuitem"><span>{{ _('Tunnel creation') }}</span></div></a></li> - <li><a href="{{ site_url('docs/spec/tunnel-message') }}"><div class="menuitem"><span>{{ _('Tunnel messages') }}</span></div></a></li> - <li><a href="{{ site_url('docs/spec/updates') }}"><div class="menuitem"><span>{{ _('Software updates') }}</span></div></a></li> - </ul> - </li> + <li><a href="{{ url_for('spec_index') }}"><div class="menuitem"><span>{{ _('Specifications') }}</span></div></a></li> <li class="has-sub"><div class="menuitem"><span>{{ _('API') }}</span></div> <ul> <li><a href="{{ site_url('docs/api/i2ptunnel') }}"><div class="menuitem"><span>I2PTunnel</span></div></a></li> diff --git a/i2p2www/pages/site/docs/how/cryptography.html b/i2p2www/pages/site/docs/how/cryptography.html deleted file mode 100644 index e009dc314f506ca9ca5d9761e66409f4fb160773..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/how/cryptography.html +++ /dev/null @@ -1,523 +0,0 @@ -{% extends "global/layout.html" %} -{% block title %}{% trans %}Low-level Cryptography Details{% endtrans %}{% endblock %} -{% block lastupdated %}{% trans %}December 2014{% endtrans %}{% endblock %} -{% block accuratefor %}0.9.17{% endblock %} -{% block content %} -<p>{% trans -%} -This page specifies the low-level details of the cryptography in I2P. -{%- endtrans %}</p> - -<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%} -There are a handful of cryptographic algorithms in use within I2P, but we have -reduced them to a bare minimum to deal with our needs - one symmetric algorithm -one asymmetric algorithm, one signing algorithm, and one hashing algorithm. However, -we do combine them in some particular ways to provide message integrity (rather than -relying on a MAC). In addition, as much as we hate doing anything new in regards to -cryptography, we can't seem to find a reference discussing (or even naming) the -technique used in <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> (but we're sure others have done it). -{%- endtrans %}</p> - -<h2><a name="elgamal">{% trans %}ElGamal encryption{% endtrans %}</a></h2> - -<p>{% trans %} -ElGamal is used for asymmetric encryption. -ElGamal is used in several places in I2P: -{%- endtrans %}</p> -<ul> -<li>{% trans tunnelcreation=site_url('docs/spec/tunnel-creation') -%} -To encrypt router-to-router <a href="{{ tunnelcreation }}">Tunnel Build Messages</a> -{%- endtrans %}</li> -<li>{% trans elgamalaes=site_url('docs/how/elgamal-aes'), commonstructures=site_url('docs/spec/common-structures') -%} -For end-to-end (destination-to-destination) encryption as a part of <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> -using the encryption key in the <a href="{{ commonstructures }}#struct_LeaseSet">LeaseSet</a> -{%- endtrans %}</li> -<li>{% trans netdb=site_url('docs/how/network-database'), elgamalaes=site_url('docs/how/elgamal-aes') -%} -For encryption of some <a href="{{ netdb }}#delivery">netDb stores and queries sent to floodfill routers</a> -as a part of <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> -(destination-to-router or router-to-router). -{%- endtrans %}</li> -</ul> - -<p>{% trans -%} -We use common primes for 2048 ElGamal encryption and decryption, as given by <a href="http://tools.ietf.org/html/rfc3526">IETF RFC-3526</a>. -We currently only use ElGamal to encrypt the IV and session key in a single block, followed by the -AES encrypted payload using that key and IV. -{%- endtrans %}</p> - -<p>{% trans -%} -The unencrypted ElGamal contains: -{%- endtrans %}</p> -{% highlight lang='dataspec' %} - +----+----+----+----+----+----+----+----+ - |nonz| H(data) | - +----+ + - | | - + + - | | - + + - | | - + +----+----+----+----+----+----+----+ - | | data... - +----+----+----+-// -{% endhighlight %} - -<p>{% trans -%} -The H(data) is the SHA256 of the data that is encrypted in the ElGamal block, -and is preceded by a nonzero byte. -This byte could be random, but as implemented it is always 0xFF. -It could possibly be used for flags in the future. -The data encrypted in the block may be up to 222 bytes long. -As the encrypted data may contain a substantial number of zeros if the -cleartext is smaller than 222 bytes, it is recommended that higher layers pad -the cleartext to 222 bytes with random data. -Total length: typically 255 bytes. -{%- endtrans %}</p> - -<p>{% trans -%} -The encrypted ElGamal contains: -{%- endtrans %}</p> -</p> -{% highlight lang='dataspec' %} - +----+----+----+----+----+----+----+----+ - | zero padding... | | - +----+----+----+-//-+----+ + - | | - + + - | ElG encrypted part 1 | - ~ ~ - | | - + +----+----+----+----+----+----+----+ - | | zero padding... | | - +----+----+----+----+-//-+----+ + - | | - + + - | ElG encrypted part 2 | - ~ ~ - | | - + +----+----+----+----+----+----+ - | + - +----+----+ -{% endhighlight %} - -<p>{% trans -%} -Each encrypted part is prepended with zeros to a size of exactly 257 bytes. -Total length: 514 bytes. -In typical usage, higher layers pad the cleartext data to 222 bytes, -resulting in an unencrypted block of 255 bytes. -This is encoded as two 256-byte encrypted parts, -and there is a single byte of zero padding before each part at this layer. -{%- endtrans %}</p> - -<p>{% trans url='https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/ElGamalEngine.java' -%} -See <a href="{{ url }}">the ElGamal code</a>. -{%- endtrans %}</p> - -<p>{% trans -%} -The shared prime is the -<a href="http://tools.ietf.org/html/rfc3526#section-3">[Oakley prime for 2048 bit keys]</a> -{%- endtrans %}</p> -<pre> - 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } -</pre> -<p>{% trans -%} -or as a hexadecimal value: -{%- endtrans %}</p> -<pre> - FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 - 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD - EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 - E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED - EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D - C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F - 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D - 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B - E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 - DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 - 15728E5A 8AACAA68 FFFFFFFF FFFFFFFF -</pre> -<p>{% trans -%} -Using 2 as the generator. -{%- endtrans %}</p> - -<h3><a name="exponent">{% trans %}Short Exponent{% endtrans %}</a></h3> -<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%} -While the standard exponent size is 2048 bits (256 bytes) and the I2P -<a href="{{ commonstructures }}#type_PrivateKey">PrivateKey</a> -is a full 256 bytes, in some cases -we use the short exponent size of 226 bits (28.25 bytes). -{%- endtrans %}</p> - -<p>{% trans pdf='http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.14.5952&rep=rep1&type=pdf', -benchmarks=site_url('misc/benchmarks'), -oldbenchmarks='http://www.eskimo.com/~weidai/benchmarks.html' -%} -This should be safe for use with the Oakley primes, per -<a href="{{ pdf }}">On Diffie-Hellman Key Agreement with Short Exponents - van Oorschot, Weiner</a> -at EuroCrypt 96, and <a href="{{ benchmarks }}">crypto++'s benchmarks</a>. -Benchmarks originally at <a rel="nofollow" href="{{ oldbenchmarks }}">this link, now dead</a>, -rescued from <a href="http://www.archive.org/">the wayback machine</a>, dated Apr 23, 2008. -{%- endtrans %}</p> - -<p>{% trans book='http://www.springerlink.com/content/2jry7cftp5bpdghm/', -fulltext='http://books.google.com/books?id=cXyiNZ2_Pa0C&lpg=PA173&ots=PNIz3dWe4g&pg=PA173#v=onepage&q&f=false', -thread='http://groups.google.com/group/sci.crypt/browse_thread/thread/1855a5efa7416677/339fa2f945cc9ba0#339fa2f945cc9ba0' -%} -Also, <a href="{{ book }}">Koshiba & Kurosawa: Short Exponent Diffie-Hellman Problems</a> (PKC 2004, LNCS 2947, pp. 173-186) -<a href="{{ fulltext }}">(full text on Google Books)</a> apparently supports this, according to -<a href="{{ thread }}">this sci.crypt thread</a>. -The remainder of the PrivateKey is padded with zeroes. -{%- endtrans %}</p> - -<p>{% trans -%} -Prior to release 0.9.8, all routers used the short exponent. -As of release 0.9.8, 64-bit x86 routers use a full 2048-bit exponent. -Other routers continue to use the short exponent due to concerns about processor load. -The transition to a longer exponent for these platforms is a topic for further study. -{%- endtrans %}</p> - -<h4>{% trans %}Obsolescence{% endtrans %}</h4> -<p>{% trans -%} -The vulnerability of the network to an ElGamal attack and the impact of transitioning to a longer bit length is to be studied. -It may be quite difficult to make any change backward-compatible. -{%- endtrans %}</p> - - -<h2><a name="AES">AES</a></h2> - -<p>{% trans -%} -AES is used for symmetric encryption, in several cases: -{%- endtrans %}</p> - -<ul> -<li>{% trans -%} -For <a href="#transports">transport encryption</a> after DH key exchange -{%- endtrans %}</li> - -<li>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%} -For end-to-end (destination-to-destination) encryption as a part of <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> -{%- endtrans %}</li> - -<li>{% trans netdb=site_url('docs/how/network-database'), elgamalaes=site_url('docs/how/elgamal-aes') -%} -For encryption of some <a href="{{ netdb }}#delivery">netDb stores and queries sent to floodfill routers</a> -as a part of <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> -(destination-to-router or router-to-router). -{%- endtrans %}</li> - -<li>{% trans tunnelrouting=site_url('docs/how/tunnel-routing') -%} -For encryption of <a href="{{ tunnelrouting }}#testing">periodic tunnel test messages</a> sent from the router to itself, through its own tunnels. -{%- endtrans %}</li> -</ul> - -<p>{% trans rfc2313='http://tools.ietf.org/html/rfc2313', -code1='https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/CryptixAESEngine.java', -code2='https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/CryptixRijndael_Algorithm.java', -code3='https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/ElGamalAESEngine.java' -%} -We use AES with 256 bit keys and 128 bit blocks in CBC mode. -The padding used is specified in <a href="{{ rfc2313 }}">IETF RFC-2313 (PKCS#5 1.5, section 8.1 (for block type 02))</a>. -In this case, padding exists of pseudorandomly generated octets to match 16 byte blocks. -Specifically, see <a href="{{ code1 }}">[the CBC code]</a> and the Cryptix AES -<a href="{{ code2 }}">[implementation]</a>, as well as the padding, found in the -<a href="{{ code3 }}">ElGamalAESEngine.getPadding</a> function. -{%- endtrans %}</p> - -<!-- ********************************************************************************* - Believe it or not, we don't do this any more. If we ever did. safeEncode() and safeDecode() are unused. - -<p> -In all cases, we know the size of the data to be sent, and we AES encrypt the following: -<p> -<pre> - +----+----+----+----+----+----+----+----+ - | H(data) | - + + - | | - + + - | | - + + - | | - +----+----+----+----+----+----+----+----+ - | size | data ... | - +----+----+----+----+ + - | | - ~ ~ - | | - + + - | | - + +----//---+----+ - | | | - +----+----+----//---+----+ + - | Padding to 16 bytes | - +----+----+----+----+----+----+----+----+ - -H(data): 32-byte SHA-256 Hash of the data - -size: 4-byte Integer, number of data bytes to follow - -data: payload - -padding: random data, to a multiple of 16 bytes - -</pre> -<p> -After the data comes an application-specified number of randomly generated padding bytes. -This application-specified number is rounded up to a multiple of 16. -The entire segment (from H(data) through the end of the random bytes) is AES encrypted -(256 bit CBC w/ PKCS#5). - -<p> -This code is implemented in the safeEncrypt and safeDecrypt methods of -AESEngine but it is unused. -</p> - -*************************************************************** --> - - -<h4>{% trans %}Obsolescence{% endtrans %}</h4> -<p>{% trans -%} -The vulnerability of the network to an AES attack and the impact of transitioning to a longer bit length is to be studied. -It may be quite difficult to make any change backward-compatible. -{%- endtrans %}</p> - -<h4>{% trans %}References{% endtrans %}</h4> -<ul> -<li> -<a href="{{ get_url('blog_post', slug='2006/02/07/status') }}">{% trans %}Feb. 7, 2006 Status Notes{% endtrans %}</a> -</li> -</ul> - - -<h2><a name="sig">{% trans %}Digital Signatures{% endtrans %}</a></h2> - -<p>{% trans -%} -DSA is the default signature algorithm, but we are in the process of migrating to more secure algorithms. See below. -{%- endtrans %}</p> - -<h3><a name="DSA">DSA</a></h3> - -<p>{% trans code='https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/DSAEngine.java' -%} -Signatures are generated and verified with 1024 bit DSA (L=1024, N=160), as implemented in -<a href="{{ code }}">[DSAEngine]</a>. -DSA was chosen because it is much faster for signatures than ElGamal. -{%- endtrans %}</p> - -<h4>SEED</h4> - -<p>160 bit</p> - -<pre> - 86108236b8526e296e923a4015b4282845b572cc -</pre> - -<h4>Counter</h4> - -<pre> - 33 -</pre> -<p> -<H4>DSA prime (p)</H4> - -<p>1024 bit</p> - -<p> -<pre> - 9C05B2AA 960D9B97 B8931963 C9CC9E8C 3026E9B8 ED92FAD0 - A69CC886 D5BF8015 FCADAE31 A0AD18FA B3F01B00 A358DE23 - 7655C496 4AFAA2B3 37E96AD3 16B9FB1C C564B5AE C5B69A9F - F6C3E454 8707FEF8 503D91DD 8602E867 E6D35D22 35C1869C - E2479C3B 9D5401DE 04E0727F B33D6511 285D4CF2 9538D9E3 - B6051F5B 22CC1C93 -</pre> -<p> -<H4>DSA quotient (q)</H4> - -<p> -<pre> - A5DFC28F EF4CA1E2 86744CD8 EED9D29D 684046B7 -</pre> -<p> -<H4>DSA generator (g)</H4> - -<p>1024 bit</p> - -<p> -<pre> - 0C1F4D27 D40093B4 29E962D7 223824E0 BBC47E7C 832A3923 - 6FC683AF 84889581 075FF908 2ED32353 D4374D73 01CDA1D2 - 3C431F46 98599DDA 02451824 FF369752 593647CC 3DDC197D - E985E43D 136CDCFC 6BD5409C D2F45082 1142A5E6 F8EB1C3A - B5D0484B 8129FCF1 7BCE4F7F 33321C3C B3DBB14A 905E7B2B - 3E93BE47 08CBCC82 -</pre> - -<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%} -The <a href="{{ commonstructures }}#type_SigningPublicKey">Signing Public Key</a> is 1024 bits. -The <a href="{{ commonstructures }}#type_SigningPrivateKey">Signing Private Key</a> is 160 bits. -{%- endtrans %}</p> - - -<h4>{% trans %}Obsolescence{% endtrans %}</h4> -<p>{% trans pdf='http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57-Part1-revised2_Mar08-2007.pdf' -%} -<a href="{{ pdf }}">NIST 800-57</a> -recommends a minimum of (L=2048, N=224) for usage beyond 2010. -This may be mitigated somewhat by the "cryptoperiod", or lifespan of a given key. -{%- endtrans %}</p> - -<p>{% trans -%} -The prime number was chosen <a href="#choosing_constants">in 2003</a>, -and the person that chose the number (TheCrypto) is currently no longer an I2P developer. -As such, we do not know if the prime chosen is a 'strong prime'. -If a larger prime is chosen for future purposes, this should be a strong prime, and we will document the construction process. -{%- endtrans %}</p> - - -<h4>{% trans %}References{% endtrans %}</h4> -<ul> -<li> -<a href="{{ get_url('meetings_show', id=51) }}">{% trans num=51 %}Meeting {{ num }}{% endtrans %}</a> -<li> -<a href="{{ get_url('meetings_show', id=52) }}">{% trans num=52 %}Meeting {{ num }}{% endtrans %}</a> -<li> -<a name="choosing_constants" href="http://article.gmane.org/gmane.comp.security.invisiblenet.iip.devel/343">{% trans %}Choosing the constants{% endtrans %}</a> -<li> -<a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm">DSA</a> -</ul> - - - -<h2>{% trans %}New Signature Algorithms{% endtrans %}</h2> -<p>{% trans -%} -As of release 0.9.12, the router supports additional signature algorithms that are more secure than 1024-bit DSA. -The first usage is for Destinations; support for Router Identities was added in release 0.9.16. -Support for migrating existing Destinations from old to new signatures will be added in a future release. -Signature type is encoded in the Destination and Router Identity, so that new signature algorithms -or curves may be added at any time. -The current supported signature types are as follows: -{%- endtrans %}</p> -<ul> -<li>DSA-SHA1</li> -<li>ECDSA-SHA256-P256</li> -<li>ECDSA-SHA384-P384</li> -<li>ECDSA-SHA512-P521</li> -<li>RSA-SHA256-2048</li> -<li>RSA-SHA384-3072</li> -<li>RSA-SHA512-4096</li> -<li>EdDSA-SHA512-Ed25519 (as of release 0.9.15)</li> -</ul> - -<h3>ECDSA</h3> - -<p>{% trans -%} -ECDSA uses the standard NIST curves and standard SHA-2 hashes. -We will migrate new destinations to ECDSA-SHA256-P256 in the 0.9.16 - 0.9.19 release time frame. -Usage for Router Identities is supported as of release 0.9.16 and migration may occur in early 2015. -{%- endtrans %}</p> - - -<h3>RSA</h3> - -<p>{% trans -%} -Standard RSA PKCS#1 v1.5 (RFC 2313) with the public exponent F4 = 65537. -RSA is now used for signing all out-of-band trusted content, including router updates, reseeding, plugins, and news. -The signatures are embedded in the "su3" format documented on the router updates page. -4096-bit keys are recommended and used by all known signers. -RSA is not used, or planned for use, in any in-network Destinations or Router Identities. -{%- endtrans %}</p> - - -<h3>EdDSA 25519</h3> - -<p>{% trans -%} -Standard EdDSA using curve 25519 and standard 512-bit SHA-2 hashes. -Supported as of release 0.9.15. -Migration for Destinations and Router Identities is scheduled for mid-2015. -{%- endtrans %}</p> - - - -<H2><a name="SHA256">SHA256</a></H2> - -<p>{% trans code='https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/SHA256Generator.java' -%} -Hashes within I2P are plain old SHA256, as implemented in -<a href="{{ code }}">[SHA256Generator]</a> -{%- endtrans %}</p> - -<h4>{% trans %}Obsolescence{% endtrans %}</h4> -<p>{% trans -%} -The vulnerability of the network to a SHA-256 attack and the impact of transitioning to a longer hash is to be studied. -It may be quite difficult to make any change backward-compatible. -{%- endtrans %}</p> - -<h4>{% trans %}References{% endtrans %}</h4> -<ul> -<li> -<a href="http://en.wikipedia.org/wiki/SHA-2">SHA-2</a> -</ul> - -<h2 id="transports">{% trans %}Transports{% endtrans %}</h2> -<p>{% trans -%} -At the lowest protocol layer, -point-to-point inter-router communication is protected by the transport layer security. -Both transports use 256 byte (2048 bit) Diffie-Hellman key exchange -using -<a href="#elgamal">the same shared prime and generator as specified above for ElGamal</a>, -followed by symmetric AES encryption as described above. -This provides -<a href="http://en.wikipedia.org/wiki/Perfect_forward_secrecy">perfect forward secrecy</a> -on the transport links. -{%- endtrans %}</p> - -<h3><a name="tcp">{% trans %}NTCP connections{% endtrans %}</a></h3> - -<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%} -NTCP connections are negotiated with a 2048 Diffie-Hellman implementation, -using the router's identity to proceed with a station to station agreement, followed by -some encrypted protocol specific fields, with all subsequent data encrypted with AES -(as above). -The primary reason to do the DH negotiation instead of using <a href="{{ elgamalaes }}">ElGamalAES+SessionTag</a> is that it provides '<a href="http://en.wikipedia.org/wiki/Perfect_forward_secrecy">(perfect) forward secrecy</a>', while <a href="{{ elgamalaes }}">ElGamalAES+SessionTag</a> does not. -{%- endtrans %}</p> - -<p>{% trans -%} -In order to migrate to a more standardized implementation (TLS/SSL or even SSH), the following issues must be addressed: -{%- endtrans %}</p> -<ol> -<li>{% trans -%} -Can we somehow reestablish sessions securely (ala session tags) or do we need to do full negotiation each time? -{%- endtrans %}</li> -<li>{% trans -%} -Can we simplify/avoid the x509 or other certificate formats and use our own RouterInfo structure (which -contains the ElGamal and DSA keys)? -{%- endtrans %}</li> -</ol> -<p>{% trans ntcp=site_url('docs/transport/ntcp') -%} -See <a href="{{ ntcp }}">the NTCP specification</a> for details. -{%- endtrans %}</p> - -<h3><a name="udp">{% trans %}UDP connections{% endtrans %}</a></h3> -<p>{% trans -%} -SSU (the UDP transport) encrypts each packet with AES256/CBC with both an explicit IV and MAC -(HMAC-MD5-128) after agreeing upon an ephemeral session key through a 2048 bit -Diffie-Hellman exchange, station-to-station authentication with the other -router's DSA key, plus each network message has their own hash for local integrity -checking. -{%- endtrans %}</p> - -<p>{% trans ssu=site_url('docs/transport/ssu') -%} -See <a href="{{ ssu }}#keys">the SSU specification</a> for details. -{%- endtrans %}</p> - -<p>{% trans statusnotes=get_url('blog_post', slug='2005/07/05/status') -%} -WARNING - I2P's HMAC-MD5-128 used in SSU is apparently non-standard. -Apparently, an early version of SSU used HMAC-SHA256, and then it was switched -to MD5-128 for performance reasons, but left the 32-byte buffer size intact. -See HMACGenerator.java and -<a href="{{ statusnotes }}">the 2005-07-05 status notes</a> -for details. -{%- endtrans %}</p> - - -<h2>{% trans %}References{% endtrans %}</h2> -<ul> -<li> -<a href="http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57-Part1-revised2_Mar08-2007.pdf">NIST 800-57</a> -</li> -</ul> - -{% endblock %} diff --git a/i2p2www/pages/site/docs/index.html b/i2p2www/pages/site/docs/index.html index 00c3883a5f8a68f71b5c80f9d934c66328ecb8cf..2d27d21b0de7ca94efa0002db13ed56efadfaa6c 100644 --- a/i2p2www/pages/site/docs/index.html +++ b/i2p2www/pages/site/docs/index.html @@ -39,13 +39,13 @@ If you find any inaccuracies in the documents linked below, please <li><a href="{{ site_url('get-involved/develop/applications') }}">Application Development Overview and Guide</a></li> <li><a href="{{ site_url('docs/naming') }}">{{ _('Naming and Addressbook') }}</a></li> <li><a href="{{ site_url('docs/plugins') }}">{{ _('Plugins Overview') }}</a></li> -<li><a href="{{ site_url('docs/spec/plugin') }}">{{ _('Plugin Specification') }}</a></li> +<li><a href="{{ spec_url('plugin') }}">{{ _('Plugin Specification') }}</a></li> <li><a href="{{ site_url('docs/applications/managed-clients') }}">{{ _('Managed Clients') }}</a></li> <li><a href="{{ site_url('docs/applications/embedding') }}">{{ _('Embedding the router in your application') }}</a></li> <li><a href="{{ site_url('docs/applications/bittorrent') }}">{{ _('Bittorrent over I2P') }}</a></li> <li><a href="{{ site_url('docs/api/i2pcontrol') }}">{{ _('I2PControl Plugin API') }}</a></li> -<li><a href="{{ site_url('docs/spec/blockfile') }}">{{ _('hostsdb.blockfile Format') }}</a></li> -<li><a href="{{ site_url('docs/spec/configuration') }}">{{ _('Configuration File Format') }}</a></li> +<li><a href="{{ spec_url('blockfile') }}">{{ _('hostsdb.blockfile Format') }}</a></li> +<li><a href="{{ spec_url('configuration') }}">{{ _('Configuration File Format') }}</a></li> </ul> <h3>{% trans %}Application Layer API and Protocols{% endtrans %}</h3> @@ -55,7 +55,7 @@ If you find any inaccuracies in the documents linked below, please </li><li> <a href="{{ site_url('docs/api/i2ptunnel') }}">I2PTunnel</a> </li><li> -<a href="{{ site_url('docs/spec/configuration') }}">{{ _('I2PTunnel Configuration') }}</a></li> +<a href="{{ spec_url('configuration') }}">{{ _('I2PTunnel Configuration') }}</a></li> </li><li> <a href="{{ site_url('docs/api/socks') }}">SOCKS Proxy</a> </li><li> @@ -85,11 +85,11 @@ HTTP Bidir Proxy <ul><li> <a href="{{ site_url('docs/api/streaming') }}">{{ _('Streaming Library') }}</a> </li><li> -<a href="{{ site_url('docs/spec/streaming') }}">{{ _('Streaming Protocol Specification') }}</a> +<a href="{{ spec_url('streaming') }}">{{ _('Streaming Protocol Specification') }}</a> </li><li> <a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/client/streaming/package-summary.html">{{ _('Streaming Javadoc') }}</a> </li><li> -<a href="{{ site_url('docs/spec/datagrams') }}">{{ _('Datagrams') }}</a> +<a href="{{ spec_url('datagrams') }}">{{ _('Datagrams') }}</a> </li><li> <a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/client/datagram/package-summary.html">{{ _('Datagram Javadoc') }}</a> </li></ul> @@ -102,11 +102,11 @@ Traditionally used only by Java applications and higher-level APIs. <ul><li> <a href="{{ site_url('docs/protocol/i2cp') }}">{{ _('I2CP - I2P Control Protocol / API overview') }}</a> </li><li> -<a href="{{ site_url('docs/spec/i2cp') }}">{{ _('I2CP Specification') }}</a> +<a href="{{ spec_url('i2cp') }}">{{ _('I2CP Specification') }}</a> </li><li> <a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/client/package-summary.html">{{ _('I2CP API Javadoc') }}</a> </li><li> -<a href="{{ site_url('docs/spec/common-structures') }}">{{ _('Common data structures specification') }}</a> +<a href="{{ spec_url('common-structures') }}">{{ _('Common data structures specification') }}</a> </li><li> <a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/package-summary.html">{{ _('Data Structures Javadoc') }}</a> </li></ul> @@ -124,7 +124,7 @@ Traditionally used only by Java applications and higher-level APIs. <li><a href="{{ site_url('docs/how/network-database') }}">{{ _('Network database overview, details, and threat analysis') }}</a></li> <li><a href="{{ site_url('docs/how/cryptography') }}#SHA256">{{ _('Cryptographic hashes') }}</a></li> <li><a href="{{ site_url('docs/how/cryptography') }}#sig">{{ _('Cryptographic signatures') }}</a></li> -<li><a href="{{ site_url('docs/spec/updates') }}">{{ _('Router reseed specification') }}</a></li> +<li><a href="{{ spec_url('updates') }}">{{ _('Router reseed specification') }}</a></li> </ul> <h3>{% trans %}Router Message Protocol{% endtrans %}</h3> @@ -132,11 +132,11 @@ Traditionally used only by Java applications and higher-level APIs. <ul><li> <a href="{{ site_url('docs/protocol/i2np') }}">{{ _('I2NP - I2P Network Protocol Overview') }}</a> </li><li> -<a href="{{ site_url('docs/spec/i2np') }}">{{ _('I2NP Specification') }}</a> +<a href="{{ spec_url('i2np') }}">{{ _('I2NP Specification') }}</a> </li><li> <a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/i2np/package-summary.html">{{ _('I2NP Javadoc') }}</a> </li><li> -<a href="{{ site_url('docs/spec/common-structures') }}">{{ _('Common data structures specification') }}</a> +<a href="{{ spec_url('common-structures') }}">{{ _('Common data structures specification') }}</a> </li><li> <a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/package-summary.html">{{ _('Data Structures Javadoc') }}</a> </li></ul> @@ -150,8 +150,8 @@ Traditionally used only by Java applications and higher-level APIs. <li><a href="{{ site_url('docs/tunnels/implementation') }}">{{ _('Tunnel building and encryption') }}</a></li> <li><a href="{{ site_url('docs/how/elgamal-aes') }}">{{ _('ElGamal/AES') }}</a> {{ _('for build request encryption') }}</li> <li><a href="{{ site_url('docs/how/cryptography') }}">{{ _('ElGamal and AES cryptography details') }}</a></li> -<li><a href="{{ site_url('docs/spec/tunnel-creation') }}">{{ _('Tunnel building specification') }}</a></li> -<li><a href="{{ site_url('docs/spec/tunnel-message') }}">{{ _('Low-level tunnel message specification') }}</a></li> +<li><a href="{{ spec_url('tunnel-creation') }}">{{ _('Tunnel building specification') }}</a></li> +<li><a href="{{ spec_url('tunnel-message') }}">{{ _('Low-level tunnel message specification') }}</a></li> <li><a href="{{ site_url('docs/tunnels/unidirectional') }}">{{ _('Unidirectional Tunnels') }}</a></li> <li><a href="{{ url_for('static', filename='pdf/I2P-PET-CON-2009.1.pdf') }}">{{ _('Peer Profiling and Selection in the I2P Anonymous Network') }}</a> {{ _('2009 paper (pdf), not current but still generally accurate') }}</li> @@ -166,7 +166,7 @@ Traditionally used only by Java applications and higher-level APIs. </li><li> <a href="{{ site_url('docs/transport/ssu') }}">SSU</a> {{ _('UDP-based transport overview') }} </li><li> -<a href="{{ site_url('docs/spec/ssu') }}">{{ _('SSU specification') }}</a> +<a href="{{ spec_url('ssu') }}">{{ _('SSU specification') }}</a> </li><li> <a href="{{ site_url('docs/how/cryptography') }}#tcp">{{ _('NTCP transport encryption') }}</a> </li><li> @@ -181,9 +181,9 @@ Traditionally used only by Java applications and higher-level APIs. <h3>{% trans %}Other Router Topics{% endtrans %}</h3> <ul><li> -<a href="{{ site_url('docs/spec/updates') }}">{{ _('Router software updates') }}</a> +<a href="{{ spec_url('updates') }}">{{ _('Router software updates') }}</a> </li><li> -<a href="{{ site_url('docs/spec/updates') }}">{{ _('Router reseed specification') }}</a> +<a href="{{ spec_url('updates') }}">{{ _('Router reseed specification') }}</a> </li><li> <a href="{{ site_url('misc/jbigi') }}">{{ _('Native BigInteger Library') }}</a> </li><li> @@ -191,9 +191,9 @@ Traditionally used only by Java applications and higher-level APIs. </li><li> <a href="{{ site_url('about/performance') }}">{{ _('Performance') }}</a> </li><li> -<a href="{{ site_url('docs/spec/configuration') }}">{{ _('Configuration File Format') }}</a></li> +<a href="{{ spec_url('configuration') }}">{{ _('Configuration File Format') }}</a></li> </li><li> -<a href="{{ site_url('docs/spec/geoip') }}">GeoIP File Format</a></li> +<a href="{{ spec_url('geoip') }}">GeoIP File Format</a></li> </li></ul> <h3>{% trans %}Developer's Guides and Resources{% endtrans %}</h3> diff --git a/i2p2www/pages/site/docs/spec/blockfile.html b/i2p2www/pages/site/docs/spec/blockfile.html deleted file mode 100644 index 7be4db17e4af783259fae81ea84245167c7842e1..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/spec/blockfile.html +++ /dev/null @@ -1,230 +0,0 @@ -{% extends "global/layout.html" %} -{% block title %}{% trans %}Blockfile and Hosts Database Specification{% endtrans %}{% endblock %} -{% block lastupdated %}{% trans %}November 2014{% endtrans %}{% endblock %} -{% block accuratefor %}0.9.17{% endblock %} -{% block content %} -<h3>{% trans %}Overview{% endtrans %}</h3> -<p>{% 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 <a href="{{ naming }}">Naming Service</a>. -{%- endtrans %}</p> - -<p>{% 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 %}</p> - -<p>{% 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 -<a href="{{ url }}">Metanotion Blockfile Database</a>. -First we will define the file format, then the use of that format by the BlockfileNamingService. -{%- endtrans %}</p> - -<h3>{% trans %}Blockfile Format{% endtrans %}</h3> -<p>{% 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 %}</p> - -<p>{% 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 %}</p> - -<p>{% trans -%} -The database is designed to be opened and accessed by a single thread. -The BlockfileNamingService provides synchronization. -{%- endtrans %}</p> - -<p>{% trans -%} -Superblock format: -{%- endtrans %}</p> -{% 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 %} - -<p>{% trans -%} -Skip list block page format: -{%- endtrans %}</p> -{% 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 %} - - -<p>{% trans -%} -Skip level block page format is as follows. -All levels have a span. Not all spans have levels. -{%- endtrans %}</p> -{% 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 %} - - -<p>{% 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 %}</p> -{% 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 %} - -<p>{% trans -%} -Span Continuation block page format: -{%- endtrans %}</p> -{% highlight %} -Byte Contents -0-3 Magic number 0x434f4e54 "CONT" -4-7 Next continuation page or 0 -8-1023 key/value structures -{% endhighlight %} - - -<p>{% 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 %}</p> -{% highlight %} -Byte Contents -0-1 key length in bytes -2-3 value length in bytes -4- key data - value data -{% endhighlight %} - -<p>{% trans -%} -Free list block page format: -{%- endtrans %}</p> -{% 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 %} - - -<p>{% trans -%} -Free page block format: -{%- endtrans %}</p> -{% highlight %} -Byte Contents -0-7 Magic number 0x7e2146524545217e "~!FREE!~" -8-1023 unused -{% endhighlight %} - -<p>{% 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 %}</p> - -<h3>{% trans %}Blockfile Naming Service Tables{% endtrans %}</h3> -<p>{% trans -%} -The tables created and used by the BlockfileNamingService are as follows. -The maximum number of entries per span is 16. -{%- endtrans %}</p> - -<h4>{% trans %}Properties Skiplist{% endtrans %}</h4> -<p>{% trans INFO='"%%__INFO__%%"' -%} -{{ INFO }} is the master database skiplist with String/Properties key/value entries containing only one entry: -{%- endtrans %}</p> -<pre> - "info": a Properties (UTF-8 String/String Map), serialized as a <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a>: - "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". -</pre> - -<h4>{% trans %}Reverse Lookup Skiplist{% endtrans %}</h4> -<p>{% trans REVERSE='"%%__REVERSE__%%"' -%} -{{ REVERSE }} is the reverse lookup skiplist with Integer/Properties key/value entries - (as of database version 2): -{%- endtrans %}</p> -<pre> - 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 <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a> - 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. -</pre> - -<h4>{% trans %}hosts.txt, userhosts.txt, and privatehosts.txt Skiplists{% endtrans %}</h4> -<p>{% 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 %}</p> -<pre> - key: a UTF-8 String (the hostname) - value: a DestEntry, which is a Properties (a UTF-8 String/String Map) serialized as a <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a> - followed by a binary Destination (serialized <a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">as usual</a>). -</pre> - -<p>{% trans -%} -The DestEntry Properties typically contains: -{%- endtrans %}</p> -<pre> - "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 -</pre> - -<p>{% trans -%} -Hostname keys are stored in lower-case and always end in ".i2p". -{%- endtrans %}</p> - - -{% endblock %} diff --git a/i2p2www/pages/site/docs/spec/common-structures.html b/i2p2www/pages/site/docs/spec/common-structures.html deleted file mode 100644 index 8f25f9fa6100e4a76799a35a308801c9a16b8ea9..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/spec/common-structures.html +++ /dev/null @@ -1,1068 +0,0 @@ -{% extends "global/layout.html" %} -{% block title %}{% trans %}Common structures Specification{% endtrans %}{% endblock %} -{% block lastupdated %}{% trans %}February 2016{% endtrans %}{% endblock %} -{% block accuratefor %}0.9.24{% endblock %} -{% block content_nav %} -<table border=1> -<tr><th>{% trans %}Type{% endtrans %}</th></tr> -<tr><td><a href="#type_Boolean">Boolean</a></td></tr> -<tr><td><a href="#type_Certificate">Certificate</a></td></tr> -<tr><td><a href="#type_Date">Date</a></td></tr> -<tr><td><a href="#struct_DeliveryInstructions">Delivery Instructions</a></td></tr> -<tr><td><a href="#struct_Destination">Destination</a></td></tr> -<tr><td><a href="#type_Hash">Hash</a></td></tr> -<tr><td><a href="#type_Integer">Integer</a></td></tr> -<tr><td><a href="#struct_KeysAndCert">KeysAndCert</a></td></tr> -<tr><td><a href="#struct_Lease">Lease</a></td></tr> -<tr><td><a href="#struct_LeaseSet">LeaseSet</a></td></tr> -<tr><td><a href="#type_Mapping">Mapping</a></td></tr> -<tr><td><a href="#type_PrivateKey">PrivateKey</a></td></tr> -<tr><td><a href="#type_PublicKey">PublicKey</a></td></tr> -<tr><td><a href="#struct_RouterAddress">RouterAddress</a></td></tr> -<tr><td><a href="#struct_RouterIdentity">RouterIdentity</a></td></tr> -<tr><td><a href="#struct_RouterInfo">RouterInfo</a></td></tr> -<tr><td><a href="#type_SessionTag">SessionTag</a></td></tr> -<tr><td><a href="#type_Signature">Signature</a></td></tr> -<tr><td><a href="#type_SigningPrivateKey">SigningPrivateKey</a></td></tr> -<tr><td><a href="#type_SigningPublicKey">SigningPublicKey</a></td></tr> -<tr><td><a href="#type_String">String</a></td></tr> -<tr><td><a href="#type_TunnelId">TunnelId</a></td></tr> -</table> -{% endblock %} - -{% block content %} -<p>{% 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 -<a href="{{ i2np }}">I2NP</a>, <a href="{{ i2cp }}">I2CP</a>, -<a href="{{ ssu }}">SSU</a>, etc. -{%- endtrans %}</p> - -<h2 id="type_Integer">Integer</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -Represents a non-negative integer. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -1 to 8 bytes in network byte order representing an unsigned integer -{% endtrans %}</p> - -<h2 id="type_Date">Date</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% 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 %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -8 byte <a href="#type_Integer">Integer</a> -{% endtrans %}</p> - -<h2 id="type_String">String</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -Represents a UTF-8 encoded string. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% 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 %}</p> - -<h2 id="type_Boolean">Boolean</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -A boolean value, supporting null/unknown representation -0=false, 1=true, 2=unknown/null -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -1 byte <a href="#type_Integer">Integer</a> -{% endtrans %}</p> -<h4>{% trans %}Notes{% endtrans %}</h4> -<p>{% trans -%} -Deprecated - unused -{% endtrans %}</p> - -<h2 id="type_PublicKey">PublicKey</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% 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 -<a href="{{ cryptography }}#elgamal">the cryptography specification</a>. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -256 bytes -{% endtrans %}</p> - -<h4><a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/PublicKey.html">Javadoc</a></h4> - -<h2 id="type_PrivateKey">PrivateKey</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% 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 -<a href="{{ cryptography }}#elgamal">the cryptography specification</a>. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -256 bytes -{% endtrans %}</p> - -<h4><a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/PrivateKey.html">Javadoc</a></h4> - -<h2 id="type_SessionKey">SessionKey</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -This structure is used for AES256 encryption and decryption. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -32 bytes -{% endtrans %}</p> - -<h4><a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/SessionKey.html">Javadoc</a></h4> - - -<h2 id="type_SigningPublicKey">SigningPublicKey</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans cryptography=site_url('docs/how/cryptography') -%} -This structure is used for verifying signatures. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% 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 %}</p> - -<table border=1> -<tr><th>{% trans %}Type{% endtrans %}</th><th>{% trans %}Length (bytes){% endtrans %}</th><th>{% trans %}Since{% endtrans %}</th><th>{% trans %}Usage{% endtrans %}</th></tr> -<tr><td>DSA_SHA1</td><td align="center">128</td><td> </td> -<td>Legacy Router Identities and Destinations</td></tr> -<tr><td>ECDSA_SHA256_P256</td><td align="center">64</td><td align="center">0.9.12</td> -<td>Recent Destinations</td></tr> -<tr><td>ECDSA_SHA384_P384</td><td align="center">96</td><td align="center">0.9.12</td> -<td>Rarely used for Destinations</td></tr> -<tr><td>ECDSA_SHA512_P521</td><td align="center">132</td><td align="center">0.9.12</td> -<td>Rarely used for Destinations</td></tr> -<tr><td>RSA_SHA256_2048</td><td align="center">256</td><td align="center">0.9.12</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -<tr><td>RSA_SHA384_3072</td><td align="center">384</td><td align="center">0.9.12</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -<tr><td>RSA_SHA512_4096</td><td align="center">512</td><td align="center">0.9.12</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -<tr><td>EdDSA_SHA512_Ed25519</td><td align="center">32</td><td align="center">0.9.15</td> -<td>Recent Router Identities and Destinations</td></tr> -<tr><td>EdDSA_SHA512_Ed25519ph</td><td align="center">32</td><td align="center">0.9.25</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -</table> - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul> -<li>{% 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 %}</li> -<li>{% trans -%} -All types are Big Endian, except for -EdDSA, which is stored and transmitted in a Little Endian format. -{%- endtrans %}</li> -</ul> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/SigningPublicKey.html">Javadoc</a></h4> - - -<h2 id="type_SigningPrivateKey">SigningPrivateKey</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans cryptography=site_url('docs/how/cryptography') -%} -This structure is used for creating signatures. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% 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 %}</p> - -<table border=1> -<tr><th>{% trans %}Type{% endtrans %}</th><th>{% trans %}Length (bytes){% endtrans %}</th><th>{% trans %}Since{% endtrans %}</th><th>{% trans %}Usage{% endtrans %}</th></tr> -<tr><td>DSA_SHA1</td><td align="center">20</td><td> </td> -<td>Legacy Router Identities and Destinations</td></tr> -<tr><td>ECDSA_SHA256_P256</td><td align="center">32</td><td align="center">0.9.12</td> -<td>Recent Destinations</td></tr> -<tr><td>ECDSA_SHA384_P384</td><td align="center">48</td><td align="center">0.9.12</td> -<td>Rarely used for Destinations</td></tr> -<tr><td>ECDSA_SHA512_P521</td><td align="center">66</td><td align="center">0.9.12</td> -<td>Rarely used for Destinations</td></tr> -<tr><td>RSA_SHA256_2048</td><td align="center">512</td><td align="center">0.9.12</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -<tr><td>RSA_SHA384_3072</td><td align="center">768</td><td align="center">0.9.12</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -<tr><td>RSA_SHA512_4096</td><td align="center">1024</td><td align="center">0.9.12</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -<tr><td>EdDSA_SHA512_Ed25519</td><td align="center">32</td><td align="center">0.9.15</td> -<td>Recent Router Identities and Destinations</td></tr> -<tr><td>EdDSA_SHA512_Ed25519ph</td><td align="center">32</td><td align="center">0.9.25</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -</table> - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul> -<li>{% 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 %}</li> -<li>{% trans -%} -All types are Big Endian, except for -EdDSA, which is stored and transmitted in a Little Endian format. -{%- endtrans %}</li> -</ul> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/SigningPrivateKey.html">Javadoc</a></h4> - - -<h2 id="type_Signature">Signature</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans cryptography=site_url('docs/how/cryptography') -%} -This structure represents the signature of some data. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% 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 %}</p> - -<table border=1> -<tr><th>{% trans %}Type{% endtrans %}</th><th>{% trans %}Length (bytes){% endtrans %}</th><th>{% trans %}Since{% endtrans %}</th><th>{% trans %}Usage{% endtrans %}</th></tr> -<tr><td>DSA_SHA1</td><td align="center">40</td><td> </td> -<td>Legacy Router Identities and Destinations</td></tr> -<tr><td>ECDSA_SHA256_P256</td><td align="center">64</td><td align="center">0.9.12</td> -<td>Recent Destinations</td></tr> -<tr><td>ECDSA_SHA384_P384</td><td align="center">96</td><td align="center">0.9.12</td> -<td>Rarely used for Destinations</td></tr> -<tr><td>ECDSA_SHA512_P521</td><td align="center">132</td><td align="center">0.9.12</td> -<td>Rarely used for Destinations</td></tr> -<tr><td>RSA_SHA256_2048</td><td align="center">256</td><td align="center">0.9.12</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -<tr><td>RSA_SHA384_3072</td><td align="center">384</td><td align="center">0.9.12</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -<tr><td>RSA_SHA512_4096</td><td align="center">512</td><td align="center">0.9.12</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -<tr><td>EdDSA_SHA512_Ed25519</td><td align="center">64</td><td align="center">0.9.15</td> -<td>Recent Router Identities and Destinations</td></tr> -<tr><td>EdDSA_SHA512_Ed25519ph</td><td align="center">64</td><td align="center">0.9.25</td> -<td>Offline signing, never used for Router Identities or Destinations</td></tr> -</table> - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul> -<li>{% 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 %}</li> -<li>{% trans -%} -All types are Big Endian, except for -EdDSA, which is stored and transmitted in a Little Endian format. -{%- endtrans %}</li> -</ul> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/Signature.html">Javadoc</a></h4> - - -<h2 id="type_Hash">Hash</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -Represents the SHA256 of some data. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -32 bytes -{% endtrans %}</p> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/Hash.html">Javadoc</a></h4> - -<h2 id="type_SessionTag">Session Tag</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -A random number -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -32 bytes -{% endtrans %}</p> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/SessionTag.html">Javadoc</a></h4> - -<h2 id="type_TunnelId">TunnelId</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% 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 %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -4 byte <a href="#type_Integer">Integer</a> -{% endtrans %}</p> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/TunnelId.html">Javadoc</a></h4> - -<h2 id="type_Certificate">Certificate</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -A certificate is a container for various receipts or proof of works used throughout the I2P network. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -1 byte <a href="#type_Integer">Integer</a> specifying certificate type, followed by a 2 byte <a href="#type_Integer">Integer</a> specifying the size of the certificate payload, then that many bytes. -{% endtrans %}</p> -{% 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 %} - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul> -<li>{% trans -%} -For <a href="#struct_RouterIdentity">Router Identities</a>, 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 %}</li> - -<li>{% trans i2np=site_url('docs/spec/i2np') -%} -For <a href="{{ i2np }}#struct_GarlicClove">Garlic Cloves</a>, the Certificate is always NULL, no others are currently implemented. -{%- endtrans %}</li> - -<li>{% trans i2np=site_url('docs/spec/i2np') -%} -For <a href="{{ i2np }}#msg_Garlic">Garlic Messages</a>, the Certificate is always NULL, no others are currently implemented. -{%- endtrans %}</li> - -<li>{% trans -%} -For <a href="#struct_Destination">Destinations</a>, 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 %}</li> -</ul> - -<h4>{% trans %}Certificate Types{% endtrans %}</h4> -<p>The following certificate types are defined:</p> -<table border=1> -<tr><th>Type</th><th>Type Code</th><th>Payload Length</th><th>Total Length</th><th>Notes</th></tr> -<tr><td>Null</td><td align="center">0</td><td align="center">0</td><td align="center">3</td><td></td></tr> -<tr><td>HashCash</td><td align="center">1</td><td align="center">varies</td><td align="center">varies</td><td> - Experimental, unused. Payload contains an ASCII colon-separated hashcash string. -</td></tr> -<tr><td>Hidden</td><td align="center">2</td><td align="center">0</td><td align="center">3</td><td> - Experimental, unused. Hidden routers generally do not announce that they are hidden. -</td></tr> -<tr><td>Signed</td><td align="center">3</td><td align="center">40 or 72</td><td align="center">43 or 75</td><td> - Experimental, unused. Payload contains a 40-byte DSA signature, - optionally followed by the 32-byte Hash of the signing Destination. -</td></tr> -<tr><td>Multiple</td><td align="center">4</td><td align="center">varies</td><td align="center">varies</td><td> - Experimental, unused. Payload contains multiple certificates. -</td></tr> -<tr><td>Key</td><td align="center">5</td><td align="center">4+</td><td align="center">7+</td><td> - Since 0.9.12. See below for details. -</td></tr> -</table> - - -<h4>{% trans %}Key Certificates{% endtrans %}</h4> -<p> -Key certificates were 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. -</p><p> -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 Router Identities. - -</p><p> -The key certificate payload contains: -</p><table border=1> -<tr><th>Data</th><th>Length</th></tr> -<tr><td>Signing Public Key Type -(<a href="#type_Integer">Integer</a>) -</td><td align="center">2</td></tr> -<tr><td>Crypto Public Key Type -(<a href="#type_Integer">Integer</a>) -</td><td align="center">2</td></tr> -<tr><td>Excess Signing Public Key Data</td><td align="center">0+</td></tr> -<tr><td>Excess Crypto Public Key Data</td><td align="center">0+</td></tr> -</table> - -<p> -The defined Signing Key types are: -</p><table border=1> -<tr><th>Type</th><th>Type Code</th><th>Total Public Key Length</th><th>{% trans %}Since{% endtrans %}</th><th>{% trans %}Usage{% endtrans %}</th></tr> -<tr><td>DSA_SHA1</td><td align="center">0</td><td align="center">128</td><td align="center">0.9.12</td> -<td>Legacy Router Identities and Destinations, never explicitly set</td></tr> -<tr><td>ECDSA_SHA256_P256</td><td align="center">1</td><td align="center">64</td><td align="center">0.9.12</td> -<td>Recent Destinations</td></tr> -<tr><td>ECDSA_SHA384_P384</td><td align="center">2</td><td align="center">96</td><td align="center">0.9.12</td> -<td>Sometimes used for Destinations</td></tr> -<tr><td>ECDSA_SHA512_P521</td><td align="center">3</td><td align="center">132</td><td align="center">0.9.12</td> -<td>Sometimes used for Destinations</td></tr> -<tr><td>RSA_SHA256_2048</td><td align="center">4</td><td align="center">256</td><td align="center">0.9.12</td> -<td>Offline only; never used in Key Certificates for Router Identities or Destinations</td></tr> -<tr><td>RSA_SHA384_3072</td><td align="center">5</td><td align="center">384</td><td align="center">0.9.12</td> -<td>Offline only; never used in Key Certificates for Router Identities or Destinations</td></tr> -<tr><td>RSA_SHA512_4096</td><td align="center">6</td><td align="center">512</td><td align="center">0.9.12</td> -<td>Offline only; never used in Key Certificates for Router Identities or Destinations</td></tr> -<tr><td>EdDSA_SHA512_Ed25519</td><td align="center">7</td><td align="center">32</td><td align="center">0.9.15</td> -<td>Recent Router Identities and Destinations</td></tr> -<tr><td>EdDSA_SHA512_Ed25519ph</td><td align="center">8</td><td align="center">32</td><td align="center">0.9.25</td> -<td>Offline only; never used in Key Certificates for Router Identities or Destinations</td></tr> -<tr><td>reserved</td><td align="center">65280 - 65534</td><td align="center"></td><td align="center"></td> -<td><i>Reserved for experimental use</i></td></tr> -<tr><td>reserved</td><td align="center">65535</td><td align="center"></td><td align="center"></td> -<td><i>Reserved for future expansion</i></td></tr> -</table> - -<p> -The defined Crypto Public Key types are: -</p><table border=1> -<tr><th>Type</th><th>Type Code</th><th>Total Public Key Length</th><th>{% trans %}Since{% endtrans %}</th><th>{% trans %}Usage{% endtrans %}</th></tr> -<tr><td>ElGamal</td><td align="center">0</td><td align="center">256</td><td align="center">0.9.12</td> -<td>All Router Identities and Destinations</td></tr> -<tr><td>reserved</td><td align="center">65280 - 65534</td><td align="center"></td><td align="center"></td> -<td><i>Reserved for experimental use</i></td></tr> -<tr><td>reserved</td><td align="center">65535</td><td align="center"></td><td align="center"></td> -<td><i>Reserved for future expansion</i></td></tr> -</table> - -<p> -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: -<ul><li> -Complete or first portion of Crypto Public Key -</li><li> -Random padding if the total lengths of the two keys are less than 384 bytes -</li><li> -Complete or first portion of Signing Public Key -</li></ul> -</p><p> -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. -</p> - -<p> -Example layouts using an ElGamal Crypto Public Key and the Signing Public Key type indicated: -</p><table border=1> -<tr><th>Signing Key Type</th><th>Padding Length</th><th>Excess Signing Key Data in Cert</th></tr> -<tr><td>DSA_SHA1</td><td align="center">0</td><td align="center">0</td></tr> -<tr><td>ECDSA_SHA256_P256</td><td align="center">64</td><td align="center">0</td></tr> -<tr><td>ECDSA_SHA384_P384</td><td align="center">32</td><td align="center">0</td></tr> -<tr><td>ECDSA_SHA512_P521</td><td align="center">0</td><td align="center">4</td></tr> -<tr><td>RSA_SHA256_2048</td><td align="center">0</td><td align="center">128</td></tr> -<tr><td>RSA_SHA384_3072</td><td align="center">0</td><td align="center">256</td></tr> -<tr><td>RSA_SHA512_4096</td><td align="center">0</td><td align="center">384</td></tr> -<tr><td>EdDSA_SHA512_Ed25519</td><td align="center">96</td><td align="center">0</td></tr> -<tr><td>EdDSA_SHA512_Ed25519ph</td><td align="center">96</td><td align="center">0</td></tr> -</table> - - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/Certificate.html">Javadoc</a></h4> - - -<h2 id="type_Mapping">Mapping</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -A set of key/value mappings or properties -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -A 2-byte size Integer followed by a series of String=String; pairs -{% endtrans %}</p> -{% 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 %} - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul> -<li>{% trans -%} -The encoding isn't optimal - we either need the '=' and ';' characters, or the string lengths, but not both -{%- endtrans %}</li> - -<li>{% trans -%} -Some documentation says that the strings may not include '=' or ';' but this encoding supports them -{%- endtrans %}</li> - -<li>{% 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 %}</li> - -<li>{% trans -%} -The encoding allows duplicate keys, however in any usage where the mapping is signed, -duplicates may cause a signature failure. -{%- endtrans %}</li> - -<li>{% 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 %}</li> - -<li>{% trans i2cp=site_url('docs/spec/i2cp') -%} -Mappings contained in an <a href="{{ i2cp }}#struct_SessionConfig">I2CP SessionConfig</a> -must be sorted by key so that the signature will be invariant. -Duplicate keys are not allowed. -{%- endtrans %}</li> - -<li>{% trans -%} -The sort method is defined as in Java String.compareTo(), -using the Unicode value of the characters. -{%- endtrans %}</li> - -<li>{% trans -%} -While it is application-dependent, keys and values are generally case-sensitive. -{%- endtrans %}</li> - -<li>{% trans -%} -Key and value string length limits are 255 bytes (not characters) each, plus the length byte. Length byte may be 0. -{%- endtrans %}</li> - -<li>{% trans -%} -Total length limit is 65535 bytes, plus the 2 byte size field, or 65537 total. -{%- endtrans %}</li> -</ul> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/DataHelper.html">Javadoc</a></h4> - - - -<h1>{% trans %}Common structure specification{% endtrans %}</h1> - -<h2 id="struct_KeysAndCert">KeysAndCert</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -An encryption public key, a signing public key, and a certificate, used as either a RouterIdentity or a Destination. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -<a href="#type_PublicKey">PublicKey</a> followed by <a href="#type_SigningPublicKey">SigningPublicKey</a> and then a <a href="#type_Certificate">Certificate</a> -{% endtrans %}</p> -{% 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 %} - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul><li> -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. -</li><li> -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. -</li><li> -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. -</li></ul> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/KeysAndCert.html">Javadoc</a></h4> - -<h2 id="struct_RouterIdentity">RouterIdentity</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -Defines the way to uniquely identify a particular router -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -Identical to KeysAndCert. -{% endtrans %}</p> - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul><li>{% trans -%} -The certificate for a RouterIdentity was always NULL until release 0.9.12. -{%- endtrans %}</li><li> -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. -</li><li> -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. -</li><li> -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. -</li></ul> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/router/RouterIdentity.html">Javadoc</a></h4> - -<h2 id="struct_Destination">Destination</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -A Destination defines a particular endpoint to which messages can be directed for secure delivery. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -Identical to KeysAndCert. -{% endtrans %}</p> - -<h4>Notes</h4> -<ul><li> -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. -</li><li> -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. -</li><li> -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. -</li><li> -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. -</li></ul> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/Destination.html">Javadoc</a></h4> - -<h2 id="struct_Lease">Lease</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -Defines the authorization for a particular tunnel to receive messages targeting a <a href="#struct_Destination">Destination</a>. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -SHA256 <a href="#type_Hash">Hash</a> of the -<a href="#struct_RouterIdentity">RouterIdentity</a> of the gateway router, then the <a href="#type_TunnelId">TunnelId</a>, and finally an end <a href="#type_Date">Date</a> -{% endtrans %}</p> -{% 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 %} - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul> -<li>{% trans -%} -Total size: 44 bytes -{%- endtrans %}</li> -</ul> - - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/Lease.html">Javadoc</a></h4> - -<h2 id="struct_LeaseSet">LeaseSet</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -Contains all of the currently authorized <a href="#struct_Lease">Lease</a>s for a particular <a href="#struct_Destination">Destination</a>, the <a href="#type_PublicKey">PublicKey</a> to which garlic messages can be encrypted, -and then the <a href="#type_SigningPublicKey">public key</a> that can be used to revoke this particular version of the structure. The <a href="#struct_LeaseSet">LeaseSet</a> is one of the two structures stored in the network database( -the other being <a href="#struct_RouterInfo">RouterInfo</a>), and is keyed under the SHA256 of the contained <a href="#struct_Destination">Destination</a>. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -<a href="#struct_Destination">Destination</a>, followed by a <a href="#type_PublicKey">PublicKey</a> for encryption, then a <a href="#type_SigningPublicKey">SigningPublicKey</a> which can be used to revoke this version of the <a href="#struct_LeaseSet">LeaseSet</a>, -then a 1 byte <a href="#type_Integer">Integer</a> specifying how many <a href="#struct_Lease">Lease</a> structures are in the set, followed by the actual <a href="#struct_Lease">Lease</a> structures and finally a <a href="#type_Signature">Signature</a> of the previous -bytes signed by the <a href="#struct_Destination">Destination's</a> <a href="#type_SigningPrivateKey">SigningPrivateKey</a> -{%- endtrans %}</p> -{% 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 %} - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul> -<li>{% 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 %}</li> - -<li>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%} -The encryption key is used for end-to-end <a href="{{ elgamalaes }}">ElGamal/AES+SessionTag</a> encryption. -It is currently generated anew at every router startup, it is not persistent. -{%- endtrans %}</li> - -<li>{% trans -%} -The signature may be verified using the signing public key of the destination. -{%- endtrans %}</li> - -<li>{% 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 %}</li> -<li>{% 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 %}</li> -<li>{% 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 %}</li> -</ul> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/LeaseSet.html">Javadoc</a></h4> - - - -<h2 id="struct_RouterAddress">RouterAddress</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -This structure defines the means to contact a router through a transport protocol. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -1 byte <a href="#type_Integer">Integer</a> defining the relative cost of using the address, where 0 is free and 255 is expensive, followed by the expiration <a href="#type_Date">Date</a> after which the address should not be used, or if null, the address never expires. -After that comes a <a href="#type_String">String</a> defining the transport protocol this router address uses. Finally there is a <a href="#type_Mapping">Mapping</a> containing all of the transport specific options necessary to establish the connection, such as -IP address, port number, email address, URL, etc. -{% endtrans %}</p> -{% 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 %} - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul> -<li>{% trans -%} -Cost is typically 5 or 6 for SSU, and 10 or 11 for NTCP. -{%- endtrans %}</li> - -<li>{% 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 %}</li> - -<li>{% 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 %}</li> -</ul> - - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/router/RouterAddress.html">Javadoc</a></h4> - -<h2 id="struct_RouterInfo">RouterInfo</h2> -<h4>{% trans %}Description{% endtrans %}</h4> -<p>{% trans -%} -Defines all of the data that a router wants to publish for the network to see. The <a href="#struct_RouterInfo">RouterInfo</a> is one of two structures stored in the network database(the other being <a href="#struct_LeaseSet">LeaseSet</a>, and is keyed under the SHA256 of -the contained <a href="#struct_RouterIdentity">RouterIdentity</a>. -{% endtrans %}</p> -<h4>{% trans %}Contents{% endtrans %}</h4> -<p>{% trans -%} -<a href="#struct_RouterIdentity">RouterIdentity</a> followed by the <a href="#type_Date">Date</a>, when the entry was published -{% endtrans %}</p> -{% 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 RouterAddresses to follow, 0-255 - -addresses :: [`RouterAddress`] - length -> varies - -peer_size :: `Integer` - length -> 1 byte - The number of peer Hashes to follow, 0-255, unused, always zero - value -> 0 - -options :: `Mapping` - -signature :: `Signature` - length -> 40 bytes - -{% endhighlight %} - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul> -<li>{% 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 %}</li> - -<li>{% trans -%} -The signature may be verified using the signing public key of the router_ident. -{%- endtrans %}</li> - -<li>{% trans netdb=site_url('docs/how/network-database') -%} -See <a href="{{ netdb }}#routerInfo">the network database page</a> -for standard options that are expected to be present in all router infos. -{%- endtrans %}</li> -</ul> - -<h4><a href="http://{{ i2pconv('i2p-javadocs') }}/net/i2p/data/router/RouterInfo.html">Javadoc</a></h4> - - -<h2 id="struct_DeliveryInstructions">Delivery Instructions</h2> -<p>{% trans tunnelmessage=site_url('docs/spec/tunnel-message') -%} -Tunnel Message Delivery Instructions are defined in the <a href="{{ tunnelmessage }}#struct_TunnelMessageDeliveryInstructions">Tunnel Message Specification</a>. -{% endtrans %}</p> -<p>{% trans i2npmessage=site_url('docs/spec/i2np') -%} -Garlic Message Delivery Instructions are defined in the <a href="{{ i2npmessage }}#struct_GarlicCloveDeliveryInstructions">I2NP Message Specification</a>. -{% endtrans %}</p> -{% endblock %} diff --git a/i2p2www/pages/site/docs/spec/configuration.html b/i2p2www/pages/site/docs/spec/configuration.html deleted file mode 100644 index 018ea23bafddb074d9c81cd0c46b19eebf5739a9..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/spec/configuration.html +++ /dev/null @@ -1,414 +0,0 @@ -{% extends "global/layout.html" %} -{% block title %}{% trans %}Configuration File Specification{% endtrans %}{% endblock %} -{% block lastupdated %}{% trans %}February 2016{% endtrans %}{% endblock %} -{% block accuratefor %}0.9.25{% endblock %} -{% block content %} -<h2>{% trans %}Overview{% endtrans %}</h2> -<p>{% 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 %}</p> - - -<h2>{% trans %}General Format{% endtrans %}</h2> -<p>{% 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 -<a href="{{ url }}">Java Properties</a> -with the following exceptions: -{%- endtrans %}</p> -<ul> -<li>{% trans %}Encoding must be UTF-8{% endtrans %}</li> -<li>{% trans %}Does not use or recognize any escapes, including '\', so lines may not be continued{% endtrans %}</li> -<li>{% trans %}'#' or ';' starts a comment, but '!' does not{% endtrans %}</li> -<li>{% trans %}'#' starts a comment in any position but ';' must be in column 1 to start a comment{% endtrans %}</li> -<li>{% trans %}Leading and trailing whitespace is not trimmed on keys{% endtrans %}</li> -<li>{% trans %}Leading and trailing whitespace is trimmed on values{% endtrans %}</li> -<li>{% trans %}'=' is the only key-termination character (not ':' or whitespace){% endtrans %}</li> -<li>{% trans %}Lines without '=' are ignored. As of release 0.9.10, keys with a value of "" are supported.{% endtrans %}</li> -<li>{% trans %}As there are no escapes, keys may not contain '#', '=', or '\n', or start with ';'{% endtrans %}</li> -<li>{% trans %}As there are no escapes, values may not contain '#' or '\n', or start or end with '\r' or whitespace{% endtrans %}</li> -</ul> - -<p>{% 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 %}</p> - -<p>{% trans url='http://'+i2pconv('i2p-javadocs.i2p')+'/net/i2p/data/DataHelper.html', -commonstructures=site_url('docs/spec/common-structures') -%} -Reads and writes are implemented in -<a href="{{ url }}">DataHelper loadProps() and storeProps()</a>. -Note that the file format is significantly different than the -serialized format for I2P protocols specified in -<a href="{{ commonstructures }}#type_Mapping">Mapping</a>. -{%- endtrans %}</p> - -<h2>{% trans %}Core library and router{% endtrans %}</h2> - -<h3>{% trans %}Clients{% endtrans %} (clients.config)</h3> -<p>{% trans -%} -Configured via /configclients in the router console. -{%- endtrans %}</p> -<p> -The format is as follows: -</p><p> -Lines are of the form clientApp.x.prop=val, where x is the app number. -App numbers MUST start with 0 and be consecutive. -</p><p> -Properties are as follows: -<pre> - 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 -</pre> -</p><p> -The following additional properties are used only by plugins: -<pre> - stopargs: Arguments to stop the client. - uninstallargs: Arguments to uninstall the client. - classpath: Additional classpath elements for the client, - separated by commas. -</pre> -</p><p> -The following substitutions are made in the args, stopargs, -uninstallargs, and classpath lines, for plugins only: -<pre> - $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) -</pre> -</p><p> -All properties except "main" are optional. -Lines starting with "#" are comments. -</p><p> -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. -</p> -<p> -Clients may be "managed" or "unmanaged". -</p> - - -<h3>{% trans %}Logger{% endtrans %} (logger.config)</h3> -<p>{% trans -%} -Configured via /configlogging in the router console. -{%- endtrans %}</p> -<p> -{% trans -%} -Properties are as follows: -{%- endtrans %} -<pre> - # 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 -</pre> -</p> - -<h3>{% trans %}Individual Plugin{% endtrans %} (xxx/plugin.config)</h3> -<p>{% trans pluginspec=site_url('docs/spec/plugin') -%} -See <a href="{{ pluginspec }}">the plugin specification</a>. -{%- endtrans %}</p> - -<h3>{% trans %}Plugins{% endtrans %} (plugins.config)</h3> -<p>{% trans -%} -Enable/disable for each installed plugin. -{%- endtrans %} -{% trans -%} -Properties are as follows: -{%- endtrans %} -<pre> - plugin.{name}.startOnLoad=true|false -</pre> -</p> - -<h3>{% trans %}Webapps{% endtrans %} (webapps.config)</h3> -<p>{% trans -%} -Enable/disable for each installed webapp. -{%- endtrans %} -{% trans -%} -Properties are as follows: -{%- endtrans %} -<pre> - webapps.{name}.classpath=[space- or comma-separated paths] - webapps.{name}.startOnLoad=true|false -</pre> -</p> - -<h3>{% trans %}Router{% endtrans %} (router.config)</h3> -<p>{% trans -%} -Configured via /configadvanced in the router console. -{%- endtrans %}</p> - -<h2>{% trans %}Applications{% endtrans %}</h2> - -<h3>{% trans %}Addressbook{% endtrans %} (addressbook/config.txt)</h3> -<p>{% trans -%} -See documentation in SusiDNS. -{%- endtrans %}</p> - -<h3>I2PSnark (i2psnark.config)</h3> -<p>{% trans -%} -Configured via the application gui. -{%- endtrans %}</p> - -<h3>I2PTunnel (i2ptunnel.config)</h3> -<p>{% trans -%} -Configured via the /i2ptunnel application in the router console. -{%- endtrans %} -{% trans -%} -Properties are as follows: -{%- endtrans %} -<pre> -# 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= - -# For clients only. Alias for the the private key in the keystore for the SSL socket. -# Will be autogenerated if a new key is created. -tunnel.N.option.keyAlias= - -# For clients only. Password for the private key for the SSL socket. -# Will be autogenerated if a new key is created. -tunnel.N.option.keyPassword= - -# For clients only. Path to the keystore file containing the private key for the SSL socket. -# Will be autogenerated if a new keystore is created. -# Relative to $(I2P_CONFIG_DIR)/keystore/ if not absolute. -tunnel.N.option.keystoreFile=i2ptunnel-(random string).ks - -# For clients only. Password for the keystore containing the private key for the SSL socket. -# Default is "changeit" -tunnel.N.option.keystorePassword=changeit - -# 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 - -# HTTP Servers only. Whether to reject incoming connections containing a referer header. Default false. Since 0.9.25. -tunnel.N.option.rejectReferer=true|false - -# HTTP Servers only. Whether to reject incoming connections containing specific user-agent headers. Default false. Since 0.9.25. -# See tunnel.N.option.userAgentRejectList -tunnel.N.option.rejectUserAgents=true|false - -# Servers only. Overrides targetHost and targetPort for incoming port NNNN. -tunnel.N.option.targetForPort.NNNN=hostnameOrIP:nnnn - -# HTTP Servers only. Comma-separated list of strings to match in the user-agent header. Since 0.9.25. -# Example: "Mozilla,Opera". Case-sensitive. See tunnel.N.option.rejectuserAgents -tunnel.N.option.userAgentRejectList=string1[,string2]* - -# Default false. For servers, use SSL for connections to local server. -# For clients, SSL is required for connections from local clients. -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 - -</pre> -Note: Each 'N' is a tunnel number starting with 0. -There may not be any gaps in numbering. -</p> - -<h3>{% trans %}Router Console{% endtrans %}</h3> -<p>{% trans -%} -The router console uses the router.config file. -{%- endtrans %}</p> - -<h3>SusiMail (susimail.config)</h3> -<p>{% trans -%} -See post on zzz.i2p. -{%- endtrans %}</p> -<!-- -<h3>Systray (systray.config)</h3> -<p> -TBD -</p> ---> -{% endblock %} diff --git a/i2p2www/pages/site/docs/spec/datagrams.html b/i2p2www/pages/site/docs/spec/datagrams.html deleted file mode 100644 index 93c5d63c9e70f452987467d50913f6c9db58ed7b..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/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 %} -<p><a href="{{ site_url('docs/api/datagrams') }}">{% trans -%} -See the Datagrams page for an overview of the Datagrams API. -{%- endtrans %}</a></p> - -<h2 id="spec">{% trans %}Specification{% endtrans %}</h2> - -<h3 id="raw">{% trans %}Non-Repliable Datagrams{% endtrans %}</h3> -<p>{% 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 %}</p> - -<h4>{% trans %}Format{% endtrans %}</h4> -{% highlight lang='dataspec' %} -+----+----+----+----+----// -| payload... -+----+----+----+----+----// - -length: 0 - unlimited (see notes) -{% endhighlight %} - -<h4>{% trans %}Notes{% endtrans %}</h4> -<p>{% trans tunnelmessage=site_url('docs/spec/tunnel-message'), -transports=site_url('docs/transport') -%} -The practical length is limited by lower layers of protocols - the -<a href="{{ tunnelmessage }}#notes">tunnel message spec</a> -limits messages to about 61.2 KB and the -<a href="{{ transports }}">transports</a> -currently limit messages to about 32 KB, although this may be raised in the future. -{%- endtrans %}</p> - -<h3 id="repliable">{% trans %}Repliable Datagrams{% endtrans %}</h3> -<p>{% trans -%} -Repliable datagrams contain a 'from' address and a signature. These add at least 427 bytes of overhead. -{%- endtrans %}</p> -<h4>Format</h4> -{% 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 %} - -<h4>{% trans %}Notes{% endtrans %}</h4> -<ul> -<li>{% trans transports=site_url('docs/transport') -%} -The practical length is limited by lower layers of protocols - the -<a href="{{ transports }}">transports</a> -currently limit messages to about 32 KB, so the data length here is limited to about -31.5 KB. -{%- endtrans %}</li> -<li>{% trans dgrams=site_url('docs/api/datagrams') -%} -See <a href="{{ dgrams }}">important notes</a> about the reliability of large datagrams. -For best results, limit the payload to about 10 KB or less. -{%- endtrans %}</li> -<li>{% trans -%} -Signatures for types other than DSA_SHA1 were redefined in release 0.9.14. -{%- endtrans %}</li> -</ul> - - - -{% endblock %} diff --git a/i2p2www/pages/site/docs/spec/geoip.html b/i2p2www/pages/site/docs/spec/geoip.html deleted file mode 100644 index dc452f4a651739adbd86fc0d7d82615692649973..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/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 %} - -<h2>{% trans %}Overview{% endtrans %}</h2> -<p>{% trans -%} -This page specifies the format of the various GeoIP files, -used by the router to look up a country for an IP. -{%- endtrans %}</p> - - -<h2>{% trans %}Country Name (countries.txt) Format{% endtrans %}</h2> -<p>{% trans -%} -This format is easily generated from data files available from many public sources. -For example: -{%- endtrans %}</p> -{% 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 %} -<ul> -<li>Encoding is UTF-8 -<li>'#' in column 1 specifies a comment line -<li>Entry lines are CountryCode,CountryName -<li>CountryCode is the ISO two-letter code, upper case -<li>CountryName is in English -</ul> - - -<h2>{% trans %}IPv4 (geoip.txt) Format{% endtrans %}</h2> -<p>{% trans -%} -This format is borrowed from Tor and is easily generated from data files available from many public sources. -For example: -{%- endtrans %}</p> -{% 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 %} -<ul> -<li>Encoding is ASCII -<li>'#' in column 1 specifies a comment line -<li>Entry lines are FromIP,ToIP,CountryCode -<li>FromIP and ToIP are unsigned integer representations of the 4-byte IP -<li>CountryCode is the ISO two-letter code, upper case -<li>Entry lines must be sorted by numeric FromIP -</ul> - - -<h2>{% trans %}IPv6 (geoipv6.dat.gz) Format{% endtrans %}</h2> -<p>{% trans -%} -This is a compressed binary format designed for I2P. -The file is gzipped. Ungzipped format: -{%- endtrans %}</p> -{% 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 %} -<p>{% trans %}NOTES:{% endtrans %}</p> -<ul> -<li>Data must be sorted (SIGNED long twos complement), no overlap. -So the order is 80000000 ... FFFFFFFF 00000000 ... 7FFFFFFF. -<li> -The GeoIPv6.java class contains a program to generate this format from -public sources such as the Maxmind GeoLite data. -<li> -IPv6 GeoIP lookup is supported as of release 0.9.8. -</ul> -{% endblock %} diff --git a/i2p2www/pages/site/docs/spec/i2cp.html b/i2p2www/pages/site/docs/spec/i2cp.html deleted file mode 100644 index deab2c2f5b451e3e991896e5c474af326a9b128c..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/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 %} -<h2>Overview</h2> -<p> -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. -</p><p> -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. -</p><p> -More information is on the <a href="{{ site_url('docs/protocol/i2cp') }}">I2CP Overview page</a>. -</p> - - - -<h2>Sessions</h2> -<p> -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 <a href="#multisession">multisession section below</a>. -Do not attempt to use multiple sessions on a single I2CP connection -with routers older than version 0.9.21. -</p> - -<p> -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. -</p> - -<p> -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. -</p> - - - - -<h2>Example Message Sequences</h2> -<p> -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 <a href="{{ site_url('docs/protocol/i2cp') }}">I2CP Overview page</a>. -</p> - - -<h3>Standard Session Establish</h3> -{% highlight %} - Client Router - - ---------------------> Get Date Message - Set Date Message <--------------------- - ---------------------> Create Session Message - Session Status Message <--------------------- -Request LeaseSet Message <--------------------- - ---------------------> Create LeaseSet Message -{% endhighlight %} - - -<h3>Get Bandwidth Limits (Simple Session)</h3> -{% highlight %} - Client Router - - ---------------------> Get Bandwidth Limits Message -Bandwidth Limits Message <--------------------- -{% endhighlight %} - - - -<h3>Destination Lookup (Simple Session)</h3> -{% highlight %} - Client Router - - ---------------------> Dest Lookup Message - Dest Reply Message <--------------------- -{% endhighlight %} - - - -<h3>Outgoing Message</h3> -<p>Existing session, with i2cp.messageReliability=none</p> -{% highlight %} - Client Router - - ---------------------> Send Message Message - -{% endhighlight %} - -<p>Existing session, with i2cp.messageReliability=none and nonzero nonce</p> -{% highlight %} - Client Router - - ---------------------> Send Message Message - Message Status Message <--------------------- - (succeeded) -{% endhighlight %} - -<p>Existing session, with i2cp.messageReliability=BestEffort</p> -{% highlight %} - Client Router - - ---------------------> Send Message Message - Message Status Message <--------------------- - (accepted) - Message Status Message <--------------------- - (succeeded) -{% endhighlight %} - - - -<h3>Incoming Message</h3> -<p>Existing session, with i2cp.fastReceive=true (as of 0.9.4)</p> -{% highlight %} - Client Router - - Message Payload Message <--------------------- - -{% endhighlight %} -<p>Existing session, with i2cp.fastReceive=false</p> -{% highlight %} - Client Router - - Message Status Message <--------------------- - (available) - ---------------------> Receive Message Begin Message - Message Payload Message <--------------------- - ---------------------> Receive Message End Message -{% endhighlight %} - - - - -<h2 id="multisession">Multisession Notes</h2> -<p> -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. -</p><p> -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. -</p><p> -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. -</p><p> -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. -</p><p> -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. -</p><p> -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. -</p><p> -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. -</p> - - - - -<h2 id="notes">Version Notes</h2> -<p> -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. -</p><p> -The exchanged version information is the "core" version or I2CP protocol version, -and is not necessarily the router version. -</p><p> -A basic summary of the I2CP protocol versions is as follows. For details, see below. -<table border=1> - <tr> - <th>Version</th> - <th>Required I2CP Features</th> - </tr><tr> - <td align="center">0.9.21</td> - <td align="left">Multiple sessions on a single I2CP connection supported</td> - </td> - </tr><tr> - <td align="center">0.9.20</td> - <td align="left">Additional SetDate messages may be sent to the client at any time</td> - </td> - </tr><tr> - <td align="center">0.9.16</td> - <td align="left">Authentication, if enabled, is required via GetDate before all other messages</td> - </td> - </tr><tr> - <td align="center">0.9.15</td> - <td align="left">Dest/LS key certs w/ EdDSA Ed25519 sig type supported</td> - </tr><tr> - <td align="center">0.9.14</td> - <td align="left">Per-message override of messageReliability=none with nonzero nonce</td> - </tr><tr> - <td align="center">0.9.12</td> - <td align="left">Dest/LS key certs w/ ECDSA P-256, P-384, and P-521 sig types supported<br> - Note: RSA sig types also supported as of this version, but currently unused - </td> - </tr><tr> - <td align="center">0.9.11</td> - <td align="left">Host Lookup and Host Reply messages supported<br> - Authentication mapping in Get Date message supported - </td> - </tr><tr> - <td align="center">0.9.7</td> - <td align="left">Request Variable Lease Set message supported</td> - </tr><tr> - <td align="center">0.9.5</td> - <td align="left">Additional Message Status codes defined</td> - </tr><tr> - <td align="center">0.9.4</td> - <td align="left">Send Message nonce=0 allowed<br> - Fast receive mode is the default - </td> - </tr><tr> - <td align="center">0.9.2</td> - <td align="left">Send Message Expires flag tag bits supported</td> - </tr><tr> - <td align="center">0.9</td> - <td align="left">Supports up to 16 leases in a lease set (6 previously)</td> - </tr><tr> - <td align="center">0.8.7</td> - <td align="left">Get Date and Set Date version strings included.<br> - If not present, the client or router is version 0.8.6 or older. - </td> - </tr><tr> - <td align="center">0.8.4</td> - <td align="left">Send Message Expires flag bits supported</td> - </tr><tr> - <td align="center">0.8.3</td> - <td align="left">Dest Lookup and Get Bandwidth messages supported in standard session<br> - Concurrent Dest Lookup messages supported - </td> - </tr><tr> - <td align="center">0.8.1</td> - <td align="left">i2cp.messageReliability=none supported</td> - </tr><tr> - <td align="center">0.7.2</td> - <td align="left">Get Bandwidth Limits and Bandwidth Limits messages supported</td> - </tr><tr> - <td align="center">0.7.1</td> - <td align="left">Send Message Expires message supported<br> - Reconfigure Session message supported - </td> - </tr><tr> - <td align="center">0.7</td> - <td align="left">Dest Lookup and Dest Reply messages supported</td> - </tr><tr> - <td align="center">0.6.5 or lower</td> - <td align="left">All messages and features not listed above</td> - </tr> -</table> - - -<h2 id="structures">Common structures</h2> - - - -<h3 id="struct_I2CPMessageHeader">I2CP message header</h3> -<h4>Description</h4> -<p> - Common header to all I2CP messages, containing the message length and message type. -</p> -<h4>Contents</h4> -<ol><li> - 4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> specifying the length of the message body -</li><li> - 1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> specifying the message type. -</li><li> - The I2CP message body, 0 or more bytes -</li></ol> - -<h4>Notes</h4> -<p> -Actual message length limit is about 64 KB. -</p> - - - - -<h3 id="struct_MessageId">Message ID</h3> -<h4>Description</h4> -<p> -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. -</p> -<h4>Contents</h4> -<ol><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -</li></ol> - -<h4>Notes</h4> -<p> -Message IDs are unique within a session only; they are not globally unique. -</p> - - - - -<h3 id="struct_Payload">Payload</h3> -<h4>Description</h4> -<p> -This structure is the content of a message being delivered from one -Destination to another. -</p> -<h4>Contents</h4> -<ol><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> length -</li><li> -That many bytes -</li></ol> - -<h4>Notes</h4> -<p> -The payload is in a gzip format as specified on the -<a href="{{ site_url('docs/protocol/i2cp') }}#format">I2CP Overview page</a>. -</p> - - - - -<h3 id="struct_SessionConfig">Session Config</h3> -<h4>Description</h4> -<p> -Defines the configuration options for a particular client session. -</p> -<h4>Contents</h4> -<ol><li> -<a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">Destination</a> -</li><li> -<a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a> of options -</li><li> -Creation <a href="{{ site_url('docs/spec/common-structures') }}#type_Date">Date</a> -</li><li> -<a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">Signature</a> of the previous 3 fields, signed by the -<a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPrivateKey">Signing Private Key</a> -</li></ol> - -<h4>Notes</h4> -<ul><li> -The options are specified on the -<a href="{{ site_url('docs/protocol/i2cp') }}#options">I2CP Overview page</a>. -</li><li> -The <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a> -must be sorted by key so that the signature will be validated correctly in the router. -</li><li> -The creation date must be within +/- 30 seconds of the current time when processed by -the router, or the config will be rejected. -</li></ul> - - - - -<h3 id="struct_SessionId">Session ID</h3> -<h4>Description</h4> -<p> -Uniquely identifies a session on a particular router at a point in -time. -</p> -<h4>Contents</h4> -<ol><li> -2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -</li></ol> - -<h4>Notes</h4> -<p> -</p> - - - - -<h2 id="messages">Messages</h2> -See also the -<a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/i2cp/package-summary.html">I2CP Javadocs</a>. -<h3 id="types">Message Types</h3> -<table border=1> -<tr><th>Message<th>Direction<th>Type<th>Since -<tr><td> -<a href="#msg_BandwidthLimits"> -BandwidthLimitsMessage -</a> -</a> -<td align="center">R->C -<td align=right>23 -<td align="center">0.7.2 -<tr><td> -<a href="#msg_CreateLeaseSet"> -CreateLeaseSetMessage -</a> -<td align="center">C->R -<td align=right>4 -<td> -<tr><td> -<a href="#msg_CreateSession"> -CreateSessionMessage -</a> -<td align="center">C->R -<td align=right>1 -<td> -<tr><td> -<a href="#msg_DestLookup"> -DestLookupMessage -</a> -<td align="center">C->R -<td align=right>34 -<td align="center">0.7 -<tr><td> -<a href="#msg_DestReply"> -DestReplyMessage -</a> -<td align="center">R->C -<td align=right>35 -<td align="center">0.7 -<tr><td> -<a href="#msg_DestroySession"> -DestroySessionMessage -</a> -<td align="center">C->R -<td align=right>3 -<td> -<tr><td> -<a href="#msg_Disconnect"> -DisconnectMessage -</a> -<td align="center">bidir. -<td align=right>30 -<td> -<tr><td> -<a href="#msg_GetBandwidthLimits"> -GetBandwidthLimitsMessage -</a> -<td align="center">C->R -<td align=right>8 -<td align="center">0.7.2 -<tr><td> -<a href="#msg_GetDate"> -GetDateMessage -</a> -<td align="center">C->R -<td align=right>32 -<td> -<tr><td> -<a href="#msg_HostLookup"> -HostLookupMessage -</a> -<td align="center">C->R -<td align=right>38 -<td align="center">0.9.11 -<tr><td> -<a href="#msg_HostReply"> -HostReplyMessage -</a> -<td align="center">R->C -<td align=right>39 -<td align="center">0.9.11 -<tr><td> -<a href="#msg_MessagePayload"> -MessagePayloadMessage -</a> -<td align="center">R->C -<td align=right>31 -<td> -<tr><td> -<a href="#msg_MessageStatus"> -MessageStatusMessage -</a> -<td align="center">R->C -<td align=right>22 -<td> -<tr><td> -<a href="#msg_ReceiveMessageBegin"> -ReceiveMessageBeginMessage -</a> -<td align="center">C->R -<td align=right>6 -<td> -<tr><td> -<a href="#msg_ReceiveMessageEnd"> -ReceiveMessageEndMessage -</a> -<td align="center">C->R -<td align=right>7 -<td> -<tr><td> -<a href="#msg_ReconfigureSession"> -ReconfigureSessionMessage -</a> -<td align="center">C->R -<td align=right>2 -<td align="center">0.7.1 -<tr><td> -<a href="#msg_ReportAbuse"> -ReportAbuseMessage -</a> -<td align="center">bidir. -<td align=right>29 -<td> -<tr><td> -<a href="#msg_RequestLeaseSet"> -RequestLeaseSetMessage -</a> -<td align="center">R->C -<td align=right>21 -<td> -<tr><td> -<a href="#msg_RequestVariableLeaseSet"> -RequestVariableLeaseSetMessage -</a> -<td align="center">R->C -<td align=right>37 -<td align="center">0.9.7 -<tr><td> -<a href="#msg_SendMessage"> -SendMessageMessage -</a> -<td align="center">C->R -<td align=right>5 -<td> -<tr><td> -<a href="#msg_SendMessageExpires"> -SendMessageExpiresMessage -</a> -<td align="center">C->R -<td align=right>36 -<td align="center">0.7.1 -<tr><td> -<a href="#msg_SessionStatus"> -SessionStatusMessage -</a> -<td align="center">R->C -<td align=right>20 -<td> -<tr><td> -<a href="#msg_SetDate"> -SetDateMessage -</a> -<td align="center">R->C -<td align=right>33 -<td> -</table> - - - -<h3 id="msg_BandwidthLimits">Bandwidth Limits</h3> -<h4>Description</h4> -<p> -Tell the client what the bandwidth limits are. -Sent from Router to Client in response to a Get Bandwidth Limits Message. -</p> -<h4>Contents</h4> -<ol><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -Client inbound limit (KBps) -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -Client outbound limit (KBps) -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -Router inbound limit (KBps) -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -Router inbound burst limit (KBps) -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -Router outbound limit (KBps) -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -Router outbound burst limit (KBps) -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -Router burst time (seconds) -</li><li> -Nine 4-byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integers</a> -undefined -</li></ol> - -<h4>Notes</h4> -<p> -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. -</p> - - - -<h3 id="msg_CreateLeaseSet">Create Lease Set</h3> -<h4>Description</h4> -<p> -This message is sent in response to a -<a href="#msg_RequestLeaseSet">Request Lease Set Message</a> -or -<a href="#msg_RequestVariableLeaseSet">Request Variable Lease Set Message</a> -and contains all -of the Lease structures that should be published to the I2NP Network Database. -Sent from Client to Router. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -<a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPrivateKey">Signing Private Key</a> -</li><li> -<a href="{{ site_url('docs/spec/common-structures') }}#type_PrivateKey">Private Key</a> -</li><li> -<a href="{{ site_url('docs/spec/common-structures') }}#struct_LeaseSet">LeaseSet</a> -</li></ol> - -<h4>Notes</h4> -<p> -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. -</p> - - - -<h3 id="msg_CreateSession">Create Session</h3> -<h4>Description</h4> -<p> -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 <a href="#msg_SessionStatus">Session Status Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionConfig">Session Config</a> -</li></ol> - -<h4>Notes</h4> -<ul><li> -This is the second message sent by the client. Previously the client sent a Get Date Message and received a Set Date Message response. -</li><li> -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. -</li><li> -If there is already a session on the router for this Destination, the session will be rejected. -</li><li> -The <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a> in the Session Config -must be sorted by key so that the signature will be validated correctly in the router. -</li></ul> - - - -<h3 id="msg_DestLookup">Dest Lookup</h3> -<h4>Description</h4> -<p> - -Sent from Client to Router. -The router responds with a <a href="#msg_DestReply">Dest Reply Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="{{ site_url('docs/spec/common-structures') }}#struct_Hash">SHA-256 Hash</a> -</li></ol> - -<h4>Notes</h4> -<p> -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. -<a href="#msg_HostLookup">Host Lookup Message</a> is preferred as of release 0.9.11. -</p> - - - -<h3 id="msg_DestReply">Dest Reply</h3> -<h4>Description</h4> -<p> -Sent from Router to Client in response to a Dest Lookup Message. -</p> -<h4>Contents</h4> -<ol><li> -<a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">Destination</a> -on success, or -<a href="{{ site_url('docs/spec/common-structures') }}#struct_Hash">Hash</a> -on failure -</li></ol> - -<h4>Notes</h4> -<p> -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. -</p> - - - -<h3 id="msg_Destroy Session">Destroy Session</h3> -<h4>Description</h4> -<p> -This message is sent from a client to destroy a session. -Sent from Client to Router. -The router responds with a <a href="#msg_SessionStatus">Session Status Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li></ol> - -<h4>Notes</h4> -<p> -The router at this point should release all resources related to the session. -</p> - - - -<h3 id="msg_Disconnect">Disconnect</h3> -<h4>Description</h4> -<p> -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. -</p> -<h4>Contents</h4> -<ol><li> -Reason <a href="{{ site_url('docs/spec/common-structures') }}#struct_String">String</a> -</li></ol> - -<h4>Notes</h4> -<p> -Only implemented in the router-to-client direction. -Disconnecting probably does end a session, in practice. -</p> - - - -<h3 id="msg_GetBandwidthLimits">Get Bandwidth Limits</h3> -<h4>Description</h4> -<p> -Request that the router state what its current bandwidth limits are. -Sent from Client to Router. -The router responds with a <a href="#msg_BandwidthLimits">Bandwidth Limits Message</a>. -</p> -<h4>Contents</h4> -<i>None</i> - -<h4>Notes</h4> -<p> -As of release 0.7.2. -As of release 0.8.3, -supported in both I2PSimpleSession and in standard sessions. -</p> - - - -<h3 id="msg_GetDate">Get Date</h3> -<h4>Description</h4> -<p> -Sent from Client to Router. -The router responds with a <a href="#msg_SetDate">Set Date Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -I2CP Version <a href="{{ site_url('docs/spec/common-structures') }}#struct_String">String</a> -</li><li> -Authentication <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a> -(optional, as of release 0.9.11) -</li></ol> - -<h4>Notes</h4> -<ul><li> -Generally the first message sent by the client after sending the protocol version byte. -</li><li> -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. -</li><li> -As of release 0.9.11, the authentication -<a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a> -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 -<a href="#struct_SessionConfig">Session Config</a> 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. -</li></ul> -</p> - - - -<h3 id="msg_HostLookup">Host Lookup</h3> -<h4>Description</h4> -<p> -Sent from Client to Router. -The router responds with a <a href="#msg_HostReply">Host Reply Message</a>. -This replaces the <a href="#msg_DestLookup">Dest Lookup Message</a> -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. -</p> - -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> request ID -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> timeout (ms) -</li><li> -1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> request type -</li><li> -<a href="{{ site_url('docs/spec/common-structures') }}#struct_Hash">SHA-256 Hash</a> -or -host name <a href="{{ site_url('docs/spec/common-structures') }}#struct_String">String</a> -</li></ol> - -<h4>Notes</h4> -<ul><li> -As of release 0.9.11. -Use <a href="#msg_DestLookup">Dest Lookup Message</a> for older routers. -</li><li> -The session ID and request ID will be returned in the <a href="#msg_HostReply">Host Reply Message</a>. -Use 0xFFFF for the session ID if there is no session. -</li><li> -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. -</li><li> -The request type is 0 for Hash and 1 for host name. -</li><li> -Base 32 host name lookup is supported but it is preferred to convert -it to a Hash first. -</ul> - - - -<h3 id="msg_HostReply">Host Reply</h3> -<h4>Description</h4> -<p> -Sent from Router to Client in response to a -<a href="#msg_HostLookup">Host Lookup Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> request ID -</li><li> -1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> result code -</li><li> -<a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">Destination</a>, -only present if result code is zero. -</li></ol> - -<h4>Notes</h4> -<ul><li> -As of release 0.9.11. -See Host Lookup notes. -</li><li> -The session ID and request ID are those from the Host Lookup. -</li><li> -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. -</ul> - - - - -<h3 id="msg_MessagePayload">Message Payload</h3> -<h4>Description</h4> -<p> -Deliver the payload of a message to the client. -Sent from Router to Client. -The client responds with a <a href="#msg_ReceiveMessageEnd">Receive Message End Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -<a href="#struct_MessageId">Message ID</a> -</li><li> -<a href="#struct_Payload">Payload</a> -</li></ol> - -<h4>Notes</h4> -<p> -</p> - - - -<h3 id="msg_MessageStatus">Message Status</h3> -<h4>Description</h4> -<p> -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 <a href="#msg_ReceiveMessageBegin">Receive Message Begin Message</a>. -For an outgoing message, this is a response to a -<a href="#msg_SendMessage">Send Message Message</a> or -<a href="#msg_SendMessageExpires">Send Message Expires Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -<a href="#struct_MessageId">Message ID</a> generated by the router -</li><li> -1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> status -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> size -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> nonce previously generated by the client -</li></ol> - -<h4>Notes</h4> -<p> -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 -<a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/i2cp/MessageStatusMessage.html">MessageStatusMessage Javadocs</a> -for details. -All status codes: -<table border=1> -<tr><th>Status Code<th>As Of Release<th>Name<th>Description -<tr><td align="center">0<td align="center"> <td>Available<td>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. -<tr><td align="center">1<td align="center"> <td>Accepted<td>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. -<tr><td align="center">2<td align="center"> <td>Best Effort Success<td>Probable success (unused) -<tr><td align="center">3<td align="center"> <td>Best Effort Failure<td>Probable failure -<tr><td align="center">4<td align="center"> <td>Guaranteed Success<td>Probable success -<tr><td align="center">5<td align="center"> <td>Guaranteed Failure<td>Generic failure, specific cause unknown. - May not really be a guaranteed failure. -<tr><td align="center">6<td align="center">0.9.5<td>Local Success<td>Local delivery successful. - The destination was another client on the same router. -<tr><td align="center">7<td align="center">0.9.5<td>Local Failure<td>Local delivery failure. - The destination was another client on the same router. -<tr><td align="center">8<td align="center">0.9.5<td>Router Failure<td>The local router is not ready, has shut down, - or has major problems. - This is a guaranteed failure. -<tr><td align="center">9<td align="center">0.9.5<td>Network Failure<td>The local computer apparently has no network connectivity at all. - This is a guaranteed failure. -<tr><td align="center">10<td align="center">0.9.5<td>Bad Session<td>The I2CP session is invalid or closed. - This is a guaranteed failure. -<tr><td align="center">11<td align="center">0.9.5<td>Bad Message<td>The message payload is invalid or zero-length or too big. - This is a guaranteed failure. -<tr><td align="center">12<td align="center">0.9.5<td>Bad Options<td>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. -<tr><td align="center">13<td align="center">0.9.5<td>Overflow Failure<td>Some queue or buffer in the router is full and the message was dropped. - This is a guaranteed failure. -<tr><td align="center">14<td align="center">0.9.5<td>Message Expired<td>The message expired before it could be sent. - This is a guaranteed failure. -<tr><td align="center">15<td align="center">0.9.5<td>Bad Local Leaseset<td>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. -<tr><td align="center">16<td align="center">0.9.5<td>No Local Tunnels<td>Local problems. No outbound tunnel to send through, - or no inbound tunnel if a reply is required. - This is a guaranteed failure. -<tr><td align="center">17<td align="center">0.9.5<td>Unsupported Encryption<td>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. -<tr><td align="center">18<td align="center">0.9.5<td>Bad Destination<td>Something is wrong with the far-end destination. - Bad format, unsupported options, certificates, etc. - This is a guaranteed failure. -<tr><td align="center">19<td align="center">0.9.5<td>Bad Leaseset<td>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. -<tr><td align="center">20<td align="center">0.9.5<td>Expired Leaseset<td>We got the far-end leaseset but it's expired and we can't get a new one. - This is a guaranteed failure. -<tr><td align="center">21<td align="center">0.9.5<td>No Leaseset<td>Could not find the far-end leaseset. - This is a common failure, equivalent to a DNS lookup failure. - This is a guaranteed failure. -</table> -</p> -<p> -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. -</p> - - - -<h3 id="msg_ReceiveMessageBegin">Receive Message Begin</h3> -<h4>Description</h4> -<p> -Request the router to deliver a message that it was previously notified of. -Sent from Client to Router. -The router responds with a <a href="#msg_MessagePayload">Message Payload Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -<a href="#struct_MessageId">Message ID</a> -</li></ol> - -<h4>Notes</h4> -<p> -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. -</p> -<p> -This is unused in "fast receive" mode, which is the default as of release 0.9.4. -</p> - - - - -<h3 id="msg_ReceiveMessageEnd">Receive Message End</h3> -<h4>Description</h4> -<p> -Tell the router that delivery of a message was completed successfully and that -the router can discard the message. -Sent from Client to Router. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -<a href="#struct_MessageId">Message ID</a> -</li></ol> - -<h4>Notes</h4> -<p> -The ReceiveMessageBeginMessage is sent after a MessagePayloadMessage fully -delivers a message's payload. -</p> -<p> -This is unused in "fast receive" mode, which is the default as of release 0.9.4. -</p> - - - - -<h3 id="msg_ReconfigureSession">Reconfigure Session</h3> -<h4>Description</h4> -<p> - -Sent from Client to Router to update the session configuration. -The router responds with a <a href="#msg_SessionStatus">Session Status Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -<a href="#struct_SessionConfig">Session Config</a> -</li></ol> - -<h4>Notes</h4> -<ul><li> -As of release 0.7.1. -</li><li> -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. -</li><li> -The <a href="{{ site_url('docs/spec/common-structures') }}#type_Mapping">Mapping</a> in the Session Config -must be sorted by key so that the signature will be validated correctly in the router. -</li><li> -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. -</li></ul> - - - - -<h3 id="msg_ReportAbuse">Report Abuse</h3> -<h4>Description</h4> -<p> -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. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> abuse severity -(0 is minimally abusive, 255 being extremely abusive) -</li><li> -Reason <a href="{{ site_url('docs/spec/common-structures') }}#struct_String">String</a> -</li><li> -<a href="#struct_MessageId">Message ID</a> -</li></ol> - -<h4>Notes</h4> -<p> -Unused. -Not fully implemented. Both router and client can generate Report Abuse Messages, -but neither has a handler for the message when received. -</p> - - - - -<h3 id="msg_RequestLeaseSet">Request LeaseSet</h3> -<h4>Description</h4> -<p> -Request that a client authorize the inclusion of a particular set of inbound tunnels. -Sent from Router to Client. -The client responds with a <a href="#msg_CreateLeaseSet">Create LeaseSet Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> number of tunnels -</li><li> - That many pairs of: - <ol><li> - <a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">Router Identity</a> - </li><li> - <a href="{{ site_url('docs/spec/common-structures') }}#type_TunnelId">Tunnel ID</a> - </li></ol> -</li><li> -End <a href="{{ site_url('docs/spec/common-structures') }}#type_Date">Date</a> -</li></ol> - -<h4>Notes</h4> -<p> -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. -</p> - - - - - -<h3 id="msg_RequestVariableLeaseSet">Request Variable LeaseSet</h3> -<h4>Description</h4> -<p> -Request that a client authorize the inclusion of a particular set of inbound tunnels. -Sent from Router to Client. -The client responds with a <a href="#msg_CreateLeaseSet">Create LeaseSet Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> number of tunnels -</li><li> - That many - <a href="{{ site_url('docs/spec/common-structures') }}#struct_Lease">Leases</a> -</li></ol> - -<h4>Notes</h4> -<p> -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. -</p> - - - - - -<h3 id="msg_SendMessage">Send Message</h3> -<h4>Description</h4> -<p> -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 <a href="#msg_MessageStatus">Message Status Message</a>. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -<a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">Destination</a> -</li><li> -<a href="#struct_Payload">Payload</a> -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> nonce -</li></ol> - -<h4>Notes</h4> -<p> -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. -</p><p> -As of release 0.8.1, the router does not send either Message Status Message if -i2cp.messageReliability=none. -</p><p> -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. -</p><p> -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. -</p> - - - - -<h3 id="msg_SendMessageExpires">Send Message Expires</h3> -<h4>Description</h4> -<p> -Sent from Client to Router. Same as Send Message Message, except includes an expiration and options. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -<a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">Destination</a> -</li><li> -<a href="#struct_Payload">Payload</a> -</li><li> -4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> nonce -</li><li> -2 bytes of flags (options) -</li><li> -Expiration <a href="{{ site_url('docs/spec/common-structures') }}#type_Date">Date</a> -truncated from 8 bytes to 6 bytes -</li></ol> - -<h4>Notes</h4> -<p> -As of release 0.7.1. -</p><p> -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. -</p><p> -As of release 0.8.1, the router does not send either Message Status Message if -i2cp.messageReliability=none. -</p><p> -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. -</p><p> -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. -</p> - -<h4>Flags Field</h4> -<p> -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. -</p><p> -Bit order: 15...0 -</p><p> -Bits 15-11: Unused, must be zero -</p><p> -Bits 10-9: Message Reliability Override (Unimplemented, to be removed). - -<table border=1> -<tr><th>Field value<th>Description -<tr><td align="center">00<td>Use session setting i2cp.messageReliabiltiy (default) -<tr><td align="center">01<td>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". -<tr><td align="center">10<td>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". -<tr><td align="center">11<td>Unused. Use a nonce value of 0 to force "none" and override a session setting - of "best effort" or "guaranteed". -</table> -</p><p> -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. -</p><p> -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. -<table border=1> -<tr><th>Field value<th>Tag threshold -<tr><td align="center">0000<td align="center">Use session key manager settings -<tr><td align="center">0001<td align="center">2 -<tr><td align="center">0010<td align="center">3 -<tr><td align="center">0011<td align="center">6 -<tr><td align="center">0100<td align="center">9 -<tr><td align="center">0101<td align="center">14 -<tr><td align="center">0110<td align="center">20 -<tr><td align="center">0111<td align="center">27 -<tr><td align="center">1000<td align="center">35 -<tr><td align="center">1001<td align="center">45 -<tr><td align="center">1010<td align="center">57 -<tr><td align="center">1011<td align="center">72 -<tr><td align="center">1100<td align="center">92 -<tr><td align="center">1101<td align="center">117 -<tr><td align="center">1110<td align="center">147 -<tr><td align="center">1111<td align="center">192 -</table> -</p><p> -Bits 3-0: Number of tags to send if required. -This is advisory and does not force tags to be delivered. -<table border=1> -<tr><th>Field value<th>Tags to send -<tr><td align="center">0000<td align="center">Use session key manager settings -<tr><td align="center">0001<td align="center">2 -<tr><td align="center">0010<td align="center">4 -<tr><td align="center">0011<td align="center">6 -<tr><td align="center">0100<td align="center">8 -<tr><td align="center">0101<td align="center">12 -<tr><td align="center">0110<td align="center">16 -<tr><td align="center">0111<td align="center">24 -<tr><td align="center">1000<td align="center">32 -<tr><td align="center">1001<td align="center">40 -<tr><td align="center">1010<td align="center">51 -<tr><td align="center">1011<td align="center">64 -<tr><td align="center">1100<td align="center">80 -<tr><td align="center">1101<td align="center">100 -<tr><td align="center">1110<td align="center">125 -<tr><td align="center">1111<td align="center">160 -</table> -</p> - - - - -<h3 id="msg_SessionStatus">Session Status</h3> -<h4>Description</h4> -<p> -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. -</p> -<h4>Contents</h4> -<ol><li> -<a href="#struct_SessionId">Session ID</a> -</li><li> -1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> status -</li></ol> - -<table border=1> -<tr><th>Status<th>Definition -<tr><td align="center">0<td>Destroyed: The session with the given ID is terminated. -<tr><td align="center">1<td>Created: In response to a Create Session, a new session with the given ID is now active. -<tr><td align="center">2<td>Updated: In response to a Reconfigure Session, an existing session with the given ID has been reconfigured. -<tr><td align="center">3<td>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. -<tr><td align="center">4<td>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. -</table> - -<h4>Notes</h4> -<p> -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. -</p> - - - -<h3 id="msg_SetDate">Set Date</h3> -<h4>Description</h4> -<p> -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. -</p> -<h4>Contents</h4> -<ol><li> -<a href="{{ site_url('docs/spec/common-structures') }}#type_Date">Date</a> -</li><li> -I2CP Version <a href="{{ site_url('docs/spec/common-structures') }}#struct_String">String</a> -</li></ol> - -<h4>Notes</h4> -<p> -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. -<p></p> -Additional SetDate messages will not be sent to clients in the same JVM. -</p> - - - - - - - -{% endblock %} diff --git a/i2p2www/pages/site/docs/spec/i2np.html b/i2p2www/pages/site/docs/spec/i2np.html deleted file mode 100644 index dfb3c85b2704a816ce332a33001924082542da48..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/spec/i2np.html +++ /dev/null @@ -1,1281 +0,0 @@ -{% extends "global/layout.html" %} -{% block title %}I2NP Specification{% endblock %} -{% block lastupdated %}January 2016{% endblock %} -{% block accuratefor %}0.9.24{% endblock %} -{% block content %} -<p> -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. -</p> - -<h2 id="versions">Protocol Versions</h2> -<p> -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. -</p><p> -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. -</p><p> -A basic summary of the I2NP protocol versions is as follows. For details, see below. -<table border=1> - <tr> - <th>Version</th> - <th>Required I2NP Features</th> - </tr><tr> - <td align="center">0.9.18</td> - <td align="left">DSM type bits 7-1 ignored - </td> - </tr><tr> - <td align="center">0.9.16</td> - <td align="left">RI key certs / ECDSA and EdDSA sig types<br> - Note: RSA sig types also supported as of this version, but currently unused<br> - DLM lookup types (DLM flag bits 3-2) - </td> - </tr><tr> - <td align="center">0.9.15</td> - <td align="left">Dest/LS key certs w/ EdDSA Ed25519 sig type (if floodfill)</td> - </tr><tr> - <td align="center">0.9.12</td> - <td align="left">Dest/LS key certs w/ ECDSA P-256, P-384, and P-521 sig types (if floodfill)<br> - Note: RSA sig types also supported as of this version, but currently unused<br> - Nonzero expiration allowed in RouterAddress - </td> - </tr><tr> - <td align="center">0.9.7</td> - <td align="left">Encrypted DSM/DSRM replies supported (DLM flag bit 1) (if floodfill)</td> - </tr><tr> - <td align="center">0.9.6</td> - <td align="left">Nonzero DLM flag bits 7-1 allowed</td> - </tr><tr> - <td align="center">0.9.3</td> - <td align="left">Requires zero expiration in RouterAddress</td> - </tr><tr> - <td align="center">0.9</td> - <td align="left">Supports up to 16 leases in a DSM LS store (6 previously)</td> - </tr><tr> - <td align="center">0.7.12</td> - <td align="left">VTBM and VTBRM message support</td> - </tr><tr> - <td align="center">0.7.10</td> - <td align="left">Floodfill supports encrypted DSM stores</td> - </tr><tr> - <td align="center">0.7.9 or lower</td> - <td align="left">All messages and features not listed above</td> - </tr><tr> - <td align="center">0.6.1.10</td> - <td align="left">TBM and TBRM messages introduced<br> - Minimum version compatible with current network - </td> - </tr> -</table> - -</p><p> -Note that there are also transport-related features and compatibility issues; -see the NTCP and SSU transport documentation for details. -</p> - - - - - -<h2 id="structures">Common structures</h2> -The following structures are elements of multiple I2NP messages. -They are not complete messages. - -<h3 id="struct_I2NPMessageHeader">I2NP message header</h3> -<h4>Description</h4> -<p> - Common header to all I2NP messages, which contains important information like a checksum, expiration date, etc. -</p> -<h4>Contents</h4> -<p> - 1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> specifying the type of this message, - followed by a 4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> specifying the message-id. - After that there is an expiration <a href="{{ site_url('docs/spec/common-structures') }}#type_Date">Date</a>, - followed by a 2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> specifying - the length of the message payload, followed by a <a href="{{ site_url('docs/spec/common-structures') }}#type_Hash">Hash</a>, - which is truncated to the first byte. After that the actual message data follows. -</p> -{% highlight lang='dataspec' %} -Standard (16 bytes): - -+----+----+----+----+----+----+----+----+ -|type| msg_id | expiration -+----+----+----+----+----+----+----+----+ - | size |chks| -+----+----+----+----+----+----+----+----+ - -Short (SSU, 5 bytes): - -+----+----+----+----+----+ -|type| short_expiration | -+----+----+----+----+----+ - -{% endhighlight %} - -<h4>Definition</h4> -{% 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 %} - -<h4>Notes</h4> -<ul><li> -When transmitted over <a href="{{ site_url('docs/transport/ssu') }}">SSU</a>, -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. -</li><li> -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. -</li><li> -The short expiration is unsigned and will wrap around on Feb. 7, 2106. -As of that date, an offset must be added to get the correct time. -</li></ul> - - -<h3 id="struct_BuildRequestRecord">BuildRequestRecord</h3> -<h4>Description</h4> -<p> - One Record in a set of multiple records to request the creation of one hop in the tunnel. For more details see - <a href="{{ site_url('docs/tunnels/implementation') }}">the tunnel overview</a> and - <a href="{{ site_url('docs/spec/tunnel-creation') }}">the tunnel creation specification</a>. -</p> -<h4>Contents</h4> -<p> - <a href="{{ site_url('docs/spec/common-structures') }}#type_TunnelId">TunnelId</a> to receive messages on, followed by the <a href="{{ site_url('docs/spec/common-structures') }}#type_Hash">Hash</a> of our <a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">RouterIdentity</a>. After that the <a href="{{ site_url('docs/spec/common-structures') }}#type_TunnelId">TunnelId</a> and the <a href="{{ site_url('docs/spec/common-structures') }}#type_Hash">Hash</a> of the next router's <a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">RouterIdentity</a> follow. -</p> -<h4>Definition</h4> -{% highlight lang='dataspec' %} -Cleartext: -+----+----+----+----+----+----+----+----+ -| 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 | -+ + -| | -+ +----+----+ -| | -+----+----+----+----+----+----+ - - -ElGamal encrypted: -+----+----+----+----+----+----+----+----+ -| toPeer | -+ + -| | -+----+----+----+----+----+----+----+----+ -| encrypted data... | -~ ~ -| | -+----+----+----+----+----+----+----+----+ - - -ElGamal and AES encrypted: -+----+----+----+----+----+----+----+----+ -| encrypted data... | -~ ~ -| | -+----+----+----+----+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% highlight lang='dataspec' %} -unencrypted: - -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 - - -ElGamal encrypted: - -toPeer :: First 16 bytes of the SHA-256 Hash of the peer's router identity - length -> 16 bytes - -encrypted_data :: ElGamal-2048 encrypted data (see notes) - length -> 512 - -total length: 528 - - -ElGamal and AES encrypted: - -encrypted_data :: ElGamal and AES encrypted data - length -> 528 - -total length: 528 - -{% endhighlight %} - -<h4>Notes</h4> -<ul><li> -In the 512-byte encrypted record, -the ElGamal data contains bytes 1-256 and 258-513 of the -<a href="{{ site_url('docs/how/cryptography') }}#elgamal">514-byte ElGamal encrypted block</a>. -The two padding bytes from the block (the zero bytes at locations 0 and 257) are removed. -</li><li> - See the <a href="{{ site_url('docs/spec/tunnel-creation') }}">tunnel creation specification</a> for details on field contents. -</li></ul> -</p> - - -<h3 id="struct_BuildResponseRecord">BuildResponseRecord</h3> -{% highlight lang='dataspec' %} -unencrypted: -+----+----+----+----+----+----+----+----+ -| | -+ + -| | -+ SHA-256 Hash of following bytes + -| | -+ + -| | -+----+----+----+----+----+----+----+----+ -| random data... | -~ ~ -| | -+ +----+ -| |ret | -+----+----+----+----+----+----+----+----+ -{% endhighlight %} -<h4>Definition</h4> -{% highlight lang='dataspec' %} -unencrypted: -bytes 0-31 : SHA-256 Hash of bytes 32-527 -bytes 32-526 : random data -byte 527 : reply - -encrypted: -bytes 0-527: AES-encrypted record (note: same size as `BuildRequestRecord`) - -total length: 528 - -{% endhighlight %} - -<h4>Notes</h4> -<ul><li> - The random data field could, in the future, be used to return congestion or peer connectivity information - back to the requestor. -</li><li> - See the <a href="{{ site_url('docs/spec/tunnel-creation') }}">tunnel creation specification</a> for details on the reply field. -</li></ul> - - -<h3 id="struct_GarlicClove">GarlicClove</h3> -{% highlight lang='dataspec' %} -unencrypted: -+----+----+----+----+----+----+----+----+ -| Delivery Instructions | -~ ~ -~ ~ -| | -+----+----+----+----+----+----+----+----+ -| I2NP Message | -~ ~ -~ ~ -| | -+----+----+----+----+----+----+----+----+ -| Clove ID | Expiration -+----+----+----+----+----+----+----+----+ - | Certificate | -+----+----+----+----+----+----+----+ -{% endhighlight %} -<h4>Definition</h4> -{% 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 %} - -<h4>Notes</h4> -<ul> -<li> - 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. -<li> - See also the <a href="{{ site_url('docs/how/garlic-routing') }}">garlic routing specification</a>. -<li> - Maximum length is a function of the total length of all the cloves and the - maximum length of the GarlicMessage. -<li> - In the future, the certificate could possibly be used for a HashCash to "pay" for the routing. -<li> - 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. -<li> - 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) -</ul> - - -<h3 id="struct_GarlicCloveDeliveryInstructions">Garlic Clove Delivery Instructions</h3> - -<p> -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 -<a href="{{ site_url('docs/spec/tunnel-message') }}#struct_TunnelMessageDeliveryInstructions">Tunnel Message documentation</a> -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 %} - -<h4>Definition</h4> -{% 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 %} - - - -<h2 id="messages">Messages</h2> -<table border=1> - <tr> - <th>Message</th> - <th>Type</th> - </tr> - <tr> - <td><a href="#msg_DatabaseStore">DatabaseStore</a></td> - <td align="right">1</td> - </tr> - <tr> - <td><a href="#msg_DatabaseLookup">DatabaseLookup</a></td> - <td align="right">2</td> - </tr> - <tr> - <td><a href="#msg_DatabaseSearchReply">DatabaseSearchReply</a></td> - <td align="right">3</td> - </tr> - <tr> - <td><a href="#msg_DeliveryStatus">DeliveryStatus</a></td> - <td align="right">10</td> - </tr> - <tr> - <td><a href="#msg_Garlic">Garlic</a></td> - <td align="right">11</td> - </tr> - <tr> - <td><a href="#msg_TunnelData">TunnelData</a></td> - <td align="right">18</td> - </tr> - <tr> - <td><a href="#msg_TunnelGateway">TunnelGateway</a></td> - <td align="right">19</td> - </tr> - <tr> - <td><a href="#msg_Data">Data</a></td> - <td align="right">20</td> - </tr> - <tr> - <td><a href="#msg_TunnelBuild">TunnelBuild</a></td> - <td align="right">21</td> - </tr> - <tr> - <td><a href="#msg_TunnelBuildReply">TunnelBuildReply</a></td> - <td align="right">22</td> - </tr> - <tr> - <td><a href="#msg_VariableTunnelBuild">VariableTunnelBuild</a></td> - <td align="right">23</td> - </tr> - <tr> - <td><a href="#msg_VariableTunnelBuildReply">VariableTunnelBuildReply</a></td> - <td align="right">24</td> - </tr> - <tr> - <td><i>Reserved for experimental messages</i></td> - <td align="right">224 - 254</td> - </tr> - <tr> - <td><i>Reserved for future expansion</i></td> - <td align="right">255</td> - </tr> -</table> - - - -<h3 id="msg_DatabaseStore">DatabaseStore</h3> -<h4>Description</h4> -<p> - An unsolicited database store, or the response to a successful Database Lookup Message -</p> -<h4>Contents</h4> -<p> - An uncompressed LeaseSet or a compressed RouterInfo -</p> -{% 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 ... -+----+----+----+----+----+-// -{% endhighlight %} -<h4>Definition</h4> -{% 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 %} - -<h4>Notes</h4> -<ul><li> -For security, the reply fields are ignored if the message is received down a tunnel. -</li><li> -The key is the "real" hash of the RouterIdentity or Destination, NOT the routing key. -</li></ul> - - - -<h3 id="msg_DatabaseLookup">DatabaseLookup</h3> -<h4>Description</h4> -<p> - A request to look up an item in the network database. - The response is either a DatabaseStore or a DatabaseSearchReply. -</p> -<h4>Contents</h4> -{% 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 %} - -<h4>Definition</h4> -{% 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 %} - -<h4>Notes</h4> -<ul><li> -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. -</li><li> -Encryption flag, reply key, and reply tags as of release 0.9.7. -</li><li> -Encrypted replies are only useful when the response is through a tunnel. -</li><li> -The number of included tags could be greater than one if alternative DHT lookup strategies -(for example, recursive lookups) are implemented. -</li><li> -The lookup key and exclude keys are the "real" hashes, NOT routing keys. -</li></ul> - - -<h3 id="msg_DatabaseSearchReply">DatabaseSearchReply</h3> -<h4>Description</h4> -<p> - The response to a failed Database Lookup Message -</p> -<h4>Contents</h4> -<p> - A list of router hashes closest to the requested key -</p> -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+----+ -| SHA256 hash as query key | -+ + -| | -+ + -| | -+ + -| | -+----+----+----+----+----+----+----+----+ -|num | peer_hashes | -+----+ + -| | -+ + -| | -+ + -| | -+ +----+----+----+----+----+----+----+ -| | from | -+----+ + -| | -+ + -| | -+ + -| | -+ +----+----+----+----+----+----+----+ -| | -+----+ - - -{% endhighlight %} - -<h4>Definition</h4> -{% 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 %} - -<h4>Notes</h4> -<ul><li> - The 'from' hash is unauthenticated and cannot be trusted. -</li><li> - The returned peer hashes are not necessarily closer to the key - than the router being queried. -</li><li> - Typical number of hashes returned: 3 -</li><li> -The lookup key, peer hashes, and from hash are "real" hashes, NOT routing keys. -</li> -</ul> - - - -<h3 id="msg_DeliveryStatus">DeliveryStatus</h3> -<h4>Description</h4> -<p> - 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. -</p> -<h4>Contents</h4> -<p> - The ID of the delivered message, and the creation or arrival time. -</p> -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+----+----+----+----+----+ -|msg_id | time_stamp | -+----+----+----+----+----+----+----+----+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% 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 %} - -<h4>Notes</h4> -<ul><li> - 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. -</li><li> - This message is also used as a session established confirmation in <a href="{{ site_url('docs/transport/ssu') }}#establishDirect">SSU</a>. - 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). -</ul> - -<h3 id="msg_Garlic">Garlic</h3> -<h4>Description</h4> -<p> - Used to wrap multiple encrypted I2NP Messages -</p> -<h4>Contents</h4> -<p> - When decrypted, a series of <a href="#struct_GarlicClove">Garlic Cloves</a>. -</p> -{% highlight lang='dataspec' %} -encrypted: -+----+----+----+----+----+----+----+----+ -| length | data | -+----+----+----+----+ + -| | -~ ~ -~ ~ -| | -+----+----+----+----+----+----+----+----+ - - -unencrypted data: -+----+----+----+----+----+----+----+----+ -|num | clove 1 | -+----+ + -| | -~ ~ -~ ~ -| | -+----+----+----+----+----+----+----+----+ -| clove 2 ... | -~ ~ -~ ~ -| | -+----+----+----+----+----+----+----+----+ -| Certificate | Message_ID | -+----+----+----+----+----+----+----+----+ - Expiration | -+----+----+----+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% 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 %} - -<h4>Notes</h4> -<ul> -<li> - When unencrypted, data contains one or more <a href="#struct_GarlicClove">Garlic Cloves</a>. -<li> - 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. -<li> - Actual max length is less than 64 KB; see the <a href="{{ site_url('docs/protocol/i2np') }}">I2NP Overview</a>. -<li> - See also the <a href="{{ site_url('docs/how/elgamal-aes') }}">ElGamal/AES specification</a>. -<li> - See also the <a href="{{ site_url('docs/how/garlic-routing') }}">garlic routing specification</a>. -<li> - 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. -<li> - The message ID is generally set to a random number on transmit and - appears to be ignored on receive. -<li> - In the future, the certificate could possibly be used for a HashCash to "pay" for the routing. -</ul> - - -<h3 id="msg_TunnelData">TunnelData</h3> -<h4>Description</h4> -<p> - 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. -</p> -<h4>Contents</h4> -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+----+ -| tunnnelID | data | -+----+----+----+----+ | -| | -~ ~ -~ ~ -| | -+ +----+----+----+----+ -| | -+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% highlight lang='dataspec' %} -tunnelId :: - 4 byte `TunnelId` - identifies the tunnel this message is directed at - -data :: - 1024 bytes - payload data.. fixed to 1024 bytes -{% endhighlight %} - -<h4>Notes</h4> -<ul> -<li> - The I2NP message ID for this message is set to a new random number at each hop. -<li> - See also the <a href="{{ site_url('docs/spec/tunnel-message') }}">Tunnel Message Specification</a> -</ul> - - -<h3 id="msg_TunnelGateway">TunnelGateway</h3> -<h4>Description</h4> -<p> - Wraps another I2NP message to be sent into a tunnel at the tunnel's inbound gateway. -</p> -<h4>Contents</h4> -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+-// -| tunnelId | length | data... -+----+----+----+----+----+----+----+-// -{% endhighlight %} - -<h4>Definition</h4> -{% highlight lang='dataspec' %} -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 %} - -<h4>Notes</h4> -<ul> -<li> - The payload is an I2NP message with a standard 16-byte header. -</ul> - - -<h3 id="msg_Data">Data</h3> -<h4>Description</h4> -<p> - Used by Garlic Messages and Garlic Cloves to wrap arbitrary data. -</p> -<h4>Contents</h4> -<p> - A length Integer, followed by opaque data. -</p> -{% highlight lang='dataspec' %} -+----+----+----+----+----+-//-+ -| length | data... | -+----+----+----+----+----+-//-+ -{% endhighlight %} - -<h4>Notes</h4> -<ul> -<li> - This message contains no routing information and will never be sent "unwrapped". - It is only used inside Garlic messages. -</ul> - - - - - -<h4>Definition</h4> -{% highlight lang='dataspec' %} -length :: - 4 bytes - length of the payload - -data :: - $length bytes - actual payload of this message -{% endhighlight %} - -<h3 id="msg_TunnelBuild">TunnelBuild</h3> -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+----+ -| Record 0 ... | - -| | -+----+----+----+----+----+----+----+----+ -| Record 1 ... | - -..... -+----+----+----+----+----+----+----+----+ -| Record 7 ... | - -| | -+----+----+----+----+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% highlight lang='dataspec' %} -Just 8 `BuildRequestRecord`s attached together -record size: 528 bytes -total size: 8*528 = 4224 bytes -{% endhighlight %} - -<h4>Notes</h4> -<ul> -<li> - See also the <a href="{{ site_url('docs/spec/tunnel-creation') }}">tunnel creation specification</a>. -<li> - The I2NP message ID for this message must be set according to the tunnel creation specification. -<li> - While this message is rarely seen in today's network, having been replaced by the VariableTunnelBuild message, - it may still be used for very long tunnels, and has not been deprecated. - Routers must implement. -</ul> - - -<h3 id="msg_TunnelBuildReply">TunnelBuildReply</h3> -{% highlight lang='dataspec' %} -Same format as `TunnelBuildMessage`, with `BuildResponseRecord`s -{% endhighlight %} - -<h4>Notes</h4> -<ul> -<li> - See also the <a href="{{ site_url('docs/spec/tunnel-creation') }}">tunnel creation specification</a>. -<li> - The I2NP message ID for this message must be set according to the tunnel creation specification. -<li> - While this message is rarely seen in today's network, having been replaced by the VariableTunnelBuildReply message, - it may still be used for very long tunnels, and has not been deprecated. - Routers must implement. -</ul> - -<h3 id="msg_VariableTunnelBuild">VariableTunnelBuild</h3> -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+----+ -|num | BuildRequestRecords... -+----+----+----+----+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% 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 %} - -<h4>Notes</h4> -<ul> -<li> - This message was introduced in router version 0.7.12, and may not be sent to tunnel participants earlier than that version. -<li> - See also the <a href="{{ site_url('docs/spec/tunnel-creation') }}">tunnel creation specification</a>. -<li> - The I2NP message ID for this message must be set according to the tunnel creation specification. -<li> - Typical number of records in today's network is 5. -</ul> - -<h3 id="msg_VariableTunnelBuildReply">VariableTunnelBuildReply</h3> -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+----+ -|num | BuildResponseRecords... -+----+----+----+----+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% highlight lang='dataspec' %} -Same format as `VariableTunnelBuildMessage`, with `BuildResponseRecord`s. -{% endhighlight %} - - -<h4>Notes</h4> -<ul> -<li> - This message was introduced in router version 0.7.12, and may not be sent to tunnel participants earlier than that version. -<li> - See also the <a href="{{ site_url('docs/spec/tunnel-creation') }}">tunnel creation specification</a>. -<li> - The I2NP message ID for this message must be set according to the tunnel creation specification. -<li> - Typical number of records in today's network is 5. -</ul> - - - -{% endblock %} diff --git a/i2p2www/pages/site/docs/spec/plugin.html b/i2p2www/pages/site/docs/spec/plugin.html deleted file mode 100644 index 037fe41da93fee842db8ed1816d3d714f5a0ab32..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/spec/plugin.html +++ /dev/null @@ -1,607 +0,0 @@ -{% extends "global/layout.html" %} -{% block title %}I2P Plugin Specification{% endblock %} -{% block lastupdated %}February 2016{% endblock %} -{% block accuratefor %}0.9.25{% endblock %} -{% block content %} -<h3>Overview</h3> -<p> -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. -<p> -In addition, this document provides a brief overview of how the router installs plugins, -and policies and guidelines for plugin developers. -<p> -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. -<p> -As of release 0.9.15, the <a href="updates">su3 file format</a> is supported and is preferred. -This format enables stronger signing keys. - - -<p> -The standard directory structure will let users install the following types of addons: -<ul> -<li> - console webapps -<li> - new eepsite with cgi-bin, webapps -<li> - console themes -<li> - console translations -<li> - Java programs -<li> - Java programs in a separate JVM -<li> - Any shell script or program -</ul> - -<p> -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. - -<p> -This should be viewed only as a way to make installation, uninstallation, and upgrading easier, -and to lessen basic inter-plugin conflicts. - -<p> -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. - -<h3>Details</h3> -<p> -foo.xpi2p is a <a href="{{ site_url('docs/spec/updates') }}">signed update (sud) file</a> containing the following: -<h4> -Standard .sud header prepended to the zip file, containing the following: -</h4> -<pre> - 40-byte <a href="{{ site_url('docs/how/cryptography') }}#DSA">DSA signature</a> - 16-byte plugin version in UTF-8, padded with trailing zeroes if necessary -</pre> -<h4> -Zip file containing the following: -</h4> -<h5> -plugin.config file -</h5> -<p> -This file is required. It is a -<a href="{{ site_url('docs/spec/configuration') }}">standard I2P configuration file</a>, -containing the following properties: -</p> -</p><p> -The following four are required properties. -The first three must be identical to those in the installed plugin for an update plugin. -<pre> - - 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 (<a href="{{ site_url('docs/how/cryptography') }}#DSA">DSA public key</a> 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. - - -</pre> - Values for the following properties are displayed on /configclients in the router console if present: -<pre> - 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. - -</pre> - The following properties are used to add a link on the console summary bar: -<pre> - - 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) - - -</pre> - The following optional properties may be used to add a custom icon on the console: -<pre> - - 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. - - icon-code (supported as of 0.9.25) - Provides a console icon for plugins without web resources. - A B64 string produced by calling 'net.i2p.data.Base64 encode FILE' - on a 32x32 image png file. - -</pre> - The following properties are used by the plugin installer: -<pre> - - 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) - -</pre> - The following property is used for translation plugins: -<pre> - langs=xx,yy,Klingon,... (unimplemented) (yy is the country flag) - -</pre> -<h5> -Application Directories and Files -</h5> -<p> -Each of the following directories or files is optional, but something must be there or it won't do anything: -</p> -<pre> -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 -</pre> -<h5> -clients.config file -</h5> -<p> -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 <a href="{{ site_url('docs/spec/configuration') }}">clients.config configuration file specification</a> -for more information about the format and important details -about how clients are started and stopped. -</p> -<pre> - 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) -</pre> - - -<h3>Plugin installer tasks</h3> -This lists what happens when a plugin is installed by I2P. -<ul> - - <li>The .xpi2p file is downloaded.</li> - <li>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.</li> - <li>Verify the integrity of the zip file.</li> - <li>Extract the plugin.config file.</li> - <li>Verify the I2P version, to make sure the plugin will work.</li> - <li>Check that webapps don't duplicate the existing $I2P applications.</li> - <li>Stop the existing plugin (if present).</li> - <li>Verify that the install directory does not exist yet if update=false, or ask to overwrite.</li> - <li>Verify that the install directory does exist if update=true, or ask to create.</li> - <li>Unzip the plugin in to appDir/plugins/name/</li> - <li>Add the plugin to plugins.config</li> -</ul> - -<h3> -Plugin starter tasks -</h3> -This lists what happens when plugins are started. -First, plugins.config is checked to see which plugins need to be started. -For each plugin: -<ul> - <li>Check clients.config, and load and start each item (add the configured jars to the classpath).</li> - <li>Check console/webapp and console/webapp.config. Load and start required items (add the configured jars to the classpath).</li> - <li>Add console/locale/foo.jar to the translation classpath if present.</li> - <li>Add console/theme to the theme search path if present.</li> - <li>Add the summary bar link.</li> -</ul> - -<h3> -Console webapp notes -</h3> -<p> -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. -<p> -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. -<p> -Don't include .java or .jsp files; otherwise jetty will recompile them at installation. -<p> -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. - - -<h3> -Eepsite notes -</h3> -<p> -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. -<p> - 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. -<p> -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 <a href="http://{{ i2pconv('stats.i2p') }}/i2p/plugins/">zzz's plugins page</a>. -<p> -How to get path substitution into jetty.xml? -See zzzot and pebble plugins for examples. - - -<h3> -Client start/stop notes -</h3> -<p> -As of release 0.9.4, the router supports "managed" plugin clients. -Managed plugin clients are instantiated and started by the <code>ClientAppManager</code>. -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 <a href="{{ site_url('docs/spec/configuration') }}">clients.config configuration file specification</a> -for more information on writing a managed client. -</p><p> -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. - - -<h3> -Shell script and external program notes -</h3> -<p> -To run shell scripts or other external programs, see <a href="http://{{ i2pconv('zzz.i2p') }}/topics/141">{{ i2pconv('zzz.i2p') }}</a> -<p> -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. -<p> -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. - - - - -<h3> -Other plugin guidelines -</h3> -<ul> -<li> -See i2p.scripts branch or any of the sample plugins on zzz's page for a xpi2p file generator to make it easy. -<li> -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. - -<li> - Plugins should not attempt to write anywhere in $I2P as it may be readonly, and that isn't good policy anyway. -<li> - 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. - -<li> - $CWD may be anywhere; do not assume it is in a particular place, do not attempt to read or write files relative to $CWD. -<li> - Java programs should find out where they are with the directory getters in I2PAppContext. -<li> - 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. -<li> - See <a href="http://{{ i2pconv('zzz.i2p') }}/topics/16">Howto</a> for info on generating signing keys and generating/verifying keys and sud files -<li> - All config files must be UTF-8. -<li> - 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. -<li> - 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. -<li> - Do not include classes duplicating those in the standard installation. Extend the classes if necessary. -<li> - Beware of the different classpath definitions in wrapper.config between old and new installations - - see classpath section below. -<li> - 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. -<li> - 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. -<li> - 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. -<li> -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. -<li> -Plugins must never call System.exit(). -<li> -Please respect licenses by meeting license requirements for any software you bundle. -<li> -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". -</ul> - -<h3> -Classpaths -</h3> - -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: -<table> -<tr><th>Jar<th>Contains<th>Usage -<tr><td>commons-logging.jar -<td>Apache Logging<td>For plugins requiring Apache logging. -Prior to Jetty 6 (release 0.9), -this contained Apache Commons Logging only. -From release 0.9 to release 0.9.23, -this contained both Commons Logging and Tomcat JULI. -As of release 0.9.24. -this contains Apache Tomcat JULI logging only. - -<tr><td>commons-el.jar -<td>JSP Expression Language<td>For plugins with JSPs that use EL - -<tr><td>i2p.jar -<td>Core API<td>Almost all plugins will need - -<tr><td>i2ptunnel.jar -<td>I2PTunnel<td>For plugins with HTTP or other servers - -<tr><td>jasper-compiler.jar -<td>nothing<td>Empty since Jetty 6 (release 0.9) - -<tr><td>jasper-runtime.jar -<td>Jasper Complier and Runtime, and some Tomcat utils<td>Needed for plugins with JSPs - -<tr><td>javax.servlet.jar -<td>Servlet API<td>Needed for plugins with JSPs - -<tr><td>jbigi.jar -<td>Binaries<td>No plugin should need - -<tr><td>mstreaming.jar -<td>Streaming API<td>Almost all plugins will need - -<tr><td>org.mortbay.jetty.jar -<td>Jetty Base<td>Only plugins starting their own Jetty instance will need. -Recommended way of starting Jetty is with net.i2p.jetty.JettyStart in jetty-i2p.jar. - -<tr><td>router.jar -<td>Router<td>Only plugins using router context will need; most will not - -<tr><td>sam.jar -<td>SAM<td>No plugin should need - -<tr><td>streaming.jar -<td>Streaming Implementation<td>Almost all plugins will need - -<tr><td>systray.jar -<td>URL Launcher<td>Most plugins should not need - -<tr><td>systray4j.jar -<td>Systray<td>No plugin should need - -<tr><td>wrapper.jar -<td>Router<td>Most plugins should not need - -</table> - -<p> -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: -<p> -<table> -<tr><th>Jar<th>Contains<th>Usage -<tr><td>jstl.jar -<td>Standard Taglib<td>For plugins using JSP tags - -<tr><td>standard.jar -<td>Standard Taglib<td>For plugins using JSP tags - -</table> - -<p> - 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. -<p> -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 -<a href="http://{{ i2pconv('zzz.i2p') }}/topics/633">this thread on zzz.i2p</a> for background. -Therefore, specify the full required classpath for each client. - - -<h3> -Java Version Notes -</h3> -I2P has required Java 7 since release 0.9.24 (January 2016). -I2P has required Java 6 since release 0.9.12 (April 2014). -Any I2P users on the latest release should be running a 1.7 (7.0) JVM. -In early 2016, -unless you require 1.7 language or library features, you should create your plugin so it works on 1.6. -Later in the year, most of the network will be on 0.9.24 or higher with Java 7. -<p> -If your plugin <b>does not require 1.7</b>: -<ul> -<li> -Ensure that all java and jsp files are compiled with source="1.6" target="1.6", -or source="1.5" target="1.5", -<li> -Ensure that all bundled library jars are also for 1.6 or lower. -</ul> - -<p> -If your plugin <b>requires 1.7</b>: -<ul> -<li> -Note that on your download page. -<li> -Add min-java-version=1.7 to your plugin.config -</ul> - -<p> -In any case, you <b>must</b> set a bootclasspath when compiling with Java 8 -to prevent runtime crashes. -</p> - - -<h3> -JVM Crashes When Updating -</h3> -Note - this should all be fixed now. -<p> -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. -<p> -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. -<p> -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. -<p> -The least safe, and apparently the source of most crashes, is clients with plugin jars specified -in the classpath in clients.config. - -<p> -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/pages/site/docs/spec/ssu.html b/i2p2www/pages/site/docs/spec/ssu.html deleted file mode 100644 index 1bedd138b7a6405cd4ebccdabf83415c5fdd5755..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/spec/ssu.html +++ /dev/null @@ -1,1148 +0,0 @@ -{% extends "global/layout.html" %} -{% block title %}SSU Protocol Specification{% endblock %} -{% block lastupdated %}November 2015{% endblock %} -{% block accuratefor %}0.9.24{% endblock %} -{% block content %} - -<p> -<a href="{{ site_url('docs/transport/ssu') }}">See the SSU page for an overview of the SSU transport</a>. -</p> - -<h2 id="DH">DH Key Exchange</h2> -<p> -The initial 2048-bit DH key exchange is described on the -<a href="{{ site_url('docs/transport/ssu') }}#keys">SSU page</a>. -This exchange uses the same shared prime as that used for I2P's -<a href="{{ site_url('docs/how/cryptography') }}#elgamal">ElGamal encryption</a>. -</p> - - -<h2 id="header">Message Header</h2> - -<p> -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:</p> -<pre> - HMAC-MD5(encryptedPayload + IV + (payloadLength ^ protocolVersion), macKey) -</pre> -where '+' means append and '^' means exclusive-or. -</p><p> -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. -<b>WARNING</b> - the HMAC-MD5-128 used here is non-standard, -see <a href="{{ site_url('docs/how/cryptography') }}#udp">the cryptography page</a> for details. - - -<p>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. -</p> - -<p>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.</p> - -<h3>HMAC Specification</h3> -<ul><li> -Inner padding: 0x36... -</li><li> -Outer padding: 0x5C... -</li><li> -Key: 32 bytes -</li><li> -Hash digest function: MD5, 16 bytes -</li><li> -Block size: 64 bytes -</li><li> -MAC size: 16 bytes -</li><li> -Example C implementations: -hmac.h in <a href="https://github.com/orignal/i2pd">i2pd</a> -and -I2PHMAC.cpp in <a href="https://github.com/i2pcpp/i2pcpp">i2pcpp</a>. -</li><li> -Example Java implementation: -I2PHMac.java in <a href="https://github.com/i2p/i2p.i2p">i2p</a> -</li></ul> - - -<h3>Session Key Details</h3> -The 32-byte session key is created as follows: -<ol><li> -Take the exchanged DH key, represented as a positive minimal-length BigInteger byte array (two's complement big-endian) -</li><li> -If the most significant bit is 1 (i.e. array[0] & 0x80 != 0), -prepend a 0x00 byte, as in Java's BigInteger.toByteArray() representation -</li><li> -If the byte array is greater than or equal to 32 bytes, use the first (most significant) 32 bytes -</li><li> -If the byte array is less than 32 bytes, append 0x00 bytes to extend to 32 bytes. -<i>Very unlikely - See note below.</i> -</li></ol> - -<h3>MAC Key Details</h3> -The 32-byte MAC key is created as follows: -<ol><li> -Take the exchanged DH key byte array, prepended with a 0x00 byte if necessary, -from step 2 in the Session Key Details above. -</li><li> -If that byte array is greater than or equal to 64 bytes, the MAC key is -bytes 33-64 from that byte array. -</li><li> -If that byte array is less than 64 bytes, the MAC key is the SHA-256 Hash of that byte array. -<i>As of release 0.9.8. See note below.</i> -</li></ol> -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. - - -<h3>Header Format</h3> -<p>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). -</p> - -<p>The header format is:</p> - -{% 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 %} - -<p>The flag byte contains the following bitfields:</p> -{% highlight %} - Bit order: 76543210 (bit 7 is MSB) - - bits 7-4: payload type - bit 3: If 1, rekey data is included. Always 0, unimplemented - bit 2: If 1, extended options are included. Always 0 before release 0.9.24. - bits 1-0: reserved, set to 0 for compatibility with future uses -{% endhighlight %} - -<p> -Without rekeying and extended options, the header size is 37 bytes. -</p> - - -<h3 id="rekey">Rekeying</h3> -<p>If the rekey flag is set, 64 bytes of keying material follow the -timestamp. - -<p>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.</p> - -<p>NOTE: Rekeying is currently unimplemented.</p> - -<h3 id="extend">Extended Options</h3> -<p> -If the extended options flag is set, a one byte option -size value is appended, followed by that many extended option -bytes. -Extended options has always been part of the specification, but was unimplemented until release 0.9.24. -When present, the option format is specific to the message type. -See message documentation below on whether extended options are expected -for the given message, and the specified format. -While Java routers have always recognized the flag and options length, -other implementations have not. Therefore, do not send extended options to -routers older than release 0.9.24. -</p> - -<h2 id="padding">Padding</h2> -<p> -All messages contain 0 or more bytes of padding. -Each message must be padded to a 16 byte boundary, as required by the <a href="{{ site_url('docs/how/cryptography') }}#AES">AES256 encryption layer</a>. -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. -</p> - - -<h2 id="keys">Keys</h2> -<p> -Signatures in the SessionCreated and SessionConfirmed messages are generated using -the -<a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPublicKey">Signing Public Key</a> -from the -<a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">Router Identity</a> -which is distributed out-of-band by publishing in the network database, and the associated -<a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPrivateKey">Signing Private Key</a>. -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 <a href="{{ site_url('docs/spec/common-structures') }}#type_Certificate">Key Certificate</a> -in Bob's <a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">Router Identity</a>. -</p><p> -Both introduction keys and session keys are 32 bytes, -and are defined by the -<a href="{{ site_url('docs/spec/common-structures') }}#type_SessionKey">Common structures specification</a>. -The key used for the MAC and encryption is specified for each message below. -</p> -<p>Introduction keys are delivered through an external channel -(the network database, where they are identical to the router Hash for now). -</p> - - -<h2 id="notes">Notes</h2> - -<h3 id="ipv6">IPv6 Notes</h3> -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. - -<h3 id="time">Timestamps</h3> -While most of I2P uses 8-byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Date">Date</a> timestamps with -millisecond resolution, SSU uses 4-byte unsigned integer timestamps with one-second resolution. -Because these values are unsigned, they will not roll over until February 2106. - - - - -<h2 id="messages">Messages</h2> -<p> -There are 10 messages (payload types) defined: -</p><p> -<table border="1"> -<tr><th>Type<th>Message<th>Notes -<tr><td align="center">0<td>SessionRequest<td> -<tr><td align="center">1<td>SessionCreated<td> -<tr><td align="center">2<td>SessionConfirmed<td> -<tr><td align="center">3<td>RelayRequest<td> -<tr><td align="center">4<td>RelayResponse<td> -<tr><td align="center">5<td>RelayIntro<td> -<tr><td align="center">6<td>Data<td> -<tr><td align="center">7<td>PeerTest<td> -<tr><td align="center">8<td>SessionDestroyed<td>Implemented as of 0.8.9 -<tr><td align="center">n/a<td>HolePunch<td> -</table> -</p> - -<h3 id="sessionRequest">SessionRequest (type 0)</h3> -<p> -This is the first message sent to establish a session. -</p> - -<table border="1"> -<tr><td align="right" valign="top"><b>Peer:</b></td> - <td>Alice to Bob</td></tr> -<tr><td align="right" valign="top"><b>Data:</b></td> - <td><ul> - <li>256 byte X, to begin the DH agreement</li> - <li>1 byte IP address size</li> - <li>that many byte representation of Bob's IP address</li> - <li>N bytes, currently uninterpreted</li> - </ul></td></tr> -<tr><td align="right" valign="top"><b>Crypto Key used:</b></td> - <td>Bob's introKey, as retrieved from the network database</td></tr> -<tr><td align="right" valign="top"><b>MAC Key used:</b></td> - <td>Bob's introKey, as retrieved from the network database</td></tr> -</table> - -<p>Message format:</p> - -{% highlight lang='dataspec' %} - +----+----+----+----+----+----+----+----+ - | X, as calculated from DH | - ~ . . . ~ - | | - +----+----+----+----+----+----+----+----+ - |size| that many byte IP address (4-16) | - +----+----+----+----+----+----+----+----+ - | arbitrary amount of uninterpreted data| - ~ . . . ~ -{% endhighlight %} - -<p> -Typical size including header, in current implementation: 304 (IPv4) or 320 (IPv6) bytes -(before non-mod-16 padding) -</p> - -<h4>Extended Options</h4> -<p> -<i>Note: This is a proposal, to be implemented in 0.9.24. Subject to change.</i> -</p> -<ul><li> -Minimum length: 3 (option length byte + 2 bytes) -</li><li>Option length: 2 minimum -</li><li>2 bytes flags:<pre> -Bit order: 15...76543210 (bit 15 is MSB) - bit 0: 1 for Alice to request a relay tag from Bob in the SessionCreated response, - 0 if Alice does not need a relay tag. - Note that "1" is the default if no extended options are present - bits 15-1: unused, set to 0 for compatibility with future uses -</pre></ul> - - -<h4>Notes</h4> -<ul><li> -IPv4 and IPv6 addresses are supported. -</li><li> -The uninterpreted data could possibly be used in the future for challenges. -</li></ul> - - - -<h3 id="sessionCreated">SessionCreated (type 1)</h3> -<p> -This is the response to a Session Request. -</p> - -<table border="1"> -<tr><td align="right" valign="top"><b>Peer:</b></td> - <td>Bob to Alice</td></tr> -<tr><td align="right" valign="top"><b>Data:</b></td> - <td><ul> - <li>256 byte Y, to complete the DH agreement</li> - <li>1 byte IP address size</li> - <li>that many byte representation of Alice's IP address</li> - <li>2 byte Alice's port number</li> - <li>4 byte relay (introduction) tag which Alice can publish (else 0x00000000)</li> - <li>4 byte timestamp (seconds from the epoch) for use in the DSA - signature</li> - <li>Bob's <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">Signature</a> 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. - </li> - <li>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. - </li> - <li>N bytes, currently uninterpreted</li> - </ul></td></tr> -<tr><td align="right" valign="top"><b>Crypto Key used:</b></td> - <td>Bob's introKey, with an additional layer of encryption over the 40 byte - signature and the following 8 bytes padding.</td></tr> -<tr><td align="right" valign="top"><b>MAC Key used:</b></td> - <td>Bob's introKey</td></tr> -</table> - -<p>Message format:</p> - -{% 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 %} - -<p> -Typical size including header, in current implementation: 368 bytes (IPv4 or IPv6) -(before non-mod-16 padding) -</p> - -<h4>Notes</h4> -<ul><li> -IPv4 and IPv6 addresses are supported. -</li><li> -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. -</li><li> -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. -</li><li> -See <a href="#keys">the Keys section above</a> for details on signatures. -Alice already has Bob's public signing key, from the network database. -</li><li> -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 <a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPublicKey">Signing Public Key</a> -in Bob's <a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">Router Identity</a>. -The padding is as necessary to a multiple of 16 bytes. -</li><li> -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. -</li><li> -Signed-on time appears to be unused or unverified in the current implementation. -</li><li> -The uninterpreted data could possibly be used in the future for challenges. -</li><li> -Extended options in the header: Not expected, undefined. -</li></ul> - - - -<h3 id="sessionConfirmed">SessionConfirmed (type 2)</h3> -<p> -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. -</p> - -<table border="1"> -<tr><td align="right" valign="top"><b>Peer:</b></td> - <td>Alice to Bob</td></tr> -<tr><td align="right" valign="top"><b>Data:</b></td> - <td><ul> - <li>1 byte identity fragment info:<pre> -Bit order: 76543210 (bit 7 is MSB) -bits 7-4: current identity fragment # 0-14 -bits 3-0: total identity fragments (F) 1-15</pre></li> - <li>2 byte size of the current identity fragment</li> - <li>that many byte fragment of Alice's - <a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">Router Identity</a> - </li> - <li>After the last identity fragment only: - <ul><li>4 byte signed-on time - </li></ul> - </li> - <li>N bytes padding, currently uninterpreted</li> - <li>After the last identity fragment only: - <ul><li>The remaining bytes contain - Alice's <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">Signature</a> 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. - </li></ul> - </li> - </ul></td></tr> -<tr><td align="right" valign="top"><b>Crypto Key used:</b></td> - <td>Alice/Bob sessionKey, as generated from the DH exchange</td></tr> -<tr><td align="right" valign="top"><b>MAC Key used:</b></td> - <td>Alice/Bob MAC Key, as generated from the DH exchange</td></tr> -</table> - -<p> - <b>Fragment 0 through F-2</b> -(only if F > 1; currently unused, see notes below) : -</p> -{% highlight lang='dataspec' %} - +----+----+----+----+----+----+----+----+ - |info| cursize | | - +----+----+----+ + - | fragment of Alice's full | - ~ Router Identity ~ - ~ . . . ~ - | | - +----+----+----+----+----+----+----+----+ - | arbitrary amount of uninterpreted data| - ~ . . . ~ -{% endhighlight %} - -<p> - <b>Fragment F-1 (last or only fragment):</b> -</p> -{% 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 %} - -<p> -Typical size including header, in current implementation: 480 bytes -(before non-mod-16 padding) -</p> - -<h4>Notes</h4> -<ul><li> -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. -</li><li> -The typical <a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">Router Identity</a> -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. -</li><li> -There is no mechanism for requesting or redelivering missing fragments. -</li><li> -The total fragments field F must be set identically in all fragments. -</li><li> -See <a href="#keys">the Keys section above</a> for details on DSA signatures. -</li><li> -Signed-on time appears to be unused or unverified in the current implementation. -</li><li> -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. -</li><li> -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 <a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPublicKey">Signing Public Key</a> -in Alice's <a href="{{ site_url('docs/spec/common-structures') }}#struct_RouterIdentity">Router Identity</a>. -The padding is as necessary to a multiple of 16 bytes. -</li><li> -Extended options in the header: Not expected, undefined. -</li></ul> - - - - -<h3 id="sessionDestroyed">SessionDestroyed (type 8)</h3> -<p> -The Session Destroyed message was implemented (reception only) in release 0.8.1, -and is sent as of release 0.8.9. -</p> - -<table border="1"> -<tr><td align="right" valign="top"><b>Peer:</b></td> - <td>Alice to Bob or Bob to Alice</td></tr> -<tr><td align="right" valign="top"><b>Data:</b></td> - <td>none - </td></tr> -<tr><td align="right" valign="top"><b>Crypto Key used:</b></td> - <td>Alice/Bob sessionKey</td></tr> -<tr><td align="right" valign="top"><b>MAC Key used:</b></td> - <td>Alice/Bob MAC Key</td></tr> -</table> - - -<p> -This message does not contain any data. -Typical size including header, in current implementation: 48 bytes -(before non-mod-16 padding) -</p> - -<h4>Notes</h4> -<ul><li> -Destroy messages received with the sender's or receiver's intro key will be ignored. -</li><li> -Extended options in the header: Not expected, undefined. -</li></ul> - - -<h3 id="relayRequest">RelayRequest (type 3)</h3> -<p> -This is the first message sent from Alice to Bob to request an introduction to Charlie. -</p> - -<table border="1"> -<tr><td align="right" valign="top"><b>Peer:</b></td> - <td>Alice to Bob</td></tr> -<tr><td align="right" valign="top"><b>Data:</b></td> - <td><ul> - <li>4 byte relay (introduction) tag, nonzero, as received by Alice in the Session Created message from Bob</li> - <li>1 byte IP address size</li> - <li>that many byte representation of Alice's IP address</li> - <li>2 byte port number (of Alice)</li> - <li>1 byte challenge size</li> - <li>that many bytes to be relayed to Charlie in the intro</li> - <li>Alice's 32-byte introduction key (so Bob can reply with Charlie's info)</li> - <li>4 byte nonce of Alice's relay request</li> - <li>N bytes, currently uninterpreted</li> - </ul></td></tr> -<tr><td align="right" valign="top"><b>Crypto Key used:</b></td> - <td>Bob's introKey, as retrieved from the network database (or Alice/Bob sessionKey, if established)</td></tr> -<tr><td align="right" valign="top"><b>MAC Key used:</b></td> - <td>Bob's introKey, as retrieved from the network database (or Alice/Bob MAC Key, if established)</td></tr> -</table> - -<p>Message format:</p> - -{% 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 %} - -<p> -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) -</p> - -<h4>Notes</h4> -<ul><li> -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. -</li><li> -This message may be sent via IPv4 or IPv6. If IPv6, Alice must include her IPv4 address and port. -</li><li> -If Alice includes her address/port, Bob may perform additional validation before continuing. -Prior to release 0.9.24, Java I2P rejected any address or port that was different from the connection. -</li><li> -Challenge is unimplemented, challenge size is always zero -</li><li> -There are no plans to implement relaying for IPv6. -</li><li> -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. -</li><li> -Extended options in the header: Not expected, undefined. -</li></ul> - - -<h3 id="relayResponse">RelayResponse (type 4)</h3> -<p> -This is the response to a Relay Request and is sent from Bob to Alice. -</p> - -<table border="1"> -<tr><td align="right" valign="top"><b>Peer:</b></td> - <td>Bob to Alice</td></tr> -<tr><td align="right" valign="top"><b>Data:</b></td> - <td><ul> - <li>1 byte IP address size</li> - <li>that many byte representation of Charlie's IP address</li> - <li>2 byte Charlie's port number</li> - <li>1 byte IP address size</li> - <li>that many byte representation of Alice's IP address</li> - <li>2 byte Alice's port number</li> - <li>4 byte nonce sent by Alice</li> - <li>N bytes, currently uninterpreted</li> - </ul></td></tr> -<tr><td align="right" valign="top"><b>Crypto Key used:</b></td> - <td>Alice's introKey, as received in the Relay Request (or Alice/Bob sessionKey, if established)</td></tr> -<tr><td align="right" valign="top"><b>MAC Key used:</b></td> - <td>Alice's introKey, as received in the Relay Request (or Alice/Bob MAC Key, if established)</td></tr> -</table> - -<p>Message format:</p> - -{% highlight lang='dataspec' %} - +----+----+----+----+----+----+----+----+ - |size| Charlie IP | Port (C)|size| - +----+----+----+----+----+----+----+----+ - | Alice IP | Port (A)| nonce - +----+----+----+----+----+----+----+----+ - | arbitrary amount of | - +----+----+ + - | uninterpreted data | - ~ . . . ~ -{% endhighlight %} - -<p> -Typical size including header, in current implementation: 64 (Alice IPv4) or 80 (Alice IPv6) bytes -(before non-mod-16 padding) -</p> - -<h4>Notes</h4> -<ul><li> -This message may be sent via IPv4 or IPv6. -</li><li> -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. -</li><li> -Charlie's IP address must be IPv4, as that is the address that Alice will send -the SessionRequest to after the Hole Punch. -</li><li> -There are no plans to implement relaying for IPv6. -</li><li> -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. -</li><li> -Extended options in the header: Not expected, undefined. -</li></ul> - - - -<h3 id="relayIntro">RelayIntro (type 5)</h3> -<p> -This is the introduction for Alice, which is sent from Bob to Charlie. -</p> - -<table border="1"> -<tr><td align="right" valign="top"><b>Peer:</b></td> - <td>Bob to Charlie</td></tr> -<tr><td align="right" valign="top"><b>Data:</b></td> - <td><ul> - <li>1 byte IP address size</li> - <li>that many byte representation of Alice's IP address</li> - <li>2 byte port number (of Alice)</li> - <li>1 byte challenge size</li> - <li>that many bytes relayed from Alice</li> - <li>N bytes, currently uninterpreted</li> - </ul></td></tr> -<tr><td align="right" valign="top"><b>Crypto Key used:</b></td> - <td>Bob/Charlie sessionKey</td></tr> -<tr><td align="right" valign="top"><b>MAC Key used:</b></td> - <td>Bob/Charlie MAC Key</td></tr> -</table> - -<p>Message format:</p> - -{% highlight lang='dataspec' %} - +----+----+----+----+----+----+----+----+ - |size| Alice IP | Port (A)|size| - +----+----+----+----+----+----+----+----+ - | that many bytes of challenge | - + + - | data relayed from Alice | - +----+----+----+----+----+----+----+----+ - | arbitrary amount of uninterpreted data| - ~ . . . ~ -{% endhighlight %} - -<p> -Typical size including header, in current implementation: 48 bytes -(before non-mod-16 padding) -</p> - -<h4>Notes</h4> -<ul><li> -Alice's IP address is always 4 bytes in the current implementation, because Alice is trying to connect -to Charlie via IPv4. -</li><li> -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. -</li><li> -Challenge is unimplemented, challenge size is always zero -</li><li> -Extended options in the header: Not expected, undefined. -</li></ul> - - - - -<h3 id="data">Data (type 6)</h3> -<p> -This message is used for data transport and acknowledgment. -</p> - -<table border="1"> -<tr><td align="right" valign="top"><b>Peer:</b></td> - <td>Any</td></tr> -<tr><td align="right" valign="top"><b>Data:</b></td> - <td><ul> - <li>1 byte flags:<pre> - 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</pre></li> - <li>if explicit ACKs are included:<ul> - <li>a 1 byte number of ACKs</li> - <li>that many 4 byte MessageIds being fully ACKed</li> - </ul></li> - <li>if ACK bitfields are included:<ul> - <li>a 1 byte number of ACK bitfields</li> - <li>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: -<pre> -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) -</pre></li> - </ul></li> - <li>If extended data included:<ul> - <li>1 byte data size</li> - <li>that many bytes of extended data (currently uninterpreted)</li></ul></li> - <li>1 byte number of fragments (can be zero)</li> - <li>If nonzero, that many message fragments. Each fragment contains:<ul> - <li>4 byte messageId</li> - <li>3 byte fragment info:<pre> - 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</pre></li> - <li>that many bytes</li></ul> - <li>N bytes padding, uninterpreted</li> - </ul></td></tr> -<tr><td align="right" valign="top"><b>Crypto Key used:</b></td> - <td>Alice/Bob sessionKey</td></tr> -<tr><td align="right" valign="top"><b>MAC Key used:</b></td> - <td>Alice/Bob MAC Key</td></tr> -</table> - -<p>Message format:</p> - -{% 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 %} - -<h4>Notes</h4> -<ul><li> -The current implementation adds a limited number of duplicate acks for -messages previously acked, if space is available. -</li><li> -If the number of fragments is zero, this is an ack-only or keepalive message. -</li><li> -The ECN feature is unimplemented, and the bit is never set. -</li><li> -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. -</li><li> -Extended data is unimplemented and never present. -</li><li> -Reception of multiple fragments is supported in all releases. -Transmission of multiple fragments is implemented in release 0.9.16. -</li><li> -As currently implemented, maximum fragments is 64 -(maximum fragment number = 63). -</li><li> -As currently implemented, maximum fragment size is of course -less than the MTU. -</li><li> -Take care not to exceed the maximum MTU even if there is a large number of -ACKs to send. -</li><li> -The protocol allows zero-length fragments but there's no reason to send them. -</li><li> -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. -</li><li> -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. -</li><li> -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. -</li><li> -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. -</li><li> -Extended options in the header: Not expected, undefined. -</li></ul> - - - -<h3 id="peerTest">PeerTest (type 7)</h3> -<p> -See <a href="{{ site_url('docs/transport/ssu') }}#peerTesting">the SSU overview page</a> for details. -</p> - -<table border="1"> -<tr><td align="right" valign="top"><b>Peer:</b></td> - <td>Any</td></tr> -<tr><td align="right" valign="top"><b>Data:</b></td> - <td><ul> - <li>4 byte nonce</li> - <li>1 byte IP address size (may be zero)</li> - <li>that many byte representation of Alice's IP address, if size > 0</li> - <li>2 byte Alice's port number</li> - <li>Alice's or Charlie's 32-byte introduction key</li> - <li>N bytes, currently uninterpreted</li> - </ul></td></tr> -<tr><td align="right" valign="top"><b>Crypto Key used:</b></td> - <td> -Listed in order of occurrence: -<ol><li> -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.) -</li><li> -When sent from Bob to Charlie: -Bob/Charlie sessionKey -</li><li> -When sent from Charlie to Bob: -Bob/Charlie sessionKey -</li><li> -When sent from Bob to Alice: -Alice's introKey, as received in the Peer Test message from Alice -</li><li> -When sent from Charlie to Alice: -Alice's introKey, as received in the Peer Test message from Bob -</li><li> -When sent from Alice to Charlie: -Charlie's introKey, as received in the Peer Test message from Charlie -</li></ol> - </td></tr> -<tr><td align="right" valign="top"><b>MAC Key used:</b></td> - <td> -Listed in order of occurrence: -<ol><li> -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.) -</li><li> -When sent from Bob to Charlie: -Bob/Charlie MAC Key -</li><li> -When sent from Charlie to Bob: -Bob/Charlie MAC Key -</li><li> -When sent from Bob to Alice: -Alice's introKey, as received in the Peer Test message from Alice -</li><li> -When sent from Charlie to Alice: -Alice's introKey, as received in the Peer Test message from Bob -</li><li> -When sent from Alice to Charlie: -Charlie's introKey, as received in the Peer Test message from Charlie -</li></ol> - </td></tr> -</table> - -<p>Message format:</p> - -{% 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 %} - -<p> -Typical size including header, in current implementation: 80 bytes -(before non-mod-16 padding) -</p> - -<h4>Notes</h4> -<ul><li> -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. -</li><li> -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. -</li><li> -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. -</li><li> -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. -</li><li> -As of release 0.9.15, Alice must have an established session with Bob and use the session key. -</li><li> -Extended options in the header: Not expected, undefined. -</li></ul> - -<h3 id="holePunch">HolePunch</h3> -<p> -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. -</p> - - -<h2><a name="sampleDatagrams">Sample datagrams</a></h2> - -<b>Minimal data message (no fragments, no ACKs, no NACKs, etc)</b><br /> -<i>(Size: 39 bytes)</i> - -{% highlight lang='dataspec' %} - +----+----+----+----+----+----+----+----+ - | MAC | - + + - | | - +----+----+----+----+----+----+----+----+ - | IV | - + + - | | - +----+----+----+----+----+----+----+----+ - |flag| time |flag|#frg| | - +----+----+----+----+----+----+----+ + - | padding to fit a full AES256 block | - +----+----+----+----+----+----+----+----+ -{% endhighlight %} - -<b>Minimal data message with payload</b><br /> -<i>(Size: 46+fragmentSize bytes)</i> - -{% highlight lang='dataspec' %} - +----+----+----+----+----+----+----+----+ - | MAC | - + + - | | - +----+----+----+----+----+----+----+----+ - | IV | - + + - | | - +----+----+----+----+----+----+----+----+ - |flag| time |flag|#frg| - +----+----+----+----+----+----+----+----+ - messageId | frag info | | - +----+----+----+----+----+----+ + - | that many bytes of fragment data | - ~ . . . ~ - | | - +----+----+----+----+----+----+----+----+ -{% endhighlight %} - - -{% endblock %} diff --git a/i2p2www/pages/site/docs/spec/streaming.html b/i2p2www/pages/site/docs/spec/streaming.html deleted file mode 100644 index 9925a40580fa3a9b847d6250254b5bb1c67b9f0a..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/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 %} -<p><a href="{{ site_url('docs/api/streaming') }}">{% trans -%} -See the Streaming page for an overview of the Streaming Library. -{%- endtrans %}</a></p> - -<h2>{% trans %}Protocol Specification{% endtrans %}</h2> -<h3>{% trans %}Packet Format{% endtrans %}</h3> -<p>{% trans -%} -The format of a single packet in the streaming protocol is: -{%- endtrans %}</p> -{% highlight lang='dataspec' %} - -+----+----+----+----+----+----+----+----+ -| send Stream ID | rcv Stream ID | -+----+----+----+----+----+----+----+----+ -| sequence Num | ack Through | -+----+----+----+----+----+----+----+----+ -| nc | NACKs ... -+----+----+----+----+----+----+----+----+ - | rd | flags | opt size| opt data -+----+----+----+----+----+----+----+----+ - ... | -+----+----+----+----+----+----+----+----+ -| payload ... -+----+----+----+-// - - -{% endhighlight %} - -<table> -<tr><th>{{ _('Field') }}<th>{{ _('Length') }}<th>{{ _('Contents') }} -<tr><td>sendStreamId <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -<td>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. - -<tr><td>receiveStreamId <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a> -<td>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. - -<tr><td>sequenceNum <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td> -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. - -<tr><td>ackThrough <td>4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td> -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. - -<tr><td>NACK count<td>1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td> -The number of 4-byte NACKs in the next field - -<tr><td>NACKs <td>n * 4 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integers</a><td> -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. - -<tr><td>resendDelay<td>1 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td> -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. - -<tr><td>flags <td>2 byte value<td> -See below. - -<tr><td>option size<td>2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td> -The number of bytes in the next field - -<tr><td>option data<td>0 or more bytes<td> -As specified by the flags. See below. - -<tr><td>payload <td>remaining packet size<td> -</table> - -<h3>{% trans %}Flags and Option Data Fields{% endtrans %}</h3> -<p>{% 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 %}</p> - -<p> -Bit order: 15....0 (15 is MSB) -</p> -<table> -<tr><th>Bit<th>Flag<th>Option Order<th>Option Data<th>Function -<tr><td>0<td>SYNCHRONIZE<td align="center">--<td align="center">--<td> -Similar to TCP SYN. Set in the initial packet and in the first response. -FROM_INCLUDED and SIGNATURE_INCLUDED must be set also. -<tr><td>1<td>CLOSE<td align="center">--<td align="center">--<td> -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. -<tr><td>2<td>RESET<td align="center">--<td align="center">--<td> -Abnormal close. -SIGNATURE_INCLUDED must be set also. -Prior to release 0.9.20, due to a bug, FROM_INCLUDED must also be set. -<tr><td>3<td>SIGNATURE_INCLUDED<td align="center">4<td>variable length <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">Signature</a> -<td> -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 <a href="{{ site_url('docs/spec/common-structures') }}#type_SigningPublicKey">signing keys</a> -to sign the entire header and payload with the space in the option data field -for the signature being set to all zeroes. -<br> -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. -<tr><td>4<td>SIGNATURE_REQUESTED<td align="center">--<td align="center">--<td> -Unused. Requests every packet in the other direction to have SIGNATURE_INCLUDED -<tr><td>5<td>FROM_INCLUDED<td align="center">2<td>387+ byte <a href="{{ site_url('docs/spec/common-structures') }}#struct_Destination">Destination</a> -<td> -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. -<tr><td>6<td>DELAY_REQUESTED<td align="center">1<td>2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td> -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. -<tr><td>7<td>MAX_PACKET_SIZE_INCLUDED<td align="center">3<td>2 byte <a href="{{ site_url('docs/spec/common-structures') }}#type_Integer">Integer</a><td> -Currently sent with SYNCHRONIZE only. -Was also sent in retransmitted packets until release 0.9.1. -<tr><td>8<td>PROFILE_INTERACTIVE<td align="center">--<td align="center">--<td> -Unused or ignored; the interactive profile is unimplemented. -<tr><td>9<td>ECHO<td align="center">--<td align="center">--<td> -Unused except by ping programs. -If set, most other options are ignored. See -<a href="{{ site_url('docs/api/streaming') }}">the streaming docs</a>. -<tr><td>10<td>NO_ACK<td align="center">--<td align="center">--<td> -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. -<tr><td>11-15<td>unused<td><td><td> -Set to zero for compatibility with future uses. -</table> - -<h4>Variable Length Signature Notes</h4> -<p> -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 <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">Signature documentation</a>. -<ul><li> -When a packet contains both FROM_INCLUDED and SIGNATURE_INCLUDED (as in SYNCHRONIZE), the inference may be made directly. -</li><li> -When a packet does not contain FROM_INCLUDED, the inference must be made from a previous SYNCHRONIZE packet. -</li><li> -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. -</li></ul> -</p> - - -{% endblock %} diff --git a/i2p2www/pages/site/docs/spec/tunnel-creation.html b/i2p2www/pages/site/docs/spec/tunnel-creation.html deleted file mode 100644 index eb233ac158aa18ff552b605d3a394ccba2c75b5f..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/spec/tunnel-creation.html +++ /dev/null @@ -1,355 +0,0 @@ -{% extends "global/layout.html" %} -{% block title %}Tunnel Creation{% endblock %} -{% block lastupdated %}January 2016{% endblock %} -{% block accuratefor %}0.9.24{% endblock %} -{% block content %} - -This page documents the current tunnel build implementation. - -<h2 id="tunnelCreate.overview">Tunnel Creation Specification</h2> - -<p> -This document specifies the details of the encrypted tunnel build messages -used to create tunnels using a "non-interactive telescoping" method. -See <a href="{{ site_url('docs/tunnels/implementation') }}">the tunnel build document</a> -for an overview of the process, including peer selection and ordering methods. - -<p>The tunnel creation is accomplished by a single message passed along -the path of peers in the tunnel, rewritten in place, and transmitted -back to the tunnel creator. This single tunnel message is made up -of a variable number of records (up to 8) - one for each potential peer in -the tunnel. Individual records are asymmetrically -<a href="{{ site_url('docs/how/cryptography') }}#elgamal">(ElGamal)</a> -encrypted to be -read only by a specific peer along the path, while an additional -symmetric layer of encryption -<a href="{{ site_url('docs/how/cryptography') }}#AES">(AES)</a> -is added at each hop so as to expose -the asymmetrically encrypted record only at the appropriate time.</p> - -<h3 id="number">Number of Records</h3> -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 -<a href="{{ site_url('docs/spec/i2np') }}#msg_TunnelBuild">Tunnel Build Message</a> (TBM) -contains 8 records, which is more than enough for any practical tunnel length. -The newer -<a href="{{ site_url('docs/spec/i2np') }}#msg_VariableTunnelBuild">Variable Tunnel Build Message</a> (VTBM) -contains 1 to 8 records. The originator may trade off the size of the message -with the desired amount of tunnel length obfuscation. -<p> -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. -<p> -The reply message must be the same type and length as the build message. - - -<h3 id="tunnelCreate.requestRecord">Request Record Specification</h3> - -Also specified in the -<a href="{{ site_url('docs/spec/i2np') }}#struct_BuildRequestRecord">I2NP Specification</a> - -<p>Cleartext of the record, visible only to the hop being asked:</p><pre> - bytes 0-3: tunnel ID to receive messages as - bytes 4-35: local router identity hash - bytes 36-39: next tunnel ID - bytes 40-71: next router identity hash - bytes 72-103: AES-256 tunnel layer key - bytes 104-135: AES-256 tunnel IV key - bytes 136-167: AES-256 reply key - bytes 168-183: 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</pre> - -<p>The next tunnel ID and next router identity hash fields are used to -specify the next hop in the tunnel, though for an outbound tunnel -endpoint, they specify where the rewritten tunnel creation reply -message should be sent. In addition, the next message ID specifies the -message ID that the message (or reply) should use.</p> - -<p> -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. -</p> - -<p>The flags field contains the following: -<pre> - 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 -</pre> -<p> -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. -</p> - -<h4>Request Record Creation</h4> -<p> -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. -</p> - - -<h4 id="encryption">Request Record Encryption</h4> - -<p>That cleartext record is <a href="{{ site_url('docs/how/cryptography') }}#elgamal">ElGamal 2048 encrypted</a> with the hop's -public encryption key and formatted into a 528 byte record:</p><pre> - 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</pre> -<p> -In the 512-byte encrypted record, -the ElGamal data contains bytes 1-256 and 258-513 of the -<a href="{{ site_url('docs/how/cryptography') }}#elgamal">514-byte ElGamal encrypted block</a>. -The two padding bytes from the block (the zero bytes at locations 0 and 257) are removed. -</p> -<p>Since the cleartext uses the full field, there is no need for -additional padding beyond <code>SHA256(cleartext) + cleartext</code>.</p> - -<p> -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. -</p> - -<h3 id="tunnelCreate.hopProcessing">Hop Processing and Encryption</h3> - -<p>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. -Records that are not stamped with the current hour, -or the previous hour if shortly after the top of the hour, -must be dropped. -For example, take the hour in the timestamp, convert to a full time, -then if it's more than 65 minutes behind or 5 minutes ahead of the -current time, it is invalid. -The Bloom filter must have a duration of at least one hour -(plus a few minutes, to allow for clock skew), -so that duplicate records in the current hour that are not rejected -by checking the hour timestamp in the record, will be rejected by the filter. -</p> - -<p>After deciding whether they will agree to participate in the tunnel -or not, they replace the record that had contained the request with -an encrypted reply block. All other records are <a href="{{ site_url('docs/how/cryptography') }}#AES">AES-256 -encrypted</a> 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.</p> - -<p> -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. -</p> - - -<h4 id="tunnelCreate.replyRecord">Reply Record Specification</h4> - -<p>After the current hop reads their record, they replace it with a -reply record stating whether or not they agree to participate in the -tunnel, and if they do not, they classify their reason for -rejection. This is simply a 1 byte value, with 0x0 meaning they -agree to participate in the tunnel, and higher values meaning higher -levels of rejection. -<p> -The following rejection codes are defined: -<ul> -<li> -TUNNEL_REJECT_PROBABALISTIC_REJECT = 10 -<li> -TUNNEL_REJECT_TRANSIENT_OVERLOAD = 20 -<li> -TUNNEL_REJECT_BANDWIDTH = 30 -<li> -TUNNEL_REJECT_CRIT = 50 -</ul> -To hide other causes, such as router shutdown, from peers, the current implementation -uses TUNNEL_REJECT_BANDWIDTH for almost all rejections. - -<p> - 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: -</p><pre> - 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 -</pre> -<p> -This is also described in the -<a href="{{ site_url('docs/spec/i2np') }}#struct_BuildResponseRecord">I2NP spec</a>. -</p> - -<h3 id="tunnelCreate.requestPreparation">Tunnel Build Message Preparation</h3> - -<p>When building a new Tunnel Build Message, all of the Build Request Records must first be -built and asymmetrically encrypted using -<a href="{{ site_url('docs/how/cryptography') }}#elgamal">ElGamal</a>. -Each record is then -premptively decrypted with the reply keys and IVs of the hops earlier in the -path, using -<a href="{{ site_url('docs/how/cryptography') }}#AES">AES</a>. -That decryption should be run in reverse order so that the -asymmetrically encrypted data will show up in the clear at the -right hop after their predecessor encrypts it.</p> - -<p>The excess records not needed for individual requests are simply -filled with random data by the creator.</p> - -<h3 id="tunnelCreate.requestDelivery">Tunnel Build Message Delivery</h3> - -<p>For outbound tunnels, the delivery is done directly from the tunnel -creator to the first hop, packaging up the TunnelBuildMessage as if -the creator was just another hop in the tunnel. For inbound -tunnels, the delivery is done through an existing outbound tunnel. -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.</p> - -<h3 id="tunnelCreate.endpointHandling">Tunnel Build Message Endpoint Handling</h3> - -<p> -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 -<a href="{{ site_url('docs/spec/i2np') }}#msg_TunnelBuildReply">TunnelBuildReplyMessage</a> -or -<a href="{{ site_url('docs/spec/i2np') }}#msg_VariableTunnelBuildReply">VariableTunnelBuildReplyMessage</a> -(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, -<a href="{{ site_url('docs/tunnels/implementation') }}#tunnel.operation">just as for any other message</a>. -The tunnel creator then -processes it, as described below.</p> - -<p>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.</p> - -<p> -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.</p> - -<h3 id="tunnelCreate.replyProcessing">Tunnel Build Reply Message Processing</h3> - -<p>To process the reply records, the creator simply has to AES decrypt -each record individually, using the reply key and IV of each hop in -the tunnel after the peer (in reverse order). This then exposes the -reply specifying whether they agree to participate in the tunnel or -why they refuse. If they all agree, the tunnel is considered -created and may be used immediately, but if anyone refuses, the -tunnel is discarded.</p> - -<p> -The agreements and rejections are noted in each peer's -<a href="{{ site_url('docs/how/peer-selection') }}">profile</a>, to be used in future assessments -of peer tunnel capacity. - - -<h2 id="tunnelCreate.notes">History and Notes</h2> -<p> -This strategy came about during a discussion on the I2P mailing list - between Michael Rogers, Matthew Toseland (toad), and jrandom regarding - the predecessor attack. See: <ul> - <li><a href="http://osdir.com/ml/network.i2p/2005-10/msg00138.html">Summary</a></li> - <li><a href="http://osdir.com/ml/network.i2p/2005-10/msg00129.html">Reasoning</a></li> - </ul></li> -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. -</p> - -<p> -Notes: -<ul> -<li>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.</li> -<li>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.</li> -<li>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?</li> -<li>Are there any nonfatal methods of tagging the request?</li> -<li> -The timestamp with a one-hour resolution is used for replay prevention. -The constraint was not enforced until release 0.9.16. -</li> -</ul> - -<h2 id="ref">References</h2> -<ul> -<li> -<a href="http://forensics.umass.edu/pubs/wright-tissec.pdf">Predecessor -attack</a> -<li> -<a href="http://forensics.umass.edu/pubs/wright.tissec.2008.pdf">2008 -update</a> -<li> -<a href="http://www-users.cs.umn.edu/~hopper/hashing_it_out.pdf">Hashing it out in Public</a> -</ul> - -<h2 id="future">Future Work</h2> -<ul> -<li> -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. -<li> -Further analysis of possible tagging and timing attacks described in the above notes. -</li><li> -Use only VTBM; do not select old peers that don't support it. -</li><li> -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. -</li></ul> - - -{% endblock %} diff --git a/i2p2www/pages/site/docs/spec/tunnel-message.html b/i2p2www/pages/site/docs/spec/tunnel-message.html deleted file mode 100644 index 4f4e00c95078d27d2ee2074d1ceb44fb9d55174e..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/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 %} -<p> -This document specifies the format of tunnel messages. -For general information about tunnels see -<a href="{{ site_url('docs/tunnels/implementation') }}">the tunnel documentation</a>. -</p> - -<h2>Message preprocessing</h2> - - -A <i>tunnel gateway</i> 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. - -<p> -A gateway <i>preprocesses</i> <a href="{{ site_url('docs/protocol/i2np') }}">I2NP messages</a> -by fragmenting and combining them into tunnel messages. - -<p> -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. - -<p> -After the tunnel messages are created, they are encrypted as described in -<a href="{{ site_url('docs/tunnels/implementation') }}">the tunnel documentation</a>. - -<h2 id="msg_Tunnel">Tunnel Message (Encrypted)</h2> -These are the contents of a tunnel data message after encryption. -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+----+ -| Tunnel ID | IV | -+----+----+----+----+ + -| | -+ +----+----+----+----+ -| | | -+----+----+----+----+ + -| | -+ Encrypted Data + -~ ~ -| | -+ +-------------------+ -| | -+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% 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 %} - - -<h2>Tunnel Message (Decrypted)</h2> -These are the contents of a tunnel data message when decrypted. -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+----+ -| Tunnel ID | IV | -+----+----+----+----+ + -| | -+ +----+----+----+----+ -| | Checksum | -+----+----+----+----+----+----+----+----+ -| nonzero padding... | -~ ~ -| | -+ +----+ -| |zero| -+----+----+----+----+----+----+----+----+ -| | -| Delivery Instructions 1 | -~ ~ -| | -+----+----+----+----+----+----+----+----+ -| | -+ I2NP Message Fragment 1 + -| | -~ ~ -| | -+----+----+----+----+----+----+----+----+ -| | -| Delivery Instructions 2... | -~ ~ -| | -+----+----+----+----+----+----+----+----+ -| | -+ I2NP Message Fragment 2... + -| | -~ ~ -| | -+ +-------------------+ -| | -+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% 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 %} - -<h4>Notes</h4> -<ul><li> -The padding, if any, must be before the instruction/message pairs. -There is no provision for padding at the end. -</li><li> -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. -</li></ul> - - -<h2 id="struct_TunnelMessageDeliveryInstructions">Tunnel Message Delivery Instructions</h2> - -<p>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.</p> - -<p> -This specification is for Delivery Instructions inside Tunnel Messages only. -Note that "Delivery Instructions" are also used inside -<a href="{{ site_url('docs/spec/i2np') }}#struct_GarlicClove">Garlic Cloves</a>, -where the format is significantly different. -See the -<a href="{{ site_url('docs/spec/i2np') }}#struct_GarlicCloveDeliveryInstructions">I2NP documentation</a> -for details. -Do NOT use the following specification for Garlic Clove Delivery Instructions! - - -<h3>First Fragment Delivery Instructions</h3> -<p>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:</p> -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+----+ -|flag| Tunnel ID (opt) | | -+----+----+----+----+----+ + -| | -+ + -| To Hash (optional) | -+ + -| | -+ +--------------+ -| |dly | Message -+----+----+----+----+----+----+----+----+ - ID (opt) |extended opts (opt)| size | -+----+----+----+----+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% 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 %} - -<h3>Follow-on Fragment Delivery Instructions</h3> -<p>If the MSB of the first byte is 1, this is a follow-on fragment, and the instructions are:</p> -{% highlight lang='dataspec' %} -+----+----+----+----+----+----+----+ -|frag| Message ID | size | -+----+----+----+----+----+----+----+ -{% endhighlight %} - -<h4>Definition</h4> -{% 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 %} - -<h3><a href="http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/i2np/DeliveryInstructions.html">Delivery Instructions Javadoc</a></h3> - -<h2 id="notes">Notes</h2> -<h3>I2NP Message Maximum Size</h3> -<p> -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. -<p> -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. -</p> - -<h3>Ordering, Batching, Packing</h3> -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. - -<h3>Cover Traffic</h3> -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/pages/site/docs/spec/updates.html b/i2p2www/pages/site/docs/spec/updates.html deleted file mode 100644 index bde99bf33ac969902bcf65503a9e191ac4bd8921..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/docs/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 %} -<h3>{% trans %}Overview{% endtrans %}</h3> -<p>{% 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 %}</p> - -<p>{% 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 %}</p> - -<p>{% trans -%} -The router may optionally download, or download and install, the new version -if configured to do so. -{%- endtrans %}</p> - -<h3>{% trans %}Old News File Specification{% endtrans %}</h3> -<p>{% trans -%} -This format is replaced by the su3 news format as of release 0.9.17. -{%- endtrans %}</p> -<p>{% trans -%} -The news.xml file may contain the following elements: -{%- endtrans %}</p> -<pre> -<i2p.news date="$Date: 2010-01-22 00:00:00 $" /> -<i2p.release version="0.7.14" date="2010/01/22" minVersion="0.6" /> -</pre> - -<p>{% trans -%} -Parameters in the i2p.release entry are as follows. -All keys are case-insensitive. All values must be enclosed in double quotes. -{%- endtrans %}</p> - -<ul> -<li> -date: The release date of the router version. Unused. Format not specified. -</li><li> -minJavaVersion: The minimum version of Java required to run the current version. -As of release 0.9.9. -</li><li> -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. -</li><li> -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. -</li><li> -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. -</li><li> -sudTorrent: The magnet link for the .sud (non-pack200) torrent of the update. -As of release 0.9.4. -</li><li> -su2Torrent: The magnet link for the .su2 (pack200) torrent of the update. -As of release 0.9.4. -</li><li> -su3Torrent: The magnet link for the .su3 (new format) torrent of the update. -As of release 0.9.9. -</li><li> -version: Required. The latest current router version available. -</li></ul> - -<p>{% 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 %}</p> - - -<h3>{% trans %}Update File Specification{% endtrans %}</h3> -<p>{% 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 %}</p> - - -<h3>{% trans %}Old Update File Specification{% endtrans %}</h3> -<p>{% trans -%} -This format is obsolete as of release 0.9.9. -{%- endtrans %}</p> -<p>{% trans -%} -The signed update file, traditionally named i2pupdate.sud, -is simply a zip file with a prepended 56 byte header. -The header contains: -{%- endtrans %}</p> -<ul> -<li>{% trans commonstructures=site_url('docs/spec/common-structures') -%} -A 40-byte <a href="{{ commonstructures }}#type_signature">DSA signature</a> -{%- endtrans %}</li> -<li>{% trans -%} -A 16-byte I2P version in UTF-8, padded with trailing zeroes if necessary -{%- endtrans %}</li> -</ul> - -<p>{% 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 <a href="{{ commonstructures }}#type_SigningPublicKey">DSA public keys</a> configured into the router, -which has a hardcoded default list of keys of the current project release managers. -{%- endtrans %}</p> - -<p>{% trans -%} -For version comparison purposes, version fields contain [0-9]*, field separators are -'-', '_', and '.', and all other characters are ignored. -{%- endtrans %}</p> - -<p>{% 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 %}</p> - -<h3>{% trans %}Download and Installation{% endtrans %}</h3> -<p>{% 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 %}</p> - -<p>{% trans -%} -The zip file is extracted and copied to "i2pupdate.zip" in the I2P configuration directory (~/.i2p on Linux). -{%- endtrans %}</p> - -<p>{% 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 %}</p> - -<p>{% 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 %}</p> - -<p>{% 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 %}</p> -<ul> -<li>{% trans %}One file name per line{% endtrans %}</li> -<li>{% trans %}All file names are relative to the installation directory; no absolute file names allowed, no files starting with ".."{% endtrans %}</li> -<li>{% trans %}Comments start with '#'{% endtrans %}</li> -</ul> - -<p>{% trans -%} -The router will then delete the deletelist.txt file. -{%- endtrans %}</p> - - - -<h3 id="su3">{% trans %}SU3 File Specification{% endtrans %}</h3> - -<p>{% 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 %}</p> - -<h4>{% trans %}Issues with the previous .sud/.su2 format:{% endtrans %}</h4> -<ul> -<li>{% trans -%} -No magic number or flags -{%- endtrans %}</li> -<li>{% trans -%} -No way to specify compression, pack200 or not, or signing algo -{%- endtrans %}</li> -<li>{% 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 %}</li> -<li>{% trans -%} -Signer not specified so verifier must try all known keys -{%- endtrans %}</li> -<li>{% trans -%} -Signature-before-data format requires two passes to generate file -{%- endtrans %}</li> -</ul> - - -<h4>{% trans %}Goals:{% endtrans %}</h4> - -<ul> -<li>{% trans -%} -Fix above problems -{%- endtrans %}</li> -<li>{% trans -%} -Migrate to more secure signature algorithm -{%- endtrans %}</li> -<li>{% trans -%} -Keep version info in same format and offset for compatibility with -existing version checkers -{%- endtrans %}</li> -<li>{% trans -%} -One-pass signature verification and file extraction -{%- endtrans %}</li> -</ul> - -<h4>{% trans %}Specification:{% endtrans %}</h4> - -<table><tr> -<th>Bytes<th>Contents -<tr><td> -0-5 <td>Magic number "I2Psu3" -<tr><td> -6 <td>unused = 0 -<tr><td> -7 <td>su3 file format version = 0 -<tr><td> -8-9 <td>Signature type - <ul><li>0x0000 = DSA-SHA1 - </li><li>0x0001 = ECDSA-SHA256-P256 - </li><li>0x0002 = ECDSA-SHA384-P384 - </li><li>0x0003 = ECDSA-SHA512-P521 - </li><li>0x0004 = RSA-SHA256-2048 - </li><li>0x0005 = RSA-SHA384-3072 - </li><li>0x0006 = RSA-SHA512-4096 - </li></ul> -<tr><td> -10-11 <td>Signature length, e.g. 40 (0x0028) for DSA-SHA1. - Must match that specified for the signature type on the - <a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">common structures page</a>. -<tr><td> -12 <td>unused = 0 -<tr><td> -13 <td>Version length (in bytes not chars, including padding) - must be at least 16 (0x10) for compatibility -<tr><td> -14 <td>unused = 0 -<tr><td> -15 <td>Signer ID length (in bytes not chars) -<tr><td> -16-23 <td>Content length (not including header or sig) -<tr><td> -24 <td>unused = 0 -<tr><td> -25 <td>File type - <ul><li>0x00 = zip file - </li><li>0x01 = xml file (as of 0.9.15) - </li><li>0x02 = html file (as of 0.9.17) - </li><li>0x03 = xml.gz file (as of 0.9.17) - </li></ul> -<tr><td> -26 <td>unused = 0 -<tr><td> -27 <td>Content type - <ul><li>0x00 = unknown - </li><li>0x01 = router update - </li><li>0x02 = plugin or plugin update - </li><li>0x03 = reseed data - </li><li>0x04 = news feed (as of 0.9.15) - </li></ul> -<tr><td> -28-39 <td>unused = 0 -<tr><td> -40-55+ <td>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. -<tr><td> -xx+ <td>ID of signer, (e.g. "zzz@mail.i2p") UTF-8, not padded, length specified at byte 15 -<tr><td> -xx+ <td>Content: Length specified in header at bytes 16-23, - format specified in header at byte 25, - content specified in header at byte 27 -<tr><td> -xx+ <td>Signature: Length is specified in header at bytes 10-11, covers everything starting at byte 0 -</table> - -<p>{% trans -%} -All unused fields must be set to 0 for compatibility with future versions. -{%- endtrans %}</p> - - -<h4>{% trans %}Signature Details{% endtrans %}</h4> -<p> -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). -<p></p> -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. -<p></p> -Signature lengths for the various signature types are specified on the -<a href="{{ site_url('docs/spec/common-structures') }}#type_Signature">common structures page</a>. -Pad the signature with leading zeros if necessary. -See <a href="{{ site_url('docs/how/cryptography') }}#sig">the cryptography details page</a> -for parameters of the various signature types. -</p> - - - -<h4>{% trans %}Notes{% endtrans %}</h4> -<p> -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. -<p></p> -All values are in network byte order (big endian). -</p> - - - - -<h3>{% trans %}SU3 Router Update File Specification{% endtrans %}</h3> - -<p><b>SU3 Details:</b></p> -<ul><li> -SU3 Content Type: 1 (ROUTER UPDATE) -</li><li> -SU3 File Type: 0 (ZIP) -</li><li> -SU3 Version: The router version -</li><li> -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. -</li></ul> - -<p><b>Notes:</b></p> -<ul><li> -For releases, the SU3 version is the "base" router version, e.g. "0.9.20". -</li><li> -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. -</li></ul> - - - -<h3>{% trans %}SU3 Reseed File Specification{% endtrans %}</h3> -<p>{% trans -%} -As of 0.9.14, reseed data is delivered in an "su3" file format. -{%- endtrans %}</p> - -<h4>{% trans %}Goals:{% endtrans %}</h4> - -<ul> -<li>{% 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 %}</li> -<li>{% trans -%} -Use su3 file format already used for updates, reseeding, and plugins -{%- endtrans %}</li> -<li>{% trans -%} -Single compressed file to speed up reseeding, which was slow to fetch 200 files -{%- endtrans %}</li> -</ul> - -<h4>{% trans %}Specification:{% endtrans %}</h4> - -<p><ol> -<li>{% trans -%} -The file must be named "i2pseeds.su3". -{%- endtrans %}</li> -<li>{% trans -%} -The file must be in the same directory as the router infos on the web server. -{%- endtrans %}</li> -<li>{% 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 %}</li> -</ol></p> - -<p><b>SU3 Details:</b></p> -<ul><li> -SU3 Content Type: 3 (RESEED) -</li><li> -SU3 File Type: 0 (ZIP) -</li><li> -SU3 Version: Seconds since the epoch, in ASCII (date +%s) -</li><li> -Router info files in the zip file must be at the "top level". No directories are in the zip file. -</li><li> -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. -</li></ul> - - - - -<h3>{% trans %}SU3 Plugin File Specification{% endtrans %}</h3> - -<p>{% trans -%} -As of 0.9.15, plugins may be packaged in an "su3" file format. -{%- endtrans %}</p> - -<p><b>SU3 Details:</b></p> -<ul><li> -SU3 Content Type: 2 (PLUGIN) -</li><li> -SU3 File Type: 0 (ZIP) -See <a href="plugin">the plugin specification</a> for details. -</li><li> -SU3 Version: The plugin version, must match that in plugin.config. -</li><li> -Jar and war files in the zip are compressed with pack200 as documented above for "su2" files. -</li></ul> - - - - - - -<h3>{% trans %}SU3 News File Specification{% endtrans %}</h3> -<p>{% trans -%} -As of 0.9.17, the news is delivered in an "su3" file format. -{%- endtrans %}</p> - -<h4>{% trans %}Goals:{% endtrans %}</h4> - -<ul> -<li>{% trans -%} -Signed news with strong signatures and trusted certificates -{%- endtrans %}</li> -<li>{% trans -%} -Use su3 file format already used for updates, reseeding, and plugins -{%- endtrans %}</li> -<li>{% trans -%} -Standard XML format for use with standard parsers -{%- endtrans %}</li> -<li>{% trans -%} -Standard Atom format for use with standard feed readers and generators -{%- endtrans %}</li> -<li>{% trans -%} -Sanitization and verification of HTML before displaying on console -{%- endtrans %}</li> -<li>{% trans -%} -Suitable for easy implementation on Android and other platforms without an HTML console -{%- endtrans %}</li> -</ul> - -<h4>{% trans %}Specification:{% endtrans %}</h4> - -<p><b>SU3 Details:</b></p> -<ul><li> -SU3 Content Type: 4 (NEWS) -</li><li> -SU3 File Type: 1 (XML) or 3 (XML.GZ) -</li><li> -SU3 Version: Seconds since the epoch, in ASCII (date +%s) -</li><li> -File Format: XML or gzipped XML, containing an <a href="http://tools.ietf.org/html/rfc4287">RFC 4287 (Atom) XML Feed</a>. -Charset must be UTF-8. -</li></ul> - - -<p><b>Atom <feed> Details:</b></p> -The following <feed> elements are used: -<ul><li> -<entry> A news item. See below. -</li><li> -<i2p:release> I2P update metadata. See below. -</li><li> -<updated> Timestamp for the feed (conforming to -<a href="http://tools.ietf.org/html/rfc4287">RFC 4287 (Atom) section 3.3</a> and -<a href="http://tools.ietf.org/html/rfc3339">RFC 3339</a>. (required) -</li></ul> - - -<p><b>Atom <entry> Details:</b></p> -Each Atom <entry> in the news feed may be parsed and displayed in the router console. -The following elements are used: -<ul><li> -<author> (optional) containing: - <ul><li> - <name> The name of the entry author - </li></ul> -</li><li> -<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) -</li><li> -<link> Link for further information (optional) -</li><li> -<summary> Short summary, suitable for a tooltip (optional) -</li><li> -<title> Title of the news entry (required) -</li><li> -<updated> Timestamp for this entry (conforming to -<a href="http://tools.ietf.org/html/rfc4287">RFC 4287 (Atom) section 3.3</a> and -<a href="http://tools.ietf.org/html/rfc3339">RFC 3339</a>. (required) -</li></ul> - - -<p><b>Atom <i2p:release> Details:</b></p> -There must be at least one <i2p:release> entity in the feed. Each contains the following attributes and entities: -<ul><li> -date (attribute): Timestamp for this entry (conforming to -<a href="http://tools.ietf.org/html/rfc4287">RFC 4287 (Atom) section 3.3</a> and -<a href="http://tools.ietf.org/html/rfc3339">RFC 3339</a>. (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. -</li><li> -minJavaVersion (attribute): If present, the minimum version of Java required to run the current version. -</li><li> -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. -</li><li> -<i2p:version> Required. The latest current router version available. -</li><li> -<i2p:update> An update file (one or more). It must contain at least one child. - <ul><li> - type (attribute): "sud", "su2", or "su3". Must be unique across all <i2p:update> elements. - </li><li> - <i2p:clearnet> Out-of-network direct download links (zero or more) - <ul><li> - href (attribute): a standard clearnet http link - </li></ul> - </li><li> - <i2p:clearnetssl> Out-of-network direct download links (zero or more) - <ul><li> - href (attribute): a standard clearnet https link - </li></ul> - </li><li> - <i2p:torrent> In-network magnet link - <ul><li> - href (attribute): a magnet link - </li></ul> - </li><li> - <i2p:url> In-network direct download links (zero or more) - <ul><li> - href (attribute): an in-network http .i2p link - </li></ul> - </li></ul> -</li></ul> - - - -<h3>{% trans %}Future Work{% endtrans %}</h3> -<ul> -<li>{% 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 %}</li> -</ul> - - - -{% endblock %} diff --git a/i2p2www/pages/site/spectags b/i2p2www/pages/site/spectags deleted file mode 100644 index 5033c3ba165f8b2fe6f4ad8347b02a1efc67e430..0000000000000000000000000000000000000000 --- a/i2p2www/pages/site/spectags +++ /dev/null @@ -1,76 +0,0 @@ -!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ -!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ -!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ -!_TAG_PROGRAM_NAME Exuberant Ctags // -!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ -!_TAG_PROGRAM_VERSION 5.9~svn20110310 // -BandwidthLimits docs/spec/i2cp.html 588;" m -Boolean docs/spec/common-structures.html 74;" t -BuildRequestRecord docs/spec/i2np.html 183;" s -BuildResponseRecord docs/spec/i2np.html 353;" s -Certificate docs/spec/common-structures.html 296;" t -CreateLeaseSet docs/spec/i2cp.html 630;" m -CreateSession docs/spec/i2cp.html 668;" m -Data docs/spec/i2np.html 1118;" m -DatabaseLookup docs/spec/i2np.html 688;" m -DatabaseSearchReply docs/spec/i2np.html 835;" m -DatabaseStore docs/spec/i2np.html 590;" m -Date docs/spec/common-structures.html 51;" t -DeliveryInstructions docs/spec/common-structures.html 1010;" s -DeliveryStatus docs/spec/i2np.html 910;" m -DestLookup docs/spec/i2cp.html 697;" m -DestReply docs/spec/i2cp.html 719;" m -Destination docs/spec/common-structures.html 639;" s -Disconnect docs/spec/i2cp.html 763;" m -Garlic docs/spec/i2np.html 948;" m -GarlicClove docs/spec/i2np.html 395;" s -GarlicCloveDeliveryInstructions docs/spec/i2np.html 454;" s -GetBandwidthLimits docs/spec/i2cp.html 783;" m -GetDate docs/spec/i2cp.html 802;" m -Hash docs/spec/common-structures.html 257;" t -HostLookup docs/spec/i2cp.html 840;" m -HostReply docs/spec/i2cp.html 889;" m -I2CPMessageHeader docs/spec/i2cp.html 302;" s -I2NPMessageHeader docs/spec/i2np.html 93;" s -Integer docs/spec/common-structures.html 41;" t -KeysAndCert docs/spec/common-structures.html 549;" s -Lease docs/spec/common-structures.html 668;" s -LeaseSet docs/spec/common-structures.html 713;" s -Mapping docs/spec/common-structures.html 461;" t -MessageId docs/spec/i2cp.html 324;" s -MessagePayload docs/spec/i2cp.html 921;" m -MessageStatus docs/spec/i2cp.html 943;" m -Payload docs/spec/i2cp.html 344;" s -PrivateKey docs/spec/common-structures.html 102;" t -PublicKey docs/spec/common-structures.html 89;" t -ReceiveMessageBegin docs/spec/i2cp.html 1048;" m -ReceiveMessageEnd docs/spec/i2cp.html 1077;" m -ReconfigureSession docs/spec/i2cp.html 1103;" m -ReportAbuse docs/spec/i2cp.html 1133;" m -RequestLeaseSet docs/spec/i2cp.html 1164;" m -RequestVariableLeaseSet docs/spec/i2cp.html 1197;" m -RouterAddress docs/spec/common-structures.html 843;" s -RouterIdentity docs/spec/common-structures.html 613;" s -RouterInfo docs/spec/common-structures.html 910;" s -SendMessage docs/spec/i2cp.html 1225;" m -SendMessageExpires docs/spec/i2cp.html 1272;" m -SessionConfig docs/spec/i2cp.html 366;" s -SessionId docs/spec/i2cp.html 398;" s -SessionKey docs/spec/common-structures.html 115;" t -SessionStatus docs/spec/i2cp.html 1403;" m -SessionTag docs/spec/common-structures.html 269;" t -SetDate docs/spec/i2cp.html 1437;" m -Signature docs/spec/common-structures.html 214;" t -SigningPrivateKey docs/spec/common-structures.html 171;" t -SigningPublicKey docs/spec/common-structures.html 128;" t -String docs/spec/common-structures.html 62;" t -Tunnel docs/spec/tunnel-message.html 34;" m -TunnelBuild docs/spec/i2np.html 1144;" m -TunnelBuildReply docs/spec/i2np.html 1177;" m -TunnelData docs/spec/i2np.html 1044;" m -TunnelGateway docs/spec/i2np.html 1084;" m -TunnelId docs/spec/common-structures.html 281;" t -TunnelMessageDeliveryInstructions docs/spec/tunnel-message.html 159;" s -VariableTunnelBuild docs/spec/i2np.html 1190;" m -VariableTunnelBuildReply docs/spec/i2np.html 1220;" m -sampleDatagrams docs/spec/ssu.html 1062;" a diff --git a/i2p2www/pages/spec/index.html b/i2p2www/pages/spec/index.html new file mode 100644 index 0000000000000000000000000000000000000000..c98d239a2b4775a94e6a0629872935f0ceb977ff --- /dev/null +++ b/i2p2www/pages/spec/index.html @@ -0,0 +1,40 @@ +{% extends "global/layout.html" %} +{% block title %}I2P Specification Documents{% endblock %} +{% block content %} +This page provides the specifications for various components of the I2P network +and router software. These are living documents, and the specifications are +updated as modifications are made to the network and software. + +<ul><li> +"Last updated" is the last date when the specification given within a document +was altered in any way, except for changes to the "accurate for" information. +</li><li> +The "accurate for" column gives the version of the I2P network and reference +Java implementation that the document is verified to be valid for. Because the +documents are usually only updated when changes are made, the listed versions +can sometimes be several releases behind. This does not mean that documents with +old listed versions are necessarily inaccurate, but small differences may creep +in during the course of development. Periodic reviews are conducted to update +the "accurate for" information. +</li></ul> + +<table> + <tr> + <th>Title</th> + <th>Last updated</th> + <th>Accurate for</th> + <th>Link</th> + </tr> + {% for spec in specs %} + <tr> + <td>{{ spec.title }}</td> + <td><time>{{ spec.lastupdated }}</time></td> + <td>{{ spec.accuratefor }}</td> + <td> + <a href="{{ url_for('spec_show', name=spec.name) }}">HTML</a> | + <a href="{{ url_for('spec_show_txt', name=spec.name) }}">TXT</a> + </td> + </tr> +{% endfor %} +</table> +{% endblock %} diff --git a/i2p2www/pages/spec/show.html b/i2p2www/pages/spec/show.html new file mode 100644 index 0000000000000000000000000000000000000000..1d9cf1a683ee7d8b6a00ca2708ee6f73e7d1c74a --- /dev/null +++ b/i2p2www/pages/spec/show.html @@ -0,0 +1,15 @@ +{% extends "global/layout.html" %} +{%- from "global/macros" import render_categories with context -%} +{% block title %}{{ title }}{% endblock %} +{% block lastupdated %}{{ meta.lastupdated }}{% endblock %} +{% block accuratefor %}{{ meta.accuratefor }}{% endblock %} +{% block content_nav %} +{% autoescape false %} +{{ toc }} +{% endautoescape %} +{% endblock %} +{% block content %} +{% autoescape false %} +{{ body }} +{% endautoescape %} +{% endblock %} diff --git a/i2p2www/spec/__init__.py b/i2p2www/spec/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/i2p2www/spec/blockfile.rst b/i2p2www/spec/blockfile.rst new file mode 100644 index 0000000000000000000000000000000000000000..91984e5f02f018afca28380d711de6b4812a68e9 --- /dev/null +++ b/i2p2www/spec/blockfile.rst @@ -0,0 +1,249 @@ +========================================== +Blockfile and Hosts Database Specification +========================================== +.. meta:: + :lastupdated: November 2014 + :accuratefor: 0.9.17 + +.. contents:: + + +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 +========== + +.. [Destination] + {{ ctags_url('Destination') }} + +.. [Mapping] + {{ ctags_url('Mapping') }} + +.. [METANOTION] + http://www.metanotion.net/software/sandbox/block.html + +.. [NAMING] + {{ site_url('docs/naming', True) }} diff --git a/i2p2www/spec/common-structures.rst b/i2p2www/spec/common-structures.rst new file mode 100644 index 0000000000000000000000000000000000000000..3ec8bd0f7b3a0525e107fe23f418b6604a851040 --- /dev/null +++ b/i2p2www/spec/common-structures.rst @@ -0,0 +1,1066 @@ +=============================== +Common structures Specification +=============================== +.. meta:: + :lastupdated: February 2016 + :accuratefor: 0.9.24 + +.. contents:: + + +This document describes some data types common to all I2P protocols, like +[I2NP]_, [I2CP]_, [SSU]_, etc. + + +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://{{ i2pconv('i2p-javadocs.i2p') }}/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://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/PrivateKey.html + +.. _type-SessionKey: + +SessionKey +---------- + +Description +``````````` +This structure is used for AES256 encryption and decryption. + +Contents +```````` +32 bytes + +JavaDoc: http://{{ i2pconv('i2p-javadocs.i2p') }}/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 Usage +====================== ============== ====== ===== +DSA_SHA1 128 Legacy Router Identities and Destinations +ECDSA_SHA256_P256 64 0.9.12 Recent Destinations +ECDSA_SHA384_P384 96 0.9.12 Rarely used for Destinations +ECDSA_SHA512_P521 132 0.9.12 Rarely used for Destinations +RSA_SHA256_2048 256 0.9.12 Offline signing, never used for Router Identities or Destinations +RSA_SHA384_3072 384 0.9.12 Offline signing, never used for Router Identities or Destinations +RSA_SHA512_4096 512 0.9.12 Offline signing, never used for Router Identities or Destinations +EdDSA_SHA512_Ed25519 32 0.9.15 Recent Router Identities and Destinations +EdDSA_SHA512_Ed25519ph 32 0.9.25 Offline signing, never used for Router Identities or Destinations +====================== ============== ====== ===== + +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://{{ i2pconv('i2p-javadocs.i2p') }}/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 Usage +====================== ============== ====== ===== +DSA_SHA1 20 Legacy Router Identities and Destinations +ECDSA_SHA256_P256 32 0.9.12 Recent Destinations +ECDSA_SHA384_P384 48 0.9.12 Rarely used for Destinations +ECDSA_SHA512_P521 66 0.9.12 Rarely used for Destinations +RSA_SHA256_2048 512 0.9.12 Offline signing, never used for Router Identities or Destinations +RSA_SHA384_3072 768 0.9.12 Offline signing, never used for Router Identities or Destinations +RSA_SHA512_4096 1024 0.9.12 Offline signing, never used for Router Identities or Destinations +EdDSA_SHA512_Ed25519 32 0.9.15 Recent Router Identities and Destinations +EdDSA_SHA512_Ed25519ph 32 0.9.25 Offline signing, never used for Router Identities or Destinations +====================== ============== ====== ===== + +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://{{ i2pconv('i2p-javadocs.i2p') }}/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 Usage +====================== ============== ====== ===== +DSA_SHA1 40 Legacy Router Identities and Destinations +ECDSA_SHA256_P256 64 0.9.12 Recent Destinations +ECDSA_SHA384_P384 96 0.9.12 Rarely used for Destinations +ECDSA_SHA512_P521 132 0.9.12 Rarely used for Destinations +RSA_SHA256_2048 256 0.9.12 Offline signing, never used for Router Identities or Destinations +RSA_SHA384_3072 384 0.9.12 Offline signing, never used for Router Identities or Destinations +RSA_SHA512_4096 512 0.9.12 Offline signing, never used for Router Identities or Destinations +EdDSA_SHA512_Ed25519 64 0.9.15 Recent Router Identities and Destinations +EdDSA_SHA512_Ed25519ph 64 0.9.25 Offline signing, never used for Router Identities or Destinations +====================== ============== ====== ===== + +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://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/Signature.html + +.. _type-Hash: + +Hash +---- + +Description +``````````` +Represents the SHA256 of some data. + +Contents +```````` +32 bytes + +JavaDoc: http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/Hash.html + +.. _type-SessionTag: + +Session Tag +----------- + +Description +``````````` +A random number + +Contents +```````` +32 bytes + +JavaDoc: http://{{ i2pconv('i2p-javadocs.i2p') }}/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://{{ i2pconv('i2p-javadocs.i2p') }}/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 were 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 Router Identities. + +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 Usage +====================== =========== ======================= ====== ===== +DSA_SHA1 0 128 0.9.12 Legacy Router Identities and Destinations, never explicitly set +ECDSA_SHA256_P256 1 64 0.9.12 Recent Destinations +ECDSA_SHA384_P384 2 96 0.9.12 Sometimes used for Destinations +ECDSA_SHA512_P521 3 132 0.9.12 Sometimes used for Destinations +RSA_SHA256_2048 4 256 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations +RSA_SHA384_3072 5 384 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations +RSA_SHA512_4096 6 512 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations +EdDSA_SHA512_Ed25519 7 32 0.9.15 Recent Router Identities and Destinations +EdDSA_SHA512_Ed25519ph 8 32 0.9.25 Offline only; never used in Key Certificates for Router Identities or Destinations +reserved 65280-65534 Reserved for experimental use +reserved 65535 Reserved for future expansion +====================== =========== ======================= ====== ===== + +The defined Crypto Public Key types are: + +======== =========== ======================= ===== + Type Type Code Total Public Key Length Usage +======== =========== ======================= ===== +ElGamal 0 256 All Router Identities and Destinations +reserved 65280-65534 Reserved for experimental use +reserved 65535 Reserved for future expansion +======== =========== ======================= ===== + +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 +EdDSA_SHA512_Ed25519ph 96 0 +====================== ============== =============================== + +JavaDoc: http://{{ i2pconv('i2p-javadocs.i2p') }}/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://{{ i2pconv('i2p-javadocs.i2p') }}/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://{{ i2pconv('i2p-javadocs.i2p') }}/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://{{ i2pconv('i2p-javadocs.i2p') }}/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://{{ i2pconv('i2p-javadocs.i2p') }}/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://{{ i2pconv('i2p-javadocs.i2p') }}/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://{{ i2pconv('i2p-javadocs.i2p') }}/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://{{ i2pconv('i2p-javadocs.i2p') }}/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://{{ i2pconv('i2p-javadocs.i2p') }}/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] + {{ ctags_url('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] + {{ ctags_url('TunnelMessageDeliveryInstructions') }} diff --git a/i2p2www/spec/configuration.rst b/i2p2www/spec/configuration.rst new file mode 100644 index 0000000000000000000000000000000000000000..d909b0502e491cdd00c17d145f418796ceb812d7 --- /dev/null +++ b/i2p2www/spec/configuration.rst @@ -0,0 +1,468 @@ +================================ +Configuration File Specification +================================ +.. meta:: + :lastupdated: February 2016 + :accuratefor: 0.9.25 + +.. contents:: + + +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= + + # For clients only. Alias for the private key in the keystore for the SSL + # socket. Will be autogenerated if a new key is created. + tunnel.N.option.keyAlias= + + # For clients only. Password for the private key for the SSL socket. Will be + # autogenerated if a new key is created. + tunnel.N.option.keyPassword= + + # For clients only. Path to the keystore file containing the private key for + # the SSL socket. Will be autogenerated if a new keystore is created. + # Relative to $(I2P_CONFIG_DIR)/keystore/ if not absolute. + tunnel.N.option.keystoreFile=i2ptunnel-(random string).ks + + # For clients only. Password for the keystore containing the private key for + # the SSL socket. Default is "changeit". + tunnel.N.option.keystorePassword=changeit + + # 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 + + # HTTP Servers only. Whether to reject incoming connections containing a + # referer header. Default false. Since 0.9.25. + tunnel.N.option.rejectReferer=true|false + + # HTTP Servers only. Whether to reject incoming connections containing + # specific user-agent headers. Default false. Since 0.9.25. See + # tunnel.N.option.userAgentRejectList + tunnel.N.option.rejectUserAgents=true|false + + # Servers only. Overrides targetHost and targetPort for incoming port NNNN. + tunnel.N.option.targetForPort.NNNN=hostnameOrIP:nnnn + + # HTTP Servers only. Comma-separated list of strings to match in the + # user-agent header. Since 0.9.25. Example: "Mozilla,Opera". Case-sensitive. + # See tunnel.N.option.rejectUserAgents + tunnel.N.option.userAgentRejectList=string1[,string2]* + + # Default false. For servers, use SSL for connections to local server. For + # clients, SSL is required for connections from local clients. + 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://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/DataHelper.html + +.. [Mapping] + {{ ctags_url('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/cryptography.rst b/i2p2www/spec/cryptography.rst new file mode 100644 index 0000000000000000000000000000000000000000..651b5a9d1ed8c3d0016bd349f1b378245209a5bc --- /dev/null +++ b/i2p2www/spec/cryptography.rst @@ -0,0 +1,547 @@ +==================================== +Low-level Cryptography Specification +==================================== +.. meta:: + :lastupdated: December 2014 + :accuratefor: 0.9.17 + +.. contents:: + + +Overview +======== + +This page specifies the low-level details of the cryptography in I2P. + +There are a handful of cryptographic algorithms in use within I2P, but we have +reduced them to a bare minimum to deal with our needs - one symmetric algorithm +one asymmetric algorithm, one signing algorithm, and one hashing algorithm. +However, we do combine them in some particular ways to provide message +integrity (rather than relying on a MAC). In addition, as much as we hate +doing anything new in regards to cryptography, we can't seem to find a +reference discussing (or even naming) the technique used in +ElGamal/AES+SessionTag [ELG-AES]_ (but we're sure others have done it). + + +Asymmetric encryption +===================== + +ElGamal +------- + +ElGamal is used for asymmetric encryption. ElGamal is used in several places +in I2P: + +* To encrypt router-to-router [TunnelBuild]_ messages + +* For end-to-end (destination-to-destination) encryption as a part of + ElGamal/AES+SessionTag [ELG-AES]_ using the encryption key in the [LeaseSet]_ + +* For encryption of some netDb stores and queries sent to floodfill routers + [NETDB-DELIVERY]_ as a part of ElGamal/AES+SessionTag [ELG-AES]_ + (destination-to-router or router-to-router). + +We use common primes for 2048 ElGamal encryption and decryption, as given by +IETF [RFC-3526]_. We currently only use ElGamal to encrypt the IV and session +key in a single block, followed by the AES encrypted payload using that key and +IV. + +The unencrypted ElGamal contains: + +.. raw:: html + + {% highlight lang='dataspec' %} ++----+----+----+----+----+----+----+----+ + |nonz| H(data) | + +----+ + + | | + + + + | | + + + + | | + + +----+----+----+----+----+----+----+ + | | data... + +----+----+----+-// +{% endhighlight %} + +The H(data) is the SHA256 of the data that is encrypted in the ElGamal block, +and is preceded by a nonzero byte. This byte could be random, but as +implemented it is always 0xFF. It could possibly be used for flags in the +future. The data encrypted in the block may be up to 222 bytes long. As the +encrypted data may contain a substantial number of zeros if the cleartext is +smaller than 222 bytes, it is recommended that higher layers pad the cleartext +to 222 bytes with random data. Total length: typically 255 bytes. + +The encrypted ElGamal contains: + +.. raw:: html + + {% highlight lang='dataspec' %} ++----+----+----+----+----+----+----+----+ + | zero padding... | | + +----+----+----+-//-+----+ + + | | + + + + | ElG encrypted part 1 | + ~ ~ + | | + + +----+----+----+----+----+----+----+ + | | zero padding... | | + +----+----+----+----+-//-+----+ + + | | + + + + | ElG encrypted part 2 | + ~ ~ + | | + + +----+----+----+----+----+----+ + | + + +----+----+ +{% endhighlight %} + +Each encrypted part is prepended with zeros to a size of exactly 257 bytes. +Total length: 514 bytes. In typical usage, higher layers pad the cleartext +data to 222 bytes, resulting in an unencrypted block of 255 bytes. This is +encoded as two 256-byte encrypted parts, and there is a single byte of zero +padding before each part at this layer. + +See the ElGamal code [ElGamalEngine]_. + +The shared prime is the Oakley prime for 2048 bit keys [RFC-3526-S3]_:: + + 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } + +or as a hexadecimal value:: + + FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 + 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD + EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 + E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED + EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D + C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F + 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D + 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B + E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 + DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 + 15728E5A 8AACAA68 FFFFFFFF FFFFFFFF + +Using 2 as the generator. + +.. _exponent: + +Short Exponent +`````````````` +While the standard exponent size is 2048 bits (256 bytes) and the I2P +[PrivateKey]_ is a full 256 bytes, in some cases we use the short exponent size +of 226 bits (28.25 bytes). This should be safe for use with the Oakley primes +[vanOorschot1996]_ [BENCHMARKS]_. + +Also, [Koshiba2004]_ apparently supports this, according to this sci.crypt +thread [SCI.CRYPT]_. The remainder of the PrivateKey is padded with zeroes. + +Prior to release 0.9.8, all routers used the short exponent. As of release +0.9.8, 64-bit x86 routers use a full 2048-bit exponent. Other routers continue +to use the short exponent due to concerns about processor load. The transition +to a longer exponent for these platforms is a topic for further study. + +Obsolescence +```````````` +The vulnerability of the network to an ElGamal attack and the impact of +transitioning to a longer bit length is to be studied. It may be quite +difficult to make any change backward-compatible. + + +Symmetric encryption +==================== + +AES +--- + +AES is used for symmetric encryption, in several cases: + +* For transport encryption (see section "`Transports`_") after DH key exchange + +* For end-to-end (destination-to-destination) encryption as a part of + ElGamal/AES+SessionTag [ELG-AES]_ + +* For encryption of some netDb stores and queries sent to floodfill routers + [NETDB-DELIVERY]_ as a part of ElGamal/AES+SessionTag [ELG-AES]_ + (destination-to-router or router-to-router). + +* For encryption of periodic tunnel test messages [TUNNEL-TESTING]_ sent from + the router to itself, through its own tunnels. + +We use AES with 256 bit keys and 128 bit blocks in CBC mode. The padding used +is specified in IETF [RFC-2313]_ (PKCS#5 1.5, section 8.1 (for block type 02)). +In this case, padding exists of pseudorandomly generated octets to match 16 +byte blocks. Specifically, see the CBC code [CryptixAESEngine]_ and the +Cryptix AES implementation [CryptixRijndael_Algorithm]_, as well as the +padding, found in the ElGamalAESEngine.getPadding function [ElGamalAESEngine]_. + +.. Believe it or not, we don't do this any more. If we ever did. safeEncode() and safeDecode() are unused. + +.. In all cases, we know the size of the data to be sent, and we AES encrypt the following: + +.. .. raw:: html + +.. % highlight lang='dataspec' %} +.. +----+----+----+----+----+----+----+----+ + | H(data) | + + + + | | + + + + | | + + + + | | + +----+----+----+----+----+----+----+----+ + | size | data ... | + +----+----+----+----+ + + | | + ~ ~ + | | + + + + | | + + +----//---+----+ + | | | + +----+----+----//---+----+ + + | Padding to 16 bytes | + +----+----+----+----+----+----+----+----+ + +.. H(data) :: 32-byte SHA-256 `Hash` of the data + +.. . size :: 4-byte `Integer`, number of data bytes to follow + +.. . data :: payload + +.. . padding :: random data, to a multiple of 16 bytes +.. % endhighlight %} + +.. After the data comes an application-specified number of randomly generated + padding bytes. This application-specified number is rounded up to a multiple + of 16. The entire segment (from H(data) through the end of the random bytes) + is AES encrypted (256 bit CBC w/ PKCS#5). + +.. This code is implemented in the safeEncrypt and safeDecrypt methods of + AESEngine but it is unused. + + +Obsolescence +```````````` +The vulnerability of the network to an AES attack and the impact of +transitioning to a longer bit length is to be studied. It may be quite +difficult to make any change backward-compatible. + +References +`````````` +* [STATUS-AES]_ + + +.. _sig: + +Signatures +========== + +DSA is the default signature algorithm, but we are in the process of migrating +to more secure algorithms. See below. + +DSA +--- + +Signatures are generated and verified with 1024 bit [DSA]_ (L=1024, N=160), as +implemented in [DSAEngine]_. DSA was chosen because it is much faster for +signatures than ElGamal. + +SEED +```` +160 bit:: + + 86108236b8526e296e923a4015b4282845b572cc + +Counter +``````` +:: + + 33 + +DSA prime (p) +````````````` +1024 bit:: + + 9C05B2AA 960D9B97 B8931963 C9CC9E8C 3026E9B8 ED92FAD0 + A69CC886 D5BF8015 FCADAE31 A0AD18FA B3F01B00 A358DE23 + 7655C496 4AFAA2B3 37E96AD3 16B9FB1C C564B5AE C5B69A9F + F6C3E454 8707FEF8 503D91DD 8602E867 E6D35D22 35C1869C + E2479C3B 9D5401DE 04E0727F B33D6511 285D4CF2 9538D9E3 + B6051F5B 22CC1C93 + +DSA quotient (q) +```````````````` +:: + + A5DFC28F EF4CA1E2 86744CD8 EED9D29D 684046B7 + +DSA generator (g) +````````````````` +1024 bit:: + + 0C1F4D27 D40093B4 29E962D7 223824E0 BBC47E7C 832A3923 + 6FC683AF 84889581 075FF908 2ED32353 D4374D73 01CDA1D2 + 3C431F46 98599DDA 02451824 FF369752 593647CC 3DDC197D + E985E43D 136CDCFC 6BD5409C D2F45082 1142A5E6 F8EB1C3A + B5D0484B 8129FCF1 7BCE4F7F 33321C3C B3DBB14A 905E7B2B + 3E93BE47 08CBCC82 + +The [SigningPublicKey]_ is 1024 bits. The [SigningPrivateKey]_ is 160 bits. + +Obsolescence +```````````` +[NIST-800-57]_ recommends a minimum of (L=2048, N=224) for usage beyond 2010. +This may be mitigated somewhat by the "cryptoperiod", or lifespan of a given +key. + +The prime number was chosen in 2003 [CHOOSING-CONSTANTS]_, and the person that +chose the number (TheCrypto) is currently no longer an I2P developer. As such, +we do not know if the prime chosen is a 'strong prime'. If a larger prime is +chosen for future purposes, this should be a strong prime, and we will document +the construction process. + +References +`````````` +* [MEETING-51]_ +* [MEETING-52]_ + + +New Signature Algorithms +======================== + +As of release 0.9.12, the router supports additional signature algorithms that +are more secure than 1024-bit DSA. The first usage is for Destinations; +support for Router Identities was added in release 0.9.16. Support for +migrating existing Destinations from old to new signatures will be added in a +future release. Signature type is encoded in the Destination and Router +Identity, so that new signature algorithms or curves may be added at any time. +The current supported signature types are as follows: + +* DSA-SHA1 +* ECDSA-SHA256-P256 +* ECDSA-SHA384-P384 +* ECDSA-SHA512-P521 +* RSA-SHA256-2048 +* RSA-SHA384-3072 +* RSA-SHA512-4096 +* EdDSA-SHA512-Ed25519 (as of release 0.9.15) + +ECDSA +----- + +ECDSA uses the standard NIST curves and standard SHA-2 hashes. + +We will migrate new destinations to ECDSA-SHA256-P256 in the 0.9.16 - 0.9.19 +release time frame. Usage for Router Identities is supported as of release +0.9.16 and migration may occur in early 2015. + +RSA +--- + +Standard RSA PKCS#1 v1.5 (RFC 2313) with the public exponent F4 = 65537. + +RSA is now used for signing all out-of-band trusted content, including router +updates, reseeding, plugins, and news. The signatures are embedded in the +"su3" format [UPDATES]_. 4096-bit keys are recommended and used by all known +signers. RSA is not used, or planned for use, in any in-network Destinations +or Router Identities. + +EdDSA 25519 +----------- + +Standard EdDSA using curve 25519 and standard 512-bit SHA-2 hashes. + +Supported as of release 0.9.15. + +Migration for Destinations and Router Identities is scheduled for mid-2015. + + +Hashes +====== + +SHA256 +------ + +Hashes within I2P are plain old SHA256, as implemented in [SHA256Generator]_. + +Obsolescence +```````````` +The vulnerability of the network to a SHA-256 attack and the impact of +transitioning to a longer hash is to be studied. It may be quite difficult to +make any change backward-compatible. + +References +`````````` +* [SHA-2]_ + + +Transports +========== + +At the lowest protocol layer, point-to-point inter-router communication is +protected by the transport layer security. Both transports use 256 byte (2048 +bit) Diffie-Hellman key exchange using the same shared prime and generator as +specified above for ElGamal_, followed by symmetric AES encryption as described +above. This provides perfect forward secrecy [PFS]_ on the transport links. + +.. _tcp: + +NTCP connections +---------------- + +NTCP connections are negotiated with a 2048 Diffie-Hellman implementation, +using the router's identity to proceed with a station to station agreement, +followed by some encrypted protocol specific fields, with all subsequent data +encrypted with AES (as above). The primary reason to do the DH negotiation +instead of using ElGamalAES+SessionTag [ELG-AES]_ is that it provides +'(perfect) forward secrecy' [PFS]_, while ElGamalAES+SessionTag does not. + +In order to migrate to a more standardized implementation (TLS/SSL or even +SSH), the following issues must be addressed: + +1. Can we somehow reestablish sessions securely (ala session tags) or do we + need to do full negotiation each time? + +2. Can we simplify/avoid the x509 or other certificate formats and use our own + RouterInfo structure (which contains the ElGamal and DSA keys)? + +See the NTCP specification [NTCP]_ for details. + +.. _udp: + +UDP connections +--------------- + +SSU (the UDP transport) encrypts each packet with AES256/CBC with both an +explicit IV and MAC (HMAC-MD5-128) after agreeing upon an ephemeral session key +through a 2048 bit Diffie-Hellman exchange, station-to-station authentication +with the other router's DSA key, plus each network message has their own hash +for local integrity checking. + +See the SSU specification [SSU-KEYS]_ for details. + +WARNING - I2P's HMAC-MD5-128 used in SSU is apparently non-standard. +Apparently, an early version of SSU used HMAC-SHA256, and then it was switched +to MD5-128 for performance reasons, but left the 32-byte buffer size intact. +See HMACGenerator.java and the 2005-07-05 status notes [STATUS-HMAC]_ for +details. + + +References +========== + +.. [BENCHMARKS] + {{ site_url('misc/benchmarks', True) }} + + Crypto++ benchmarks, originally at http://www.eskimo.com/~weidai/benchmarks.html (now dead), + rescued from http://www.archive.org/, dated Apr 23, 2008. + +.. [CHOOSING-CONSTANTS] + http://article.gmane.org/gmane.comp.security.invisiblenet.iip.devel/343 + +.. [CryptixAESEngine] + https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/CryptixAESEngine.java + +.. [CryptixRijndael_Algorithm] + https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/CryptixRijndael_Algorithm.java + +.. [DSA] + http://en.wikipedia.org/wiki/Digital_Signature_Algorithm + +.. [DSAEngine] + https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/DSAEngine.java + +.. [ELG-AES] + {{ site_url('docs/how/elgamal-aes') }} + +.. [ElGamalEngine] + https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/ElGamalEngine.java + +.. [ElGamalAESEngine] + https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/ElGamalAESEngine.java + +.. [Koshiba2004] + Koshiba & Kurosawa. Short Exponent Diffie-Hellman Problems. PKC 2004, LNCS 2947, pp. 173-186 + + http://www.springerlink.com/content/2jry7cftp5bpdghm/ + + Full text: http://books.google.com/books?id=cXyiNZ2_Pa0C&lpg=PA173&ots=PNIz3dWe4g&pg=PA173#v=onepage&q&f=false + +.. [LeaseSet] + {{ ctags_url('LeaseSet') }} + +.. [MEETING-51] + {{ get_url('meetings_show', id=51) }} + +.. [MEETING-52] + {{ get_url('meetings_show', id=52) }} + +.. [NETDB-DELIVERY] + {{ site_url('docs/how/network-database', True) }}#delivery + +.. [NIST-800-57] + http://csrc.nist.gov/publications/nistpubs/800-57/sp800-57-Part1-revised2_Mar08-2007.pdf + +.. [NTCP] + {{ site_url('docs/transport/ntcp', True) }} + +.. [PFS] + http://en.wikipedia.org/wiki/Perfect_forward_secrecy + +.. [PrivateKey] + {{ ctags_url('PrivateKey') }} + +.. [RFC-2313] + http://tools.ietf.org/html/rfc2313 + +.. [RFC-3526] + http://tools.ietf.org/html/rfc3526 + +.. [RFC-3526-S3] + http://tools.ietf.org/html/rfc3526#section-3 + +.. [SCI.CRYPT] + http://groups.google.com/group/sci.crypt/browse_thread/thread/1855a5efa7416677/339fa2f945cc9ba0#339fa2f945cc9ba0 + +.. [SHA-2] + https://en.wikipedia.org/wiki/SHA-2 + +.. [SHA256Generator] + https://github.com/i2p/i2p.i2p/tree/master/core/java/src/net/i2p/crypto/SHA256Generator.java + +.. [SigningPrivateKey] + {{ ctags_url('SigningPrivateKey') }} + +.. [SigningPublicKey] + {{ ctags_url('SigningPublicKey') }} + +.. [SSU-KEYS] + {{ site_url('docs/transport/ssu', True) }}#keys + +.. [STATUS-AES] + Feb. 7, 2006 Status Notes + + {{ get_url('blog_post', slug='2006/02/07/status') }} + +.. [STATUS-HMAC] + Jul. 5, 2005 Status Notes + + {{ get_url('blog_post', slug='2005/07/05/status') }} + +.. [TunnelBuild] + {{ ctags_url('TunnelBuild') }} + +.. [TUNNEL-TESTING] + {{ site_url('docs/how/tunnel-routing', True) }}#testing + +.. [UPDATES] + {{ spec_url('updates') }} + +.. [vanOorschot1996] + van Oorschot, Weiner. On Diffie-Hellman Key Agreement with Short Exponents. EuroCrypt '96 + + http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.14.5952&rep=rep1&type=pdf diff --git a/i2p2www/spec/datagrams.rst b/i2p2www/spec/datagrams.rst new file mode 100644 index 0000000000000000000000000000000000000000..6cd2045d4369200c43f8946d641cb3fd09b6ad87 --- /dev/null +++ b/i2p2www/spec/datagrams.rst @@ -0,0 +1,130 @@ +====================== +Datagram Specification +====================== +.. meta:: + :lastupdated: July 2014 + :accuratefor: 0.9.14 + +.. contents:: + + +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] + {{ spec_url('tunnel-message') }}#notes diff --git a/i2p2www/spec/geoip.rst b/i2p2www/spec/geoip.rst new file mode 100644 index 0000000000000000000000000000000000000000..0f84e680cae3403c187322126ddbaaca88d44f87 --- /dev/null +++ b/i2p2www/spec/geoip.rst @@ -0,0 +1,86 @@ +======================== +GeoIP File Specification +======================== +.. meta:: + :lastupdated: December 2013 + :accuratefor: 0.9.9 + +.. contents:: + + +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.rst b/i2p2www/spec/i2cp.rst new file mode 100644 index 0000000000000000000000000000000000000000..d01eea659294f6664c39fa28ae691268509d560c --- /dev/null +++ b/i2p2www/spec/i2cp.rst @@ -0,0 +1,1385 @@ +================== +I2CP Specification +================== +.. meta:: + :lastupdated: June 2015 + :accuratefor: 0.9.21 + +.. contents:: + + +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<br> + 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 +<a href="{{ site_url('docs/protocol/i2cp') }}#options">I2CP Overview page</a>. + +* 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] + {{ ctags_url('Date') }} + +.. [Destination] + {{ ctags_url('Destination') }} + +.. [Hash] + {{ ctags_url('Hash') }} + +.. [I2CP] + {{ site_url('docs/protocol/i2cp', True) }} + +.. [I2CP-FORMAT] + {{ site_url('docs/protocol/i2cp', True) }}#format + +.. [I2CP-JAVADOCS] + http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/i2cp/package-summary.html + +.. [Integer] + {{ ctags_url('Integer') }} + +.. [Leases] +.. [Lease] + {{ ctags_url('Lease') }} + +.. [LeaseSet] + {{ ctags_url('LeaseSet') }} + +.. [Mapping] + {{ ctags_url('Mapping') }} + +.. [MSM-JAVADOCS] + http://{{ i2pconv('i2p-javadocs.i2p') }}/net/i2p/data/i2cp/MessageStatusMessage.html + +.. [PrivateKey] + {{ ctags_url('PrivateKey') }} + +.. [PublicKey] + {{ ctags_url('PublicKey') }} + +.. [RouterIdentity] + {{ ctags_url('RouterIdentity') }} + +.. [Signature] + {{ ctags_url('Signature') }} + +.. [SigningPrivateKey] + {{ ctags_url('SigningPrivateKey') }} + +.. [SigningPublicKey] + {{ ctags_url('SigningPublicKey') }} + +.. [String] + {{ ctags_url('String') }} + +.. [TunnelId] + {{ ctags_url('TunnelId') }} diff --git a/i2p2www/spec/i2np.rst b/i2p2www/spec/i2np.rst new file mode 100644 index 0000000000000000000000000000000000000000..023a5e68f7297e9f8128fd37670105b52a6925e8 --- /dev/null +++ b/i2p2www/spec/i2np.rst @@ -0,0 +1,1309 @@ +================== +I2NP Specification +================== +.. meta:: + :lastupdated: January 2016 + :accuratefor: 0.9.24 + +.. contents:: + + +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. + +* The short expiration is unsigned and will wrap around on Feb. 7, 2106. As of + that date, an offset must be added to get the correct time. + +.. _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 +Reserved for experimental messages 224-254 +Reserved for future expansion 255 +================================== ======= + +.. _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 %} + +Notes +````` +* This message contains no routing information and will never be sent + "unwrapped". It is only used inside `Garlic` messages. + +.. _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. + +* While this message is rarely seen in today's network, having been replaced by + the `VariableTunnelBuild` message, it may still be used for very long tunnels, + and has not been deprecated. Routers must implement. + +.. _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. + +* While this message is rarely seen in today's network, having been replaced by + the `VariableTunnelBuildReply` message, it may still be used for very long + tunnels, and has not been deprecated. Routers must implement. + +.. _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. + +* Typical number of records in today's network is 5. + +.. _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. + +* Typical number of records in today's network is 5. + + +References +========== + +.. [CRYPTO-ELG] + {{ site_url('docs/how/cryptography', True) }}#elgamal + +.. [Date] + {{ ctags_url('Date') }} + +.. [ElG-AES] + {{ site_url('docs/how/elgamal-aes', True) }} + +.. [GARLIC] + {{ site_url('docs/how/garlic-routing', True) }} + +.. [Hash] + {{ ctags_url('Hash') }} + +.. [I2NP] + {{ site_url('docs/protocol/i2np', True) }} + +.. [Integer] + {{ ctags_url('Integer') }} + +.. [RouterIdentity] + {{ ctags_url('RouterIdentity') }} + +.. [SSU] + {{ site_url('docs/transport/ssu', True) }} + +.. [SSU-ED] + {{ site_url('docs/transport/ssu', True) }}#establishDirect + +.. [TMDI] + {{ ctags_url('TunnelMessageDeliveryInstructions') }} + +.. [TUNNEL-CREATION] + {{ spec_url('tunnel-creation') }} + +.. [TUNNEL-MSG] + {{ spec_url('tunnel-message') }} + +.. [TUNNEL-IMPL] + {{ site_url('docs/tunnels/implementation', True) }} + +.. [TunnelId] + {{ ctags_url('TunnelId') }} diff --git a/i2p2www/spec/plugin.rst b/i2p2www/spec/plugin.rst new file mode 100644 index 0000000000000000000000000000000000000000..2a0295892489939ff7cb740d19f1b32f48d49dff --- /dev/null +++ b/i2p2www/spec/plugin.rst @@ -0,0 +1,691 @@ +==================== +Plugin Specification +==================== +.. meta:: + :lastupdated: February 2016 + :accuratefor: 0.9.25 + +.. contents:: + + +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 properties 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. + + icon-code + supported as of 0.9.25 + + Provides a console icon for plugins without web resources. + + A B64 string produced by calling `net.i2p.data.Base64 encode FILE` on a + 32x32 png image file. + +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: + +===================== ============================ ===== + Jar Contains Usage +===================== ============================ ===== +commons-logging.jar Apache Logging For plugins requiring Apache logging. + Prior to Jetty 6 (release 0.9), this + contained Apache Commons Logging only. + From release 0.9 to release 0.9.23, this + contained both Commons Logging and Tomcat JULI. + As of release 0.9.24, this contains + Apache Tomcat JULI logging only. + +commons-el.jar JSP Expressions Language For plugins with JSPs that use EL +i2p.jar Core API Almost all plugins will need +i2ptunnel.jar I2PTunnel For plugins with HTTP or other servers +jasper-compiler.jar nothing Empty since Jetty 6 (release 0.9) +jasper-runtime.jar Jasper Compiler and Runtime, Needed for plugins with JSPs + and some Tomcat utils +javax.servlet.jar Servlet API Needed for plugins with JSPs +jbigi.jar Binaries No plugin should need +mstreaming.jar Streaming API Almost all plugins will need +org.mortbay.jetty.jar Jetty Base Only plugins starting their own Jetty instance + will need. Recommended way of starting Jetty + is with net.i2p.jetty.JettyStart in jetty-i2p.jar. +router.jar Router Only plugins using router context will need; most will not +sam.jar SAM API No plugin should need +streaming.jar Streaming Implementation Almost all plugins will need +systray.jar URL Launcher Most plugins should not need +systray4j.jar Systray No plugin should need +wrapper.jar Router Most plugins should not need +===================== ============================ ===== + +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: + +============ =============== ===== + Jar Contains Usage +============ =============== ===== +jstl.jar Standard Taglib For plugins using JSP tags +standard.jar Standard Taglib For plugins using JSP tags +============ =============== ===== + +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 +================== + +I2P has required Java 7 since release 0.9.24 (January 2016). +I2P has required Java 6 since release 0.9.12 (April 2014). +Any I2P users on the latest release should be running a 1.7 (7.0) JVM. +In early 2016, unless you require 1.7 language or library features, you should +create your plugin so it works on 1.6. Later in the year, most of the network +will be on 0.9.24 or higher with Java 7. + +If your plugin **does not require 1.7**: + +* Ensure that all java and jsp files are compiled with source="1.6" + target="1.6". + +* Ensure that all bundled library jars are also for 1.6 or lower. + +If your plugin **requires 1.7**: + +* Note that on your download page. + +* Add min-java-version=1.7 to your plugin.config + +In any case, you **must** set a bootclasspath when compiling with Java 8 to +prevent runtime crashes. + + +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/spectags b/i2p2www/spec/spectags new file mode 100644 index 0000000000000000000000000000000000000000..f1c30bc2191f26988e82b3f54c4ba2c35f57a4fc --- /dev/null +++ b/i2p2www/spec/spectags @@ -0,0 +1,76 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ +!_TAG_PROGRAM_NAME Exuberant Ctags // +!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ +!_TAG_PROGRAM_VERSION 5.9~svn20110310 // +BandwidthLimits i2cp.rst 441;" m +Boolean common-structures.rst 110;" t +BuildRequestRecord i2np.rst 175;" s +BuildResponseRecord i2np.rst 349;" s +Certificate common-structures.rst 340;" t +CreateLeaseSet i2cp.rst 469;" m +CreateSession i2cp.rst 503;" m +Data i2np.rst 1098;" m +DatabaseLookup i2np.rst 653;" m +DatabaseSearchReply i2np.rst 808;" m +DatabaseStore i2np.rst 552;" m +Date common-structures.rst 80;" t +DeliveryInstructions common-structures.rst 1070;" s +DeliveryStatus i2np.rst 882;" m +DestLookup i2cp.rst 535;" m +DestReply i2cp.rst 557;" m +Destination common-structures.rst 680;" s +DestroySession i2cp.rst 580;" m +Disconnect i2cp.rst 599;" m +Garlic i2np.rst 925;" m +GarlicClove i2np.rst 394;" s +GarlicCloveDeliveryInstructions i2np.rst 456;" s +GetBandwidthLimits i2cp.rst 619;" m +GetDate i2cp.rst 642;" m +Hash common-structures.rst 293;" t +HostLookup i2cp.rst 675;" m +HostReply i2cp.rst 715;" m +I2CPMessageHeader i2cp.rst 299;" s +I2NPMessageHeader i2np.rst 93;" s +Integer common-structures.rst 67;" t +KeysAndCert common-structures.rst 580;" s +Lease common-structures.rst 713;" s +LeaseSet common-structures.rst 761;" s +Mapping common-structures.rst 502;" t +MessageId i2cp.rst 319;" s +MessagePayload i2cp.rst 740;" m +MessageStatus i2cp.rst 761;" m +Payload i2cp.rst 338;" s +PrivateKey common-structures.rst 145;" t +PublicKey common-structures.rst 128;" t +ReceiveMessageBegin i2cp.rst 903;" m +ReceiveMessageEnd i2cp.rst 929;" m +ReconfigureSession i2cp.rst 954;" m +ReportAbuse i2cp.rst 984;" m +RequestLeaseSet i2cp.rst 1012;" m +RequestVariableLeaseSet i2cp.rst 1040;" m +RouterAddress common-structures.rst 897;" s +RouterIdentity common-structures.rst 651;" s +RouterInfo common-structures.rst 969;" s +SendMessage i2cp.rst 1066;" m +SendMessageExpires i2cp.rst 1109;" m +SessionConfig i2cp.rst 358;" s +SessionId i2cp.rst 385;" s +SessionKey common-structures.rst 162;" t +SessionStatus i2cp.rst 1252;" m +SessionTag common-structures.rst 308;" t +SetDate i2cp.rst 1297;" m +Signature common-structures.rst 254;" t +SigningPrivateKey common-structures.rst 216;" t +SigningPublicKey common-structures.rst 177;" t +String common-structures.rst 94;" t +Tunnel tunnel-message.rst 33;" m +TunnelBuild i2np.rst 1127;" m +TunnelBuildReply i2np.rst 1162;" m +TunnelData i2np.rst 1020;" m +TunnelGateway i2np.rst 1063;" m +TunnelId common-structures.rst 323;" t +TunnelMessageDeliveryInstructions tunnel-message.rst 161;" s +VariableTunnelBuild i2np.rst 1180;" m +VariableTunnelBuildReply i2np.rst 1213;" m diff --git a/i2p2www/spec/ssu.rst b/i2p2www/spec/ssu.rst new file mode 100644 index 0000000000000000000000000000000000000000..83d04b91d5cdce4702119afc0604a1e6377e2370 --- /dev/null +++ b/i2p2www/spec/ssu.rst @@ -0,0 +1,1199 @@ +========================== +SSU Protocol Specification +========================== +.. meta:: + :lastupdated: November 2015 + :accuratefor: 0.9.24 + +.. contents:: + + +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 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 %} + +The flag byte contains the following bitfields: + +.. raw:: html + + {% highlight %} + Bit order: 76543210 (bit 7 is MSB) + + bits 7-4: payload type + bit 3: If 1, rekey data is included. Always 0, unimplemented + bit 2: If 1, extended options are included. Always 0 before release + 0.9.24. + bits 1-0: reserved, set to 0 for compatibility with future uses +{% endhighlight %} + +Without rekeying and extended options, the header size is 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. Extended options have always been +part of the specification, but were unimplemented until release 0.9.24. When +present, the option format is specific to the message type. See message +documentation below on whether extended options are expected for the given +message, and the specified format. While Java routers have always recognized the +flag and options length, other implementations have not. Therefore, do not send +extended options to routers older than release 0.9.24. + + +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 4-byte unsigned integer timestamps with one-second resolution. Because +these values are unsigned, they will not roll over until February 2106. + + +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) + +Extended options +```````````````` +*Note: This is a proposal, to be implemented in 0.9.24. Subject to change.* + +* Minimum length: 3 (option length byte + 2 bytes) + +* Option length: 2 minimum + +* 2 bytes flags: + +.. raw:: html + + {% highlight %} + Bit order: 15...76543210 (bit 15 is MSB) + + bit 0: 1 for Alice to request a relay tag from Bob in the + `SessionCreated` response, 0 if Alice does not need a relay tag. + Note that "1" is the default if no extended options are present + bits 15-1: unused, set to 0 for compatibility with future uses +{% endhighlight %} + +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. + +* Extended options in the header: Not expected, undefined. + +.. _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. + +* Extended options in the header: Not expected, undefined. + +.. _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. + +* Extended options in the header: Not expected, undefined. + + +.. _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. + + * Prior to release 0.9.24, Java I2P rejected any address or port that was + different from the connection. + +* 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. + +* Extended options in the header: Not expected, undefined. + +.. _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. + +* Extended options in the header: Not expected, undefined. + +.. _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 + +* Extended options in the header: Not expected, undefined. + +.. _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. + +* Extended options in the header: Not expected, undefined. + +.. _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. + +* Extended options in the header: Not expected, undefined. + +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] + {{ ctags_url('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] + {{ ctags_url('RouterIdentity') }} + +.. [SESSIONKEY] + {{ ctags_url('SessionKey') }} + +.. [Signature] + {{ ctags_url('Signature') }} + +.. [SigningPrivateKey] + {{ ctags_url('SigningPrivateKey') }} + +.. [SigningPublicKey] + {{ ctags_url('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.rst b/i2p2www/spec/streaming.rst new file mode 100644 index 0000000000000000000000000000000000000000..77b82ab5d9ebcd7a22cf4cba6f6e9d4cec6f708b --- /dev/null +++ b/i2p2www/spec/streaming.rst @@ -0,0 +1,193 @@ +=============================== +Streaming Library Specification +=============================== +.. meta:: + :lastupdated: June 2015 + :accuratefor: 0.9.20 + +.. contents:: + + +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] + {{ ctags_url('Destination') }} + +.. [Integer] + {{ ctags_url('Integer') }} + +.. [Signature] + {{ ctags_url('Signature') }} + +.. [SigningPrivateKey] + {{ ctags_url('SigningPrivateKey') }} + +.. [STREAMING] + {{ site_url('docs/api/streaming', True) }} diff --git a/i2p2www/spec/tunnel-creation.rst b/i2p2www/spec/tunnel-creation.rst new file mode 100644 index 0000000000000000000000000000000000000000..7ba79c1ae5fb5e3a256d976799694835e125a65b --- /dev/null +++ b/i2p2www/spec/tunnel-creation.rst @@ -0,0 +1,365 @@ +============================= +Tunnel Creation Specification +============================= +.. meta:: + :lastupdated: January 2016 + :accuratefor: 0.9.24 + +.. contents:: + + +.. _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. Records that are not stamped with +the current hour, or the previous hour if shortly after the top of the hour, +must be dropped. For example, take the hour in the timestamp, convert to a full +time, then if it's more than 65 minutes behind or 5 minutes ahead of the current +time, it is invalid. The Bloom filter must have a duration of at least one hour +(plus a few minutes, to allow for clock skew), so that duplicate records in the +current hour that are not rejected by checking the hour timestamp in the record, +will be rejected by the filter. + +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. + +* 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] + {{ ctags_url('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] + {{ ctags_url('TunnelBuild') }} + +.. [TBRM] + {{ ctags_url('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] + {{ ctags_url('VariableTunnelBuild') }} + +.. [VTBRM] + {{ ctags_url('VariableTunnelBuildReply') }} diff --git a/i2p2www/spec/tunnel-message.rst b/i2p2www/spec/tunnel-message.rst new file mode 100644 index 0000000000000000000000000000000000000000..c53d3345ce450b661dfb5d779af855583cad5ed3 --- /dev/null +++ b/i2p2www/spec/tunnel-message.rst @@ -0,0 +1,353 @@ +============================ +Tunnel Message Specification +============================ +.. meta:: + :lastupdated: February 2014 + :accuratefor: 0.9.11 + +.. contents:: + + +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://{{ i2pconv('i2p-javadocs.i2p') }}/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] + {{ ctags_url('GarlicClove') }} + +.. [I2NP-GCDI] + {{ ctags_url('GarlicCloveDeliveryInstructions') }} + +.. [TUNNEL-IMPL] + {{ site_url('docs/tunnels/implementation', True) }} diff --git a/i2p2www/spec/updates.rst b/i2p2www/spec/updates.rst new file mode 100644 index 0000000000000000000000000000000000000000..5fb3c4527646c15528dc8ce0c3c3e134c1845ea0 --- /dev/null +++ b/i2p2www/spec/updates.rst @@ -0,0 +1,563 @@ +============================= +Software Update Specification +============================= +.. meta:: + :lastupdated: May 2015 + :accuratefor: 0.9.20 + +.. contents:: + + +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:: + + <i2p.news date="$Date: 2010-01-22 00:00:00 $" /> + <i2p.release version="0.7.14" date="2010/01/22" minVersion="0.6" /> + +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 <feed> Details:** + +The following <feed> elements are used: + + <entry> + A news item. See below. + + <i2p:release> + I2P update metadata. See below. + + <updated> + Required + + Timestamp for the feed (conforming to [RFC-4287]_ (Atom) section 3.3 and + [RFC-3339]_. + +**Atom <entry> Details:** + +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> + 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. + + <link> + Optional + + Link for further information + + <summary> + Optional + + Short summary, suitable for a tooltip + + <title> + Required + + Title of the news entry + + <updated> + Required + + Timestamp for this entry (conforming to [RFC-4287]_ (Atom) section 3.3 + and [RFC-3339]_). + +**Atom <i2p:release> Details:** + +There must be at least one <i2p:release> 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. + + <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 + + +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] + {{ ctags_url('Signature') }} + +.. [SigningPublicKey] + {{ ctags_url('SigningPublicKey') }} diff --git a/i2p2www/spec/views.py b/i2p2www/spec/views.py new file mode 100644 index 0000000000000000000000000000000000000000..3d4393db8d063e2da3b1625267dff8c5495380fa --- /dev/null +++ b/i2p2www/spec/views.py @@ -0,0 +1,109 @@ +import codecs +from docutils.core import ( + publish_doctree, + publish_from_doctree, + publish_parts, +) +from flask import ( + abort, + g, + make_response, + redirect, + render_template, + render_template_string, + request, + safe_join, + url_for, +) +import os.path + +from i2p2www import PROPOSAL_DIR, SPEC_DIR +from i2p2www import helpers + + +SPEC_METATAGS = { + 'accuratefor': None, + 'lastupdated': None, + } + +SPEC_LIST_METATAGS = [ + ] + + +def spec_index(): + specs = [] + for f in os.listdir(SPEC_DIR): + if f.endswith('.rst'): + path = safe_join(SPEC_DIR, f) + # read file header + header = '' + with codecs.open(path, encoding='utf-8') as fd: + for line in fd: + header += line + if not line.strip(): + break + parts = publish_parts(source=header, source_path=SPEC_DIR, writer_name="html") + meta = get_metadata_from_meta(parts['meta']) + + spec = { + 'name': f[:-4], + 'title': parts['title'], + } + spec.update(meta) + specs.append(spec) + + specs.sort(key=lambda s: s['name']) + return render_template('spec/index.html', specs=specs) + +def spec_show(name, txt=False): + # check if that file actually exists + path = safe_join(SPEC_DIR, name + '.rst') + if not os.path.exists(path): + abort(404) + + # read file + with codecs.open(path, encoding='utf-8') as fd: + content = fd.read() + + if txt: + # Strip out RST + content = content.replace('.. meta::\n', '') + content = content.replace('.. contents::\n\n', '') + content = content.replace('.. raw:: html\n\n', '') + content = content.replace('\n.. [', '\n[') + content = content.replace(']_.', '].') + content = content.replace(']_', '] ') + # Change highlight formatter + content = content.replace('{% highlight', "{% highlight formatter='textspec'") + + # render the post with Jinja2 to handle URLs etc. + rendered_content = render_template_string(content) + rendered_content = rendered_content.replace('</pre></div>', ' </pre></div>') + + if txt: + # Send response + r = make_response(rendered_content) + r.mimetype = 'text/plain' + return r + + # Render the ToC + doctree = publish_doctree(source=rendered_content) + bullet_list = doctree[1][1] + doctree.clear() + doctree.append(bullet_list) + toc = publish_from_doctree(doctree, writer_name='html') + + # Remove the ToC from the main document + rendered_content = rendered_content.replace('.. contents::\n', '') + + # publish the spec with docutils + parts = publish_parts(source=rendered_content, source_path=SPEC_DIR, writer_name="html") + meta = get_metadata_from_meta(parts['meta']) + + return render_template('spec/show.html', title=parts['title'], toc=toc, body=parts['fragment'], name=name, meta=meta) + +def spec_show_txt(name): + return spec_show(name, True) + +def get_metadata_from_meta(meta): + return helpers.get_metadata_from_meta(meta, SPEC_METATAGS, SPEC_LIST_METATAGS) diff --git a/i2p2www/static/styles/duck/default.css b/i2p2www/static/styles/duck/default.css index 49d8052bf8f7fd0d14aaa81cc4d83da158eb1db6..4d6592fbbb06639d19a3401c5b71f36ec84eebbd 100644 --- a/i2p2www/static/styles/duck/default.css +++ b/i2p2www/static/styles/duck/default.css @@ -18,6 +18,29 @@ a:hover { color: #f00e0e } +dl p.first { + margin-top: 0 !important; +} + +dt { + float: left; + clear: left; + min-width: 100px; + margin-right: 10px; + text-align: right; + font-weight: bold; + color: green; +} + +dt:after { + content: ":"; +} + +dd { + margin: 0 0 0 110px; + padding: 0 0 0.5em 0; +} + div.hide { display: none } diff --git a/i2p2www/templatevars.py b/i2p2www/templatevars.py index 975e4a9e2180f70b0c37b4a5b49ceac8683dc172..13a2693061bd47c912a56ada42d6b27cabc3654a 100644 --- a/i2p2www/templatevars.py +++ b/i2p2www/templatevars.py @@ -1,7 +1,8 @@ +import ctags from flask import g, request, safe_join, url_for import os.path -from i2p2www import CANONICAL_DOMAIN, CURRENT_I2P_VERSION, RTL_LANGS, SUPPORTED_LANGS, SUPPORTED_LANG_NAMES, STATIC_DIR, app +from i2p2www import CANONICAL_DOMAIN, CURRENT_I2P_VERSION, RTL_LANGS, SUPPORTED_LANGS, SUPPORTED_LANG_NAMES, SPEC_DIR, STATIC_DIR, app INPROXY = '.xyz' # http://zzz.i2p/topics/1771-i2p-xyz-inproxy @@ -21,15 +22,50 @@ I2P_TO_CLEAR = { @app.context_processor def utility_processor(): + _ctags = ctags.CTags(os.path.join(SPEC_DIR, 'spectags')) + kinds = { + 't': 'type', + 's': 'struct', + 'm': 'msg', + } + # Shorthand for getting a site url - def get_site_url(path=None): + def get_site_url(path=None, external=False): lang = 'en' if hasattr(g, 'lang') and g.lang: lang = g.lang if path: - return url_for('site_show', lang=lang, page=path) + return url_for('site_show', lang=lang, page=path, _external=external) + else: + return url_for('site_show', lang=lang, _external=external) + + def get_spec_url(name): + url = url_for('spec_show', name=name, _external=True) + # Remove ?lang=xx + if '?' in url: + url = url[:url.index('?')] + return url + + def get_ctags_url(value): + filename, kind = _lookup_ctag(value) + # Handle message types + if not kind and value.endswith('Message'): + value = value[:-7] + filename, kind = _lookup_ctag(value) + if kind: + specname, _ = os.path.splitext(filename) + url = get_spec_url(specname) + return '%s#%s-%s' % \ + (url, kinds[kind], value.lower()) + else: + return '' + + def _lookup_ctag(token): + entry = ctags.TagEntry() + if _ctags.find(entry, token, 0): + return entry['file'], entry['kind'] else: - return url_for('site_show', lang=lang) + return None, None # Shorthand for getting a language-specific url def get_url_with_lang(endpoint, **args): @@ -112,6 +148,8 @@ def utility_processor(): change_theme=change_theme, logo_url=get_logo_for_theme, site_url=get_site_url, + spec_url=get_spec_url, + ctags_url=get_ctags_url, get_url=get_url_with_lang, is_rtl=is_rtl_lang, get_flag=get_flag, diff --git a/i2p2www/urls.py b/i2p2www/urls.py index 33fa42184117cd16f5aeaf780de41babb3a1924d..63faa463b6ed7b08fe240f65ba2b4ad00b791f91 100644 --- a/i2p2www/urls.py +++ b/i2p2www/urls.py @@ -44,6 +44,10 @@ url('/', 'views.main_index') url('/<lang:lang>/', 'views.site_show', defaults={'page': 'index'}) url('/<lang:lang>/<path:page>', 'views.site_show') +url('/spec', 'spec.views.spec_index') +url('/spec/<string:name>', 'spec.views.spec_show') +url('/spec/<string:name>.txt', 'spec.views.spec_show_txt') + url('/<lang:lang>/papers/', 'anonbib.views.papers_list') url('/<lang:lang>/papers/bibtex', 'anonbib.views.papers_bibtex') url('/<lang:lang>/papers/by-<string:choice>', 'anonbib.views.papers_list') diff --git a/i2p2www/views.py b/i2p2www/views.py index 2efecd78475254cdb5dff0d92aa811e20534e2b9..53335dc8f96fda7b7a5d925ab2e3aa7c2a3bcf9d 100644 --- a/i2p2www/views.py +++ b/i2p2www/views.py @@ -12,11 +12,22 @@ from i2p2www.blog.helpers import get_blog_posts def main_index(): return redirect(url_for('site_show', lang='en')) +SPEC_REDIRECTS = { + 'docs/how/cryptography': 'cryptography', +} + # Site pages @cache.cached() def site_show(page): if page.endswith('.html'): return redirect(url_for('site_show', page=page[:-5])) + + # Redirect for old spec pages + if page.startswith('docs/spec/'): + return redirect(url_for('spec_show', name=page[10:])) + if page in SPEC_REDIRECTS: + return redirect(url_for('spec_show', name=SPEC_REDIRECTS[page])) + name = 'site/%s.html' % page page_file = safe_join(TEMPLATE_DIR, name)