28 Commits

Author SHA1 Message Date
eyedeekay
3041e87ebe Fix spacing and add hashes to blog post 2025-09-09 15:56:29 -04:00
eyedeekay
9fafe29f32 update hashes, website 2025-09-08 19:24:45 -04:00
eyedeekay
4f048f75a7 quick fix docker build. Remove old firefox page. Add an endpoint to get the hashes as a json file so I can test them with a script. 2025-09-01 21:43:37 -04:00
eyedeekay
513339fa41 Merge branch 'master' of github.com:i2p/i2p.www 2025-09-01 18:43:24 -04:00
zzz
1dbd337512 I2NP: Clarify lookup type 00 is deprecated 2025-08-25 10:27:01 -04:00
zzz
0206eb63cb roadmap update 2025-08-18 15:48:06 -04:00
zzz
ee7ed83062 SAM clarifications 2025-08-18 14:04:51 -04:00
zzz
dd14d5ccf8 clarify exploratory lookup 2025-08-12 12:50:07 -04:00
zzz
c497a9a840 Renew deb repo key
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-07-25 09:35:06 -04:00
idk
4c4cffbc6d Update sync.yaml
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-07-17 23:11:34 +00:00
zzz
dbfa21d523 add paper
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-07-15 16:45:50 -04:00
zzz
836cdb9cd0 I2CP: Notes on destroy/disconnect
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-07-10 08:53:16 -04:00
zzz
80972af6b3 more fixes
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-07-05 13:06:35 -04:00
zzz
b6ac602c8d Streaming: add more notes on max window size
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-07-05 12:46:43 -04:00
zzz
d9d2fcac82 I2CP notes on enc types
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-06-30 15:46:32 -04:00
zzz
6b4634fb21 UDP announce clarifications
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-06-29 10:28:07 -04:00
zzz
dabf40a185 date fix
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-06-25 07:43:15 -04:00
zzz
d3df17be81 Copy proposal 160 to specs after review
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
roadmap update
2025-06-25 07:13:48 -04:00
zzz
0d70474034 reserve MLDSA codepoints
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-06-13 08:24:58 -04:00
zzz
3952d48b3c fix references
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-06-13 06:45:54 -04:00
eyedeekay
287e7149de Merge branch 'master' of i2pgit.org:I2P_Developers/i2p.www
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-06-12 12:18:30 -04:00
zzz
422ec5aa3a fixup gitea links
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-06-12 10:18:41 -04:00
zzz
5cb8e81a09 add reference
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-06-12 09:55:56 -04:00
zzz
2515a42427 cleanups
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-06-12 09:38:54 -04:00
zzz
0dfc92de5e Copy MLKEM parts of prop. 169 to specs, as approved
Some checks failed
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
2025-06-12 09:06:58 -04:00
zzz
68d3546fb0 Mark long build records deprecated 2025-06-12 08:52:23 -04:00
eyedeekay
de5aba25b8 update bundle version 2025-06-11 20:18:11 -04:00
eyedeekay
93fbccb206 CI: delete sync CI job for now 2025-04-24 10:40:35 -04:00
37 changed files with 1826 additions and 326 deletions

View File

@@ -62,5 +62,5 @@ name: Sync Primary Repository to GitHub Mirror
"on":
push: {}
schedule:
- cron: 0 * * * *
- cron: 0 0 * * *
workflow_dispatch: {}

View File

