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

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