propagate from branch 'i2p.www' (head 2df62e69107d5013915619b4a7116fb920e9638d)

to branch 'i2p.www.str4d' (head 316dc8ab7159c0ac13be0c8f192b3376123e5523)
This commit is contained in:
str4d
2016-03-07 02:59:45 +00:00
46 changed files with 9048 additions and 8478 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) }}

View File

@ -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>

View File

@ -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&amp;rep=rep1&amp;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&amp;lpg=PA173&amp;ots=PNIz3dWe4g&amp;pg=PA173#v=onepage&amp;q&amp;f=false',
thread='http://groups.google.com/group/sci.crypt/browse_thread/thread/1855a5efa7416677/339fa2f945cc9ba0#339fa2f945cc9ba0' -%}
Also, <a href="{{ book }}">Koshiba &amp; 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 %}

View File

@ -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>

View File

@ -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

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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

View File

@ -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&#37;.
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

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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>
&lt;i2p.news date="$Date: 2010-01-22 00:00:00 $" /&gt;
&lt;i2p.release version="0.7.14" date="2010/01/22" minVersion="0.6" /&gt;
</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&#37;.
{%- 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 &lt;feed&gt; Details:</b></p>
The following &lt;feed&gt; elements are used:
<ul><li>
&lt;entry&gt; A news item. See below.
</li><li>
&lt;i2p:release&gt; I2P update metadata. See below.
</li><li>
&lt;updated&gt; 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 &lt;entry&gt; Details:</b></p>
Each Atom &lt;entry&gt; in the news feed may be parsed and displayed in the router console.
The following elements are used:
<ul><li>
&lt;author&gt; (optional) containing:
<ul><li>
&lt;name&gt; The name of the entry author
</li></ul>
</li><li>
&lt;content&gt; 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>
&lt;link&gt; Link for further information (optional)
</li><li>
&lt;summary&gt; Short summary, suitable for a tooltip (optional)
</li><li>
&lt;title&gt; Title of the news entry (required)
</li><li>
&lt;updated&gt; 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 &lt;i2p:release&gt; Details:</b></p>
There must be at least one &lt;i2p:release&gt; 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>
&lt;i2p:version&gt; Required. The latest current router version available.
</li><li>
&lt;i2p:update&gt; 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 &lt;i2p:update&gt; elements.
</li><li>
&lt;i2p:clearnet&gt; Out-of-network direct download links (zero or more)
<ul><li>
href (attribute): a standard clearnet http link
</li></ul>
</li><li>
&lt;i2p:clearnetssl&gt; Out-of-network direct download links (zero or more)
<ul><li>
href (attribute): a standard clearnet https link
</li></ul>
</li><li>
&lt;i2p:torrent&gt; In-network magnet link
<ul><li>
href (attribute): a magnet link
</li></ul>
</li><li>
&lt;i2p:url&gt; 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 %}

View File

@ -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

View 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 %}

View 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
View File

249
i2p2www/spec/blockfile.rst Normal file
View 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) }}

File diff suppressed because it is too large Load Diff

View 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

View 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&amp;lpg=PA173&amp;ots=PNIz3dWe4g&amp;pg=PA173#v=onepage&amp;q&amp;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
View 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
View 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

File diff suppressed because it is too large Load Diff

1309
i2p2www/spec/i2np.rst Normal file

File diff suppressed because it is too large Load Diff

691
i2p2www/spec/plugin.rst Normal file
View 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&#37;. 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
View 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

File diff suppressed because it is too large Load Diff

193
i2p2www/spec/streaming.rst Normal file
View 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) }}

View 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') }}

View 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
View 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
View 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)

View File

@ -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
}

View File

@ -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,

View File

@ -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')

View File

@ -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)