forked from I2P_Developers/i2p.www
propagate from branch 'i2p.www' (head 2df62e69107d5013915619b4a7116fb920e9638d)
to branch 'i2p.www.str4d' (head 316dc8ab7159c0ac13be0c8f192b3376123e5523)
This commit is contained in:
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) }}
|
||||
|
@ -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>
|
||||
|
@ -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 %}
|
@ -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>
|
||||
|
@ -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 %}
|
File diff suppressed because it is too large
Load Diff
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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 %}
|
File diff suppressed because it is too large
Load Diff
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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
|
40
i2p2www/pages/spec/index.html
Normal file
40
i2p2www/pages/spec/index.html
Normal file
@ -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 %}
|
15
i2p2www/pages/spec/show.html
Normal file
15
i2p2www/pages/spec/show.html
Normal file
@ -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 %}
|
0
i2p2www/spec/__init__.py
Normal file
0
i2p2www/spec/__init__.py
Normal file
249
i2p2www/spec/blockfile.rst
Normal file
249
i2p2www/spec/blockfile.rst
Normal file
@ -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) }}
|
1066
i2p2www/spec/common-structures.rst
Normal file
1066
i2p2www/spec/common-structures.rst
Normal file
File diff suppressed because it is too large
Load Diff
468
i2p2www/spec/configuration.rst
Normal file
468
i2p2www/spec/configuration.rst
Normal file
@ -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
|
547
i2p2www/spec/cryptography.rst
Normal file
547
i2p2www/spec/cryptography.rst
Normal file
@ -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
|
130
i2p2www/spec/datagrams.rst
Normal file
130
i2p2www/spec/datagrams.rst
Normal file
@ -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
|
86
i2p2www/spec/geoip.rst
Normal file
86
i2p2www/spec/geoip.rst
Normal file
@ -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.
|
1385
i2p2www/spec/i2cp.rst
Normal file
1385
i2p2www/spec/i2cp.rst
Normal file
File diff suppressed because it is too large
Load Diff
1309
i2p2www/spec/i2np.rst
Normal file
1309
i2p2www/spec/i2np.rst
Normal file
File diff suppressed because it is too large
Load Diff
691
i2p2www/spec/plugin.rst
Normal file
691
i2p2www/spec/plugin.rst
Normal file
@ -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
|
76
i2p2www/spec/spectags
Normal file
76
i2p2www/spec/spectags
Normal file
@ -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
|
1199
i2p2www/spec/ssu.rst
Normal file
1199
i2p2www/spec/ssu.rst
Normal file
File diff suppressed because it is too large
Load Diff
193
i2p2www/spec/streaming.rst
Normal file
193
i2p2www/spec/streaming.rst
Normal file
@ -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) }}
|
365
i2p2www/spec/tunnel-creation.rst
Normal file
365
i2p2www/spec/tunnel-creation.rst
Normal file
@ -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') }}
|
353
i2p2www/spec/tunnel-message.rst
Normal file
353
i2p2www/spec/tunnel-message.rst
Normal file
@ -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) }}
|
563
i2p2www/spec/updates.rst
Normal file
563
i2p2www/spec/updates.rst
Normal file
@ -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') }}
|
109
i2p2www/spec/views.py
Normal file
109
i2p2www/spec/views.py
Normal file
@ -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)
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
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 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,
|
||||
|
@ -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')
|
||||
|
@ -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)
|
||||
|
||||
|
Reference in New Issue
Block a user