@@ -1,7 +1,10 @@
FROM debian:oldoldstable as builder
FROM debian:buster as builder
ENV SERVERNAME=geti2p.net \
SERVERMAIL=example@geti2p.net
# Replace the buster repos with the archive.debian.org versions
RUN sed -i 's|http://deb.debian.org/debian|http://archive.debian.org/debian|g' /etc/apt/sources.list
# Install only build dependencies first
RUN apt-get update && \
apt-get install -y --no-install-recommends \
@@ -9,8 +12,10 @@ RUN apt-get update && \
python-pip \
patch \
python-virtualenv \
virtualenv \
git \
python-polib && \
python-polib \
build-essential && \
rm -rf /var/lib/apt/lists/*
WORKDIR /build
@@ -34,7 +39,10 @@ RUN . env/bin/activate && \
echo "Git revision: $(git log -n 1 | grep commit | sed 's/commit //' | sed 's/ .*$//')" > ./i2p2www/pages/include/mtnversion
# Start second stage with same old base image
FROM debian:oldoldstable
FROM debian:buster
# Replace the buster repos with the archive.debian.org versions
RUN sed -i 's|http://deb.debian.org/debian|http://archive.debian.org/debian|g' /etc/apt/sources.list
# Install only runtime dependencies
RUN apt-get update && \
@@ -42,7 +50,8 @@ RUN apt-get update && \
apache2 \
apache2-utils \
libapache2-mod-wsgi \
python2-minimal && \
python2-minimal \
build-essential && \
rm -rf /var/lib/apt/lists/*
WORKDIR /var/www/i2p.www

View File

@@ -22,8 +22,8 @@ except ImportError:
###########
# Constants
CURRENT_I2P_VERSION = '2.9.0'
CURRENT_I2P_FIREFOX_PROFILE_VERSION = '2.8.2'
CURRENT_I2P_VERSION = '2.10.0'
CURRENT_I2P_FIREFOX_PROFILE_VERSION = '2.9.0'
CURRENT_I2P_OSX_VERSION = '1.9.0'
CANONICAL_DOMAIN = 'geti2p.net'

View File

@@ -0,0 +1,45 @@
{% trans -%}
==================
I2P 2.10.0 Release
==================
{%- endtrans %}
.. meta::
:author: idk
:date: 2025-09-08
:category: release
:excerpt: {% trans %}I2P 2.10.0 Release{% endtrans %}
{% trans -%}
Work continues on the implementation and deployment of post-quantum cryptography in I2P.
In this release post-quantum cryptography is available but not turned on by default for new tunnels.
Those of you interested in testing post-quantum support should enable it via the "Hidden Service Manager" under "Encryption Types."
Be sure to get in touch on #i2p-dev in IRC2P for help and to report any issues you encounter.
{%- endtrans %}
{% trans -%}
I2PSnark now supports UDP trackers.
This should help the network overall by reducing the load of torrent trackers.
{%- endtrans %}
{% trans -%}
Stability improvements have been made to the Hidden Mode which will reduce the chance of running out of RouterInfos.
{%- endtrans %}
{% trans -%}
Important! In the next release, I2P will require Java 17 or later.
{%- endtrans %}
{% trans -%}
As usual, we recommend that you update to this release.
The best way to maintain security and help the network is to run the latest release.
{%- endtrans %}
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
f96110b00c28591691d409bd2f1768b7906b80da5cab2e20ddc060cbb4389fbf i2pinstall_2.10.0_windows.exe
76372d552dddb8c1d751dde09bae64afba81fef551455e85e9275d3d031872ea i2pinstall_2.10.0.jar
3b651b761da530242f6db6536391fb781bc8e07129540ae7e96882bcb7bf2375 i2psource_2.10.0.tar.bz2
c89f568ebdc7d75c6fde59c4f68ac09031543d3ce8643c08e0f46d97513e90aa i2pupdate_2.10.0.zip
04aa738517d5268c157ec267348b9fdda89b5f26052603b21cd4a1bd217c2f66 i2pupdate.su3

View File

@@ -1,11 +1,13 @@
from flask import abort, redirect, render_template, request
from flask import abort, redirect, render_template, request, jsonify
try:
import json
except ImportError:
import simplejson as json
from random import randint
import re
import os.path
from i2p2www import CURRENT_I2P_VERSION, MIRRORS_FILE
from i2p2www import CURRENT_I2P_VERSION, MIRRORS_FILE, TEMPLATE_DIR
DEFAULT_MIRROR = {
"net": "clearnet",
@@ -73,6 +75,85 @@ def read_mirrors():
ret[net][protocol][domain]=obj
return ret
# Extract hashes and filenames from macros file
def extract_hashes_from_macros():
macros_path = os.path.join(TEMPLATE_DIR, 'downloads', 'macros')
if not os.path.exists(macros_path):
return {}
with open(macros_path, 'r') as f:
content = f.read()
# Dictionary to store hash variable name to hash value mapping
hashes = {}
# Regex to extract hash variables
hash_pattern = re.compile(r'{%\s*set\s+(\w+_hash)\s*=\s*[\'"]([a-fA-F0-9]+)[\'"]')
for match in hash_pattern.finditer(content):
var_name = match.group(1)
hash_value = match.group(2)
hashes[var_name] = hash_value
# Now map hash variables to their corresponding file patterns
hash_to_file = {}
# Extract the filename patterns for each package type
if 'i2pinstall_windows_hash' in hashes:
hash_to_file['i2pinstall_windows_hash'] = {
'hash': hashes['i2pinstall_windows_hash'],
'filename_pattern': 'i2pinstall_{version}_windows.exe'
}
if 'i2pinstall_jar_hash' in hashes:
hash_to_file['i2pinstall_jar_hash'] = {
'hash': hashes['i2pinstall_jar_hash'],
'filename_pattern': 'i2pinstall_{version}.jar'
}
if 'i2psource_hash' in hashes:
hash_to_file['i2psource_hash'] = {
'hash': hashes['i2psource_hash'],
'filename_pattern': 'i2psource_{version}.tar.bz2'
}
if 'i2pupdate_hash' in hashes:
hash_to_file['i2pupdate_hash'] = {
'hash': hashes['i2pupdate_hash'],
'filename_pattern': 'i2pupdate_{version}.zip'
}
if 'i2p_android_hash' in hashes:
hash_to_file['i2p_android_hash'] = {
'hash': hashes['i2p_android_hash'],
'filename_pattern': 'app.apk'
}
if 'i2p_macnative_hash' in hashes:
# Extract the OSX launcher version from macros
osx_version_pattern = re.compile(r'{%\s*set\s+i2p_macosx_launcher_version\s*=\s*[\'"]([^\'\"]+)[\'"]')
osx_match = osx_version_pattern.search(content)
osx_version = osx_match.group(1) if osx_match else '1.9.0'
hash_to_file['i2p_macnative_hash'] = {
'hash': hashes['i2p_macnative_hash'],
'filename_pattern': 'I2PMacLauncher-{version}-beta-' + osx_version + '.dmg'
}
if 'i2p_bundle_hash' in hashes:
hash_to_file['i2p_bundle_hash'] = {
'hash': hashes['i2p_bundle_hash'],
'filename_pattern': 'i2p-bundle-{version}.exe'
}
# Generate final JSON with actual filenames using current version
result = {}
for key, data in hash_to_file.items():
filename = data['filename_pattern'].format(version=CURRENT_I2P_VERSION)
result[filename] = data['hash']
return result
# List of downloads
def downloads_list():
# TODO: read mirror list or list of available files
@@ -178,3 +259,10 @@ def downloads_redirect(version, net, protocol, domain, file):
return render_template('downloads/redirect.html',
version=version, protocol=protocol, domain=domain, file=file,
url=mirrors[domain]['url'] % data)
# JSON endpoint for hashes
def downloads_hashes():
"""Return JSON with hashes and filenames from the macros file"""
hashes = extract_hashes_from_macros()
return jsonify(hashes)

View File

@@ -12,7 +12,7 @@
<li><a href="#debian">Knoppix</a></li>
</ul>
{% trans gtitlab='https://i2pgit.org/i2p-hackers/i2p.i2p/' -%}
{% trans gtitlab='https://i2pgit.org/I2P_Developers/i2p.i2p/' -%}
The I2P packages <em>may</em> work on systems not listed above. Please report any issues
with these packages on <a href="{{ gtitlab }}">Gitlab</a> at
<a href="{{ gtitlab }}">i2p.i2p</a>.

View File

@@ -20,7 +20,7 @@ Please verify that the hashes match the downloads when installing the bundle.
<h2>{{ _('What do I need to use it?') }}</h2>
<p><strong>{% trans -%}
Just Firefox (Or Tor Browser).{%- endtrans %}</strong>
{% trans issueurl="https://i2pgit.org/i2p-hackers/i2p.firefox/-/issues/2" -%}
{% trans issueurl="https://i2pgit.org/I2P_Developers/i2p.firefox/-/issues/2" -%}
This installer still requires Firefox to be installed on the system, it does not
bundle a Firefox installer of its own. Please obtain Firefox from Mozilla, or
Tor Browser from the Tor Project or one of their mirrors. If you would like to
@@ -47,7 +47,7 @@ start an installer, "double-click" the downloaded .exe file.
<p>{% trans -%}
Running the installer will create a shortcut to start browsing I2P in your start
menu and on your desktop. Clicking this shortcut will start I2P if necessary,
then start an I2P Browser. On the first run, you will also be promted with the
then start an I2P Browser. On the first run, you will also be prompted with the
bandwidth wizard in your browser window. You will also see a "Toopie" icon in
your taskbar to indicate that I2P is working when the browser window is closed.
{%- endtrans %}</p>
@@ -60,7 +60,7 @@ special configuration. You don't even need to close existing Firefox windows.
{%- set name = 'Windows' -%}
{%- set icon = 'images/download/windows.png' -%}
{%- set filename = 'I2P-Easy-Install-Bundle-%s.exe' -%}
{%- set hash = 'a8e7e02b00428a150d8287774879c3babd4f0eeede7b691403dc283c05bda750' -%}
{%- set hash = i2p_bundle_hash -%}
{% call package_outer('windows', name, icon) %}
<div class = "file">
@@ -110,7 +110,7 @@ If you would like to examine the source code for individual components, you may
find it on i2pgit.org or github.com. The license for each respective component
can be found in the license directory of the <code>i2p.firefox</code> project.
{%- endtrans %}</div>
<div><a href="https://i2pgit.org/i2p-hackers/i2p.firefox">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<div><a href="https://i2pgit.org/I2P_Developers/i2p.firefox">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<div><a href="https://github.com/i2p/i2p.firefox">{% trans -%}Github Repository{%- endtrans %}</a></div>
<div><a href="https://i2pgit.org/idk/i2p.plugins.firefox">{% trans -%}Gitlab Repository for Profile Manager{%- endtrans %}</a></div>
<div><a href="https://github.com/eyedeekay/i2p.plugins.firefox">{% trans -%}Github Repository Profile Manager{%- endtrans %}</a></div>
@@ -120,7 +120,7 @@ contact us. For security-sensitive issues, please remember to check the
"This issue is confidential and should only be visible to team members with at least Reporter access"
option when filing the issue.
{%- endtrans %}</div>
<div><a href="https://i2pgit.org/i2p-hackers/i2p.firefox/issues">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<div><a href="https://i2pgit.org/I2P_Developers/i2p.firefox/issues">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<h2>{{ _('How is it different from Tor Browser?') }}</h2>
<p>{% trans -%}
This is not a fork of Firefox. Instead, it is a browser profile with pre-configured

View File

@@ -1,5 +1,5 @@
{% extends "global/layout.html" %}
{%- from "downloads/macros" import package_outer with context -%}
{%- from "downloads/macros" import package, package_outer with context -%}
{% block title %}Firefox Profile{% endblock %}
{% block content %}
@@ -14,105 +14,4 @@ time it installs the browser profile. This page has been kept to document the
motivations and design of the included Firefox profile. To learn more about the
new bundle, visit <a href="{{ nsis }}">The Easy Install Bundle Page</a>.
{%- endtrans %}</p>
<p>{% trans -%}
The latest I2P Easy-Install bundle for Windows has been released unsigned.
Please verify that the hashes match the downloads when installing the bundle.
{%- endtrans %}</p>
<h2>{{ _('I2P Firefox Browser Profile') }}</h2>
<p>{% trans -%}
Now that you have joined the I2P network, you will want to see I2P Sites and and
other content that is hosted on the network. The Firefox browser profile is
pre-configured to allow you to access the content available on the network.
{%- endtrans %}</p>
<h2>{{ _('Why should I use it?') }}</h2>
<p>{% trans -%}
Browsers are highly complex and powerful engines for executing code and displaying
information obtained mainly from strangers on the internet. By default, they
tend to leak a great deal of information about the person using them to the servers
they retrieve information from. Using this browser profile allows you to become
part of a "common" set of very similar browser users, instead of appearing unique
or revealing details of your hardware or software. Because this involves disabling
some browser features, this also reduces the attack surface available to outsiders.
This keeps you safer while browsing the Invisible Web.
{%- endtrans %}</p>
<h2>{{ _('How do I use it?') }}</h2>
<p>{% trans firefox="https://www.mozilla.org/" -%}
First, download and install <a href="{{ firefox }}">Firefox</a>, then,
just download and install this installer(below). To
start an installer, "double-click" the downloaded .exe file.
{%- endtrans %}</p>
{%- set name = 'Windows' -%}
{%- set icon = 'images/download/windows.png' -%}
{%- set filename = 'I2P-Easy-Install-Bundle-%s.exe' -%}
{%- set hash = 'a8e7e02b00428a150d8287774879c3babd4f0eeede7b691403dc283c05bda750' -%}
{% call package_outer('windows', name, icon) %}
<div class = "file">
<a class = "default" href="{{ url_for('downloads_redirect', version=pver(), net=def_mirror.net, protocol=def_mirror.protocol, domain=def_mirror.domain, file=pver(filename) )}}">
<span class = "name">{{ pver(filename) }}</span><br/>
<span class="mirror">{{ _('Mirror:') }} <img src="{{ url_for('static', filename='images/flags/'+def_mirror.country+'.png') }}" /> {{ def_mirror.org }}</span>
</a>
<a class="mirrors" href="{{ get_url('downloads_select', version=pver(), file=pver(filename)) }}">{{ _('select alternate mirror') }}</a>
</div>
<div class="meta">
<div class="hash">
<code>{{ hash }}</code>
</div>
</div>
<p>{% trans -%}
Download that file and run it.
{%- endtrans %}</p>
{% endcall %}
<h2>{{ _('What is in it?') }}</h2>
<p><strong>{% trans -%}
A Jpackaged I2P Router: {%- endtrans %}</strong>
{% trans -%}The I2P router is "jpackaged" which means that it includes all
the required Java components it needs to run successfully. It does not require
a separate Java installation, because it bundles a Java 16 Runtime which is only
used for I2P.
{%- endtrans %}</p>
<p><strong>{% trans -%}
Browser Extensions: {%- endtrans %}</strong>
{% trans -%}The browser profile also includes both the NoScript and HTTPSEverywhere plugin for
better protection Javascript based attacks and HTTPS support where available. It
also keeps your I2P search activity separate from your visible internet search
activity. The profile configures the I2P Proxy for all sites and browser features.
I2P In Private Browsing is used to provide I2P-Specific browser integrations.
{%- endtrans %}</p>
<h3>{{ _('Source Code and Issue Tracking') }}</h3>
<div>{% trans -%}
If you would like to examine the source code for individual components, you may
find it on i2pgit.org or github.com. The license for each respective component
can be found in the license directory of the <code>i2p.firefox</code> project.
{%- endtrans %}</div>
<div><a href="https://i2pgit.org/i2p-hackers/i2p.firefox">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<div><a href="https://github.com/i2p/i2p.firefox">{% trans -%}Github Repository{%- endtrans %}</a></div>
<div><a href="https://i2pgit.org/idk/i2p.plugins.firefox">{% trans -%}Gitlab Repository for Profile Manager{%- endtrans %}</a></div>
<div><a href="https://github.com/eyedeekay/i2p.plugins.firefox">{% trans -%}Github Repository Profile Manager{%- endtrans %}</a></div>
<div>{% trans -%}
If you wish to file an issue about the Firefox profile, please use Gitlab to
contact us. For security-sensitive issues, please remember to check the
"This issue is confidential and should only be visible to team members with at least Reporter access"
option when filing the issue.
{%- endtrans %}</div>
<div><a href="https://i2pgit.org/i2p-hackers/i2p.firefox/issues">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<h2>{{ _('How is it different from Tor Browser?') }}</h2>
<p>{% trans -%}
This is not a fork of Firefox. Instead, it is a browser profile with pre-configured
settings, combined with an I2P router and some launcher scripts. That means that
it requires Firefox(Or Tor Browser) to be installed before you can use it. This
is for security reasons, it is important that you are able to recieve reliable
updates from a trustworthy vendor.
{%- endtrans %}</p>
<p>{% trans -%}
I2P routers are designed to have long uptimes, and so unlike Tor Browser, the
lifetime of your I2P Router is not tied to the lifetime of your I2P browsing
session. The browser profile will manage your history, your browser's local
storage and cache, and your browsing context but it will never stop your I2P
router on its own. You may stop the router using the web interface on the
router console homepage.
{%- endtrans %}</p>
{% endblock %}

View File

@@ -113,13 +113,13 @@ I2P to launch when your user logs in by right-clicking on the I2P Dock icon.
If you would like to examine the source code for individual components, you may
find it on i2pgit.org.
{%- endtrans %}</div>
<div><a href="https://i2pgit.org/i2p-hackers/i2p-jpackage-mac">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<div><a href="https://i2pgit.org/I2P_Developers/i2p-jpackage-mac">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<div>{% trans -%}
If you wish to file an issue about the DMG Bundle, please use Gitlab to
contact us. For security-sensitive issues, please remember to check the
"This issue is confidential and should only be visible to team members with at
least Reporter access" option when filing the issue.
{%- endtrans %}</div>
<div><a href="https://i2pgit.org/i2p-hackers/i2p-jpackage-mac/issues">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<div><a href="https://i2pgit.org/I2P_Developers/i2p-jpackage-mac/issues">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
{% endblock %}

View File

@@ -1,9 +1,10 @@
{% set i2pinstall_windows_hash = 'fe106319dcf5972b7c833150292cb72ae6a764cf18929f043dfb9f10340ee782' %}
{% set i2pinstall_jar_hash = 'fee438e9f42345eeef3f5255842bbcf725eb01f1f84589791a525cd45143555b' %}
{% set i2psource_hash = '03989319e186d9b06ed96ea0efa6ac95af1bc57af956d7f5f06f52f8da64fcd7' %}
{% set i2pupdate_hash = '1b79b2593bbe60e08da3f84411d48a5f1fe0c8cfd934f1c90d2fece436c1f2b5' %}
{% set i2pinstall_windows_hash = 'f96110b00c28591691d409bd2f1768b7906b80da5cab2e20ddc060cbb4389fbf' %}
{% set i2pinstall_jar_hash = '76372d552dddb8c1d751dde09bae64afba81fef551455e85e9275d3d031872ea' %}
{% set i2psource_hash = '3b651b761da530242f6db6536391fb781bc8e07129540ae7e96882bcb7bf2375' %}
{% set i2pupdate_hash = 'c89f568ebdc7d75c6fde59c4f68ac09031543d3ce8643c08e0f46d97513e90aa' %}
{% set i2p_android_hash = '13b6e3c35756605e8e65804ab91cb34521c819fcfaebafb348eba5d40bed6699' %}
{% set i2p_macnative_hash = '18cb22cfcc3cbe0cec150e89a394d1a35703cb508ed627ef48084b7ba7c90dde' %}
{% set i2p_bundle_hash = 'e2b70423b4f4bef4179bf54dee4284d897a8b48f1c3c63a3f24acb45388a38c8' %}
{% set i2p_windows_subver = '' %}
{% set i2p_macosx_launcher_version = '1.9.0' %}

View File

@@ -31,6 +31,17 @@
#
# Proposed new sections: application privacy, data anonymization, ...
#
@inproceedings {wangchuk,
author = {Tashi Wangchuk and Ngaira Mandela and Tumaini Mbinda and Kamboisssoi Damedjate and Felix Etyang and Joel Makopa},
title = {Forensic Analysis of I2P Communication Network in Android and macOS Environments},
booktitle = {2024 11th International Conference on Computing for Sustainable Global Development (INDIACom)},
year = {2024},
url = {https://ieeexplore.ieee.org/document/10498888},
publisher = {IEEE},
month = {April},
www_section = traffic,
}
@inproceedings {abdo,
author = {Jacques Bou Abdo and Liaquat Hossain},
title = {Modeling the Invisible Internet},

View File

@@ -30,7 +30,7 @@ The following are discussed on the <a href="{{ othernetworks }}">other networks
<li>Haystack</li>
</ul>
<p>{% trans trac='https://i2pgit.org/i2p-hackers/i2p.www/issues' -%}
<p>{% trans trac='https://i2pgit.org/I2P_Developers/i2p.www/issues' -%}
The content of this page is subject to update, discussion and dispute, and we welcome comments and additions.
You may contribute an analysis by entering a <a href="{{ trac }}">new issue on Github</a>.
{%- endtrans %}</p>

View File

@@ -14,7 +14,7 @@ The following networks are discussed on this page.
<li>Haystack</li>
</ul>
<p>{% trans comparison=site_url('comparison'), trac='https://i2pgit.org/i2p-hackers/i2p.www/issues' -%}
<p>{% trans comparison=site_url('comparison'), trac='https://i2pgit.org/I2P_Developers/i2p.www/issues' -%}
Most of the following sections are fairly old, and may not be accurate.
For an overview of available comparisons, see the
<a href="{{ comparison }}">main network comparisons page</a>.
@@ -246,13 +246,13 @@ I2P is, of course, open source. However, that source, and our
{%- endtrans %}</p>
<h2>{{ _('Paid VPN Services') }}</h2>
<p>{% trans trac='https://i2pgit.org/i2p-hackers/i2p.www/issues' -%}
<p>{% trans trac='https://i2pgit.org/I2P_Developers/i2p.www/issues' -%}
You may contribute an analysis by entering a
<a href="{{ trac }}">new issue on Github</a>.
{%- endtrans %}</p>
<h2>{{ _('Others') }}</h2>
<p>{% trans trac='https://i2pgit.org/i2p-hackers/i2p.www/issues' -%}
<p>{% trans trac='https://i2pgit.org/I2P_Developers/i2p.www/issues' -%}
You may contribute an analysis by entering a
<a href="{{ trac }}">new issue on Github</a>.
{%- endtrans %}</p>

View File

@@ -677,7 +677,8 @@ received through other forms are answered with an error message) :
[HOST=$host] # Optional for DATAGRAM* and RAW, invalid for STREAM
[FROM_PORT=nnn] # SAM 3.2 or higher only, default 0
[TO_PORT=nnn] # SAM 3.2 or higher only, default 0
[PROTOCOL=nnn] # SAM 3.2 or higher only, for STYLE=RAW only, default 18
[PROTOCOL=nnn] # SAM 3.2 or higher only, for STYLE=RAW only, default 18.
# 6, 17, 19, 20 not allowed.
[HEADER={true,false}] # SAM 3.2 or higher only, for STYLE=RAW only, default false
[sam.udp.host=hostname] # Datagram bind host, Java I2P only, DATAGRAM*/RAW only, default 127.0.0.1
[sam.udp.port=nnn] # Datagram bind port, Java I2P only, DATAGRAM*/RAW only, default 7655
@@ -1195,9 +1196,9 @@ This is all on one line (space separated), shown on multiple lines for clarity:
3.0 # As of SAM 3.2, any "3.x" is allowed. Prior to that, "3.0" is required.
$nickname
$destination
[FROM_PORT=nnn] # SAM 3.2 or higher only, default 0
[TO_PORT=nnn] # SAM 3.2 or higher only, default 0
[PROTOCOL=nnn] # SAM 3.2 or higher only, only for RAW sessions, default 18
[FROM_PORT=nnn] # SAM 3.2 or higher only, default from session options
[TO_PORT=nnn] # SAM 3.2 or higher only, default from session options
[PROTOCOL=nnn] # SAM 3.2 or higher only, only for RAW sessions, default from session options
[SEND_TAGS=nnn] # SAM 3.3 or higher only, number of session tags to send
# Overrides crypto.tagsToSend I2CP session option
# Default is router-dependent (40 for Java router)
@@ -1290,7 +1291,8 @@ CREATE command with PORT and HOST options:
[HOST=$host]
[FROM_PORT=nnn] # SAM 3.2 or higher only, default 0
[TO_PORT=nnn] # SAM 3.2 or higher only, default 0
[PROTOCOL=nnn] # SAM 3.2 or higher only, for STYLE=RAW only, default 18
[PROTOCOL=nnn] # SAM 3.2 or higher only, for STYLE=RAW only, default 18.
# 6, 17, 19, 20 not allowed.
[sam.udp.host=hostname] # Datagram bind host, Java I2P only, default 127.0.0.1
[sam.udp.port=nnn] # Datagram bind port, Java I2P only, default 7655
[option=value]* # I2CP options
@@ -1609,7 +1611,8 @@ Using the same control socket on which the PRIMARY session was created:
[HOST=$host] # Optional for DATAGRAM* and RAW, invalid for STREAM
[FROM_PORT=nnn] # For outbound traffic, default 0
[TO_PORT=nnn] # For outbound traffic, default 0
[PROTOCOL=nnn] # For outbound traffic for STYLE=RAW only, default 18
[PROTOCOL=nnn] # For outbound traffic for STYLE=RAW only, default 18.
# 6, 17, 19, 20 not allowed.
[LISTEN_PORT=nnn] # For inbound traffic, default is the FROM_PORT value.
# For STYLE=STREAM, only the FROM_PORT value or 0 is allowed.
[LISTEN_PROTOCOL=nnn] # For inbound traffic for STYLE=RAW only.

View File

@@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Streaming Protocol{% endtrans %}{% endblock %}
{% block lastupdated %}2024-09{% endblock %}
{% block accuratefor %}0.9.64{% endblock %}
{% block lastupdated %}2025-07{% endblock %}
{% block accuratefor %}0.9.67{% endblock %}
{% block content %}
<h2>{% trans %}Overview{% endtrans %}</h2>
@@ -457,16 +457,34 @@ Optional delay values greater than 60000 indicate choking, see below.
{%- endtrans %}</p>
<h3>{% trans %}Receive Window and Choking{% endtrans %}</h3>
<p>{% trans -%}
TCP headers include the receive window in bytes.
The streaming protocol does not contain a receive window, it uses only a simple choke/unchoke indication.
<h3>Transmit/Receive Windows and Choking</h3>
<p>
TCP headers include the receive window in bytes; however,
the streaming protocol does not provide a way to exchange max receive window size either in bytes or packets.
There is only a simple choke/unchoke indication indicating that the receive buffer is full.
Each endpoint must maintain its own estimate of the far-end receive window, in either bytes or packets.
The recommended minimum buffer size for receiver implementations is 128 packets or 217 KB (approximately 128x1730).
Note that a receive buffer may overflow at any window size if the
client application is slow to empty the buffer.
</p><p>
The default maximum transmit and receive window size in the Java implementation is 128 packets.
Implementations setting a maximum transmit window size higher than 128
must consider the following issues:
</p>
<ul>
<li>CHOKE responses from Java routers due to receive buffer overflow are much more likely.
<li>Far-end receiver buffer size estimation must be implemented to mitigate repeated overflows (see above)
<li>CHOKE must be handled correctly (see below)
<li>Max window sizes over 256 are even more error-prone, because the nack count option field length
is one byte, limiting the maximum NACKs to 255.
This specification does not address what to do if there are more than 255 NACKs.
Max window sizes over 256 are not recommended.
</ul>
<p>
The recommended minimum buffer size for receiver implementations is 128 packets or 232 KB (approximately 128 * 1812).
Because of I2P netowrk latency, packet drops, and the resulting congestion control,
a buffer of this size is rarely filled.
Overflow is, however, likely to occur on high-bandwidth "local loopback" (same-router) connections.
{%- endtrans %}</p>
Overflow is, however, much more likely to occur on high-bandwidth "local loopback" (same-router) connections or in local testing.
</p>
<p>{% trans -%}
To quickly indicate and smoothly recover from overflow conditions,
there is a simple mechanism for pushback in the streaming protocol.
@@ -579,13 +597,14 @@ The following Control Block Sharing parameters can be set per router:
</p>
<h3 id="other">{% trans %}Other Parameters{% endtrans %}</h3>
<p>{% trans -%}
The following parameters are hardcoded, but may be of interest for analysis:
{%- endtrans %}</p>
<p>
The following parameters are recommended defaults. Defaults may vary, implementation dependent:
</p>
<ul>
<li>MIN_RESEND_DELAY = 100 ms (minimum RTO)
<li>MAX_RESEND_DELAY = 45 sec (maximum RTO)
<li>MIN_WINDOW_SIZE = 1
<li>MAX_WINDOW_SIZE = 128
<li>TREND_COUNT = 3
<li>MIN_MESSAGE_SIZE = 512 (minimum MTU)
<li>INBOUND_BUFFER_SIZE = maxMessageSize * (maxWindowSize + 2)

View File

@@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Bittorrent over I2P{% endtrans %}{% endblock %}
{% block lastupdated %}2024-11{% endblock %}
{% block accuratefor %}0.9.64{% endblock %}
{% block lastupdated %}2025-06{% endblock %}
{% block accuratefor %}0.9.67{% endblock %}
{% block content %}
<p>{% trans -%}
@@ -133,12 +133,16 @@ the HTTP client proxy at port 4444. Doing so is both more efficient and it allow
destination enforcement by the tracker (see below).
{%- endtrans %}</p>
<p>{% trans -%}
There are no known I2P clients or trackers that currently support UDP announce/responses.
{%- endtrans %}</p>
<p>
The specification for UDP announces was finalized 2025-06.
Support in various I2P clients and trackers will be rolling out later in 2025.
See below for additional information.
</p>
<h2>{% trans %}Non-Compact Tracker Responses{% endtrans %}</h2>
Note: Deprecated. All popular trackers now support compact responses and at least one requires compact=1 in the announce.
All clients should request and support compact responses.
<p>{% trans -%}
The non-compact response is just as in standard bittorrent, with an I2P "ip".
{%- endtrans %}
@@ -357,22 +361,19 @@ Alternatives: A single byte string with concatenated hashes,
or a list of strings alone.
{%- endtrans %}</p>
{% set udp_spec = spec_url('udp-announces') %}
{% set dg2_spec = spec_url('datagrams') %}
<h2>{% trans %}Datagram (UDP) Trackers{% endtrans %}</h2>
<p>{% trans -%}
UDP tracker support in clients and trackers is not yet available.
Preliminary differences from
<p>
The specification for UDP announces in I2P was finalized 2025-06.
Support in various I2P clients and trackers will be rolling out later in 2025.
Differences from
<a href="http://www.bittorrent.org/beps/bep_0015.html">BEP 15</a>
are described below, and are subject to change.
Contact the I2P developers if you wish to develop a client or tracker supporting datagram announces.
{%- endtrans %}</p>
<p>{% trans prop160=site_url('docs/spec/proposals/160') -%}
See <a href="{{ prop160 }}">Proposal 160</a>.
{%- endtrans %}</p>
are documented in <a href="{{ udp_spec }}">the UDP announce specification</a>.
The specification also requires support for
<a href="{{ dg2_spec }}">the new Datagram 2/3 formats</a>.
</p>
<h2>{% trans %}Additional Information{% endtrans %}</h2>

View File

@@ -24,7 +24,7 @@
<pre><code>git fetch $HOME/.i2p/i2psnark/i2p.i2p.bundle</code></pre>
<h3 id="replace-the-bundle-remote-with-the-upstream-remote">{% trans -%}Replace the bundle remote with the upstream remote{%- endtrans %}</h3>
<p>{% trans -%} Now that you have a bundle, you can keep up with changes by setting the remote to the upstream repository source. {%- endtrans %}</p>
<pre><code>git remote set-url origin git@127.0.0.1:i2p-hackers/i2p.i2p</code></pre>
<pre><code>git remote set-url origin git@127.0.0.1:I2P_Developers/i2p.i2p</code></pre>
<h2 id="generating-a-bundle">{% trans -%}Generating a Bundle{%- endtrans %}</h2>
<p>{% trans -%} First, follow the <a href="GIT.md">Git guide for Users</a> until you have a successfully <code>--unshallow</code>ed clone of clone of the i2p.i2p repository. If you already have a clone, make sure you run <code>git fetch --unshallow</code> before you generate a torrent bundle. {%- endtrans %}</p>
<p>{% trans -%}Once you have that, simply run the corresponding ant target:{%- endtrans %}</p>

View File

@@ -24,7 +24,7 @@ using the instructions on the home page.{%- endtrans %}</p>
<img src="/_static/images/git/register.png" alt="" /><figcaption>Registration is easy!</figcaption>
</figure>
<h2 id="second-create-a-project-to-test-with">Second: Create a project to test with</h2>
<p>{% trans -%} To make sure the setup process works, it helps to make a repository to test with from the server, and for the sake of this tutorial, were going to use a fork of the I2P router. First, browse to the i2p-hackers/i2p.i2p repository: {%- endtrans %}</p>
<p>{% trans -%} To make sure the setup process works, it helps to make a repository to test with from the server, and for the sake of this tutorial, were going to use a fork of the I2P router. First, browse to the I2P_Developers/i2p.i2p repository: {%- endtrans %}</p>
<figure>
<img src="/_static/images/git/explore.png" alt="" /><figcaption>Browse to i2p.i2p</figcaption>
</figure>
@@ -99,7 +99,7 @@ git fetch origin</code></pre>
</ul>
<ol type="1">
<li><p>{% trans -%}Set up a second remote in your local repository using the upstream source code.{%- endtrans %}</p>
<pre><code>git remote add upstream git@127.0.0.1:i2p-hackers/i2p.i2p</code></pre></li>
<pre><code>git remote add upstream git@127.0.0.1:I2P_Developers/i2p.i2p</code></pre></li>
<li><p>{% trans -%}Pull in any upstream changes on your current master:{%- endtrans %}</p>
<pre><code>git pull upstream master</code></pre></li>
<li><p>{% trans -%}Before making any changes to the source code, check out a new feature branch to develop on:{%- endtrans %}</p>
@@ -110,7 +110,7 @@ git push origin feature-branch-name</code></pre></li>
<li><p>{% trans -%}Submit a merge request. When the merge request is approved and brought into the upstream master, check out the master locally and pull in the changes:{%- endtrans %}</p>
<pre><code>git checkout master
git pull upstream master</code></pre></li>
<li><p>{% trans -%}Whenever a change to the upstream master(i2p-hackers/i2p.i2p) is made, you can update your master code using this procedure as well.{%- endtrans %}</p>
<li><p>{% trans -%}Whenever a change to the upstream master(I2P_Developers/i2p.i2p) is made, you can update your master code using this procedure as well.{%- endtrans %}</p>
<pre><code>git checkout master
git pull upstream master</code></pre></li>
</ol>

View File

@@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Index to Technical Documentation{% endtrans %}{% endblock %}
{% block lastupdated %}2022-08{% endblock %}
{% block accuratefor %}0.9.55{% endblock %}
{% block lastupdated %}2025-06{% endblock %}
{% block accuratefor %}0.9.67{% endblock %}
{% block content %}
<p>{% trans -%}
Following is an index to the technical documentation for I2P.
@@ -19,7 +19,7 @@ The specifications linked below are currently supported in the network.
See the <a href="{{ site_url('spec/proposals') }}">{{ _('Proposals') }}</a> page for
specifications in discussion or development.
<p>{% trans trac='https://i2pgit.org/i2p-hackers/i2p.www/issues' -%}
<p>{% trans trac='https://i2pgit.org/I2P_Developers/i2p.www/issues' -%}
The I2P Project is committed to maintaining accurate, current documentation.
If you find any inaccuracies in the documents linked below, please
<a href="{{ trac }}">enter a ticket identifying the problem</a>.
@@ -50,6 +50,7 @@ If you find any inaccuracies in the documents linked below, please
<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="{{ spec_url('udp-announces') }}">{{ _('Bittorrent UDP Announces') }}</a></li>
<li><a href="{{ site_url('docs/api/i2pcontrol') }}">{{ _('I2PControl Plugin API') }}</a></li>
<li><a href="{{ spec_url('blockfile') }}">{{ _('hostsdb.blockfile Format') }}</a></li>
<li><a href="{{ spec_url('configuration') }}">{{ _('Configuration File Format') }}</a></li>
@@ -122,6 +123,7 @@ Traditionally used only by Java applications and higher-level APIs.
{% trans %}How client messages are end-to-end encrypted by the router.{% endtrans %}
<ul>
<li><a href="{{ spec_url('ecies') }}">{{ _('ECIES-X25519-AEAD-Ratchet encryption for destinations') }}</a></li>
<li><a href="{{ spec_url('ecies-hybrid') }}">PQ Hybrid {{ _('ECIES-X25519-AEAD-Ratchet encryption for destinations') }}</a></li>
<li><a href="{{ spec_url('ecies-routers') }}">{{ _('ECIES-X25519 encryption for routers') }}</a></li>
<li><a href="{{ site_url('docs/how/elgamal-aes') }}">{{ _('ElGamal/AES+SessionTag encryption') }}</a></li>
<li><a href="{{ site_url('docs/how/cryptography') }}">{{ _('ElGamal and AES cryptography details') }}</a></li>
@@ -256,7 +258,7 @@ ancient (str4d)
</li><li>
<a href="http://{{ i2pconv('zzz.i2p') }}/">{{ _('Developer forum inside I2P') }}</a>
</li><li>
<a href="https://i2pgit.org/i2p-hackers/i2p.i2p/issues">{{ _('Bug tracker') }}</a>
<a href="https://i2pgit.org/I2P_Developers/i2p.i2p/issues">{{ _('Bug tracker') }}</a>
</li><li>
<a href="https://github.com/i2p/i2p.i2p">{{ _('I2P Source exported to GitHub') }}</a>
</li><li>

View File

@@ -1036,8 +1036,8 @@ either through our IRC network, IRC2P, or on Freenode.{%- endtrans %}</p>
<ul>
<li>{% trans -%}Our Bugtracker:{%- endtrans %}
<ul>
<li>{% trans -%}Non-private internet:{%- endtrans %} <a href="https://i2pgit.org/i2p-hackers/i2p.i2p/issues">https://i2pgit.org/i2p-hackers/i2p.i2p/issues</a></li>
<li>{% trans -%}On I2P:{%- endtrans %} <a href="http://git.idk.i2p/i2p-hackers/i2p.i2p/issues">http://git.idk.i2p/i2p-hackers/i2p.i2p/issues</a></li>
<li>{% trans -%}Non-private internet:{%- endtrans %} <a href="https://i2pgit.org/I2P_Developers/i2p.i2p/issues">https://i2pgit.org/I2P_Developers/i2p.i2p/issues</a></li>
<li>{% trans -%}On I2P:{%- endtrans %} <a href="http://git.idk.i2p/I2P_Developers/i2p.i2p/issues">http://git.idk.i2p/I2P_Developers/i2p.i2p/issues</a></li>
</ul>
<li>{% trans -%}Our forums:{%- endtrans %} <a href="http://{{ i2pconv('i2pforum.i2p') }}/">{{ i2pconv('i2pforum.i2p') }}</a></li>
<li>{% trans -%}You may paste any interesting logs to a paste service such as the non-private internet services listed on the

View File

@@ -109,7 +109,7 @@ check it into a new branch on your own gitlab account, create an MR, and assign
Assign the MR to yourself. Merge the MR yourself once the reviewer approves it.
</li>
<li>
Do not create WIP branches in the main i2p-hackers account (except for i2p.www).
Do not create WIP branches in the main I2P_Developers account (except for i2p.www).
WIP belongs in your own account. When the work is done, create an MR.
The only branches in the main account should be for true forks, like a point release.
</li>

View File

@@ -65,7 +65,7 @@ Install <a href="{{ git_url }}">Git</a>.
</li>
<li><strong><a href="https://i2pgit.org">{% trans %}Outside I2P - (https://i2pgit.org){% endtrans %}</a></strong>
</li>
<code>git clone https://i2pgit.org/i2p-hackers/i2p.i2p.git</code>
<code>git clone https://i2pgit.org/I2P_Developers/i2p.i2p.git</code>
</ul>
<p>The read-only mirror is also still available at github.</p>
@@ -100,7 +100,7 @@ see the <a href="{{ apps }}">application development guide</a>.
{%- endtrans %}</p>
<h2 id="development-ideas">{% trans %}Development ideas{% endtrans %}</h2>
<p>{% trans todo=site_url('get-involved/todo'), trac='https://i2pgit.org/i2p-hackers/i2p.i2p/issues' -%}
<p>{% trans todo=site_url('get-involved/todo'), trac='https://i2pgit.org/I2P_Developers/i2p.i2p/issues' -%}
See <a href="{{ todo }}">the project TODO list</a> or
<a href="{{ trac }}">the issue list on GitLab</a>
for ideas.

View File

@@ -1,6 +1,6 @@
{% extends "global/layout.html" %}
{% block title %} {{ _('Roadmap') }}{% endblock %}
{% block lastupdated %}2025-04{% endblock %} {% block content %}
{% block lastupdated %}2025-08{% endblock %} {% block content %}
<p>
This is the official project roadmap for the desktop and Android Java I2P releases only. Some related tasks for resources such as the website and plugins may be included.
@@ -16,18 +16,51 @@
</p>
<h2 id="2.10.0">2.10.0 (API 0.9.67)</h2>
<p><b>Target release: Late August 2025</b></p>
<h2 id="2.11.0">2.11.0 (API 0.9.68)</h2>
<p><b>Target release: Early Dec. 2025</b></p>
<ul>
<li>
UDP tracker support (prop. 160)
Hybrid PQ MLKEM Ratchet final, enable by default (prop. 169)
</li>
<li>
Implement LS service record parameter (prop. 167)
Jetty 12, require Java 17+
</li>
<li>
Continue work on PQ (prop. 169);
Start checking in MLKEM parts of PQ (prop. 169)
Continue work on PQ (transports) (prop. 169)
</li>
<li>
I2CP lookup support for LS service record parameters (prop. 167)
</li>
<li>
Per-tunnel throttling
</li>
<li>
Prometheus-friendly stat subsystem
</li>
<li>
SAM support for Datagram 2/3
</li>
</ul>
<h2 id="2.10.0">2.10.0 (API 0.9.67)</h2>
<p><b>Target release: Early Sept. 2025</b></p>
<ul>
<li>
i2psnark UDP tracker support (prop. 160)
</li>
<li>
I2CP LS service record parameters (partial) (prop. 167)
</li>
<li>
I2CP async lookup API
</li>
<li>
Hybrid PQ MLKEM Ratchet Beta (prop. 169)
</li>
<li>
Continue work on PQ (transports) (prop. 169)
</li>
<li>
Tunnel build bandwidth parameters (prop. 168)
@@ -37,10 +70,19 @@
Continue work on per-tunnel throttling
</li>
<li>
Stat/graph subsystem cleanup and make prometheus-friendly
Remove unused transport ElGamal code
</li>
<li>
Tomcat update
Remove ancient SSU2 "active throttle" code
</li>
<li>
Remove ancient stat logging support
</li>
<li>
Stat/graph subsystem cleanup
</li>
<li>
Hidden mode improvements and fixes
</li>
</ul>

View File

@@ -22,7 +22,7 @@ in during the course of development. Periodic reviews are conducted to update
the "accurate for" information.
</li></ul>
<p>{% trans trac='https://i2pgit.org/i2p-hackers/i2p.www/issues' -%}
<p>{% trans trac='https://i2pgit.org/I2P_Developers/i2p.www/issues' -%}
The I2P Project is committed to maintaining accurate, current documentation.
If you find any inaccuracies in the documents linked below, please
<a href="{{ trac }}">enter a ticket identifying the problem</a>.

View File

@@ -3,8 +3,8 @@ Common structures Specification
===============================
.. meta::
:category: Design
:lastupdated: 2025-04
:accuratefor: 0.9.66
:lastupdated: 2025-06
:accuratefor: 0.9.67
.. contents::
@@ -84,15 +84,24 @@ X25519 keys are supported in RouterIdentities as of release 0.9.48.
======= ============== ====== =====
Type Length (bytes) Since Usage
======= ============== ====== =====
ElGamal 256 Deprecated for Router Identities as of 0.9.58; use for Destinations, as the public key field is unused there; discouraged for leasesets
P256 64 TBD Reserved, see proposal 145
P384 96 TBD Reserved, see proposal 145
P521 132 TBD Reserved, see proposal 145
X25519 32 0.9.38 Little-endian. See [ECIES]_ and [ECIES-ROUTERS]_
======= ============== ====== =====
================ ================= ====== =====
Type Length (bytes) Since Usage
================ ================= ====== =====
ElGamal 256 Deprecated for Router Identities as of 0.9.58; use for Destinations, as the public key field is unused there; discouraged for leasesets
P256 64 TBD Reserved, see proposal 145
P384 96 TBD Reserved, see proposal 145
P521 132 TBD Reserved, see proposal 145
X25519 32 0.9.38 Little-endian. See [ECIES]_ and [ECIES-ROUTERS]_
MLKEM512_X25519 32 0.9.67 See [ECIES-HYBRID]_, for Leasesets only, not for RIs or Destinations
MLKEM768_X25519 32 0.9.67 See [ECIES-HYBRID]_, for Leasesets only, not for RIs or Destinations
MLKEM1024_X25519 32 0.9.67 See [ECIES-HYBRID]_, for Leasesets only, not for RIs or Destinations
MLKEM512 800 0.9.67 See [ECIES-HYBRID]_, for handshakes only, not for Leasesets, RIs or Destinations
MLKEM768 1184 0.9.67 See [ECIES-HYBRID]_, for handshakes only, not for Leasesets, RIs or Destinations
MLKEM1024 1568 0.9.67 See [ECIES-HYBRID]_, for handshakes only, not for Leasesets, RIs or Destinations
MLKEM512_CT 768 0.9.67 See [ECIES-HYBRID]_, for handshakes only, not for Leasesets, RIs or Destinations
MLKEM768_CT 1088 0.9.67 See [ECIES-HYBRID]_, for handshakes only, not for Leasesets, RIs or Destinations
MLKEM1024_CT 1568 0.9.67 See [ECIES-HYBRID]_, for handshakes only, not for Leasesets, RIs or Destinations
================ ================= ====== =====
JavaDoc: http://{{ i2pconv('idk.i2p/javadoc-i2p') }}/net/i2p/data/PublicKey.html
@@ -116,15 +125,21 @@ The default type is ElGamal. As of release
0.9.38, other types may be supported, depending on context.
Keys are big-endian unless otherwise noted.
======= ============== ====== =====
Type Length (bytes) Since Usage
======= ============== ====== =====
ElGamal 256 Deprecated for Router Identities as of 0.9.58; use for Destinations, as the public key field is unused there; discouraged for leasesets
P256 32 TBD Reserved, see proposal 145
P384 48 TBD Reserved, see proposal 145
P521 66 TBD Reserved, see proposal 145
X25519 32 0.9.38 Little-endian. See [ECIES]_ and [ECIES-ROUTERS]_
======= ============== ====== =====
================ ================== ====== =====
Type Length (bytes) Since Usage
================ ================== ====== =====
ElGamal 256 Deprecated for Router Identities as of 0.9.58; use for Destinations, as the public key field is unused there; discouraged for leasesets
P256 32 TBD Reserved, see proposal 145
P384 48 TBD Reserved, see proposal 145
P521 66 TBD Reserved, see proposal 145
X25519 32 0.9.38 Little-endian. See [ECIES]_ and [ECIES-ROUTERS]_
MLKEM512_X25519 32 0.9.67 See [ECIES-HYBRID]_, for Leasesets only, not for RIs or Destinations
MLKEM768_X25519 32 0.9.67 See [ECIES-HYBRID]_, for Leasesets only, not for RIs or Destinations
MLKEM1024_X25519 32 0.9.67 See [ECIES-HYBRID]_, for Leasesets only, not for RIs or Destinations
MLKEM512 1632 0.9.67 See [ECIES-HYBRID]_, for handshakes only, not for Leasesets, RIs or Destinations
MLKEM768 2400 0.9.67 See [ECIES-HYBRID]_, for handshakes only, not for Leasesets, RIs or Destinations
MLKEM1024 3168 0.9.67 See [ECIES-HYBRID]_, for handshakes only, not for Leasesets, RIs or Destinations
================ ================== ====== =====
JavaDoc: http://{{ i2pconv('idk.i2p/javadoc-i2p') }}/net/i2p/data/PrivateKey.html
@@ -436,26 +451,39 @@ RSA_SHA384_3072 5 384 0.9.12 Deprecated
RSA_SHA512_4096 6 512 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations
EdDSA_SHA512_Ed25519 7 32 0.9.15 Recent Router Identities and Destinations
EdDSA_SHA512_Ed25519ph 8 32 0.9.25 Offline only; never used in Key Certificates for Router Identities or Destinations
reserved (GOST) 9 64 Reserved, see proposal 134
reserved (GOST) 10 128 Reserved, see proposal 134
reserved (GOST) 9 64 Reserved, see [Prop134]_
reserved (GOST) 10 128 Reserved, see [Prop134]_
RedDSA_SHA512_Ed25519 11 32 0.9.39 For Destinations and encrypted leasesets only; never used for Router Identities
reserved (MLDSA) 12 Reserved, see [Prop169]_
reserved (MLDSA) 13 Reserved, see [Prop169]_
reserved (MLDSA) 14 Reserved, see [Prop169]_
reserved (MLDSA) 15 Reserved, see [Prop169]_
reserved (MLDSA) 16 Reserved, see [Prop169]_
reserved (MLDSA) 17 Reserved, see [Prop169]_
reserved (MLDSA) 18 Reserved, see [Prop169]_
reserved (MLDSA) 19 Reserved, see [Prop169]_
reserved (MLDSA) 20 Reserved, see [Prop169]_
reserved 65280-65534 Reserved for experimental use
reserved 65535 Reserved for future expansion
====================== =========== ======================= ====== =====
The defined Crypto Public Key types are:
======== =========== ======================= =====
Type Type Code Total Public Key Length Usage
======== =========== ======================= =====
ElGamal 0 256 Deprecated for Router Identities as of 0.9.58; use for Destinations, as the public key field is unused there
P256 1 64 Reserved, see proposal 145
P384 2 96 Reserved, see proposal 145
P521 3 132 Reserved, see proposal 145
X25519 4 32 See [ECIES]_ and proposal 156
reserved 65280-65534 Reserved for experimental use
reserved 65535 Reserved for future expansion
======== =========== ======================= =====
================ =========== ======================= ====== =====
Type Type Code Total Public Key Length Since Usage
================ =========== ======================= ====== =====
ElGamal 0 256 Deprecated for Router Identities as of 0.9.58; use for Destinations, as the public key field is unused there
P256 1 64 Reserved, see proposal 145
P384 2 96 Reserved, see proposal 145
P521 3 132 Reserved, see proposal 145
X25519 4 32 0.9.38 See [ECIES]_ and proposal 156
MLKEM512_X25519 5 32 0.9.67 See [ECIES-HYBRID]_, for Leasesets only, not for RIs or Destinations
MLKEM768_X25519 6 32 0.9.67 See [ECIES-HYBRID]_, for Leasesets only, not for RIs or Destinations
MLKEM1024_X25519 7 32 0.9.67 See [ECIES-HYBRID]_, for Leasesets only, not for RIs or Destinations
reserved (NONE) 255 Reserved, see [Prop169]_
reserved 65280-65534 Reserved for experimental use
reserved 65535 Reserved for future expansion
================ =========== ======================= ====== =====
When a Key Certificate is not present, the preceeding 384 bytes in the
Destination or RouterIdentity are defined as the 256-byte ElGamal PublicKey
@@ -1881,6 +1909,9 @@ References
.. [ECIES]
{{ spec_url('ecies') }}
.. [ECIES-HYBRID]
{{ spec_url('ecies-hybrid') }}
.. [ECIES-ROUTERS]
{{ spec_url('ecies-routers') }}
@@ -1905,6 +1936,12 @@ References
.. [NETDB-ROUTERINFO]
{{ site_url('docs/how/network-database', True) }}#routerInfo
.. [Prop134]
{{ proposal_url('134') }}
.. [Prop169]
{{ proposal_url('169') }}
.. [REGISTRY]
http://www.dns-sd.org/ServiceTypes.html

View File

@@ -0,0 +1,833 @@
===================================
PQ Hybrid ECIES-X25519-AEAD-Ratchet
===================================
.. meta::
:category: Protocols
:lastupdated: 2025-06
:accuratefor: 0.9.67
.. contents::
Note
====
Implementation, testing, and rollout in progress in the various
router implementations. Check the documentation of those implementations for status.
Overview
========
This is the PQ Hybrid variant of the ECIES-X25519-AEAD-Ratchet protocol [ECIES]_.
It is the first phase of the overall PQ proposal [Prop169]_
to be approved. See that proposal for overall goals, threat models,
analysis, alternatives, and additional information.
This specification contains only the differences from standard [ECIES]_
and must be read in conjunction with that specification.
Design
======
We use the NIST FIPS 203 standard [FIPS203]_
which is based on, but not compatible with,
CRYSTALS-Kyber (versions 3.1, 3, and older).
Hybrid handshakes are as specified in [Noise-Hybrid]_.
Key Exchange
-------------
We define a hybrid key exchange for Ratchet.
PQ KEM provides ephemeral keys only, and does not directly support
static-key handshakes such as Noise IK.
We define the three ML-KEM variants as in [FIPS203]_,
for 3 new encryption types total.
Hybrid types are only defined in combination with X25519.
The new encryption types are:
================ ====
Type Code
================ ====
MLKEM512_X25519 5
MLKEM768_X25519 6
MLKEM1024_X25519 7
================ ====
Overhead will be substantial. Typical message 1 and 2 sizes (for IK)
are currently around 100 bytes (before any additional payload).
This will increase by 8x to 15x depending on algorithm.
New Crypto Required
-------------------
- ML-KEM (formerly CRYSTALS-Kyber) [FIPS203]_
- SHA3-128 (formerly Keccak-256) [FIPS202]_ Used only for SHAKE128
- SHA3-256 (formerly Keccak-512) [FIPS202]_
- SHAKE128 and SHAKE256 (XOF extensions to SHA3-128 and SHA3-256) [FIPS202]_
Test vectors for SHA3-256, SHAKE128, and SHAKE256 are at [NIST-VECTORS]_.
Note that the Java bouncycastle library supports all the above.
C++ library support is in OpenSSL 3.5 [OPENSSL]_.
Specification
=============
Common Structures
-----------------
See the common structures specification [COMMON]_ for key lengths and identifiers.
Handshake Patterns
------------------
Handshakes use [Noise]_ handshake patterns.
The following letter mapping is used:
- e = one-time ephemeral key
- s = static key
- p = message payload
- e1 = one-time ephemeral PQ key, sent from Alice to Bob
- ekem1 = the KEM ciphertext, sent from Bob to Alice
The following modifications to XK and IK for hybrid forward secrecy (hfs) are
as specified in [Noise-Hybrid]_ section 5:
.. raw:: html
{% highlight lang='dataspec' %}
IK: IKhfs:
<- s <- s
... ...
-> e, es, s, ss, p -> e, es, e1, s, ss, p
<- tag, e, ee, se, p <- tag, e, ee, ekem1, se, p
<- p <- p
p -> p ->
e1 and ekem1 are encrypted. See pattern definitions below.
NOTE: e1 and ekem1 are different sizes (unlike X25519)
{% endhighlight %}
The e1 pattern is defined as follows, as specified in [Noise-Hybrid]_ section 4:
.. raw:: html
{% highlight lang='dataspec' %}
For Alice:
(encap_key, decap_key) = PQ_KEYGEN()
// EncryptAndHash(encap_key)
ciphertext = ENCRYPT(k, n, encap_key, ad)
n++
MixHash(ciphertext)
For Bob:
// DecryptAndHash(ciphertext)
encap_key = DECRYPT(k, n, ciphertext, ad)
n++
MixHash(ciphertext)
{% endhighlight %}
The ekem1 pattern is defined as follows, as specified in [Noise-Hybrid]_ section 4:
.. raw:: html
{% highlight lang='dataspec' %}
For Bob:
(kem_ciphertext, kem_shared_key) = ENCAPS(encap_key)
// EncryptAndHash(kem_ciphertext)
ciphertext = ENCRYPT(k, n, kem_ciphertext, ad)
MixHash(ciphertext)
// MixKey
MixKey(kem_shared_key)
For Alice:
// DecryptAndHash(ciphertext)
kem_ciphertext = DECRYPT(k, n, ciphertext, ad)
MixHash(ciphertext)
// MixKey
kem_shared_key = DECAPS(kem_ciphertext, decap_key)
MixKey(kem_shared_key)
{% endhighlight %}
Defined ML-KEM Operations
-------------------------
We define the following functions corresponding to the cryptographic building blocks used
as defined in [FIPS203]_.
(encap_key, decap_key) = PQ_KEYGEN()
Alice creates the encapsulation and decapsulation keys
The encapsulation key is sent in the NS message.
encap_key and decap_key sizes vary based on ML-KEM variant.
(ciphertext, kem_shared_key) = ENCAPS(encap_key)
Bob calculates the ciphertext and shared key,
using the ciphertext received in the NS message.
The ciphertext is sent in the NSR message.
ciphertext size varies based on ML-KEM variant.
The kem_shared_key is always 32 bytes.
kem_shared_key = DECAPS(ciphertext, decap_key)
Alice calculates the shared key,
using the ciphertext received in the NSR message.
The kem_shared_key is always 32 bytes.
Note that both the encap_key and the ciphertext are encrypted inside ChaCha/Poly
blocks in the Noise handshake messages 1 and 2.
They will be decrypted as part of the handshake process.
The kem_shared_key is mixed into the chaining key with MixHash().
See below for details.
Noise Handshake KDF
---------------------
Overview
````````
The hybrid handshake is defined in [Noise-Hybrid]_.
The first message, from Alice to Bob, contains e1, the encapsulation key, before the message payload.
This is treated as an additional static key; call EncryptAndHash() on it (as Alice)
or DecryptAndHash() (as Bob).
Then process the message payload as usual.
The second message, from Bob to Alice, contains ekem1, the ciphertext, before the message payload.
This is treated as an additional static key; call EncryptAndHash() on it (as Bob)
or DecryptAndHash() (as Alice).
Then, calculate the kem_shared_key and call MixKey(kem_shared_key).
Then process the message payload as usual.
Noise identifiers
`````````````````
These are the Noise initialization strings:
- "Noise_IKhfselg2_25519+MLKEM512_ChaChaPoly_SHA256"
- "Noise_IKhfselg2_25519+MLKEM768_ChaChaPoly_SHA256"
- "Noise_IKhfselg2_25519+MLKEM1024_ChaChaPoly_SHA256"
Alice KDF for NS Message
`````````````````````````
After the 'es' message pattern and before the 's' message pattern, add:
.. raw:: html
{% highlight lang='text' %}
This is the "e1" message pattern:
(encap_key, decap_key) = PQ_KEYGEN()
// EncryptAndHash(encap_key)
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, encap_key, ad)
n++
// MixHash(ciphertext)
h = SHA256(h || ciphertext)
End of "e1" message pattern.
NOTE: For the next section (payload for XK or static key for IK),
the keydata and chain key remain the same,
and n now equals 1 (instead of 0 for non-hybrid).
{% endhighlight %}
Bob KDF for NS Message
`````````````````````````
After the 'es' message pattern and before the 's' message pattern, add:
.. raw:: html
{% highlight lang='text' %}
This is the "e1" message pattern:
// DecryptAndHash(encap_key_section)
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
encap_key = DECRYPT(k, n, encap_key_section, ad)
n++
// MixHash(encap_key_section)
h = SHA256(h || encap_key_section)
End of "e1" message pattern.
NOTE: For the next section (payload for XK or static key for IK),
the keydata and chain key remain the same,
and n now equals 1 (instead of 0 for non-hybrid).
{% endhighlight %}
Bob KDF for NSR Message
`````````````````````````
After the 'ee' message pattern and before the 'se' message pattern, add:
.. raw:: html
{% highlight lang='text' %}
This is the "ekem1" message pattern:
(kem_ciphertext, kem_shared_key) = ENCAPS(encap_key)
// EncryptAndHash(kem_ciphertext)
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, kem_ciphertext, ad)
// MixHash(ciphertext)
h = SHA256(h || ciphertext)
// MixKey(kem_shared_key)
keydata = HKDF(chainKey, kem_shared_key, "", 64)
chainKey = keydata[0:31]
End of "ekem1" message pattern.
{% endhighlight %}
Alice KDF for NSR Message
`````````````````````````
After the 'ee' message pattern and before the 'ss' message pattern, add:
.. raw:: html
{% highlight lang='text' %}
This is the "ekem1" message pattern:
// DecryptAndHash(kem_ciphertext_section)
// AEAD parameters
k = keydata[32:63]
n = 0
ad = h
kem_ciphertext = DECRYPT(k, n, kem_ciphertext_section, ad)
// MixHash(kem_ciphertext_section)
h = SHA256(h || kem_ciphertext_section)
// MixKey(kem_shared_key)
kem_shared_key = DECAPS(kem_ciphertext, decap_key)
keydata = HKDF(chainKey, kem_shared_key, "", 64)
chainKey = keydata[0:31]
End of "ekem1" message pattern.
{% endhighlight %}
KDF for split()
```````````````
unchanged
Message Format
--------------
NS Format
`````````
Changes: Current ratchet contained the static key in the first ChaCha section,
and the payload in the second section.
With ML-KEM, there are now three sections.
The first section contains the encrypted PQ public key.
The second section contains the static key.
The third section contains the payload.
Encrypted format:
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| |
+ +
| New Session Ephemeral Public Key |
+ 32 bytes +
| Encoded with Elligator2 |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ ML-KEM encap_key +
| ChaCha20 encrypted data |
+ (see table below for length) +
| |
~ ~
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for encap_key Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| |
+ X25519 Static Key +
| ChaCha20 encrypted data |
+ 32 bytes +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Static Key Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| ChaCha20 encrypted data |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Payload Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
Decrypted format:
.. raw:: html
{% highlight lang='dataspec' %}
Payload Part 1:
+----+----+----+----+----+----+----+----+
| |
+ ML-KEM encap_key +
| |
+ (see table below for length) +
| |
~ ~
| |
+----+----+----+----+----+----+----+----+
Payload Part 2:
+----+----+----+----+----+----+----+----+
| |
+ X25519 Static Key +
| |
+ (32 bytes) +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
Payload Part 3:
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
Sizes:
================ ========= ===== ========= ============= ============= ========== =======
Type Type Code X len NS len NS Enc len NS Dec len PQ key len pl len
================ ========= ===== ========= ============= ============= ========== =======
X25519 4 32 96+pl 64+pl pl -- pl
MLKEM512_X25519 5 32 912+pl 880+pl 800+pl 800 pl
MLKEM768_X25519 6 32 1296+pl 1360+pl 1184+pl 1184 pl
MLKEM1024_X25519 7 32 1680+pl 1648+pl 1568+pl 1568 pl
================ ========= ===== ========= ============= ============= ========== =======
Note that the payload must contain a DateTime block, so the minimum payload size is 7.
The minimum NS sizes may be calculated accordingly.
NSR Format
``````````
Changes: Current ratchet has an empty payload for the first ChaCha section,
and the payload in the second section.
With ML-KEM, there are now three sections.
The first section contains the encrypted PQ ciphertext.
The second section has an empty payload.
The third section contains the payload.
Encrypted format:
.. raw:: html
{% highlight lang='dataspec' %}
+----+----+----+----+----+----+----+----+
| Session Tag 8 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Ephemeral Public Key +
| |
+ 32 bytes +
| Encoded with Elligator2 |
+ +
| |
+----+----+----+----+----+----+----+----+
| |
+ +
| ChaCha20 encrypted ML-KEM ciphertext |
+ (see table below for length) +
~ ~
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for ciphertext Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for key Section (no data) +
| 16 bytes |
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| ChaCha20 encrypted data |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| Poly1305 Message Authentication Code |
+ (MAC) for Payload Section +
| 16 bytes |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
Decrypted format:
.. raw:: html
{% highlight lang='dataspec' %}
Payload Part 1:
+----+----+----+----+----+----+----+----+
| |
+ ML-KEM ciphertext +
| |
+ (see table below for length) +
| |
~ ~
| |
+----+----+----+----+----+----+----+----+
Payload Part 2:
empty
Payload Part 3:
+----+----+----+----+----+----+----+----+
| |
+ Payload Section +
| |
~ ~
| |
+ +
| |
+----+----+----+----+----+----+----+----+
{% endhighlight %}
Sizes:
================ ========= ===== ========= ============= ============= ========== =======
Type Type Code Y len NSR len NSR Enc len NSR Dec len PQ CT len opt len
================ ========= ===== ========= ============= ============= ========== =======
X25519 4 32 72+pl 32+pl pl -- pl
MLKEM512_X25519 5 32 856+pl 816+pl 768+pl 768 pl
MLKEM768_X25519 6 32 1176+pl 1136+pl 1088+pl 1088 pl
MLKEM1024_X25519 7 32 1656+pl 1616+pl 1568+pl 1568 pl
================ ========= ===== ========= ============= ============= ========== =======
Note that while NSR will normally have a nonzero payload,
the ratchet specification [ECIES]_ does not require it, so the minimum payload size is 0.
The minimum NSR sizes may be caculated accordingly.
Overhead Analysis
=================
Key Exchange
-------------
Size increase (bytes):
================ ============== =============
Type Pubkey (NS) Cipertext (NSR)
================ ============== =============
MLKEM512_X25519 +816 +784
MLKEM768_X25519 +1200 +1104
MLKEM1024_X25519 +1584 +1584
================ ============== =============
Speed:
Speeds as reported by [CLOUDFLARE]_:
================ ==============
Type Relative speed
================ ==============
X25519 DH/keygen baseline
MLKEM512 2.25x faster
MLKEM768 1.5x faster
MLKEM1024 1x (same)
XK 4x DH (keygen + 3 DH)
MLKEM512_X25519 4x DH + 2x PQ (keygen + enc/dec) = 4.9x DH = 22% slower
MLKEM768_X25519 4x DH + 2x PQ (keygen + enc/dec) = 5.3x DH = 32% slower
MLKEM1024_X25519 4x DH + 2x PQ (keygen + enc/dec) = 6x DH = 50% slower
================ ==============
Security Analysis
=================
NIST security categories are summarized in [NIST-PQ-END]_ slide 10.
Preliminary criteria:
Our minimum NIST security category should be 2 for hybrid protocols
and 3 for PQ-only.
======== ======
Category As Secure As
======== ======
1 AES128
2 SHA256
3 AES192
4 SHA384
5 AES256
======== ======
Handshakes
----------
These are all hybrid protocols.
Probably need to prefer MLKEM768; MLKEM512 is not secure enough.
NIST security categories [FIPS203]_ :
========= ========
Algorithm Security Category
========= ========
MLKEM512 1
MLKEM768 3
MLKEM1024 5
========= ========
Type Preferences
=================
The recommended type for initial support, based on security category and key length, is:
MLKEM768_X25519 (type 6)
Implementation Notes
=====================
Library Support
---------------
Bouncycastle, BoringSSL, and WolfSSL libraries support MLKEM now.
OpenSSL support is be in their 3.5 release April 8, 2025 [OPENSSL]_.
Shared Tunnels
--------------
Auto-classify/detect of multiple protocols on the same tunnels should be possible based
on a length check of message 1 (New Session Message).
Using MLKEM512_X25519 as an example, message 1 length is 816 bytes larger
than current ratchet protocol, and the minimum message 1 size (with only a DateTime payload included)
is 919 bytes. Most message 1 sizes with current ratchet have a payload less than
816 bytes, so they can be classified as non-hybrid ratchet.
Large messages are probably POSTs which are rare.
So the recommended strategy is:
- If message 1 is less than 919 bytes, it's the current ratchet protocol.
- If message 1 is greater than or equal to 919 bytes, it's probably MLKEM512_X25519.
Try MLKEM512_X25519 first, and if it fails, try the current ratchet protocol.
This should allow us to efficiently support standard ratchet and hybrid ratchet
on the same destination, just as we previously supported ElGamal and ratchet
on the same destination. Therefore, we can migrate to the MLKEM hybrid protocol
much more quickly than if we could not support dual-protocols for the same destination,
because we can add MLKEM support to existing destinations.
The required supported combinations are:
- X25519 + MLKEM512
- X25519 + MLKEM768
- X25519 + MLKEM1024
The following combinations may be complex, and are NOT required to be supported,
but may be, implementation-dependent:
- More than one MLKEM
- ElG + one or more MLKEM
- X25519 + one or more MLKEM
- ElG + X25519 + one or more MLKEM
It is not required to support multiple MLKEM algorithms
(for example, MLKEM512_X25519 and MLKEM_768_X25519)
on the same destination. Pick just one.
Implementation-dependent.
It is not required to support three algorithms (for example X25519, MLKEM512_X25519, and MLKEM769_X25519)
on the same destination. The classification and retry strategy may be too complex.
The configuration and configuration UI may be too complex.
Implementation-dependent.
It is not required to support ElGamal and hybrid algorithms on the same destination.
ElGamal is obsolete, and ElGamal + hybrid only (no X25519) doesn't make much sense.
Also, ElGamal and Hybrid New Session Messages are both large, so
classification strategies would often have to try both decryptions,
which would be inefficient.
Implementation-dependent.
Clients may use the same or different X25519 static keys for the X25519
and the hybrid protocols on the same tunnels, implementation-dependent.
Forward Secrecy
---------------
The ECIES specification allows Garlic Messages in the New Session Message payload,
which allows for 0-RTT delivery of the initial streaming packet,
usually a HTTP GET, together with the client's leaseset.
However, the New Session Message payload does not have forward secrecy.
As this proposal is emphasizing enhanced forward secrecy for ratchet,
implementations may or should defer inclusion of the streaming payload,
or the full streaming message, until the first Existing Session Message.
This would be at the expense of 0-RTT delivery.
Strategies may also depend on traffic type or tunnel type,
or on GET vs. POST, for example.
Implementation-dependent.
New Session Size
----------------
MLKEM will dramatically increase
the size of the New Session Message, as described above.
This may significantly decrease the reliability of New Session Message
delivery through tunnels, where they must be fragmented into
multiple 1024 byte tunnel messages. Delivery success is
proportional to the exponential number of fragments.
Implementations may use various strategies to limit the size of the message,
at the expense of 0-RTT delivery.
Implementation-dependent.
References
==========
.. [CLOUDFLARE]
https://blog.cloudflare.com/pq-2024/
.. [COMMON]
{{ spec_url('common-structures') }}
.. [ECIES]
{{ spec_url('ecies') }}
.. [FORUM]
http://zzz.i2p/topics/3294
.. [FIPS202]
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
.. [FIPS203]
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
.. [NIST-PQ-END]
https://www.nccoe.nist.gov/sites/default/files/2023-08/pqc-light-at-the-end-of-the-tunnel-presentation.pdf
.. [NIST-VECTORS]
https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values
.. [Noise]
https://noiseprotocol.org/noise.html
.. [Noise-Hybrid]
https://github.com/noiseprotocol/noise_hfs_spec/blob/master/output/noise_hfs.pdf
.. [OPENSSL]
https://openssl-library.org/post/2025-02-04-release-announcement-3.5/
.. [PQ-WIREGUARD]
https://eprint.iacr.org/2020/379.pdf
.. [Prop169]
{{ proposal_url('169') }}

View File

@@ -3,8 +3,8 @@ ECIES-X25519-AEAD-Ratchet
=========================
.. meta::
:category: Protocols
:lastupdated: 2025-04
:accuratefor: 0.9.66
:lastupdated: 2025-06
:accuratefor: 0.9.67
.. contents::
@@ -22,6 +22,7 @@ The following features are not implemented as of 0.9.66:
- Zero static key
- Multicast
For the MLKEM PQ Hybrid version of this protocol, see [ECIES-HYBRID]_.
Overview
@@ -3251,6 +3252,9 @@ References
.. [CRYPTO-ELG]
{{ site_url('docs/how/cryptography', True) }}#elgamal
.. [ECIES-HYBRID]
{{ spec_url('ecies-hybrid') }}
.. [Datagrams]
{{ spec_url('datagrams') }}

View File

@@ -3,8 +3,8 @@ I2CP Specification
==================
.. meta::
:category: Protocols
:lastupdated: 2025-04
:accuratefor: 0.9.66
:lastupdated: 2025-07
:accuratefor: 0.9.67
.. contents::
@@ -237,10 +237,14 @@ below.
============== ======================
Version Required I2CP Features
============== ======================
0.9.67 PQ Hybrid ML-KEM (enc types 5-7) supported in LS
0.9.66 Host lookup/reply extensions (see proposal 167)
0.9.62 MessageStatus message Loopback error code
0.9.46 X25519 (enc type 4) supported in LS
0.9.43 BlindingInfo message supported
Additional HostReply message failure codes
@@ -781,7 +785,9 @@ Description
```````````
This message is sent from a client to destroy a session.
Sent from Client to Router. The router responds with a SessionStatusMessage_.
Sent from Client to Router. The router should respond with a SessionStatusMessage_ (Destroyed).
However, see important notes below.
Contents
````````
@@ -791,6 +797,26 @@ Notes
`````
The router at this point should release all resources related to the session.
Through API 0.9.66,
the Java I2P router and client libraries deviate substantially from this specification.
The router never sends a SessionStatus(Destroyed) response.
If no sessions are left, it sends a DisconnectMessage_.
If there are subsessions or the primary session is remaining, it does not reply.
The Java client library responds to a SessionStatus message by destroying
all sessions and reconnecting.
Destroying individual subsessions on a connection with multiple sessions
may not be fully tested or working on various router and client implementations.
Use caution.
Implementations should treat a destroy for a primary session as a destroy
for all subsessions, but allow a destroy for a single subsession
and keep the connection open, but Java I2P does not do that now.
If Java I2P behavior is changed in subsequent releases, it will be documented here.
.. _msg-Disconnect:
DisconnectMessage
@@ -799,7 +825,8 @@ DisconnectMessage
Description
```````````
Tell the other party that there are problems and the current connection is about to
be destroyed. This does not necessarily end a session.
be destroyed. This ends all sessions on that connection.
The socket will be closed shortly.
Sent either from router to client or from client to router.
Contents
@@ -808,8 +835,8 @@ Contents
Notes
`````
Only implemented in the router-to-client direction. Disconnecting probably
does end a session, in practice.
Only implemented in the router-to-client direction, at least in Java I2P.
.. _msg-GetBandwidthLimits:

View File

@@ -3,7 +3,7 @@ I2NP Specification
==================
.. meta::
:category: Protocols
:lastupdated: 2025-04
:lastupdated: 2025-08
:accuratefor: 0.9.66
.. contents::
@@ -917,18 +917,18 @@ Contents
through release 0.9.5, must be set to 00
as of release 0.9.6, ignored
as of release 0.9.16:
00 => normal lookup, return `RouterInfo` or `LeaseSet` or
`DatabaseSearchReplyMessage`
Not recommended when sending to routers
with version 0.9.16 or higher.
00 => ANY lookup, return `RouterInfo` or `LeaseSet` or
`DatabaseSearchReplyMessage`. DEPRECATED.
Use LS or RI lookup as of 0.9.16.
01 => LS lookup, return `LeaseSet` or
`DatabaseSearchReplyMessage`
As of release 0.9.38, may also return a
`LeaseSet2`, `MetaLeaseSet`, or `EncryptedLeaseSet`.
10 => RI lookup, return `RouterInfo` or
`DatabaseSearchReplyMessage`
11 => exploration lookup, return `DatabaseSearchReplyMessage`
containing non-floodfill routers only (replaces an
11 => exploration lookup, return `RouterInfo` or
`DatabaseSearchReplyMessage` containing
non-floodfill routers only (replaces an
excludedPeer of all zeroes)
bit 4: ECIESFlag
before release 0.9.46 ignored

View File

@@ -5,13 +5,23 @@ UDP Trackers
:author: zzz
:created: 2022-01-03
:thread: http://zzz.i2p/topics/1634
:lastupdated: 2025-06-09
:status: Open
:target: 0.9.68
:lastupdated: 2025-06-25
:status: Closed
:target: 0.9.67
.. contents::
Status
======
Approved at review 2025-06-24.
Specification is at [UDP]_.
Implementated in zzzot 0.20.0-beta2.
Implementated in i2psnark as of API 0.9.67.
Check documentation of other implementations for status.
Overview
========
@@ -563,3 +573,6 @@ References
.. [SPEC]
{{ site_url('docs/applications/bittorrent', True) }}
.. [UDP]
{{ spec_url('udp-announces') }}

View File

@@ -7,7 +7,7 @@ Datagram2 Protocol
:thread: http://zzz.i2p/topics/3540
:lastupdated: 2025-04-16
:status: Closed
:target: 0.9.67
:target: 0.9.66
.. contents::
@@ -17,8 +17,7 @@ Status
Approved at review 2025-04-15.
Changes incorporated into specs.
Not yet supported in any known implenentations.
Target implementation for Java I2P is API 0.9.67.
Implementated in Java I2P as of API 0.9.66.
Check implementation documentation for status.

View File

@@ -5,7 +5,7 @@ Post-Quantum Crypto Protocols
:author: zzz, orignal, drzed, eyedeekay
:created: 2025-01-21
:thread: http://zzz.i2p/topics/3294
:lastupdated: 2025-04-23
:lastupdated: 2025-06-12
:status: Open
:target: 0.9.80
@@ -83,14 +83,10 @@ See the Priorities and Rollout section below for details.
================================== ======
Protocol / Feature Status
================================== ======
Hybrid EncTypes 5-7 Preliminary, final hash choices pending
Hybrid Dests, Ratchet Tested on live net, no net upgrade required
Select preferred combo Probably 6,4
Combo Hybrid/X25519 Dests, Ratchet
Combo Hybrid/X25519 NTCP2
Combo Hybrid/X25519 SSU2
Hybrid Routers, Dests, Ratchet
MLDSA SigTypes 12-14 Probably final
Hybrid MLKEM Ratchet and LS Approved 2026-06; beta target 2025-08; release target 2025-11
Hybrid MLKEM NTCP2 Some details to be finalized
Hybrid MLKEM SSU2 Some details to be finalized
MLDSA SigTypes 12-14 Proposal is stable but may not be finalized until 2026
MLDSA Dests Tested on live net, requires net upgrade for floodfill support
Hybrid SigTypes 15-17 Preliminary
Hybrid Dests
@@ -243,7 +239,7 @@ New Crypto Required
Test vectors for SHA3-256, SHAKE128, and SHAKE256 are at [NIST-VECTORS]_.
Note that the Java bouncycastle library supports all the above.
C++ library support will be in OpenSSL 3.5 [OPENSSL]_.
C++ library support is in OpenSSL 3.5 [OPENSSL]_.
Alternatives
@@ -965,7 +961,7 @@ MLKEM1024_X25519 7 32 1680+pl 1648+pl 1568+pl
================ ========= ===== ========= ============= ============= ========== =======
Note that the payload must contain a DateTime block, so the minimum payload size is 7.
The minimum message 1 sizes may be caculated accordingly.
The minimum message 1 sizes may be calculated accordingly.
@@ -1077,7 +1073,7 @@ MLKEM1024_X25519 7 32 1656+pl 1616+pl 1568+pl
Note that while message 2 will normally have a nonzero payload,
the ratchet specification [ECIES]_ does not require it, so the minimum payload size is 0.
The minimum message 2 sizes may be caculated accordingly.
The minimum message 2 sizes may be calculated accordingly.
@@ -1843,8 +1839,7 @@ Library Support
---------------
Bouncycastle, BoringSSL, and WolfSSL libraries support MLKEM and MLDSA now.
OpenSSL support will be in their 3.5 release scheduled for April 8, 2025 [OPENSSL]_.
3.5-alpha will be availabe March 11, 2025.
OpenSSL support is be in their 3.5 release April 8, 2025 [OPENSSL]_.
The southernstorm.com Noise library adapted by Java I2P contained preliminary support for
hybrid handshakes, but we removed it as unused; we will have to add it back

View File

@@ -18,7 +18,7 @@ It is a portion of the overall proposal
There are two versions specified.
The first uses the existing build messages and build record size, for compatibility with ElGamal routers.
This specification is implemented as of release 0.9.48.
This specification was implemented as of release 0.9.48 and is now deprecated.
The second uses two new build messages and a smaller build record size, and may only be used with ECIES routers.
This specification is implemented as of release 0.9.51.
@@ -138,6 +138,7 @@ ECIES replies use ChaCha20/Poly1305 AEAD for integrity, and authentication.
Long Record Specification
=========================
NOTE: Deprecated, obsolete. Use the Short Record format specified below.
Build Request Records

View File

@@ -0,0 +1,457 @@
================================
UDP Trackers
================================
.. meta::
:category: Protocols
:lastupdated: 2025-06
:accuratefor: 0.9.67
.. contents::
Overview
========
This specification documents the protocol for UDP bittorrent announces in I2P.
For the overall specification of bittorrent in I2P, see [SPEC]_.
For background and additional information on the development
of this specification, see Proposal 160 [Prop160]_.
Design
============
This proposal uses repliable datagram2, repliable datagram3, and raw datagrams,
as defined in [DATAGRAMS]_.
Datagram2 and Datagram3 are new variants of repliable datagrams,
defined in Proposal 163 [Prop163]_.
Datagram2 adds replay resistance and offline signature support.
Datagram3 is smaller than the old datagram format, but without authentication.
BEP 15
-------
For reference, the message flow defined in [BEP15]_ is as follows:
.. raw:: html
{% highlight %}
Client Tracker
Connect Req. ------------->
<-------------- Connect Resp.
Announce Req. ------------->
<-------------- Announce Resp.
Announce Req. ------------->
<-------------- Announce Resp.
{% endhighlight %}
The connect phase is required to prevent IP address spoofing.
The tracker returns a connection ID that the client uses in subsequent announces.
This connection ID expires by default in one minute at the client, and in two minutes at the tracker.
I2P will use the same message flow as BEP 15,
for ease of adoption in existing UDP-capable client code bases:
for efficiency, and for security reasons discussed below:
.. raw:: html
{% highlight %}
Client Tracker
Connect Req. -------------> (Repliable Datagram2)
<-------------- Connect Resp. (Raw)
Announce Req. -------------> (Repliable Datagram3)
<-------------- Announce Resp. (Raw)
Announce Req. -------------> (Repliable Datagram3)
<-------------- Announce Resp. (Raw)
...
{% endhighlight %}
This potentially provides a large bandwidth savings over
streaming (TCP) announces.
While the Datagram2 is about the same size as a streaming SYN,
the raw response is much smaller than the streaming SYN ACK.
Subsequent requests use Datagram3, and the subsequent responses are raw.
The announce requests are Datagram3 so that the tracker need not
maintain a large mapping table of connection IDs to announce destination or hash.
Instead, the tracker may generate connection IDs cryptographically
from the sender hash, the current timestamp (based on some interval),
and a secret value.
When an announce request is received, the tracker validates the
connection ID, and then uses the
Datagram3 sender hash as the send target.
Connection Lifetime
-------------------
[BEP15]_ specifies that the connection ID expires in one minute at the client, and in two minutes at the tracker.
It is not configurable.
That limits the potential efficiency gains, unless
clients batched announces to do all of them within a one-minute window.
i2psnark does not currently batch announces; it spreads them out, to avoid bursts of traffic.
Power users are reported to be running thousands of torrents at once,
and bursting that many announces into one minute is not realistic.
Here, we propose to extend the connect response to add an optional connection lifetime field.
The default, if not present, is one minute. Otherwise, the lifetime specified
in seconds, shall be used by the client, and the tracker will maintain the
connection ID for one minute more.
Compatibility with BEP 15
-------------------------
This design maintains compatibility with [BEP15]_ as much as possible
to limit changes required in existing clients and trackers.
The only required change is the format of peer info in the announce response.
The addition of the lifetime field in the connect response is not required
but is strongly recommended for efficiency, as explained above.
Security Analysis
------------------
An important goal of a UDP announce protocol is to prevent address spoofing.
The client must actually exist and bundle a real leaseset.
It must have inbound tunnels to receive the Connect Response.
These tunnels could be zero-hop and built instantly, but that would
expose the creator.
This protocol accomplishes that goal.
Issues
------
- This protocol does not support blinded destinations,
but may be extended to do so. See below.
Specification
=============
Protocols and Ports
-------------------
Repliable Datagram2 uses I2CP protocol 19;
repliable Datagram3 uses I2CP protocol 20;
raw datagrams use I2CP protocol 18.
Requests may be Datagram2 or Datagram3. Responses are always raw.
The older repliable datagram ("Datagram1") format using I2CP protocol 17
must NOT be used for requests or replies; these must be dropped if received
on the request/reply ports. Note that Datagram1 protocol 17
is still used for the DHT protocol.
Requests use the I2CP "to port" from the announce URL; see below.
The request "from port" is chosen by the client, but should be nonzero,
and a different port from those used by DHT, so that responses
may be easily classified.
Trackers should reject requests received on the wrong port.
Responses use the I2CP "to port" from the request.
The request "from port" is the "to port" from the request.
Announce URL
------------
The announce URL format is not specified in [BEP15]_,
but as in clearnet, UDP announce URLs are of the form "udp://host:port/path".
The path is ignored and may be empty, but is typically "/announce" on clearnet.
The :port part should always be present, however,
if the ":port" part is omitted, use a default I2CP port of 6969,
as that is the common port on clearnet.
There may also be cgi parameters &a=b&c=d appended,
those may be processed and provided in the announce request, see [BEP41]_.
If there are no parameters or path, the trailing / may also be omitted,
as implied in [BEP41]_.
Datagram Formats
----------------
All values are send in network byte order (big endian).
Do not expect packets to be exactly of a certain size.
Future extensions could increase the size of packets.
Connect Request
```````````````
Client to tracker.
16 bytes. Must be repliable Datagram2. Same as in [BEP15]_. No changes.
.. raw:: html
{% highlight %}
Offset Size Name Value
0 64-bit integer protocol_id 0x41727101980 // magic constant
8 32-bit integer action 0 // connect
12 32-bit integer transaction_id
{% endhighlight %}
Connect Response
````````````````
Tracker to client.
16 or 18 bytes. Must be raw. Same as in [BEP15]_ except as noted below.
.. raw:: html
{% highlight %}
Offset Size Name Value
0 32-bit integer action 0 // connect
4 32-bit integer transaction_id
8 64-bit integer connection_id
16 16-bit integer lifetime optional // Change from BEP 15
{% endhighlight %}
The response MUST be sent to the I2CP "to port" that was received as the request "from port".
The lifetime field is optional and indicates the connection_id client lifetime in seconds.
The default is 60, and the minimum if specified is 60.
The maximum is 65535 or about 18 hours.
The tracker should maintain the connection_id for 60 seconds more than the client lifetime.
Announce Request
````````````````
Client to tracker.
98 bytes minimum. Must be repliable Datagram3. Same as in [BEP15]_ except as noted below.
The connection_id is as received in the connect response.
.. raw:: html
{% highlight %}
Offset Size Name Value
0 64-bit integer connection_id
8 32-bit integer action 1 // announce
12 32-bit integer transaction_id
16 20-byte string info_hash
36 20-byte string peer_id
56 64-bit integer downloaded
64 64-bit integer left
72 64-bit integer uploaded
80 32-bit integer event 0 // 0: none; 1: completed; 2: started; 3: stopped
84 32-bit integer IP address 0 // default, unused in I2P
88 32-bit integer key
92 32-bit integer num_want -1 // default
96 16-bit integer port // must be same as I2CP from port
98 varies options optional // As specified in BEP 41
{% endhighlight %}
Changes from [BEP15]_:
- key is ignored
- IP address is unused
- port is probably ignored but must be same as I2CP from port
- The options section, if present, is as defined in [BEP41]_
The response MUST be sent to the I2CP "to port" that was received as the request "from port".
Do not use the port from the announce request.
Announce Response
`````````````````
Tracker to client.
20 bytes minimum. Must be raw. Same as in [BEP15]_ except as noted below.
.. raw:: html
{% highlight %}
Offset Size Name Value
0 32-bit integer action 1 // announce
4 32-bit integer transaction_id
8 32-bit integer interval
12 32-bit integer leechers
16 32-bit integer seeders
20 32 * n 32-byte hash binary hashes // Change from BEP 15
... // Change from BEP 15
{% endhighlight %}
Changes from [BEP15]_:
- Instead of 6-byte IPv4+port or 18-byte IPv6+port, we return
a multiple of 32-byte "compact responses" with the SHA-256 binary peer hashes.
As with TCP compact responses, we do not include a port.
The response MUST be sent to the I2CP "to port" that was received as the request "from port".
Do not use the port from the announce request.
I2P datagrams have a very large maximum size of about 64 KB;
however, for reliable delivery, datagrams larger than 4 KB should be avoided.
For bandwidth efficiency, trackers should probably limit the maximum peers
to about 50, which corresponds to about a 1600 byte packet before overhead
at various layers, and should be within a two-tunnel-message payload limit
after fragmentation.
As in BEP 15, there is no count included of the number of peer addresses
(IP/port for BEP 15, hashes here) to follow.
While not contemplated in BEP 15, an end-of-peers marker
of all zeros could be defined to indicate that the peer info is complete
and some extension data follows.
So that extension is possible in the future, clients should ignore
a 32-byte all-zeros hash, and any data that follows.
Trackers should reject announces from an all-zeros hash,
although that hash is already banned by Java routers.
Scrape
``````
Scrape request/response from [BEP15]_ is not required by this specification,
but may be implemented if desired, no changes required.
The client must acquire a connection ID first.
The scrape request is always repliable Datagram3.
The scrape response is always raw.
Error Response
``````````````
Tracker to client.
8 bytes minimum (if the message is empty).
Must be raw. Same as in [BEP15]_. No changes.
.. raw:: html
{% highlight %}
Offset Size Name Value
0 32-bit integer action 3 // error
4 32-bit integer transaction_id
8 string message
{% endhighlight %}
Extensions
=============
Extension bits or a version field are not included.
Clients and trackers should not assume packets to be of a certain size.
This way, additional fields can be added without breaking compatibility.
The extensions format defined in [BEP41]_ is recommended if required.
The connect response is modified to add an optional connection ID lifetime.
If blinded destination support is required, we can either add the
blinded 35-byte address to the end of the announce request,
or request blinded hashes in the responses,
using the [BEP41]_ format (paramters TBD).
The set of blinded 35-byte peer addresses could be added to the end of the announce reply,
after an all-zeros 32-byte hash.
Implementation guidelines
==========================
See the design section above for a discussion of the challenges for
non-integrated, non-I2CP clients and trackers.
Clients
--------
For a given tracker hostname, a client should prefer UDP over HTTP URLs,
and should not announce to both.
Clients with existing BEP 15 support should require only small modifications.
If a client support DHT or other datagram protocols, it should probably
select a different port as the request "from port" so that the replies
come back to that port and are not mixed up with DHT messages.
The client only receives raw datagrams as replies.
Trackers will never send a repliable datagram2 to the client.
Clients with a default list of opentrackers should update the list to
add UDP URLs after the known opentrackers are known to support UDP.
Clients may or may not implement retransmission of requests.
Retransmissions, if implemented, should use an initial timeout
of at least 15 seconds, and double the timeout for each retransmission
(exponential backoff).
Clients must back off after receiving an error response.
Trackers
---------
Trackers with existing BEP 15 support should require only small modifications.
This specification differs from the 2014 proposal, in that the tracker
must support reception of repliable datagram2 and datagram3 on the same port.
To minimize tracker resource requirements,
this protocol is designed to eliminate any requirement that the tracker
store mappings of client hashes to connection IDs for later validation.
This is possible because the announce request packet is a repliable
Datagram3 packet, so it contains the sender's hash.
A recommended implementation is:
- Define the current epoch as the current time with a resolution of the connection lifetime,
``epoch = now / lifetime``.
- Define a cryptographic hash function ``H(secret, clienthash, epoch)`` which generates
an 8 byte output.
- Generate the random constant secret used for all connections.
- For connect responses, generate ``connection_id = H(secret, clienthash, epoch)``
- For announce requests, validate the received connection ID in the current epoch by verifying
``connection_id == H(secret, clienthash, epoch) || connection_id == H(secret, clienthash, epoch - 1)``
References
==========
.. [BEP15]
http://www.bittorrent.org/beps/bep_0015.html
.. [BEP41]
http://www.bittorrent.org/beps/bep_0041.html
.. [DATAGRAMS]
{{ spec_url('datagrams') }}
.. [Prop160]
{{ proposal_url('160') }}
.. [Prop163]
{{ proposal_url('163') }}
.. [Prop169]
{{ proposal_url('169') }}
.. [SAMv3]
{{ site_url('docs/api/samv3') }}
.. [SPEC]
{{ site_url('docs/applications/bittorrent', True) }}

View File

@@ -153,18 +153,18 @@ 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
@@ -218,63 +218,76 @@ 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
=Tgt6
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
bc5ucGN3t5b/iDrKyTcPc8cC1IFa1Mc=
=uM54
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -99,6 +99,7 @@ url('/<lang:lang>/download/firefox', 'downloads.downloads_firefox')
url('/<lang:lang>/download/config', 'downloads.downloads_config')
url('/<lang:lang>/download/lab', 'downloads.downloads_lab')
url('/<lang:lang>/download/mac', 'downloads.downloads_mac')
url('/<lang:lang>/download/hashes.json', 'downloads.downloads_hashes')
url('/<lang:lang>/download/<string:version>/<path:file>/mirrors', 'downloads.downloads_select')
url('/<lang:lang>/download/<string:version>/<string:net>/any/<path:file>/download', 'downloads.downloads_redirect', defaults={'protocol': None, 'domain': None})
url('/<lang:lang>/download/<string:version>/<string:net>/<string:protocol>/any/<path:file>/download', 'downloads.downloads_redirect', defaults={'domain': None})