1 Commits
master ... 2to3

Author SHA1 Message Date
c77994a585 re-attempt migration using 2to3 2023-11-22 14:46:53 -05:00
192 changed files with 11276 additions and 36072 deletions

View File

@ -1,2 +1 @@
docker-run-dev.sh
site-updater-docker.sh
.git

View File

@ -1,66 +0,0 @@
# GitHub Actions workflow file to sync an external repository to this GitHub mirror.
# This file was automatically generated by go-github-sync.
#
# The workflow does the following:
# - Runs on a scheduled basis (and can also be triggered manually)
# - Clones the GitHub mirror repository
# - Fetches changes from the primary external repository
# - Applies those changes to the mirror repository
# - Pushes the updated content back to the GitHub mirror
#
# Authentication is handled by the GITHUB_TOKEN secret provided by GitHub Actions.
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Validate Github Actions Environment
run: if [ "$GITHUB_ACTIONS" != "true" ]; then echo 'This script must be run in a GitHub Actions environment.'; exit 1; fi
- name: Checkout GitHub Mirror
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Configure Git
run: |-
git config user.name 'GitHub Actions'
git config user.email 'actions@github.com'
- env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: Sync Primary Repository
run: |-
# Add the primary repository as a remote
git remote add primary https://i2pgit.org/I2P_Developers/i2p.www.git
# Fetch the latest changes from the primary repository
git fetch primary
# Check if the primary branch exists in the primary repository
if git ls-remote --heads primary master | grep -q master; then
echo "Primary branch master found in primary repository"
else
echo "Error: Primary branch master not found in primary repository"
exit 1
fi
# Check if we're already on the mirror branch
if git rev-parse --verify --quiet master; then
git checkout master
else
# Create the mirror branch if it doesn't exist
git checkout -b master
fi
# Force-apply all changes from primary, overriding any conflicts
echo "Performing force sync from primary/master to master"
git reset --hard primary/master
# Push changes back to the mirror repository
git push origin master
name: Sync Primary Repository to GitHub Mirror
"on":
push: {}
schedule:
- cron: 0 * * * *
workflow_dispatch: {}

View File

@ -1,64 +1,40 @@
FROM debian:oldoldstable as builder
ENV SERVERNAME=geti2p.net \
SERVERMAIL=example@geti2p.net
# Install only build dependencies first
RUN apt-get update && \
apt-get install -y --no-install-recommends \
python2-dev \
python-pip \
patch \
python-virtualenv \
git \
python-polib && \
rm -rf /var/lib/apt/lists/*
WORKDIR /build
# Copy dependency files first for better layer caching
COPY etc/reqs.txt etc/
COPY etc/multi-domain.patch etc/
# Setup virtual environment and install dependencies
RUN virtualenv --distribute env && \
. env/bin/activate && \
pip install -r etc/reqs.txt
# Now copy the rest of the application
COPY . .
# Build steps in a single layer
RUN . env/bin/activate && \
patch -p0 -N -r - < etc/multi-domain.patch && \
./compile-messages.sh && \
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
# Install only runtime dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends \
apache2 \
apache2-utils \
libapache2-mod-wsgi \
python2-minimal && \
rm -rf /var/lib/apt/lists/*
ENV SERVERNAME=geti2p.net
ENV SERVERMAIL=example@geti2p.net
WORKDIR /var/www/i2p.www
# Copy built artifacts
COPY --from=builder /build /var/www/i2p.www
COPY --from=builder /build/env /var/www/env
## Install the dependencies
#RUN #grep -v security.debian /etc/apt/sources.list > /etc/apt/sources.list.bak && \
#grep -v stretch-updates /etc/apt/sources.list.bak > /etc/apt/sources.list && \
RUN apt-get update && \
apt-get -y install apache2 apache2-utils libapache2-mod-wsgi python2-dev python-pip patch python-virtualenv git python-polib
# Configure Apache and WSGI in a single layer
RUN cp etc/docker.wsgi.i2p i2p.wsgi && \
chown -R www-data:www-data /var/www/i2p.www && \
chmod 755 i2p.wsgi && \
cp etc/apache2.i2p.conf /etc/apache2/sites-available/i2p.conf && \
a2enmod wsgi && \
ADD . /var/www/i2p.www
## Start setting up the site
RUN rm -rfv env && \
virtualenv --distribute env && \
. env/bin/activate && \
pip install -r etc/reqs.txt && \
patch -p0 -N -r - <etc/multi-domain.patch && \
./compile-messages.sh && \
echo "Git revision: $(git log -n 1 | grep commit | sed 's/commit //' | sed 's/ .*$//')" | tee ./i2p2www/pages/include/mtnversion && \
## We've now updated the site
## Next let's configure WSGI
## Set ownership of site to server
cp etc/docker.wsgi.i2p i2p.wsgi && \
chown -R www-data /var/www/i2p.www && \
## Make the WSGI script owned by the server
chown www-data:www-data /var/www/i2p.www/i2p.wsgi && \
## Make the WSGI script executable
chmod 755 /var/www/i2p.www/i2p.wsgi && \
## Copy the unmodified vhosts file to the apache2 confdir
cp etc/apache2.i2p.conf /etc/apache2/sites-available/i2p.conf && \
a2enmod wsgi && \
a2ensite i2p && \
ls /etc/apache2 && \
sed -i 's|IncludeOptional sites-enabled|# IncludeOptional sites-enabled|g' /etc/apache2/apache2.conf && \
sed -i '1 i\IncludeOptional sites-enabled/i2p.conf' /etc/apache2/apache2.conf
CMD service apache2 restart && tail -f /var/log/apache2/access.log /var/log/apache2/error.log
CMD service apache2 restart && tail -f /var/log/apache2/access.log

View File

@ -1,16 +1,190 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 486 560">
<style><![CDATA[.B{font-family:Arial}.C{font-size:24px}]]></style>
<g fill="#fff" stroke="#000" stroke-width="2">
<path d="M23.4 383.8h360v60h-360zm0-60h180v60h-180zm180 0h180v60h-180zm-180-60h180v60h-180zm180 0h180v60h-180zm-180-60h360v60h-360zm0 0"/>
<path d="M23.4 143.8h360v60h-360zm0 0"/>
<path d="M23.4 83.8h360v60h-360zm0-60h180v60h-180zm180 0h180v60h-180zm0 0"/></g>
<text xml:space="preserve" x="36.6" y="37.2" class="B C"><tspan x="59" y="60">Streaming</tspan></text>
<text xml:space="preserve" x="211.8" y="37.1" class="B C"><tspan x="234.2" y="59.9">Datagrams</tspan></text>
<text xml:space="preserve" x="153.7" y="99.6" class="B C"><tspan x="176.1" y="122.4">I2CP</tspan></text>
<text xml:space="preserve" x="89.8" y="157.2" class="B C"><tspan x="112.2" y="180">Garlic Encryption</tspan></text>
<text xml:space="preserve" x="51.4" y="279.6" class="B C"><tspan x="73.8" y="302.4">NTCP2</tspan></text><text xml:space="preserve" x="239.7" y="279.6" class="B C"><tspan x="262.1" y="302.4">SSU2</tspan></text>
<text xml:space="preserve" x="67.2" y="339.6" class="B C"><tspan x="89.6" y="362.4">TCP</tspan></text>
<text xml:space="preserve" x="245.2" y="339.4" class="B C"><tspan x="267.6" y="362.2">UDP</tspan></text>
<text xml:space="preserve" x="169.1" y="399.6" class="B C"><tspan x="191.5" y="422.4">IP</tspan></text>
<text xml:space="preserve" x="86.9" y="217.1" class="B C"><tspan x="109.3" y="239.9">Tunnel Messages</tspan></text>
</svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="362pt" height="422pt" viewBox="0 0 362 422" version="1.1">
<defs>
<g>
<symbol overflow="visible" id="glyph0-0">
<path style="stroke:none;" d="M 0.84375 3 L 0.84375 -11.984375 L 9.34375 -11.984375 L 9.34375 3 L 0.84375 3 Z M 1.796875 2.0625 L 8.40625 2.0625 L 8.40625 -11.03125 L 1.796875 -11.03125 L 1.796875 2.0625 Z M 1.796875 2.0625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-1">
<path style="stroke:none;" d="M 1.671875 -12.390625 L 3.34375 -12.390625 L 3.34375 0 L 1.671875 0 L 1.671875 -12.390625 Z M 1.671875 -12.390625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-2">
<path style="stroke:none;" d="M 3.34375 -11.015625 L 3.34375 -6.359375 L 5.453125 -6.359375 C 6.234375 -6.359375 6.835938 -6.5625 7.265625 -6.96875 C 7.691406 -7.375 7.90625 -7.945312 7.90625 -8.6875 C 7.90625 -9.425781 7.691406 -10 7.265625 -10.40625 C 6.835938 -10.8125 6.234375 -11.015625 5.453125 -11.015625 L 3.34375 -11.015625 Z M 1.671875 -12.390625 L 5.453125 -12.390625 C 6.835938 -12.390625 7.882812 -12.078125 8.59375 -11.453125 C 9.3125 -10.828125 9.671875 -9.90625 9.671875 -8.6875 C 9.671875 -7.46875 9.3125 -6.546875 8.59375 -5.921875 C 7.882812 -5.296875 6.835938 -4.984375 5.453125 -4.984375 L 3.34375 -4.984375 L 3.34375 0 L 1.671875 0 L 1.671875 -12.390625 Z M 1.671875 -12.390625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-3">
<path style="stroke:none;" d="M -0.046875 -12.390625 L 10.4375 -12.390625 L 10.4375 -10.984375 L 6.03125 -10.984375 L 6.03125 0 L 4.34375 0 L 4.34375 -10.984375 L -0.046875 -10.984375 L -0.046875 -12.390625 Z M -0.046875 -12.390625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-4">
<path style="stroke:none;" d="M 10.953125 -11.4375 L 10.953125 -9.671875 C 10.390625 -10.191406 9.785156 -10.582031 9.140625 -10.84375 C 8.503906 -11.101562 7.828125 -11.234375 7.109375 -11.234375 C 5.691406 -11.234375 4.601562 -10.800781 3.84375 -9.9375 C 3.09375 -9.070312 2.71875 -7.820312 2.71875 -6.1875 C 2.71875 -4.550781 3.09375 -3.300781 3.84375 -2.4375 C 4.601562 -1.570312 5.691406 -1.140625 7.109375 -1.140625 C 7.828125 -1.140625 8.503906 -1.269531 9.140625 -1.53125 C 9.785156 -1.789062 10.390625 -2.179688 10.953125 -2.703125 L 10.953125 -0.953125 C 10.359375 -0.554688 9.734375 -0.257812 9.078125 -0.0625 C 8.429688 0.132812 7.738281 0.234375 7 0.234375 C 5.125 0.234375 3.644531 -0.335938 2.5625 -1.484375 C 1.488281 -2.628906 0.953125 -4.195312 0.953125 -6.1875 C 0.953125 -8.175781 1.488281 -9.742188 2.5625 -10.890625 C 3.644531 -12.046875 5.125 -12.625 7 -12.625 C 7.75 -12.625 8.445312 -12.523438 9.09375 -12.328125 C 9.75 -12.128906 10.367188 -11.832031 10.953125 -11.4375 Z M 10.953125 -11.4375 "/>
</symbol>
<symbol overflow="visible" id="glyph0-5">
<path style="stroke:none;" d="M 1.484375 -12.390625 L 3.15625 -12.390625 L 3.15625 -4.859375 C 3.15625 -3.535156 3.394531 -2.582031 3.875 -2 C 4.363281 -1.414062 5.144531 -1.125 6.21875 -1.125 C 7.300781 -1.125 8.082031 -1.414062 8.5625 -2 C 9.039062 -2.582031 9.28125 -3.535156 9.28125 -4.859375 L 9.28125 -12.390625 L 10.96875 -12.390625 L 10.96875 -4.65625 C 10.96875 -3.039062 10.566406 -1.820312 9.765625 -1 C 8.960938 -0.175781 7.78125 0.234375 6.21875 0.234375 C 4.65625 0.234375 3.472656 -0.175781 2.671875 -1 C 1.878906 -1.820312 1.484375 -3.039062 1.484375 -4.65625 L 1.484375 -12.390625 Z M 1.484375 -12.390625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-6">
<path style="stroke:none;" d="M 3.34375 -11.015625 L 3.34375 -1.375 L 5.375 -1.375 C 7.082031 -1.375 8.332031 -1.757812 9.125 -2.53125 C 9.914062 -3.3125 10.3125 -4.535156 10.3125 -6.203125 C 10.3125 -7.867188 9.914062 -9.085938 9.125 -9.859375 C 8.332031 -10.628906 7.082031 -11.015625 5.375 -11.015625 L 3.34375 -11.015625 Z M 1.671875 -12.390625 L 5.109375 -12.390625 C 7.515625 -12.390625 9.28125 -11.890625 10.40625 -10.890625 C 11.53125 -9.890625 12.09375 -8.328125 12.09375 -6.203125 C 12.09375 -4.066406 11.523438 -2.5 10.390625 -1.5 C 9.265625 -0.5 7.503906 0 5.109375 0 L 1.671875 0 L 1.671875 -12.390625 Z M 1.671875 -12.390625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-7">
<path style="stroke:none;" d="M 1.671875 -12.390625 L 3.921875 -12.390625 L 9.421875 -2.03125 L 9.421875 -12.390625 L 11.046875 -12.390625 L 11.046875 0 L 8.796875 0 L 3.296875 -10.375 L 3.296875 0 L 1.671875 0 L 1.671875 -12.390625 Z M 1.671875 -12.390625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-8">
<path style="stroke:none;" d="M 9.09375 -11.984375 L 9.09375 -10.34375 C 8.457031 -10.65625 7.859375 -10.882812 7.296875 -11.03125 C 6.734375 -11.175781 6.1875 -11.25 5.65625 -11.25 C 4.75 -11.25 4.046875 -11.070312 3.546875 -10.71875 C 3.054688 -10.363281 2.8125 -9.863281 2.8125 -9.21875 C 2.8125 -8.664062 2.972656 -8.25 3.296875 -7.96875 C 3.628906 -7.6875 4.253906 -7.460938 5.171875 -7.296875 L 6.1875 -7.09375 C 7.4375 -6.851562 8.359375 -6.429688 8.953125 -5.828125 C 9.546875 -5.234375 9.84375 -4.429688 9.84375 -3.421875 C 9.84375 -2.222656 9.4375 -1.3125 8.625 -0.6875 C 7.820312 -0.0703125 6.644531 0.234375 5.09375 0.234375 C 4.507812 0.234375 3.882812 0.164062 3.21875 0.03125 C 2.5625 -0.09375 1.878906 -0.285156 1.171875 -0.546875 L 1.171875 -2.28125 C 1.847656 -1.894531 2.515625 -1.601562 3.171875 -1.40625 C 3.828125 -1.21875 4.46875 -1.125 5.09375 -1.125 C 6.050781 -1.125 6.789062 -1.3125 7.3125 -1.6875 C 7.832031 -2.0625 8.09375 -2.597656 8.09375 -3.296875 C 8.09375 -3.898438 7.90625 -4.375 7.53125 -4.71875 C 7.15625 -5.0625 6.539062 -5.320312 5.6875 -5.5 L 4.671875 -5.6875 C 3.421875 -5.9375 2.515625 -6.328125 1.953125 -6.859375 C 1.398438 -7.390625 1.125 -8.128906 1.125 -9.078125 C 1.125 -10.171875 1.507812 -11.035156 2.28125 -11.671875 C 3.050781 -12.304688 4.113281 -12.625 5.46875 -12.625 C 6.050781 -12.625 6.644531 -12.566406 7.25 -12.453125 C 7.851562 -12.347656 8.46875 -12.191406 9.09375 -11.984375 Z M 9.09375 -11.984375 "/>
</symbol>
<symbol overflow="visible" id="glyph0-9">
<path style="stroke:none;" d="M 1.4375 -3.671875 L 1.4375 -9.296875 L 2.96875 -9.296875 L 2.96875 -3.734375 C 2.96875 -2.847656 3.140625 -2.1875 3.484375 -1.75 C 3.828125 -1.3125 4.34375 -1.09375 5.03125 -1.09375 C 5.851562 -1.09375 6.503906 -1.351562 6.984375 -1.875 C 7.460938 -2.40625 7.703125 -3.125 7.703125 -4.03125 L 7.703125 -9.296875 L 9.234375 -9.296875 L 9.234375 0 L 7.703125 0 L 7.703125 -1.421875 C 7.328125 -0.859375 6.894531 -0.441406 6.40625 -0.171875 C 5.914062 0.0976562 5.347656 0.234375 4.703125 0.234375 C 3.640625 0.234375 2.828125 -0.09375 2.265625 -0.75 C 1.710938 -1.414062 1.4375 -2.390625 1.4375 -3.671875 Z M 5.28125 -9.515625 L 5.28125 -9.515625 Z M 5.28125 -9.515625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-10">
<path style="stroke:none;" d="M 9.328125 -5.609375 L 9.328125 0 L 7.796875 0 L 7.796875 -5.5625 C 7.796875 -6.4375 7.625 -7.09375 7.28125 -7.53125 C 6.945312 -7.96875 6.4375 -8.1875 5.75 -8.1875 C 4.914062 -8.1875 4.257812 -7.921875 3.78125 -7.390625 C 3.3125 -6.867188 3.078125 -6.15625 3.078125 -5.25 L 3.078125 0 L 1.546875 0 L 1.546875 -9.296875 L 3.078125 -9.296875 L 3.078125 -7.859375 C 3.441406 -8.410156 3.867188 -8.820312 4.359375 -9.09375 C 4.859375 -9.375 5.429688 -9.515625 6.078125 -9.515625 C 7.148438 -9.515625 7.957031 -9.179688 8.5 -8.515625 C 9.050781 -7.859375 9.328125 -6.890625 9.328125 -5.609375 Z M 9.328125 -5.609375 "/>
</symbol>
<symbol overflow="visible" id="glyph0-11">
<path style="stroke:none;" d="M 9.546875 -5.03125 L 9.546875 -4.28125 L 2.53125 -4.28125 C 2.59375 -3.226562 2.90625 -2.425781 3.46875 -1.875 C 4.039062 -1.320312 4.835938 -1.046875 5.859375 -1.046875 C 6.441406 -1.046875 7.007812 -1.117188 7.5625 -1.265625 C 8.113281 -1.410156 8.660156 -1.628906 9.203125 -1.921875 L 9.203125 -0.46875 C 8.648438 -0.238281 8.085938 -0.0664062 7.515625 0.046875 C 6.941406 0.171875 6.359375 0.234375 5.765625 0.234375 C 4.273438 0.234375 3.097656 -0.191406 2.234375 -1.046875 C 1.367188 -1.910156 0.9375 -3.082031 0.9375 -4.5625 C 0.9375 -6.082031 1.347656 -7.285156 2.171875 -8.171875 C 2.992188 -9.066406 4.101562 -9.515625 5.5 -9.515625 C 6.75 -9.515625 7.734375 -9.113281 8.453125 -8.3125 C 9.179688 -7.507812 9.546875 -6.414062 9.546875 -5.03125 Z M 8.03125 -5.484375 C 8.019531 -6.316406 7.785156 -6.976562 7.328125 -7.46875 C 6.867188 -7.96875 6.265625 -8.21875 5.515625 -8.21875 C 4.660156 -8.21875 3.976562 -7.976562 3.46875 -7.5 C 2.957031 -7.019531 2.660156 -6.34375 2.578125 -5.46875 L 8.03125 -5.484375 Z M 8.03125 -5.484375 "/>
</symbol>
<symbol overflow="visible" id="glyph0-12">
<path style="stroke:none;" d="M 1.609375 -12.921875 L 3.125 -12.921875 L 3.125 0 L 1.609375 0 L 1.609375 -12.921875 Z M 1.609375 -12.921875 "/>
</symbol>
<symbol overflow="visible" id="glyph0-13">
<path style="stroke:none;" d=""/>
</symbol>
<symbol overflow="visible" id="glyph0-14">
<path style="stroke:none;" d="M 8.84375 -7.515625 C 9.21875 -8.203125 9.671875 -8.707031 10.203125 -9.03125 C 10.734375 -9.351562 11.363281 -9.515625 12.09375 -9.515625 C 13.050781 -9.515625 13.789062 -9.175781 14.3125 -8.5 C 14.84375 -7.820312 15.109375 -6.859375 15.109375 -5.609375 L 15.109375 0 L 13.578125 0 L 13.578125 -5.5625 C 13.578125 -6.445312 13.421875 -7.101562 13.109375 -7.53125 C 12.796875 -7.96875 12.3125 -8.1875 11.65625 -8.1875 C 10.863281 -8.1875 10.238281 -7.921875 9.78125 -7.390625 C 9.320312 -6.867188 9.09375 -6.15625 9.09375 -5.25 L 9.09375 0 L 7.5625 0 L 7.5625 -5.5625 C 7.5625 -6.457031 7.398438 -7.117188 7.078125 -7.546875 C 6.765625 -7.972656 6.28125 -8.1875 5.625 -8.1875 C 4.84375 -8.1875 4.222656 -7.921875 3.765625 -7.390625 C 3.304688 -6.867188 3.078125 -6.15625 3.078125 -5.25 L 3.078125 0 L 1.546875 0 L 1.546875 -9.296875 L 3.078125 -9.296875 L 3.078125 -7.859375 C 3.429688 -8.421875 3.847656 -8.835938 4.328125 -9.109375 C 4.816406 -9.378906 5.394531 -9.515625 6.0625 -9.515625 C 6.738281 -9.515625 7.3125 -9.34375 7.78125 -9 C 8.257812 -8.65625 8.613281 -8.160156 8.84375 -7.515625 Z M 8.84375 -7.515625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-15">
<path style="stroke:none;" d="M 7.53125 -9.015625 L 7.53125 -7.578125 C 7.09375 -7.796875 6.640625 -7.960938 6.171875 -8.078125 C 5.710938 -8.191406 5.234375 -8.25 4.734375 -8.25 C 3.984375 -8.25 3.414062 -8.128906 3.03125 -7.890625 C 2.65625 -7.660156 2.46875 -7.3125 2.46875 -6.84375 C 2.46875 -6.488281 2.601562 -6.210938 2.875 -6.015625 C 3.144531 -5.816406 3.6875 -5.625 4.5 -5.4375 L 5.03125 -5.328125 C 6.113281 -5.085938 6.882812 -4.753906 7.34375 -4.328125 C 7.800781 -3.910156 8.03125 -3.320312 8.03125 -2.5625 C 8.03125 -1.695312 7.6875 -1.015625 7 -0.515625 C 6.320312 -0.015625 5.382812 0.234375 4.1875 0.234375 C 3.6875 0.234375 3.164062 0.1875 2.625 0.09375 C 2.082031 0 1.515625 -0.144531 0.921875 -0.34375 L 0.921875 -1.921875 C 1.484375 -1.628906 2.035156 -1.40625 2.578125 -1.25 C 3.128906 -1.101562 3.675781 -1.03125 4.21875 -1.03125 C 4.9375 -1.03125 5.488281 -1.15625 5.875 -1.40625 C 6.257812 -1.65625 6.453125 -2.003906 6.453125 -2.453125 C 6.453125 -2.867188 6.3125 -3.1875 6.03125 -3.40625 C 5.757812 -3.625 5.148438 -3.835938 4.203125 -4.046875 L 3.671875 -4.171875 C 2.722656 -4.367188 2.035156 -4.671875 1.609375 -5.078125 C 1.191406 -5.492188 0.984375 -6.0625 0.984375 -6.78125 C 0.984375 -7.65625 1.289062 -8.328125 1.90625 -8.796875 C 2.53125 -9.273438 3.414062 -9.515625 4.5625 -9.515625 C 5.125 -9.515625 5.648438 -9.472656 6.140625 -9.390625 C 6.640625 -9.304688 7.101562 -9.179688 7.53125 -9.015625 Z M 7.53125 -9.015625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-16">
<path style="stroke:none;" d="M 5.828125 -4.671875 C 4.585938 -4.671875 3.726562 -4.53125 3.25 -4.25 C 2.78125 -3.96875 2.546875 -3.488281 2.546875 -2.8125 C 2.546875 -2.269531 2.722656 -1.835938 3.078125 -1.515625 C 3.441406 -1.191406 3.929688 -1.03125 4.546875 -1.03125 C 5.390625 -1.03125 6.066406 -1.332031 6.578125 -1.9375 C 7.085938 -2.539062 7.34375 -3.335938 7.34375 -4.328125 L 7.34375 -4.671875 L 5.828125 -4.671875 Z M 8.875 -5.296875 L 8.875 0 L 7.34375 0 L 7.34375 -1.40625 C 7 -0.84375 6.566406 -0.425781 6.046875 -0.15625 C 5.523438 0.101562 4.890625 0.234375 4.140625 0.234375 C 3.179688 0.234375 2.421875 -0.03125 1.859375 -0.5625 C 1.296875 -1.09375 1.015625 -1.804688 1.015625 -2.703125 C 1.015625 -3.753906 1.363281 -4.546875 2.0625 -5.078125 C 2.769531 -5.609375 3.816406 -5.875 5.203125 -5.875 L 7.34375 -5.875 L 7.34375 -6.015625 C 7.34375 -6.722656 7.109375 -7.265625 6.640625 -7.640625 C 6.179688 -8.023438 5.535156 -8.21875 4.703125 -8.21875 C 4.171875 -8.21875 3.65625 -8.15625 3.15625 -8.03125 C 2.65625 -7.90625 2.171875 -7.71875 1.703125 -7.46875 L 1.703125 -8.875 C 2.265625 -9.09375 2.804688 -9.253906 3.328125 -9.359375 C 3.859375 -9.460938 4.367188 -9.515625 4.859375 -9.515625 C 6.203125 -9.515625 7.207031 -9.164062 7.875 -8.46875 C 8.539062 -7.769531 8.875 -6.710938 8.875 -5.296875 Z M 8.875 -5.296875 "/>
</symbol>
<symbol overflow="visible" id="glyph0-17">
<path style="stroke:none;" d="M 7.71875 -4.75 C 7.71875 -5.863281 7.488281 -6.722656 7.03125 -7.328125 C 6.570312 -7.941406 5.929688 -8.25 5.109375 -8.25 C 4.296875 -8.25 3.660156 -7.941406 3.203125 -7.328125 C 2.742188 -6.722656 2.515625 -5.863281 2.515625 -4.75 C 2.515625 -3.65625 2.742188 -2.800781 3.203125 -2.1875 C 3.660156 -1.582031 4.296875 -1.28125 5.109375 -1.28125 C 5.929688 -1.28125 6.570312 -1.582031 7.03125 -2.1875 C 7.488281 -2.800781 7.71875 -3.65625 7.71875 -4.75 Z M 9.25 -1.15625 C 9.25 0.425781 8.894531 1.601562 8.1875 2.375 C 7.488281 3.144531 6.414062 3.53125 4.96875 3.53125 C 4.425781 3.53125 3.914062 3.488281 3.4375 3.40625 C 2.96875 3.332031 2.507812 3.210938 2.0625 3.046875 L 2.0625 1.5625 C 2.507812 1.800781 2.953125 1.976562 3.390625 2.09375 C 3.828125 2.21875 4.269531 2.28125 4.71875 2.28125 C 5.71875 2.28125 6.46875 2.015625 6.96875 1.484375 C 7.46875 0.960938 7.71875 0.175781 7.71875 -0.875 L 7.71875 -1.640625 C 7.40625 -1.085938 7 -0.675781 6.5 -0.40625 C 6.007812 -0.132812 5.421875 0 4.734375 0 C 3.597656 0 2.679688 -0.429688 1.984375 -1.296875 C 1.285156 -2.171875 0.9375 -3.320312 0.9375 -4.75 C 0.9375 -6.195312 1.285156 -7.351562 1.984375 -8.21875 C 2.679688 -9.082031 3.597656 -9.515625 4.734375 -9.515625 C 5.421875 -9.515625 6.007812 -9.378906 6.5 -9.109375 C 7 -8.835938 7.40625 -8.429688 7.71875 -7.890625 L 7.71875 -9.296875 L 9.25 -9.296875 L 9.25 -1.15625 Z M 9.25 -1.15625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-18">
<path style="stroke:none;" d="M 10.125 -1.765625 L 10.125 -5.09375 L 7.375 -5.09375 L 7.375 -6.46875 L 11.78125 -6.46875 L 11.78125 -1.15625 C 11.132812 -0.695312 10.421875 -0.347656 9.640625 -0.109375 C 8.859375 0.117188 8.023438 0.234375 7.140625 0.234375 C 5.203125 0.234375 3.6875 -0.328125 2.59375 -1.453125 C 1.5 -2.585938 0.953125 -4.164062 0.953125 -6.1875 C 0.953125 -8.207031 1.5 -9.785156 2.59375 -10.921875 C 3.6875 -12.054688 5.203125 -12.625 7.140625 -12.625 C 7.941406 -12.625 8.707031 -12.519531 9.4375 -12.3125 C 10.164062 -12.113281 10.835938 -11.820312 11.453125 -11.4375 L 11.453125 -9.65625 C 10.835938 -10.175781 10.179688 -10.566406 9.484375 -10.828125 C 8.785156 -11.097656 8.050781 -11.234375 7.28125 -11.234375 C 5.757812 -11.234375 4.617188 -10.8125 3.859375 -9.96875 C 3.097656 -9.125 2.71875 -7.863281 2.71875 -6.1875 C 2.71875 -4.507812 3.097656 -3.25 3.859375 -2.40625 C 4.617188 -1.5625 5.757812 -1.140625 7.28125 -1.140625 C 7.875 -1.140625 8.398438 -1.1875 8.859375 -1.28125 C 9.328125 -1.382812 9.75 -1.546875 10.125 -1.765625 Z M 10.125 -1.765625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-19">
<path style="stroke:none;" d="M 6.984375 -7.875 C 6.816406 -7.96875 6.628906 -8.035156 6.421875 -8.078125 C 6.222656 -8.128906 6.003906 -8.15625 5.765625 -8.15625 C 4.898438 -8.15625 4.234375 -7.875 3.765625 -7.3125 C 3.304688 -6.75 3.078125 -5.941406 3.078125 -4.890625 L 3.078125 0 L 1.546875 0 L 1.546875 -9.296875 L 3.078125 -9.296875 L 3.078125 -7.859375 C 3.398438 -8.421875 3.816406 -8.835938 4.328125 -9.109375 C 4.847656 -9.378906 5.472656 -9.515625 6.203125 -9.515625 C 6.304688 -9.515625 6.421875 -9.507812 6.546875 -9.5 C 6.679688 -9.488281 6.828125 -9.46875 6.984375 -9.4375 L 6.984375 -7.875 Z M 6.984375 -7.875 "/>
</symbol>
<symbol overflow="visible" id="glyph0-20">
<path style="stroke:none;" d="M 1.609375 -9.296875 L 3.125 -9.296875 L 3.125 0 L 1.609375 0 L 1.609375 -9.296875 Z M 1.609375 -12.921875 L 3.125 -12.921875 L 3.125 -10.984375 L 1.609375 -10.984375 L 1.609375 -12.921875 Z M 1.609375 -12.921875 "/>
</symbol>
<symbol overflow="visible" id="glyph0-21">
<path style="stroke:none;" d="M 8.296875 -8.9375 L 8.296875 -7.515625 C 7.859375 -7.753906 7.421875 -7.929688 6.984375 -8.046875 C 6.554688 -8.160156 6.117188 -8.21875 5.671875 -8.21875 C 4.679688 -8.21875 3.910156 -7.90625 3.359375 -7.28125 C 2.816406 -6.65625 2.546875 -5.773438 2.546875 -4.640625 C 2.546875 -3.503906 2.816406 -2.617188 3.359375 -1.984375 C 3.910156 -1.359375 4.679688 -1.046875 5.671875 -1.046875 C 6.117188 -1.046875 6.554688 -1.101562 6.984375 -1.21875 C 7.421875 -1.34375 7.859375 -1.523438 8.296875 -1.765625 L 8.296875 -0.359375 C 7.867188 -0.160156 7.425781 -0.015625 6.96875 0.078125 C 6.507812 0.179688 6.023438 0.234375 5.515625 0.234375 C 4.109375 0.234375 2.992188 -0.203125 2.171875 -1.078125 C 1.347656 -1.960938 0.9375 -3.148438 0.9375 -4.640625 C 0.9375 -6.160156 1.351562 -7.351562 2.1875 -8.21875 C 3.019531 -9.082031 4.160156 -9.515625 5.609375 -9.515625 C 6.078125 -9.515625 6.535156 -9.46875 6.984375 -9.375 C 7.429688 -9.28125 7.867188 -9.132812 8.296875 -8.9375 Z M 8.296875 -8.9375 "/>
</symbol>
<symbol overflow="visible" id="glyph0-22">
<path style="stroke:none;" d="M 5.46875 0.859375 C 5.039062 1.972656 4.617188 2.695312 4.203125 3.03125 C 3.796875 3.363281 3.25 3.53125 2.5625 3.53125 L 1.34375 3.53125 L 1.34375 2.265625 L 2.234375 2.265625 C 2.660156 2.265625 2.988281 2.160156 3.21875 1.953125 C 3.445312 1.753906 3.707031 1.285156 4 0.546875 L 4.265625 -0.15625 L 0.5 -9.296875 L 2.125 -9.296875 L 5.03125 -2.03125 L 7.9375 -9.296875 L 9.546875 -9.296875 L 5.46875 0.859375 Z M 5.46875 0.859375 "/>
</symbol>
<symbol overflow="visible" id="glyph0-23">
<path style="stroke:none;" d="M 3.078125 -1.390625 L 3.078125 3.53125 L 1.546875 3.53125 L 1.546875 -9.296875 L 3.078125 -9.296875 L 3.078125 -7.890625 C 3.398438 -8.441406 3.804688 -8.847656 4.296875 -9.109375 C 4.785156 -9.378906 5.367188 -9.515625 6.046875 -9.515625 C 7.179688 -9.515625 8.097656 -9.066406 8.796875 -8.171875 C 9.503906 -7.273438 9.859375 -6.097656 9.859375 -4.640625 C 9.859375 -3.179688 9.503906 -2.003906 8.796875 -1.109375 C 8.097656 -0.210938 7.179688 0.234375 6.046875 0.234375 C 5.367188 0.234375 4.785156 0.101562 4.296875 -0.15625 C 3.804688 -0.425781 3.398438 -0.835938 3.078125 -1.390625 Z M 8.28125 -4.640625 C 8.28125 -5.765625 8.046875 -6.644531 7.578125 -7.28125 C 7.117188 -7.925781 6.484375 -8.25 5.671875 -8.25 C 4.867188 -8.25 4.234375 -7.925781 3.765625 -7.28125 C 3.304688 -6.644531 3.078125 -5.765625 3.078125 -4.640625 C 3.078125 -3.515625 3.304688 -2.628906 3.765625 -1.984375 C 4.234375 -1.347656 4.867188 -1.03125 5.671875 -1.03125 C 6.484375 -1.03125 7.117188 -1.347656 7.578125 -1.984375 C 8.046875 -2.628906 8.28125 -3.515625 8.28125 -4.640625 Z M 8.28125 -4.640625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-24">
<path style="stroke:none;" d="M 3.109375 -11.9375 L 3.109375 -9.296875 L 6.265625 -9.296875 L 6.265625 -8.109375 L 3.109375 -8.109375 L 3.109375 -3.0625 C 3.109375 -2.300781 3.210938 -1.8125 3.421875 -1.59375 C 3.628906 -1.382812 4.050781 -1.28125 4.6875 -1.28125 L 6.265625 -1.28125 L 6.265625 0 L 4.6875 0 C 3.507812 0 2.695312 -0.21875 2.25 -0.65625 C 1.800781 -1.09375 1.578125 -1.894531 1.578125 -3.0625 L 1.578125 -8.109375 L 0.453125 -8.109375 L 0.453125 -9.296875 L 1.578125 -9.296875 L 1.578125 -11.9375 L 3.109375 -11.9375 Z M 3.109375 -11.9375 "/>
</symbol>
<symbol overflow="visible" id="glyph0-25">
<path style="stroke:none;" d="M 5.203125 -8.21875 C 4.378906 -8.21875 3.726562 -7.898438 3.25 -7.265625 C 2.78125 -6.628906 2.546875 -5.753906 2.546875 -4.640625 C 2.546875 -3.523438 2.78125 -2.644531 3.25 -2 C 3.726562 -1.363281 4.378906 -1.046875 5.203125 -1.046875 C 6.015625 -1.046875 6.660156 -1.367188 7.140625 -2.015625 C 7.617188 -2.660156 7.859375 -3.535156 7.859375 -4.640625 C 7.859375 -5.742188 7.617188 -6.613281 7.140625 -7.25 C 6.660156 -7.894531 6.015625 -8.21875 5.203125 -8.21875 Z M 5.203125 -9.515625 C 6.535156 -9.515625 7.578125 -9.082031 8.328125 -8.21875 C 9.085938 -7.363281 9.46875 -6.171875 9.46875 -4.640625 C 9.46875 -3.117188 9.085938 -1.925781 8.328125 -1.0625 C 7.578125 -0.195312 6.535156 0.234375 5.203125 0.234375 C 3.867188 0.234375 2.820312 -0.195312 2.0625 -1.0625 C 1.3125 -1.925781 0.9375 -3.117188 0.9375 -4.640625 C 0.9375 -6.171875 1.3125 -7.363281 2.0625 -8.21875 C 2.820312 -9.082031 3.867188 -9.515625 5.203125 -9.515625 Z M 5.203125 -9.515625 "/>
</symbol>
<symbol overflow="visible" id="glyph0-26">
<path style="stroke:none;" d="M 3.265625 -1.40625 L 9.109375 -1.40625 L 9.109375 0 L 1.25 0 L 1.25 -1.40625 C 1.882812 -2.070312 2.75 -2.957031 3.84375 -4.0625 C 4.945312 -5.175781 5.640625 -5.890625 5.921875 -6.203125 C 6.453125 -6.804688 6.820312 -7.316406 7.03125 -7.734375 C 7.25 -8.160156 7.359375 -8.570312 7.359375 -8.96875 C 7.359375 -9.632812 7.128906 -10.171875 6.671875 -10.578125 C 6.210938 -10.992188 5.609375 -11.203125 4.859375 -11.203125 C 4.335938 -11.203125 3.785156 -11.109375 3.203125 -10.921875 C 2.617188 -10.742188 1.992188 -10.472656 1.328125 -10.109375 L 1.328125 -11.796875 C 2.003906 -12.066406 2.632812 -12.269531 3.21875 -12.40625 C 3.800781 -12.550781 4.335938 -12.625 4.828125 -12.625 C 6.109375 -12.625 7.128906 -12.300781 7.890625 -11.65625 C 8.660156 -11.007812 9.046875 -10.148438 9.046875 -9.078125 C 9.046875 -8.566406 8.945312 -8.082031 8.75 -7.625 C 8.5625 -7.175781 8.21875 -6.640625 7.71875 -6.015625 C 7.582031 -5.859375 7.140625 -5.394531 6.390625 -4.625 C 5.648438 -3.863281 4.609375 -2.789062 3.265625 -1.40625 Z M 3.265625 -1.40625 "/>
</symbol>
</g>
</defs>
<g id="surface0">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0 0 L 661 0 L 661 401 L 0 401 Z M 0 0 "/>
<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 15 17 L 33 17 L 33 20 L 15 20 Z M 15 17 " transform="matrix(20,0,0,20,-299,21)"/>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-1" x="173.402344" y="396.875"/>
<use xlink:href="#glyph0-2" x="178.402344" y="396.875"/>
</g>
<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 15 14 L 24 14 L 24 17 L 15 17 Z M 15 14 " transform="matrix(20,0,0,20,-299,21)"/>
<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 24 14 L 33 14 L 33 17 L 24 17 Z M 24 14 " transform="matrix(20,0,0,20,-299,21)"/>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-3" x="84.671875" y="336.875"/>
<use xlink:href="#glyph0-4" x="84.671875" y="336.875"/>
<use xlink:href="#glyph0-2" x="96.488281" y="336.875"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-5" x="253.207031" y="336.875"/>
<use xlink:href="#glyph0-6" x="265.589844" y="336.875"/>
<use xlink:href="#glyph0-2" x="278.617188" y="336.875"/>
</g>
<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 15 11 L 24 11 L 24 14 L 15 14 Z M 15 11 " transform="matrix(20,0,0,20,-299,21)"/>
<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 24 11 L 33 11 L 33 14 L 24 14 Z M 24 11 " transform="matrix(20,0,0,20,-299,21)"/>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-7" x="68.988281" y="276.875"/>
<use xlink:href="#glyph0-3" x="91" y="276.875"/>
<use xlink:href="#glyph0-4" x="91" y="276.875"/>
<use xlink:href="#glyph0-2" x="102.816406" y="276.875"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-8" x="254.066406" y="276.875"/>
<use xlink:href="#glyph0-8" x="264.808594" y="276.875"/>
<use xlink:href="#glyph0-5" x="275.550781" y="276.875"/>
</g>
<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 15 8 L 33 8 L 33 11 L 15 11 Z M 15 8 " transform="matrix(20,0,0,20,-299,21)"/>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-3" x="132.71875" y="216.875"/>
<use xlink:href="#glyph0-9" x="132.71875" y="216.875"/>
<use xlink:href="#glyph0-10" x="143.441406" y="216.875"/>
<use xlink:href="#glyph0-10" x="154.164062" y="216.875"/>
<use xlink:href="#glyph0-11" x="164.886719" y="216.875"/>
<use xlink:href="#glyph0-12" x="175.296875" y="216.875"/>
<use xlink:href="#glyph0-13" x="180.003906" y="216.875"/>
<use xlink:href="#glyph0-14" x="185.375" y="216.875"/>
<use xlink:href="#glyph0-11" x="201.859375" y="216.875"/>
<use xlink:href="#glyph0-15" x="212.269531" y="216.875"/>
<use xlink:href="#glyph0-15" x="221.078125" y="216.875"/>
<use xlink:href="#glyph0-16" x="229.886719" y="216.875"/>
<use xlink:href="#glyph0-17" x="240.257812" y="216.875"/>
<use xlink:href="#glyph0-11" x="251" y="216.875"/>
<use xlink:href="#glyph0-15" x="261.410156" y="216.875"/>
</g>
<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 15 5 L 33 5 L 33 8 L 15 8 Z M 15 5 " transform="matrix(20,0,0,20,-299,21)"/>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-18" x="108.460938" y="156.875"/>
<use xlink:href="#glyph0-16" x="121.566406" y="156.875"/>
<use xlink:href="#glyph0-19" x="131.9375" y="156.875"/>
<use xlink:href="#glyph0-12" x="138.890625" y="156.875"/>
<use xlink:href="#glyph0-20" x="143.597656" y="156.875"/>
<use xlink:href="#glyph0-21" x="148.304688" y="156.875"/>
<use xlink:href="#glyph0-13" x="157.601562" y="156.875"/>
<use xlink:href="#glyph0-11" x="162.972656" y="156.875"/>
<use xlink:href="#glyph0-10" x="173.382812" y="156.875"/>
<use xlink:href="#glyph0-21" x="184.105469" y="156.875"/>
<use xlink:href="#glyph0-19" x="193.402344" y="156.875"/>
<use xlink:href="#glyph0-22" x="200.355469" y="156.875"/>
<use xlink:href="#glyph0-23" x="210.375" y="156.875"/>
<use xlink:href="#glyph0-24" x="221.117188" y="156.875"/>
<use xlink:href="#glyph0-20" x="227.757812" y="156.875"/>
<use xlink:href="#glyph0-25" x="232.464844" y="156.875"/>
<use xlink:href="#glyph0-10" x="242.816406" y="156.875"/>
</g>
<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 15 2 L 33 2 L 33 5 L 15 5 Z M 15 2 " transform="matrix(20,0,0,20,-299,21)"/>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-1" x="162.113281" y="96.875"/>
<use xlink:href="#glyph0-26" x="167.113281" y="96.875"/>
<use xlink:href="#glyph0-4" x="177.875" y="96.875"/>
<use xlink:href="#glyph0-2" x="189.691406" y="96.875"/>
</g>
<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 15 -1 L 24 -1 L 24 2 L 15 2 Z M 15 -1 " transform="matrix(20,0,0,20,-299,21)"/>
<path style="fill-rule:evenodd;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 24 -1 L 33 -1 L 33 2 L 24 2 Z M 24 -1 " transform="matrix(20,0,0,20,-299,21)"/>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-8" x="50.472656" y="36.875"/>
<use xlink:href="#glyph0-24" x="61.214844" y="36.875"/>
<use xlink:href="#glyph0-19" x="68.089844" y="36.875"/>
<use xlink:href="#glyph0-11" x="68.089844" y="36.875"/>
<use xlink:href="#glyph0-16" x="78.5" y="36.875"/>
<use xlink:href="#glyph0-14" x="88.871094" y="36.875"/>
<use xlink:href="#glyph0-20" x="105.355469" y="36.875"/>
<use xlink:href="#glyph0-10" x="110.0625" y="36.875"/>
<use xlink:href="#glyph0-17" x="120.785156" y="36.875"/>
</g>
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
<use xlink:href="#glyph0-6" x="224.125" y="36.875"/>
<use xlink:href="#glyph0-16" x="237.152344" y="36.875"/>
<use xlink:href="#glyph0-24" x="247.523438" y="36.875"/>
<use xlink:href="#glyph0-16" x="254.164062" y="36.875"/>
<use xlink:href="#glyph0-17" x="264.535156" y="36.875"/>
<use xlink:href="#glyph0-19" x="275.277344" y="36.875"/>
<use xlink:href="#glyph0-16" x="282.230469" y="36.875"/>
<use xlink:href="#glyph0-14" x="292.601562" y="36.875"/>
<use xlink:href="#glyph0-15" x="309.085938" y="36.875"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -1,3 +1,56 @@
#! /usr/bin/env bash
export devmode="--volume $(pwd):/var/www/i2p.www"
./site-updater-docker.sh runserver.sh
## Set additional docker run arguments by changing the variable
## i2p_www_docker_run_args in an optional file called config.sh
## for example
##
##i2p_www_docker_run_args='-d'
## to run the site in the background, or
##
##i2p_www_docker_run_args='-t'
## to emulate a TTY
## To operate a quick and easy mirror of the I2P Site in a container
## simply clone the i2p.www source to a host with Docker installed, then
## add:
##
##i2p_www_docker_run_args='-d'
## to config.sh
##
## Then add:
##
##*/10 * * * * /path/to/i2p.www/site-updater-docker.sh
##
## to a crontab belonging to a member of the `docker` group. To add yourself
## to the `docker` group use the command:
##
##sudo adduser $(whoami) docker
##
## a more secure solution may be to create a user especially to run the
## docker crontab only, who is a member of the docker group. To do this,
##
##sudo adduser --disabled-password --disabled-login --ingroup docker docker
## however the specifics may vary from distribution to distribution.
dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
if [ -f "${dir}/config.sh" ]; then
. "${dir}/config.sh"
fi
if [ -z $port ]; then
port="8090"
fi
if [ -z $i2p_www_branch ]; then
i2p_www_branch=master
fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" || exit
cd "$DIR" || exit
git pull origin $i2p_www_branch
docker build $i2p_www_docker_build_args -t mirror.i2p.www$suffix .
docker rm -f mirror.i2p.www$suffix
docker run -it $i2p_www_docker_run_args --env DEV:on --name mirror.i2p.www$suffix --net=host --volume $(pwd)/env:/env mirror.i2p.www$suffix ./runserver.py
docker logs -f mirror.i2p.www$suffix

View File

@ -3,5 +3,5 @@ export spec=""
export venv="`which virtualenv-2.7`"
if [ x"$venv" = x ]; then
export venv="`which virtualenv`"
#export spec="-p 2.7"
export spec="-p 2.7"
fi

View File

@ -22,8 +22,8 @@ except ImportError:
###########
# Constants
CURRENT_I2P_VERSION = '2.9.0'
CURRENT_I2P_FIREFOX_PROFILE_VERSION = '2.9.0'
CURRENT_I2P_VERSION = '2.3.0'
CURRENT_I2P_FIREFOX_PROFILE_VERSION = '2.3.0'
CURRENT_I2P_OSX_VERSION = '1.9.0'
CANONICAL_DOMAIN = 'geti2p.net'
@ -67,32 +67,32 @@ SUPPORTED_LANGS = [
]
SUPPORTED_LANG_NAMES = {
'ar': u'Arabic العربية',
'id': u'Bahasa Indonesia',
'zh': u'Chinese 中文',
'zh_TW': u'Chinese 中文 (繁體中文, 台灣)',
'de': u'Deutsch',
'en': u'English',
'es': u'Castellano',
'fr': u'Français',
'el': u'Greek Ελληνικά',
'he': u'Hebrew עברית',
'hu': u'Hungarian',
'it': u'Italiano',
'ja': u'Japanese 日本語',
'ko': u'Korean 한국말',
'mg': u'Fiteny Malagasy',
'nl': u'Nederlands',
'fa': u'Persian فارسی',
'pl': u'Polski',
'pt': u'Português',
'pt_BR': u'Português do Brasil',
'ro': u'Română',
'ru': u'Russian Русский язык',
'fi': u'Suomi',
'sv': u'Svenska',
'tr': u'Türkçe',
'uk': u'Ukrainian Українська',
'ar': 'Arabic العربية',
'id': 'Bahasa Indonesia',
'zh': 'Chinese 中文',
'zh_TW': 'Chinese 中文 (繁體中文, 台灣)',
'de': 'Deutsch',
'en': 'English',
'es': 'Castellano',
'fr': 'Français',
'el': 'Greek Ελληνικά',
'he': 'Hebrew עברית',
'hu': 'Hungarian',
'it': 'Italiano',
'ja': 'Japanese 日本語',
'ko': 'Korean 한국말',
'mg': 'Fiteny Malagasy',
'nl': 'Nederlands',
'fa': 'Persian فارسی',
'pl': 'Polski',
'pt': 'Português',
'pt_BR': 'Português do Brasil',
'ro': 'Română',
'ru': 'Russian Русский язык',
'fi': 'Suomi',
'sv': 'Svenska',
'tr': 'Türkçe',
'uk': 'Ukrainian Українська',
}
RTL_LANGS = [
@ -213,7 +213,7 @@ def detect_theme():
theme = 'duck'
if 'style' in request.cookies:
theme = request.cookies['style']
if 'theme' in request.args.keys():
if 'theme' in list(request.args.keys()):
theme = request.args['theme']
# TEMPORARY: enable external themes
# TODO: Remove this (and the corresponding lines in global/layout.html
@ -263,5 +263,5 @@ def server_error(error):
return render_template('global/error_500.html'), 500
# Import these to ensure they get loaded
import templatevars
import urls
from . import templatevars
from . import urls

View File

@ -6,14 +6,14 @@
Based on perl code by Eddie Kohler; heavily modified.
"""
import cStringIO
import io
import re
import sys
import os
import config
from . import config
import rank
from . import rank
__all__ = [ 'ParseError', 'BibTeX', 'BibTeXEntry', 'htmlize',
'ParsedAuthor', 'FileIter', 'Parser', 'parseFile',
@ -66,7 +66,7 @@ class BibTeX:
"""Add a BibTeX entry to this file."""
k = ent.key
if self.byKey.get(ent.key.lower()):
print >> sys.stderr, "Already have an entry named %s"%k
print("Already have an entry named %s"%k, file=sys.stderr)
return
self.entries.append(ent)
self.byKey[ent.key.lower()] = ent
@ -79,7 +79,7 @@ class BibTeX:
try:
cr = self.byKey[ent['crossref'].lower()]
except KeyError:
print "No such crossref: %s"% ent['crossref']
print("No such crossref: %s"% ent['crossref'])
break
if seen.get(cr.key):
raise ParseError("Circular crossref at %s" % ent.key)
@ -87,12 +87,12 @@ class BibTeX:
del ent.entries['crossref']
if cr.entryLine < ent.entryLine:
print "Warning: crossref %s used after declaration"%cr.key
print("Warning: crossref %s used after declaration"%cr.key)
for k in cr.entries.keys():
if ent.entries.has_key(k):
print "ERROR: %s defined both in %s and in %s"%(
k,ent.key,cr.key)
for k in list(cr.entries.keys()):
if k in ent.entries:
print("ERROR: %s defined both in %s and in %s"%(
k,ent.key,cr.key))
else:
ent.entries[k] = cr.entries[k]
@ -105,7 +105,7 @@ class BibTeX:
rk = "title"
for ent in self.entries:
if ent.type in config.OMIT_ENTRIES or not ent.has_key(rk):
if ent.type in config.OMIT_ENTRIES or rk not in ent:
ent.check()
del self.byKey[ent.key.lower()]
else:
@ -122,7 +122,7 @@ def buildAuthorTable(entries):
authorsByLast.setdefault(tuple(a.last), []).append(a)
# map from author to collapsed author.
result = {}
for k,v in config.COLLAPSE_AUTHORS.items():
for k,v in list(config.COLLAPSE_AUTHORS.items()):
a = parseAuthor(k)[0]
c = parseAuthor(v)[0]
result[c] = c
@ -130,7 +130,7 @@ def buildAuthorTable(entries):
for e in entries:
for author in e.parsedAuthor:
if result.has_key(author):
if author in result:
continue
c = author
@ -141,16 +141,16 @@ def buildAuthorTable(entries):
result[author] = c
if 0:
for a,c in result.items():
for a,c in list(result.items()):
if a != c:
print "Collapsing authors: %s => %s" % (a,c)
print("Collapsing authors: %s => %s" % (a,c))
if 0:
print parseAuthor("Franz Kaashoek")[0].collapsesTo(
parseAuthor("M. Franz Kaashoek")[0])
print parseAuthor("Paul F. Syverson")[0].collapsesTo(
parseAuthor("Paul Syverson")[0])
print parseAuthor("Paul Syverson")[0].collapsesTo(
parseAuthor("Paul F. Syverson")[0])
print(parseAuthor("Franz Kaashoek")[0].collapsesTo(
parseAuthor("M. Franz Kaashoek")[0]))
print(parseAuthor("Paul F. Syverson")[0].collapsesTo(
parseAuthor("Paul Syverson")[0]))
print(parseAuthor("Paul Syverson")[0].collapsesTo(
parseAuthor("Paul F. Syverson")[0]))
return result
@ -221,7 +221,7 @@ def splitEntriesByAuthor(entries):
htmlResult[sortkey] = secname
result.setdefault(sortkey, []).append(ent)
sortnames = result.keys()
sortnames = list(result.keys())
sortnames.sort()
sections = [ (htmlResult[n], result[n]) for n in sortnames ]
return sections, url_map
@ -255,13 +255,13 @@ def sortEntriesByDate(entries):
monthname = match.group(1)
mon = MONTHS.index(monthname)
except ValueError:
print "Unknown month %r in %s"%(ent.get("month"), ent.key)
print("Unknown month %r in %s"%(ent.get("month"), ent.key))
mon = 0
try:
date = int(ent['year'])*13 + mon
except KeyError:
print "ERROR: No year field in %s"%ent.key
print("ERROR: No year field in %s"%ent.key)
date = 10000*13
except ValueError:
date = 10000*13
@ -286,7 +286,7 @@ class BibTeXEntry:
def get(self, k, v=None):
return self.entries.get(k,v)
def has_key(self, k):
return self.entries.has_key(k)
return k in self.entries
def __getitem__(self, k):
return self.entries[k]
def __setitem__(self, k, v):
@ -312,13 +312,13 @@ class BibTeXEntry:
d = ["@%s{%s,\n" % (self.type, self.key)]
if v:
df = DISPLAYED_FIELDS[:]
for k in self.entries.keys():
for k in list(self.entries.keys()):
if k not in df:
df.append(k)
else:
df = DISPLAYED_FIELDS
for f in df:
if not self.entries.has_key(f):
if f not in self.entries:
continue
v = self.entries[f]
if v.startswith("<span class='bad'>"):
@ -330,7 +330,7 @@ class BibTeXEntry:
d.append("%%%%% "+("ERROR: Non-ASCII characters: '%r'\n"%np))
d.append(" ")
v = v.replace("&", "&amp;")
if invStrings.has_key(v):
if v in invStrings:
s = "%s = %s,\n" %(f, invStrings[v])
else:
s = "%s = {%s},\n" % (f, v)
@ -359,7 +359,7 @@ class BibTeXEntry:
none."""
errs = self._check()
for e in errs:
print e
print(e)
return not errs
def _check(self):
@ -396,14 +396,14 @@ class BibTeXEntry:
not self['booktitle'].startswith("{Proceedings of"):
errs.append("ERROR: %s's booktitle (%r) doesn't start with 'Proceedings of'" % (self.key, self['booktitle']))
if self.has_key("pages") and not re.search(r'\d+--\d+', self['pages']):
if "pages" in self and not re.search(r'\d+--\d+', self['pages']):
errs.append("ERROR: Misformed pages in %s"%self.key)
if self.type == 'proceedings':
if self.get('title'):
errs.append("ERROR: %s is a proceedings: it should have a booktitle, not a title." % self.key)
for field, value in self.entries.items():
for field, value in list(self.entries.items()):
if value.translate(ALLCHARS, PRINTINGCHARS):
errs.append("ERROR: %s.%s has non-ASCII characters"%(
self.key, field))
@ -551,8 +551,8 @@ class BibTeXEntry:
cache_section = self.get('www_cache_section', ".")
if cache_section not in config.CACHE_SECTIONS:
if cache_section != ".":
print >>sys.stderr, "Unrecognized cache section %s"%(
cache_section)
print("Unrecognized cache section %s"%(
cache_section), file=sys.stderr)
cache_section="."
for key, name, ext in (('www_abstract_url', 'abstract','abstract'),
@ -766,13 +766,13 @@ class ParsedAuthor:
short = o.first; long = self.first
initials_s = "".join([n[0] for n in short])
initials_l = "".join([n[0] for n in long])
initials_l = "".join([n[0] for n in int])
idx = initials_l.find(initials_s)
if idx < 0:
return self
n = long[:idx]
n = int[:idx]
for i in range(idx, idx+len(short)):
a = long[i]; b = short[i-idx]
a = int[i]; b = short[i-idx]
if a == b:
n.append(a)
elif len(a) == 2 and a[1] == '.' and a[0] == b[0]:
@ -781,7 +781,7 @@ class ParsedAuthor:
n.append(a)
else:
return self
n += long[idx+len(short):]
n += int[idx+len(short):]
if n == self.first:
return self
@ -842,7 +842,7 @@ def _split(s,w=79,indent=8):
first = 1
indentation = ""
while len(s) > w:
for i in xrange(w-1, 20, -1):
for i in range(w-1, 20, -1):
if s[i] == ' ':
r.append(indentation+s[:i])
s = s[i+1:]
@ -864,14 +864,14 @@ class FileIter:
if fname:
file = open(fname, 'r')
if string:
file = cStringIO.StringIO(string)
file = io.StringIO(string)
if file:
it = iter(file.xreadlines())
it = iter(file)
self.iter = it
assert self.iter
self.lineno = 0
self._next = it.next
def next(self):
self._next = it.__next__
def __next__(self):
self.lineno += 1
return self._next()
@ -880,7 +880,7 @@ def parseAuthor(s):
try:
return _parseAuthor(s)
except:
print >>sys.stderr, "Internal error while parsing author %r"%s
print("Internal error while parsing author %r"%s, file=sys.stderr)
raise
def _parseAuthor(s):
@ -891,7 +891,7 @@ def _parseAuthor(s):
while s:
s = s.strip()
bracelevel = 0
for i in xrange(len(s)):
for i in range(len(s)):
if s[i] == '{':
bracelevel += 1
elif s[i] == '}':
@ -947,8 +947,8 @@ def _parseAuthor(s):
return parsedAuthors
ALLCHARS = "".join(map(chr,range(256)))
PRINTINGCHARS = "\t\n\r"+"".join(map(chr,range(32, 127)))
ALLCHARS = "".join(map(chr,list(range(256))))
PRINTINGCHARS = "\t\n\r"+"".join(map(chr,list(range(32, 127))))
LC_CHARS = "abcdefghijklmnopqrstuvwxyz"
SV_DELCHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
@ -995,7 +995,7 @@ class Parser:
self.strings.update(initial_strings)
self.newStrings = {}
self.invStrings = {}
for k,v in config.INITIAL_STRINGS.items():
for k,v in list(config.INITIAL_STRINGS.items()):
self.invStrings[v]=k
self.fileiter = fileiter
if result is None:
@ -1049,7 +1049,7 @@ class Parser:
continue
data.append(line)
data.append(" ")
line = it.next()
line = next(it)
self.litStringLine = 0
elif line[0] == '{':
bracelevel += 1
@ -1076,13 +1076,13 @@ class Parser:
#print bracelevel, "C", repr(line)
data.append(line)
data.append(" ")
line = it.next()
line = next(it)
elif line[0] == '#':
print >>sys.stderr, "Weird concat on line %s"%it.lineno
print("Weird concat on line %s"%it.lineno, file=sys.stderr)
elif line[0] in "},":
if not data:
print >>sys.stderr, "No data after field on line %s"%(
it.lineno)
print("No data after field on line %s"%(
it.lineno), file=sys.stderr)
else:
m = RAW_DATA_RE.match(line)
if m:
@ -1170,7 +1170,7 @@ class Parser:
else:
key = v[0]
d = {}
for i in xrange(1,len(v),2):
for i in range(1,len(v),2):
d[v[i].lower()] = v[i+1]
ent = BibTeXEntry(self.curEntType, key, d)
ent.entryLine = self.entryLine
@ -1197,11 +1197,11 @@ class Parser:
def _parse(self):
it = self.fileiter
line = it.next()
line = next(it)
while 1:
# Skip blank lines.
while not line or line.isspace() or OUTER_COMMENT_RE.match(line):
line = it.next()
line = next(it)
# Get the first line of an entry.
m = ENTRY_BEGIN_RE.match(line)
if m:
@ -1215,7 +1215,7 @@ class Parser:
def _advance(it,line):
while not line or line.isspace() or COMMENT_RE.match(line):
line = it.next()
line = next(it)
return line
# Matches a comment line outside of an entry.
@ -1265,5 +1265,5 @@ if __name__ == '__main__':
for e in r.entries:
if e.type in ("proceedings", "journal"): continue
print e.to_html()
print(e.to_html())

View File

@ -19,7 +19,7 @@ del _k
def load(cfgFile):
mod = {}
execfile(cfgFile, mod)
exec(compile(open(cfgFile, "rb").read(), cfgFile, 'exec'), mod)
for _k in _KEYS:
try:
globals()[_k]=mod[_k]
@ -28,7 +28,7 @@ def load(cfgFile):
INITIAL_STRINGS.update(_EXTRA_INITIAL_STRINGS)
AUTHOR_RE_LIST[:] = [
(re.compile(k, re.I), v,) for k, v in AUTHOR_URLS.items()
(re.compile(k, re.I), v,) for k, v in list(AUTHOR_URLS.items())
]
NO_COLLAPSE_AUTHORS_RE_LIST[:] = [
@ -36,7 +36,7 @@ def load(cfgFile):
]
ALPHABETIZE_AUTHOR_AS_RE_LIST[:] = [
(re.compile(k, re.I), v,) for k,v in ALPHABETIZE_AUTHOR_AS.items()
(re.compile(k, re.I), v,) for k,v in list(ALPHABETIZE_AUTHOR_AS.items())
]
_EXTRA_INITIAL_STRINGS = {

View File

@ -45,7 +45,7 @@ SINGLETONS = {
'z': 's',
}
ALLCHARS = "".join(map(chr, range(256)))
ALLCHARS = "".join(map(chr, list(range(256))))
NONLCCHARS = "".join([c for c in ALLCHARS if not c.islower()])
def metaphone(s):
"""Return the metaphone equivalent of a provided string"""
@ -182,7 +182,7 @@ def metaphone(s):
return "".join(result)
def demo(a):
print a, "=>", metaphone(a)
print(a, "=>", metaphone(a))
if __name__ == '__main__':
demo("Nick. Mathewson")

View File

@ -7,7 +7,7 @@
cache_expire = 60*60*24*30 # 30 days
# Checks
import config
from . import config
import os
import sys
from os.path import exists, isdir, join, getmtime
@ -32,8 +32,8 @@ def cache_folder():
return r
import re
from urllib2 import urlopen, build_opener
from urllib import quote
from urllib.request import urlopen, build_opener
from urllib.parse import quote
from datetime import date
import hashlib
@ -66,17 +66,17 @@ def getPageForTitle(title, cache=True, update=True, save=True):
if exists(join(cache_folder(), md5h(url))) and cache:
return url, file(join(cache_folder(), md5h(url)),'r').read()
elif update:
print "Downloading rank for %r."%title
print("Downloading rank for %r."%title)
# Make a custom user agent (so that we are not filtered by Google)!
opener = build_opener()
opener.addheaders = [('User-agent', 'Anon.Bib.0.1')]
print "connecting..."
print("connecting...")
connection = opener.open(url)
print "reading"
print("reading")
page = connection.read()
print "done"
print("done")
if save:
file(join(cache_folder(), md5h(url)),'w').write(page)
return url, page
@ -140,20 +140,20 @@ def get_rank_html(title, years=None, base_url=".", update=True,
def TestScholarFormat():
# We need to ensure that Google Scholar does not change its page format under our feet
# Use some cases to check if all is good
print "Checking google scholar formats..."
print("Checking google scholar formats...")
stopAndGoCites = getCite("Stop-and-Go MIXes: Providing Probabilistic Anonymity in an Open System", False)[0]
dragonCites = getCite("Mixes protected by Dragons and Pixies: an empirical study", False, save=False)[0]
if stopAndGoCites in (0, None):
print """OOPS.\n
print("""OOPS.\n
It looks like Google Scholar changed their URL format or their output format.
I went to count the cites for the Stop-and-Go MIXes paper, and got nothing."""
I went to count the cites for the Stop-and-Go MIXes paper, and got nothing.""")
sys.exit(1)
if dragonCites != None:
print """OOPS.\n
print("""OOPS.\n
It looks like Google Scholar changed their URL format or their output format.
I went to count the cites for a fictitious paper, and found some."""
I went to count the cites for a fictitious paper, and found some.""")
sys.exit(1)
def urlIsUseless(u):
@ -170,7 +170,7 @@ URLTYPES=[ "pdf", "ps", "txt", "ps_gz", "html" ]
if __name__ == '__main__':
# First download the bibliography file.
import BibTeX
from . import BibTeX
suggest = False
if sys.argv[1] == 'suggest':
suggest = True
@ -182,7 +182,7 @@ if __name__ == '__main__':
bib = BibTeX.parseFile(config.MASTER_BIB)
remove_old()
print "Downloading missing ranks."
print("Downloading missing ranks.")
for ent in bib.entries:
getCite(ent['title'], cache=True, update=True)
@ -190,13 +190,13 @@ if __name__ == '__main__':
for ent in bib.entries:
haveOne = False
for utype in URLTYPES:
if ent.has_key("www_%s_url"%utype):
if "www_%s_url"%utype in ent:
haveOne = True
break
if haveOne:
continue
print ent.key, "has no URLs given."
print(ent.key, "has no URLs given.")
urls = [ u for u in getPaperURLs(ent['title']) if not urlIsUseless(u) ]
for u in urls:
print "\t", u
print("\t", u)

View File

@ -13,9 +13,9 @@ import re
assert sys.version_info[:3] >= (2,2,0)
import BibTeX
import config
import metaphone
from . import BibTeX
from . import config
from . import metaphone
_MPCACHE = {}
def soundsLike(s1, s2):
@ -168,16 +168,16 @@ class MasterBibTeX(BibTeX.BibTeX):
matches = m2
if not matches:
print "No match for %s"%e.key
print("No match for %s"%e.key)
if matches[-1][1] is e:
print "%s matches for %s: OK."%(len(matches), e.key)
print("%s matches for %s: OK."%(len(matches), e.key))
else:
print "%s matches for %s: %s is best!" %(len(matches), e.key,
matches[-1][1].key)
print("%s matches for %s: %s is best!" %(len(matches), e.key,
matches[-1][1].key))
if len(matches) > 1:
for g, m in matches:
print "%%%% goodness", g
print m
print("%%%% goodness", g)
print(m)
def noteToURL(note):
@ -202,7 +202,7 @@ def emit(f,ent):
global all_ok
errs = ent._check()
if master.byKey.has_key(ent.key.strip().lower()):
if ent.key.strip().lower() in master.byKey:
errs.append("ERROR: Key collision with master file")
if errs:
@ -210,7 +210,7 @@ def emit(f,ent):
note = ent.get("note")
if ent.getURL() and not note:
ent['note'] = "\url{%s}"%ent.getURL()
ent['note'] = "\\url{%s}"%ent.getURL()
elif note:
m = re.match(r'\\url{(.*)}', note)
if m:
@ -232,61 +232,61 @@ def emit(f,ent):
if errs:
all_ok = 0
for e in errs:
print >>f, "%%%%", e
print("%%%%", e, file=f)
print >>f, ent.format(77, 4, v=1, invStrings=invStrings)
print(ent.format(77, 4, v=1, invStrings=invStrings), file=f)
def emitKnown(f, ent, matches):
print >>f, "%% Candidates are:", ", ".join([e.key for g,e in matches])
print >>f, "%%"
print >>f, "%"+(ent.format(77,4,1,invStrings).replace("\n", "\n%"))
print("%% Candidates are:", ", ".join([e.key for g,e in matches]), file=f)
print("%%", file=f)
print("%"+(ent.format(77,4,1,invStrings).replace("\n", "\n%")), file=f)
if __name__ == '__main__':
if len(sys.argv) != 3:
print "reconcile.py expects 2 arguments"
print("reconcile.py expects 2 arguments")
sys.exit(1)
config.load(sys.argv[1])
print "========= Scanning master =========="
print("========= Scanning master ==========")
master = MasterBibTeX()
master = BibTeX.parseFile(config.MASTER_BIB, result=master)
master.buildIndex()
print "========= Scanning new file ========"
print("========= Scanning new file ========")
try:
fn = sys.argv[2]
input = BibTeX.parseFile(fn)
except BibTeX.ParseError, e:
print "Error parsing %s: %s"%(fn,e)
except BibTeX.ParseError as e:
print("Error parsing %s: %s"%(fn,e))
sys.exit(1)
f = open('tmp.bib', 'w')
keys = input.newStrings.keys()
keys = list(input.newStrings.keys())
keys.sort()
for k in keys:
v = input.newStrings[k]
print >>f, "@string{%s = {%s}}"%(k,v)
print("@string{%s = {%s}}"%(k,v), file=f)
invStrings = input.invStrings
for e in input.entries:
if not (e.get('title') and e.get('author')):
print >>f, "%%\n%%%% Not enough information to search for a match: need title and author.\n%%"
print("%%\n%%%% Not enough information to search for a match: need title and author.\n%%", file=f)
emit(f, e)
continue
matches = master.includes(e, all=1)
if not matches:
print >>f, "%%\n%%%% This entry is probably new: No match found.\n%%"
print("%%\n%%%% This entry is probably new: No match found.\n%%", file=f)
emit(f, e)
else:
print >>f, "%%"
print >>f, "%%%% Possible match found for this entry; max goodness",\
matches[-1][0], "\n%%"
print("%%", file=f)
print("%%%% Possible match found for this entry; max goodness",\
matches[-1][0], "\n%%", file=f)
emitKnown(f, e, matches)
if not all_ok:
print >>f, "\n\n\nErrors remain; not finished.\n"
print("\n\n\nErrors remain; not finished.\n", file=f)
f.close()

View File

@ -3,8 +3,8 @@
"""Unit tests for anonbib."""
import BibTeX
import metaphone
from . import BibTeX
from . import metaphone
#import reconcile
#import writeHTML
#import updateCache
@ -18,40 +18,40 @@ class MetaphoneTests(unittest.TestCase):
class BibTeXTests(unittest.TestCase):
def testTranslation(self):
ut = BibTeX.url_untranslate
self.assertEquals(ut("Fred"),"Fred")
self.assertEquals(ut("Hello, World."), "Hello_2c_20World.")
self.assertEqual(ut("Fred"),"Fred")
self.assertEqual(ut("Hello, World."), "Hello_2c_20World.")
te = BibTeX.TeXescapeURL
ute = BibTeX.unTeXescapeURL
self.assertEquals(te("http://example/~me/my_file"),
self.assertEqual(te("http://example/~me/my_file"),
r"http://example/\{}~me/my\_file")
self.assertEquals(ute(r"http:{}//example/\{}~me/my\_file"),
self.assertEqual(ute(r"http:{}//example/\{}~me/my\_file"),
"http://example/~me/my_file")
h = BibTeX.htmlize
self.assertEquals(h("Hello, world"), "Hello, world")
self.assertEquals(h(r"\'a\`e\'{i}(\'\i)\"o&\^u"),
self.assertEqual(h("Hello, world"), "Hello, world")
self.assertEqual(h(r"\'a\`e\'{i}(\'\i)\"o&\^u"),
"&aacute;&egrave;&iacute;(&iacute;)&ouml;&amp;"
"&ucirc;")
self.assertEquals(h(r"\~n and \c{c}"), "&ntilde; and &ccedil;")
self.assertEquals(h(r"\AE---a ligature"), "&AElig;&mdash;a ligature")
self.assertEquals(h(r"{\it 33}"), " 33")
self.assertEquals(h(r"Pages 33--99 or vice--versa?"),
self.assertEqual(h(r"\~n and \c{c}"), "&ntilde; and &ccedil;")
self.assertEqual(h(r"\AE---a ligature"), "&AElig;&mdash;a ligature")
self.assertEqual(h(r"{\it 33}"), " 33")
self.assertEqual(h(r"Pages 33--99 or vice--versa?"),
"Pages 33-99 or vice&ndash;versa?")
t = BibTeX.txtize
self.assertEquals(t("Hello, world"), "Hello, world")
self.assertEquals(t(r"\'a\`e\'{i}(\'\i)\"o&\^u"),
self.assertEqual(t("Hello, world"), "Hello, world")
self.assertEqual(t(r"\'a\`e\'{i}(\'\i)\"o&\^u"),
"aei(i)o&u")
self.assertEquals(t(r"\~n and \c{c}"), "n and c")
self.assertEquals(t(r"\AE---a ligature"), "AE---a ligature")
self.assertEquals(t(r"{\it 33}"), " 33")
self.assertEquals(t(r"Pages 33--99 or vice--versa?"),
self.assertEqual(t(r"\~n and \c{c}"), "n and c")
self.assertEqual(t(r"\AE---a ligature"), "AE---a ligature")
self.assertEqual(t(r"{\it 33}"), " 33")
self.assertEqual(t(r"Pages 33--99 or vice--versa?"),
"Pages 33--99 or vice--versa?")
def authorsParseTo(self,authors,result):
pa = BibTeX.parseAuthor(authors)
self.assertEquals(["|".join(["+".join(item) for item in
self.assertEqual(["|".join(["+".join(item) for item in
[a.first,a.von,a.last,a.jr]])
for a in pa],
result)

View File

@ -10,13 +10,13 @@ import signal
import time
import gzip
import BibTeX
import config
import urllib2
from . import BibTeX
from . import config
import urllib.request, urllib.error, urllib.parse
import getopt
import socket
import errno
import httplib
import http.client
FILE_TYPES = [ "txt", "html", "pdf", "ps", "ps.gz", "abstract" ]
BIN_FILE_TYPES = [ 'pdf', 'ps.gz' ]
@ -53,12 +53,12 @@ def downloadFile(key, ftype, section, url,timeout=None):
signal.alarm(timeout)
try:
try:
infile = urllib2.urlopen(url)
except httplib.InvalidURL, e:
infile = urllib.request.urlopen(url)
except http.client.InvalidURL as e:
raise UIError("Invalid URL %s: %s"%(url,e))
except IOError, e:
except IOError as e:
raise UIError("Cannot connect to url %s: %s"%(url,e))
except socket.error, e:
except socket.error as e:
if getattr(e,"errno",-1) == errno.EINTR:
raise UIError("Connection timed out to url %s"%url)
else:
@ -80,9 +80,9 @@ def downloadFile(key, ftype, section, url,timeout=None):
outfile.close()
urlfile = open(fnameURL, 'w')
print >>urlfile, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), file=urlfile)
if "\n" in url: url = url.replace("\n", " ")
print >>urlfile, url
print(url, file=urlfile)
urlfile.close()
os.rename(fnameTmp, fname)
@ -105,7 +105,7 @@ def getCachedURL(key, ftype, section):
lines = f.readlines()
f.close()
if len(lines) != 2:
print >>sys.stderr, "ERROR: unexpected number of lines in", urlFname
print("ERROR: unexpected number of lines in", urlFname, file=sys.stderr)
return lines[1].strip()
def downloadAll(bibtex, missingOnly=0):
@ -115,33 +115,33 @@ def downloadAll(bibtex, missingOnly=0):
urls = getURLs(e)
key = e.key
section = e.get("www_cache_section", ".")
for ftype, url in urls.items():
for ftype, url in list(urls.items()):
if missingOnly:
cachedURL = getCachedURL(key, ftype, section)
if cachedURL == url:
print >>sys.stderr,"Skipping",url
print("Skipping",url, file=sys.stderr)
continue
elif cachedURL is not None:
print >>sys.stderr,"URL for %s.%s has changed"%(key,ftype)
print("URL for %s.%s has changed"%(key,ftype), file=sys.stderr)
else:
print >>sys.stderr,"I have no copy of %s.%s"%(key,ftype)
print("I have no copy of %s.%s"%(key,ftype), file=sys.stderr)
try:
downloadFile(key, ftype, section, url)
print "Downloaded",url
except UIError, e:
print >>sys.stderr, str(e)
print("Downloaded",url)
except UIError as e:
print(str(e), file=sys.stderr)
errors.append((key,ftype,url,str(e)))
except (IOError, socket.error), e:
except (IOError, socket.error) as e:
msg = "Error downloading %s: %s"%(url,str(e))
print >>sys.stderr, msg
print(msg, file=sys.stderr)
errors.append((key,ftype,url,msg))
if urls.has_key("ps") and not urls.has_key("ps.gz"):
if "ps" in urls and "ps.gz" not in urls:
# Say, this is something we'd like to have gzipped locally.
psFname = getCacheFname(key, "ps", section)
psGzFname = getCacheFname(key, "ps.gz", section)
if os.path.exists(psFname) and not os.path.exists(psGzFname):
# This is something we haven't gzipped yet.
print "Compressing a copy of",psFname
print("Compressing a copy of",psFname)
outf = gzip.GzipFile(psGzFname, "wb")
inf = open(psFname, "rb")
while 1:
@ -156,9 +156,9 @@ def downloadAll(bibtex, missingOnly=0):
if __name__ == '__main__':
if len(sys.argv) == 2:
print "Loading from %s"%sys.argv[1]
print("Loading from %s"%sys.argv[1])
else:
print >>sys.stderr, "Expected a single configuration file as an argument"
print("Expected a single configuration file as an argument", file=sys.stderr)
sys.exit(1)
config.load(sys.argv[1])

View File

@ -9,10 +9,10 @@ import os
import json
assert sys.version_info[:3] >= (2,2,0)
os.umask(022)
os.umask(0o22)
import BibTeX
import config
from . import BibTeX
from . import config
def getTemplate(name):
f = open(name)
@ -39,15 +39,15 @@ def writeBody(f, sections, section_urls, cache_path, base_url):
sDisp = re.sub(r'\s+', ' ', s.strip())
sDisp = sDisp.replace(" ", "&nbsp;")
if u:
print >>f, ('<li><h3><a name="%s"></a><a href="%s">%s</a></h3>'%(
(BibTeX.url_untranslate(s), u, sDisp)))
print(('<li><h3><a name="%s"></a><a href="%s">%s</a></h3>'%(
(BibTeX.url_untranslate(s), u, sDisp))), file=f)
else:
print >>f, ('<li><h3><a name="%s">%s</a></h3>'%(
BibTeX.url_untranslate(s),sDisp))
print >>f, "<ul class='expand'>"
print(('<li><h3><a name="%s">%s</a></h3>'%(
BibTeX.url_untranslate(s),sDisp)), file=f)
print("<ul class='expand'>", file=f)
for e in entries:
print >>f, e.to_html(cache_path=cache_path, base_url=base_url)
print >>f, "</ul></li>"
print(e.to_html(cache_path=cache_path, base_url=base_url), file=f)
print("</ul></li>", file=f)
def writeHTML(f, sections, sectionType, fieldName, choices,
tag, config, cache_url_path, section_urls={}):
@ -69,7 +69,7 @@ def writeHTML(f, sections, sectionType, fieldName, choices,
#
tagListStr = []
st = config.TAG_SHORT_TITLES.keys()
st = list(config.TAG_SHORT_TITLES.keys())
st.sort()
root = "../"*pathLength(config.TAG_DIRECTORIES[tag])
if root == "": root = "."
@ -104,10 +104,10 @@ def writeHTML(f, sections, sectionType, fieldName, choices,
}
header, footer = getTemplate(config.TEMPLATE_FILE)
print >>f, header%fields
print(header%fields, file=f)
writeBody(f, sections, section_urls, cache_path=cache_url_path,
base_url=root)
print >>f, footer%fields
print(footer%fields, file=f)
def jsonDumper(obj):
if isinstance(obj, BibTeX.BibTeXEntry):
@ -125,7 +125,7 @@ def writePageSet(config, bib, tag):
bib_entries = bib.entries[:]
if not bib_entries:
print >>sys.stderr, "No entries with tag %r; skipping"%tag
print("No entries with tag %r; skipping"%tag, file=sys.stderr)
return
tagdir = config.TAG_DIRECTORIES[tag]
@ -133,7 +133,7 @@ def writePageSet(config, bib, tag):
cache_url_path = BibTeX.smartJoin("../"*pathLength(tagdir),
config.CACHE_DIR)
if not os.path.exists(outdir):
os.makedirs(outdir, 0755)
os.makedirs(outdir, 0o755)
##### Sorted views:
## By topic.
@ -174,7 +174,7 @@ def writePageSet(config, bib, tag):
except ValueError:
last_year = int(entries[-2][1][0].get('year'))
years = map(str, range(first_year, last_year+1))
years = list(map(str, list(range(first_year, last_year+1))))
if entries[-1][0] == 'Unknown':
years.append("Unknown")
@ -216,15 +216,15 @@ def writePageSet(config, bib, tag):
header,footer = getTemplate(config.BIBTEX_TEMPLATE_FILE)
f = open(os.path.join(outdir,"bibtex.html"), 'w')
print >>f, header % { 'command_line' : "",
print(header % { 'command_line' : "",
'title': config.TAG_TITLES[tag],
'root': root }
'root': root }, file=f)
for ent in entries:
print >>f, (
print((
("<tr><td class='bibtex'><a name='%s'>%s</a>"
"<pre class='bibtex'>%s</pre></td></tr>")
%(BibTeX.url_untranslate(ent.key), ent.key, ent.format(90,8,1)))
print >>f, footer
%(BibTeX.url_untranslate(ent.key), ent.key, ent.format(90,8,1))), file=f)
print(footer, file=f)
f.close()
f = open(os.path.join(outdir,"bibtex.json"), 'w')
@ -234,13 +234,13 @@ def writePageSet(config, bib, tag):
if __name__ == '__main__':
if len(sys.argv) == 2:
print "Loading from %s"%sys.argv[1]
print("Loading from %s"%sys.argv[1])
else:
print >>sys.stderr, "Expected a single configuration file as an argument"
print("Expected a single configuration file as an argument", file=sys.stderr)
sys.exit(1)
config.load(sys.argv[1])
bib = BibTeX.parseFile(config.MASTER_BIB)
for tag in config.TAG_DIRECTORIES.keys():
for tag in list(config.TAG_DIRECTORIES.keys()):
writePageSet(config, bib, tag)

View File

@ -1,103 +0,0 @@
{% trans -%}
=================================================================
I2P 2.4.0 Release with Congestion and NetDB Security improvements
=================================================================
{%- endtrans %}
.. meta::
:author: idk
:date: 2023-12-18
:category: release
:excerpt: {% trans %}{% endtrans %}
{% trans -%}
Update details
{%- endtrans %}
============================================
{% trans -%}
This release, I2P 2.4.0, continues our effort to improve the security and stability of the I2P network.
It contains significant improvements to the Network Database, an essential structure within the I2P network used for disovering your peers.
{%- endtrans %}
{% trans -%}
The congestion handling changes will improve network stability by giving routers the ability to relieve congested peers by avoiding them.
This will help the network limit the effect of tunnel spam.
It will also help the network heal during and after DDoS attacks.
{%- endtrans %}
{% trans -%}
The NetDb changes also help secure individual routers and the applications that use them.
Routers can now defend against attackers by separating the NetDB into multiple "Sub-DB's" which we use to prevent information leaks between applications and the router.
This also improves the information available to Java routers about their NetDB activity and simplifies our support for multihoming applications.
{%- endtrans %}
{% trans -%}
Also included are a number of bug fixes and enhancements across the I2PSnark and SusiMail applications.
{%- 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 %}RELEASE DETAILS{% endtrans %}**
**{% trans %}Changes{% endtrans %}**
- {% trans %}i2psnark: Uncomment and fix local torrent file picker{% endtrans %}
- {% trans %}NetDB: Lookup handler/throttler fixes{% endtrans %}
- {% trans %}Router: Restructure netDb to isolate data recieved as a client from data recieved as a router{% endtrans %}
- {% trans %}Router: Implement handling and penalties for congestion caps{% endtrans %}
- {% trans %}Router: Temporarily ban routers publishing in the future{% endtrans %}
- {% trans %}Transports: Disable SSU 1{% endtrans %}
**{% trans %}Bug Fixes{% endtrans %}**
- {% trans %}Addressbook: Workaround for i2p-projekt.i2p etag bug (Gitlab #454){% endtrans %}
- {% trans %}Console: Clear out "proxy must be running" status after success{% endtrans %}
- {% trans %}Console: Don't lose tabs in log messages{% endtrans %}
- {% trans %}Console: Fix sidebar not immediately showing results of manual update check{% endtrans %}
- {% trans %}Console: Fix visibility of radio/checkboxes (light theme){% endtrans %}
- {% trans %}Console: Prevent overflow of sidebar status{% endtrans %}
- {% trans %}Debian: Change JRE dependency order (Gitlab #443, Debian #1024461){% endtrans %}
- {% trans %}i2psnark: Increase comment bucket size to reduce duplicates{% endtrans %}
- {% trans %}i2psnark: Prevent start-all from within search results erroring (Gitlab #445){% endtrans %}
- {% trans %}i2ptunnel: Exempt tunnel name from XSS filter (Gitlab #467){% endtrans %}
- {% trans %}i2ptunnel: Fix gzip footer check in GunzipOutputStream (Gitlab #458){% endtrans %}
- {% trans %}i2ptunnel: Remove nonstandard Proxy-Connection headers (Gitlab #452){% endtrans %}
- {% trans %}NTCP2: Fix updating address on transition to firewalled (Gitlab #435){% endtrans %}
- {% trans %}SAM: Fix accept after soft restart (Gitlab #399){% endtrans %}
- {% trans %}SAM: Reset incoming socket if no subsession is matched (Gitlab #456){% endtrans %}
- {% trans %}SSU2: Fix uncaught IAE caused by itags with zero values (Gitlab #415){% endtrans %}
- {% trans %}SSU2: Prevent rare IAE in peer test timer (Gitlab #433){% endtrans %}
- {% trans %}Susimail: Dark theme fixes{% endtrans %}
- {% trans %}Susimail: Fix binary content-encoding{% endtrans %}
- {% trans %}Susimail: Fix incorrect "previous" icons{% endtrans %}
- {% trans %}Susimail: Fix setting encoding for attachments{% endtrans %}
- {% trans %}Susimail: Flush output to fix truncated mails{% endtrans %}
- {% trans %}Sybil: Don't ban NAT64 addresses{% endtrans %}
- {% trans %}Transport: Fix NPE during soft restart (Gitlab #437){% endtrans %}
- {% trans %}UPnP: Fix handing of multiple IGDs{% endtrans %}
- {% trans %}UPnP: Fix missing port in Host header causing failures on libupnp-based devices{% endtrans %}
**{% trans %}Other{% endtrans %}**
- API 0.9.61
- {% trans %}Translation updates{% endtrans %}
`{% trans %}Full list of fixed bugs{% endtrans %}`__
__ http://{{ i2pconv('git.idk.i2p') }}/i2p-hackers/i2p.i2p/-/issues?scope=all&state=closed&milestone_title=2.4.0
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
d08db62457d4106ca0e36df3487bdf6731cbb81045b824a003cde38c7e1dfa27 i2pinstall_2.4.0_windows.exe
ef5f3d0629fec292aae15d027f1ecb3cc7f2432a99a5f7738803b453eaad9cad i2pinstall_2.4.0.jar
30ef8afcad0fffafd94d30ac307f86b5a6b318e2c1f44a023005841a1fcd077c i2psource_2.4.0.tar.bz2
97be217bf07319a50b6496f932700c3f3c0cceeaf1e0643260d38c9e6e139b53 i2pupdate_2.4.0.zip
8f4a17a8cbadb2eabeb527a36389fd266a4bbcfd9d634fa4f20281f48c486e11 i2pupdate.su3

View File

@ -1,84 +0,0 @@
{% trans -%}
========================================
Many Masks, One Mind: Securing the NetDB
========================================
{%- endtrans %}
.. meta::
:author: idk
:date: 2024-03-29
:category: development
:excerpt: {% trans %}Many Masks, One Mind: Securing the NetDB{% endtrans %}
{% trans -%}
Author's note: the attacks referred to in this article are not possible against current versions of I2P.
{%- endtrans %}
{% trans -%}
As a self-organizing peer-to-peer network, I2P relies on the routers participating in the network to have a way to share information about what is on the network and how to reach it.
I2P routers achieve this information sharing using the NetDB, a DHT based on Kademlia but modified to work for I2P.
The NetDB needs to share two main kinds of entries, "RouterInfos" which peers will use to communicate with other routers directly, and "LeaseSets" which other peers will use to communicate with I2P clients through anonymous tunnels.
Routers are frequently commmunicating NetDB entries with eachother, either by sending the information to a router or client, or requesting information from a router or client.
This means that the entries can arrive directly or indirectly, anonymously or non-anonymously, depending on the needs of the network and the capabilities of the client.
However, as an anonymizing network, it is also important that it remain impossible for information sent anonymously to be requested back non-anonymously.
It is also important and for information sent non-anonymously to be impossible to request back anonymously.
If it becomes possible for either of those situations to occur, then a linking attack may be carried out which allows an attacker to determine if a clients and routers are sharing a common view of the NetDB.
If it can be reliably determined that the 2 targets share a common view of the NetDB, then there's a very good chance they are on the same router, weakening the target's anonymity drastically.
Because there are so few anonymizing networks, and I2P is the only one where the routing table is shared via the operation of a DHT, this class of attack is all but unique to I2P and its resolution is important to I2P's success.
{%- endtrans %}
{% trans -%}
Consider the following scenario: There is an I2P router hosting an I2P client.
The router publishes a RouterInfo, and the I2P client publishes its LeaseSet.
Because they are both published in the NetDB, other I2P routers can query the NetDB to discover how to communicate with them.
This is normal and essential to the operation of an overlay network of the type implemented by I2P.
An attacker runs an I2P router and queries the NetDB for the target RouterInfo and the target LeaseSet.
It then crafts a new LeaseSet which is unique and and potentially even fake, and sends it down a tunnel to the LeaseSet for the client it is targeting for attack.
The client processes the crafted LeaseSet and adds it to its own NetDB.
The attacker then requests the crafted LeaseSet back directly, from the router, using the RouterInfo it got from the NetDB.
If the crafted LeaseSet is received back as a reply, then the attacker can conclude that the target client and the target router share a common view of the NetDB.
{%- endtrans %}
{% trans -%}
That is a simple example of a NetDB deanonymization attack class which relies on adding an entry into another person's NetDB with one identity, and then requesting it back out with another identity.
In this case, the identities in question are the "router" and the "client" identity.
However, client-to-client linking, which is less damaging, is also possible in some designs.
Designing a defense against this class of attack requires giving the router a way of determining whether or not it is safe to communicate a piece of information with a potential identity.
{%- endtrans %}
{% trans -%}
So how should we think about this problem?
What we're dealing with here, really, has to do with the linkability of different "identities" on the network.
The possibility of linking is created because all these identities share a common datastructure which "remembers" who it has communicated with, and who has communicated with it.
It also "remembers" how that communication occurred.
{%- endtrans %}
{% trans -%}
For a moment, we should imagine ourselves as an attacker.
Imagine if you were trying to discover the identity of a master of disguise.
You know for sure you have seen his real face, and you know for sure that you regularly communicate with one of his disguises.
How would you go about establishing that the disguise identity and the real identity belong to the same person?
I might tell the disguised person a secret.
If the non-disguised person responds by using the secret information, then I can determine that the non-disguised person knows the secret.
Under the assumption that the disguised person did not communicate the secret to anyone else, then I can assume that the non-disguised person and the disguised person are in fact, the same person.
No matter how many masks the master of disguise wears, he has but one mind.
{%- endtrans %}
{% trans -%}
In order to successfully protect the identities of I2P clients, I2P needs to be able to perform as a better master of disguise than the one described above.
It needs to be able to "remember" several important pieces of information about how it has participated in the NetDB and respond appropriately based on those details.
It must be able to recall:
{%- endtrans %}
* {% trans -%}Whether a NetDB Entry was received directly, or received down a client tunnel{%- endtrans %}
* {% trans -%}Whether a NetDB Entry was sent by a peer in response to our lookup, or sent unsolicited{%- endtrans %}
* {% trans -%}Which NetDB Entry was received down Which client Tunnel{%- endtrans %}
* {% trans -%}Multiple versions of the same entry for different client tunnels{%- endtrans %}
{% trans -%}
Structurally, the most understandable and reliable way to handle this pattern is to use "Sub-DBs."
Sub-DB's are miniature NetDB's which serve to help the NetDB organize entries without losing track.
Every client gets a Sub-DB for its own use, and the router itself gets a fully-fledged NetDB.
Using Sub-DB's, we give our master of disguise a rolodex of secrets organized by who shared those secrets with him.
When a request is sent to a client, it only looks for entries which have been communicated to the client, and when a request is sent to a router, only the router-wide NetDB is used.
By doing things this way, we resolve not only the simplest form of the attack, but also undermine the potency of the entire attack class.
{%- endtrans %}

View File

@ -1,93 +0,0 @@
{% trans -%}
=====================
New Release I2P 2.5.0
=====================
{%- endtrans %}
.. meta::
:author: idk
:date: 2024-04-08
:category: release
:excerpt: {% trans %}I2P 2.5.0 release{% endtrans %}
{% trans -%}
This release, I2P 2.5.0, provides more user-facing improvements than the 2.4.0 release, which was focused on implementing the NetDB isolation strategy.
{%- endtrans %}
{% trans -%}
New features have been added to I2PSnark like the ability to search through torrents.
Bugs have been fixed to improve compatibility with other I2P torrent clients like BiglyBT and qBittorrent.
We would like to thank all of the developers who have worked with libtorrent and qBittorrent to enable and improve their I2P support.
New features have also been added to SusiMail including support for Markdown formatting in emails and the ability to drag-and-drop attachments into emails.
Tunnels created with the Hidden Services manager now support "Keepalive" which improves performance and compatibility with web technologies, enabling more sophisticated I2P sites.
{%- endtrans %}
{% trans -%}
During this release we also made several tweaks to the NetDB to improve its resilience to spam and to improve the router's ability to reject suspicious messages.
This was part of an effort to "audit" the implementation of "Sub-DB isolation" defenses from the 2.4.0 release.
This investigation uncovered one minor isolation-piercing event which we repaired.
This issue was discovered and fixed internally by the I2P team.
{%- endtrans %}
{% trans -%}
During this release several improvements were made to the process of releasing our downstream distributions for Android and Windows.
This should result in improved delivery and availability for these downstream products.
{%- 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 %}RELEASE DETAILS{% endtrans %}**
**{% trans %}Changes{% endtrans %}**
- {% trans %}I2PTunnel: Implement support for Keepalive/Server-side Persistence{% endtrans %}
- {% trans %}Susimail: Add markdown support for formatted plain-text content{% endtrans %}
- {% trans %}Susimail: Add HTML Email support{% endtrans %}
- {% trans %}I2PSnark: Add search capability{% endtrans %}
- {% trans %}I2PSnark: Preserve private=0 in torrent files{% endtrans %}
- {% trans %}Data: Store compressed RI and LS{% endtrans %}
**{% trans %}Bug Fixes{% endtrans %}**
- {% trans %}Susimail: Fix handling of forwarded mail with attachments{% endtrans %}
- {% trans %}Susimail: Fix handling of forwarded mail with unspecified encoding{% endtrans %}
- {% trans %}Susimail: Fix forwarding of HTML-only email{% endtrans %}
- {% trans %}Susimail: Bugfixes in presentation of encoded attachmments, mail body{% endtrans %}
- {% trans %}I2PSnark: Handle data directory changes{% endtrans %}
- {% trans %}SSU2: Cancel peer test if Charlie does not have B cap{% endtrans %}
- {% trans %}SSU2: Treat peer test result as unknown if Charlie is unreachable{% endtrans %}
- {% trans %}Router: Filter additional garlic-wrapped messages{% endtrans %}
- {% trans %}I2CP: Prevent loopback messages to same session{% endtrans %}
- {% trans %}NetDB: Resolve Exploratory/Router isolation-piercing event{% endtrans %}
**{% trans %}Other{% endtrans %}**
- API 0.9.62
- {% trans %}Translation updates{% endtrans %}
`{% trans %}Full list of fixed bugs{% endtrans %}`__
__ http://{{ i2pconv('git.idk.i2p') }}/i2p-hackers/i2p.i2p/-/issues?scope=all&state=closed&milestone_title=2.5.0
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
i2pinstall_2.5.0-0.jar - 61d3720accc6935f255611680b08ba1a414d32daa00d052017630c2424c30069
i2pinstall_2.5.0-0_windows.exe - a0d84c519f3c35874a9f661b9f40220e5a1d29716166c682e2bd1ee15ff83f33
i2pinstall_2.5.0.jar - 61d3720accc6935f255611680b08ba1a414d32daa00d052017630c2424c30069
i2pinstall_2.5.0.jar.sig - c8a6d79909d06ac6bca23d8e890765c6e6ed21a535f7529e0708797fdaf9fc1b
i2pinstall_2.5.0_windows.exe - 762b9d672dfff0baccd46f970deb5a2621358d1e2dfc0dd85a78aecda3623ac6
i2pinstall_2.5.0_windows.exe.sig - 103a1bd155110514fe9ae075243cc66e2fef866353165b2c806248e15925e957
i2psource_2.5.0.tar.bz2 - 6bda9aff7daa468cbf6ddf141c670140de4d1db145329645a90c22c1e5c7bc01
i2psource_2.5.0.tar.bz2.sig - a1d0ea6f2051ed0643bc2c0207a2cf594f2b2bc4303ac49cd6a43baaf0558f62
i2pupdate-2.5.0.su3 - 7bcfc3df3a14a0b9313b9a0fe20e56db75267d5afcfd8a3203fbfcfac46deae4
i2pupdate-2.5.0.su3.torrent - a7dd76348bf404d84a67bda8b009d54cc08748c036988dbe78bff6ca6928950c
i2pupdate.su3 - 7bcfc3df3a14a0b9313b9a0fe20e56db75267d5afcfd8a3203fbfcfac46deae4
i2pupdate.zip - d0a4cfe6cb587e0ffabcfb6012682f400a38ee87f23fa90f8a18f25e77b742d8
i2pupdate_2.5.0.zip - d0a4cfe6cb587e0ffabcfb6012682f400a38ee87f23fa90f8a18f25e77b742d8
i2pupdate_2.5.0.zip.sig - 411eb4ca31e2984dae4c943136411e8ee85435f59749391edefec07509cfd5af

View File

@ -1,21 +0,0 @@
{% trans -%}
==============
Stormy Weather
==============
{%- endtrans %}
.. meta::
:author: idk
:date: 2024-04-25
:category: release
:excerpt: {% trans %}Stormy Weather{% endtrans %}
{% trans -%}
The I2P network is currently under a Denial-of-Service attack.
This attack affects I2P and i2pd but in different ways and is having a serious effect on network health.
Reachability of I2P sites is badly degraded.
{%- endtrans %}
{% trans -%}
If you are hosting a service inside I2P and it is hosted on a Floodfill router, you should consider multihoming the service on a Floodfill-disabled router to improve reachability.
Other mitigations are being discussed but a long-term, backward-compatible solution is still being worked on.
{%- endtrans %}

View File

@ -1,60 +0,0 @@
{% trans -%}
=====================
New Release I2P 2.5.1
=====================
{%- endtrans %}
.. meta::
:author: idk
:date: 2024-05-06
:category: release
:excerpt: {% trans %}I2P 2.5.1 Release{% endtrans %}
{% trans -%}
I2P 2.5.1 is being released to address Denial-of-Service Attacks affecting the I2P network and services.
With this release we disable the IP-based parts of the Sybil attack detection tool which were targeted to amplify the effect and duration of the attack.
This should help the network return to normal operation.
Those of you who have disabled the Sybil attack detection tool may safely re-enable it.
Adjustments to other subsystems to improve RouterInfo validation and peer selection have also been made.
{%- 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 %}RELEASE DETAILS{% endtrans %}**
**{% trans %}Changes{% endtrans %}**
- {% trans %}Susimail: Add search box{% endtrans %}
- {% trans %}Susimail: UI Improvements{% endtrans %}
- {% trans %}NetDB: Don't lookup RI if on banlist{% endtrans %}
- {% trans %}Tomcat: update to 9.0.88{% endtrans %}
**{% trans %}Bug Fixes{% endtrans %}**
- {% trans %}Sybil: Disable IP-Closeness Checks in Sybil Attack Analysis Tool{% endtrans %}
- {% trans %}Profiles: Don't update last heard from if tunnel fails{% endtrans %}
- {% trans %}NetDB: Improve validation of RI's before storing, sending RI's{% endtrans %}
`{% trans %}Full list of fixed bugs{% endtrans %}`__
__ http://{{ i2pconv('git.idk.i2p') }}/i2p-hackers/i2p.i2p/-/issues?scope=all&state=closed&milestone_title=2.5.1
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
1b0c1a12e64bd6dabd894a297b7bfd60ebe218a9177086f27367b8d4f1e30ab9 i2pinstall_2.5.1-0.jar
f9b2038cc6376a7b67a7cbc6ff07046b0a5f6146658dfb910ca4532c81263177 i2pinstall_2.5.1-0_windows.exe
1b0c1a12e64bd6dabd894a297b7bfd60ebe218a9177086f27367b8d4f1e30ab9 i2pinstall_2.5.1.jar
d0150a4f7abcdc85cddae277fa951c2ee76ccc7403d98cd255791ac752a7e36b i2pinstall_2.5.1.jar.sig
f9b2038cc6376a7b67a7cbc6ff07046b0a5f6146658dfb910ca4532c81263177 i2pinstall_2.5.1_windows.exe
4bc7e59ee0036389a0f76fc76b2303eeae62bf6eaaf608c9939226febf9ddeae i2psource_2.5.1.tar.bz2
251293c39c333bd7d8ad01235ef15bccf15df1b72dd18917de06cdb212b7801f i2psource_2.5.1.tar.bz2.sig
163b7fe3e9941bd412bad1b80f34e2a8cd1ade2e77cbe4cfb58eca42f3ca4b62 i2pupdate-2.5.1.su3
461b5fe51d2d953ba798eee867e434b4bf234911418c0dd5560b558f755f6657 i2pupdate-2.5.1.su3.torrent
a4db0e6a9ee56df2d9bb2b12d9eb3a04501aeeac83773817f62565e632d88228 i2pupdate_2.5.1.zip
c592bc6d1ffcc988f021bbd30ea6e5063f31bb5175846be96c5c2724294bd99b i2pupdate_2.5.1.zip.sig
163b7fe3e9941bd412bad1b80f34e2a8cd1ade2e77cbe4cfb58eca42f3ca4b62 i2pupdate.su3
a4db0e6a9ee56df2d9bb2b12d9eb3a04501aeeac83773817f62565e632d88228 i2pupdate.zip

View File

@ -1,50 +0,0 @@
===========================================
{% trans -%}2.5.2 Release{%- endtrans %}
===========================================
.. meta::
:author: zzz
:date: 2024-05-15
:category: release
:excerpt: {% trans %}2.5.2 Release with HTTP fix{% endtrans %}
{% trans -%}
I2P 2.5.2 is released to fix a bug introduced in 2.5.0 causing truncation of some HTTP content.
{%- 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 %}RELEASE DETAILS{% endtrans %}**
**{% trans %}Changes{% endtrans %}**
- {% trans %}Console: Update rrd4j to 3.9.1-preview{% endtrans %}
- {% trans %}Router: Publish G cap if symmetric natted{% endtrans %}
**{% trans %}Bug Fixes{% endtrans %}**
- {% trans %}i2ptunnel: Fix bug causing truncation of some HTTP content{% endtrans %}
- {% trans %}i2ptunnel: Fix custom option form width (light theme){% endtrans %}
- {% trans %}Tunnels: Fix selection of peers with expired RIs{% endtrans %}
**{% trans %}Other{% endtrans %}**
- {% trans %}Translation updates{% endtrans %}
`{% trans %}Full list of fixed bugs{% endtrans %}`__
__ http://{{ i2pconv('git.idk.i2p') }}/i2p-hackers/i2p.i2p/-/issues?scope=all&state=closed&milestone_title=2.5.2
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
1aa1ac29620886a7d744424318287c67dc9ead488e6ab434848597ee9db7ce18 i2pinstall_2.5.2_windows.exe
751f48cfb380c8796bd645621b149114d55f32cd4330784cb287be9413b02569 i2pinstall_2.5.2.jar
f23d0746d72a55cccbd17f40762e491ae1b42cdf55d7e73404d213a84985ca73 i2psource_2.5.2.tar.bz2
adba8b7512d27a44ed876ec4beb39a82ebb34dc243ec024aff289e91823fc0c7 i2pupdate_2.5.2.zip
0d1d09d3d8199ea1a2ea983f5023125449ea55e93e20f5fbf1b7ad9e466bb6fc i2pupdate.su3

View File

@ -1,67 +0,0 @@
============================================
{% trans -%}I2P 2.6.0 Release{%- endtrans %}
============================================
.. meta::
:author: idk
:date: 2024-07-19
:category: release
:excerpt: {% trans %}I2P 2.6.0 Release{% endtrans %}
{% trans -%}
This release, I2P 2.6.0, continues our work by fixing bugs, adding features, and improving the network's reliability.
{%- endtrans %}
{% trans -%}
Newer routers will be favored when selecting floodfill routers.
I2PSnark received features which improve the performance of PeX(Peer Exchange), in addition to bug fixes.
Legacy transport protocols are being removed, simplifying the code in the UDP transports.
Locally-hosted destination will be reachable by local clients without requesting their LeaseSet, improving performance and testability.
Additional tweaks were made to peer selection strategies.
{%- endtrans %}
{% trans -%}
I2P no longer allows I2P-over-Tor, connections from Tor exit IP addresses are now blocked.
We discourage this because it degrades the performance of I2P and uses up the resources of Tor exits for no benefit.
If you are a helpful person running both a Tor Exit and I2P we encourage you to continue to do so, using different IP addresses for each.
Non-exit relays and Tor clients are unaffected by this and do not need to change anything.
{%- 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 %}RELEASE DETAILS{% endtrans %}**
**{% trans %}Changes{% endtrans %}**
- {% trans %}Router: Increase minimum version for floodfill routers{% endtrans %}
- {% trans %}Router: Disable I2P over Tor{% endtrans %}
- {% trans %}Address Book: Cache locally hosted destinations{% endtrans %}
**{% trans %}Bug Fixes{% endtrans %}**
- {% trans %}I2PSnark: Peer Exchange Tweaks{% endtrans %}
- {% trans %}I2PSnark: Bugfixes{% endtrans %}
- {% trans %}Router: Peer Selection Tweaks{% endtrans %}
**{% trans %}Other{% endtrans %}**
- {% trans %}Translation updates{% endtrans %}
`{% trans %}Full list of fixed bugs{% endtrans %}`__
__ http://{{ i2pconv('git.idk.i2p') }}/i2p-hackers/i2p.i2p/-/issues?scope=all&state=closed&milestone_title=2.6.0
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
13f2e6b3cc9716c89c4d4d3bc9918171fbad5f450171e1c32b1237b5421bc065 i2pinstall_2.6.0_windows.exe
42ac34e4c67cf5e2582853f0cf3074f6a73ea59503e1350e1b687cee3f849814 i2pinstall_2.6.0_windows.exe.sig
24cda3f04e8c2e976b73bd45d36d0e31217e28fbe3019bf9a9d839b45d60537a i2pinstall_2.6.0.jar
249b35c1e061e194ee18048b0644cc5e2c5cf785ffce655e3124eb959dc189ff i2psource_2.6.0.tar.bz2
2867d752f6fb89a7a5ada4f4123ca601ad8d78ff78f553a9269bf0ddffe724ca i2pupdate_2.6.0.zip
be6ac988497ac0336d21cdfc57bbbe3cc5cffd983ac3282fd8ea11914e18e7ee i2pupdate.su3

View File

@ -1,49 +0,0 @@
===========================================
{% trans -%}2.6.1 Release{%- endtrans %}
===========================================
.. meta::
:author: idk
:date: 2024-08-06
:category: release
:excerpt: {% trans %}2.6.1 Release with I2PTunnel UI fix{% endtrans %}
{% trans -%}
I2P 2.6.1 is released in order to fix a User-Interface bug in the Hidden Services Manager application.
This bug caused scrolling to be disabled, rendering some configuration inaccessible.
{%- 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 %}RELEASE DETAILS{% endtrans %}**
**{% trans %}Changes{% endtrans %}**
- {% trans %}Graphs: render graphs in svg{% endtrans %}
- {% trans %}Translations: generate internal translation leaderboard{% endtrans %}
**{% trans %}Bug Fixes{% endtrans %}**
- {% trans %}i2ptunnel: Fix bug causing truncation configuration UI{% endtrans %}
**{% trans %}Other{% endtrans %}**
- {% trans %}Translation updates{% endtrans %}
`{% trans %}Full list of fixed bugs{% endtrans %}`__
__ http://{{ i2pconv('git.idk.i2p') }}/i2p-hackers/i2p.i2p/-/issues?scope=all&state=closed&milestone_title=2.6.1
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
88e69e0adac66ed41ef1d521c373a40d491fbec1a40f596dbaa56ac67b5c4b0d i2pinstall_2.6.1_windows.exe
c10d74075dac39d0f80c4fa5bbd403ed59aeba5e933e761a0ecf59d8d5afcad1 i2pinstall_2.6.1.jar
e6ce1704da6ac44909b9ee74b376e3ba10d27a287840b28caaf51dfae0903901 i2psource_2.6.1.tar.bz2
e78fe71186b7b194882132b0392dceb9b4f2ea35cabfcb224739f46f1b11cd53 i2pupdate_2.6.1.zip
42a4eac2a1802130f38ee648cc04c0f2cbc6e8ca6975d89235bdf80b3000aded i2pupdate.su3

View File

@ -1,14 +0,0 @@
===========================================
{% trans -%}I2P Easy-Install for Windows 2.6.1 Release{%- endtrans %}
===========================================
.. meta::
:author: idk
:date: 2024-08-26
:category: release
:excerpt: {% trans %}I2P Easy-Install Windows 2.6.1 Release with I2PTunnel UI fix{% endtrans %}
{% trans -%}
This release updates the embedded I2P router to I2P 2.6.1.
It also updates the embedded I2P Firefox profile to 2.6.2.
{%- endtrans %}

View File

@ -1,49 +0,0 @@
{% trans -%}
==================
I2P 2.7.0 Released
==================
{%- endtrans %}
.. meta::
:author: idk
:date: 2024-10-09
:category: release
:excerpt: {% trans %}I2P 2.7.0 Released{% endtrans %}
{% trans -%}
This release, I2P 2.7.0, continues our work by fixing bugs, improving performance, and adding features.
{%- endtrans %}
{% trans -%}
Access to information from the console and applications has been improved.
Issues have been fixed in I2PSnark and SusiMail search.
The netDB search embedded into the router console now operates in a more intuitive and useful way.
Minor improvements have been made to diagnostic displays in advanced mode.
{%- endtrans %}
{% trans -%}
Bugs have also been fixed to improve compatibility within the network.
An issue with publishing leaseSets was solved which improves reliability major hidden services.
I2PSnark no longer changes the infohash when a user changes only the trackers on an existing torrent.
This prevents torrents from being unnecessarily disrupted by these changes.
We welcomed this contribution from a new contributor.
A conflict in the handling of a streaming library option was resolved to improve compatibility with other I2P implementations.
{%- 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 %}Full list of fixed bugs{% endtrans %}`__
__ http://{{ i2pconv('git.idk.i2p') }}/i2p-hackers/i2p.i2p/-/issues?scope=all&state=closed&milestone_title=2.7.0
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
d70ee549b05e58ded4b75540bbc264a65bdfaea848ba72631f7d8abce3e3d67a i2pinstall_2.7.0_windows.exe
ea3872af06f7a147c1ca84f8e8218541963da6ad97e30e1d8f7a71504e4b0cee i2pinstall_2.7.0.jar
54eebdb1cfdbe6aeb1f60e897c68c6b2921c36ce921350d45d21773256c99874 i2psource_2.7.0.tar.bz2
b7fae5181cbd8b60be0d5a05e391f4c9d114748a8240eb64b91ee84da5c659f8 i2pupdate_2.7.0.zip
59d3d61eccf3622985b71e06d454f61f32f39baa1eb9064536d295b4a7e7ae4e i2pupdate.su3

View File

@ -1,40 +0,0 @@
{% trans -%}
==================
I2P 2.8.0 Released
==================
{%- endtrans %}
.. meta::
:author: idk
:date: 2025-02-04
:category: release
:excerpt: {% trans %}I2P 2.8.0 Released{% endtrans %}
{% trans -%}
This release improves I2P by fixing bugs, removing unused code, and improving network stability.
{%- endtrans %}
{% trans -%}
We have improved handling of congested routers in the network.
Issues in UPnP and NAT traversal were addressed to improve connectivity and error reporting.
We now have a more aggressive strategy for leaseset removal from the NetDb to improve router performance and mitigate overload.
Other changes were implemented to reduce the observability of events like a router rebooting or shutting down.
{%- 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 %}Full list of fixed bugs{% endtrans %}`__
__ http://{{ i2pconv('git.idk.i2p') }}/i2p-hackers/i2p.i2p/-/issues?scope=all&state=closed&milestone_title=2.8.0
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
f2699359fd7c5a2fddb5730666e61c0dce2184f95507d4f33dcfaca16569b580 i2pinstall_2.8.0_windows.exe
32255865c5f89bceab4902ba401c971c5aa238ebe8bc1bfb2153acb6478ce656 i2pinstall_2.8.0.jar
06b305c24ed163bb09b1afaa3a8d44b2477eb3eb0e1c84236d210606986bd820 i2psource_2.8.0.tar.bz2
3ff1e0c52757a39e20ac864aa610c92f1a1168979b42a61cd1e9284becc0fe22 i2pupdate_2.8.0.zip
bfc6fc3c6e2cb486448450d3f08cef6afe2966b57113b17df65cbb53ed6d4a82 i2pupdate.su3

View File

@ -1,76 +0,0 @@
===========================================
{% trans -%}2.8.1 Release{%- endtrans %}
===========================================
.. meta::
:author: zzz
:date: 2025-03-17
:category: release
:excerpt: {% trans %}2.8.1 Release with local site access fix{% endtrans %}
{% trans -%}
2.8.1 fixes accesses to local sites that were broken in 2.8.0.
We have added notification bubbles to several applications in the console to highlight application messages.
We fixed a tunnel test bug that may have been affecting tunnel reliability.
The addressbook now has a new "latest" tab that displays the newest hostnames added from your subscriptions.
There are several dark theme fixes and improvements.
{%- endtrans %}
{% trans -%}
We fixed the installer that previously failed on Java 21 or higher.
We also fixed installing to directory paths that contain spaces on Linux.
For those of you that use Docker, we updated outdated Docker container and container libraries.
{%- 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 %}RELEASE DETAILS{% endtrans %}**
**{% trans %}Changes{% endtrans %}**
- {% trans %}New console notification bubbles{% endtrans %}
- {% trans %}New addressbook sort-by-latest tab{% endtrans %}
- {% trans %}Add support for .i2p.alt hostnames (RFC 9476){% endtrans %}
**{% trans %}Bug Fixes{% endtrans %}**
- {% trans %}Fix local site access bug{% endtrans %}
- {% trans %}Fix installer failure on Java 21+ (IzPack 5.2.4){% endtrans %}
- {% trans %}Fix tunnel tests for outbound client tunnels{% endtrans %}
- {% trans %}Fix installing to paths with spaces (non-Windows){% endtrans %}
- {% trans %}Console dark theme fixes and improvements{% endtrans %}
- {% trans %}Fix AIOOBE on large signed streaming packets{% endtrans %}
- {% trans %}Fix compression of Router Identities{% endtrans %}
- {% trans %}Update outdated Docker container and container libraries{% endtrans %}
**{% trans %}Other{% endtrans %}**
- {% trans %}Add logo to first installer panel{% endtrans %}
- {% trans %}Add progress bar to installer panels{% endtrans %}
- {% trans %}Use SHA256 pool in Noise{% endtrans %}
- {% trans %}Move certs page to a debug page tab{% endtrans %}
- {% trans %}Reduce memory usage in AddressBean{% endtrans %}
- {% trans %}Set bulk profile for servers and i2psnark{% endtrans %}
- {% trans %}Prep for tunnel bandwidth parameters (proposal 168){% endtrans %}
- {% trans %}Proxy error page improvements{% endtrans %}
- {% trans %}Check key order when parsing RI mappings{% endtrans %}
- {% trans %}Reduce i2psnark peer check interval{% endtrans %}
- {% trans %}Translation updates{% endtrans %}
`{% trans %}Full list of fixed bugs{% endtrans %}`__
__ http://{{ i2pconv('git.idk.i2p') }}/i2p-hackers/i2p.i2p/-/issues?scope=all&state=closed&milestone_title=2.9.0
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
013f30db4116711fdb5f78f21f55da9a883a7de110f9c5b6d4f1390d60cc3441 i2pinstall_2.8.1_windows.exe
a2f590156b6c58574c54860afb196886bc23e609ec26c3797ad0ef27289727f3 i2pinstall_2.8.1.jar
6af1b88404527d9f5f88a29434979e048ac9d6fdc6ad7f5edbd0b318a1a1e57d i2psource_2.8.1.tar.bz2
f4018ed081c0980f1cc4bc9e961ba49d7eda54babb06785220e54b54a58e150d i2pupdate_2.8.1.zip
c89433df991876952fa2e4d7ebf2cb8c705911b80f240e6ddd3d8cba4aabed58 i2pupdate.su3

View File

@ -1,43 +0,0 @@
===========================================
{% trans -%}2.8.2 Release{%- endtrans %}
===========================================
.. meta::
:author: zzz
:date: 2025-03-29
:category: release
:excerpt: {% trans %}2.8.2 Release with SHA256 fix{% endtrans %}
{% trans -%}
2.8.2 fixes a bug causing SHA256 failures that was introduced in the 2.8.1 release.
The bug primarily affects high-bandwidth routers.
{%- 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 %}RELEASE DETAILS{% endtrans %}**
**{% trans %}Bug Fixes{% endtrans %}**
- {% trans %}Fix SHA256 double-free from Noise{% endtrans %}
- {% trans %}Clear i2ptunnel bubble count when clearing status messages{% endtrans %}
**{% trans %}Other{% endtrans %}**
- {% trans %}Reduce memory usage in BanlistRenderer{% endtrans %}
- {% trans %}Use torrent name instead of torrent file name in notifications{% endtrans %}
- {% trans %}Translation updates{% endtrans %}
**{% trans %}SHA256 Checksums:{% endtrans %}**
::
7658f9ba7e28ab29ffeb3ec1909bf04f5ae391ee159980145ea01bd793c46f80 i2pinstall_2.8.2_windows.exe
cd606827a9bca363bd6b3c89664772ec211d276cce3148f207643cc5e5949b8a i2pinstall_2.8.2.jar
039b59fedd4a64aaeb6b74ab974310abdc9c08cb47ef1b8568c718965b50a485 i2psource_2.8.2.tar.bz2
71cef41d7184516e42c15dc5105e52ab19960affd571b636e767e8bf8c227075 i2pupdate_2.8.2.zip
15d886a9015dcf27ccc25e31b703ef6538b8b777176adf643dfe8ee0ba4984e0 i2pupdate.su3

View File

@ -1,48 +0,0 @@
{% trans -%}
=============
2.9.0 Release
=============
{%- endtrans %}
.. meta::
:author: idk
:date: 2025-06-02
:category: release
:excerpt: {% trans %}I2P 2.9.0 Release{% endtrans %}
{% trans -%}
I2P 2.9.0 is a maintenance release that includes bug fixes and work on new features.
{%- endtrans %}
{% trans -%}
Thread usage has been improved to improve the performance of the i2ptunnel system.
NTCP2 has been improved to resist probing attacks.
The notification system has been integrated into more applications to provide better feedback to users from I2PSnark and the other applications.
Automatic floodfill enrollment has been fixed.
Users may observe increased resource usage when acting as floodfill.
If this is not desired, floodfill mode can be disabled on the /config page.
{%- endtrans %}
{% trans -%}
A new global map feature is available in the console which shows the locations of routers in your view of the netDb.
These are the peers that help your router build tunnels and provide services anonymously.
{%- endtrans %}
{% trans -%}
Work continues on implementing automatic bandwidth management for tunnels, the Datagram2 protocol, and Post-Quantum cryptography.
In two releases, at 2.11.0, I2P will require Java 17.
{%- 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 %}**
::
681884cf79f001a360dd3635f7b31e889d407af8c3edb6fe89d841a5421ba563 i2pinstall_2.9.0_windows.exe
f4474ca98914f18fce1a4ce37a6b3cd080499919e4202a29b8eae51798f0c7c1 i2pinstall_2.9.0.jar
03989319e186d9b06ed96ea0efa6ac95af1bc57af956d7f5f06f52f8da64fcd7 i2psource_2.9.0.tar.bz2
1b79b2593bbe60e08da3f84411d48a5f1fe0c8cfd934f1c90d2fece436c1f2b5 i2pupdate_2.9.0.zip
2df2d63a65d9d8743098203919693185c910ddd8a53f13e91d5be7d95d1d0e82 i2pupdate.su3

View File

@ -10,10 +10,10 @@ from i2p2www import helpers
BLOG_METATAGS = {
'author': u'I2P devs',
'author': 'I2P devs',
'category': None,
'date': None,
'excerpt': u'',
'excerpt': '',
}
BLOG_LIST_METATAGS = [

View File

@ -141,12 +141,12 @@ def downloads_config():
def downloads_select(version, file):
mirrors=read_mirrors()
obj=[]
for net in mirrors.keys():
for net in list(mirrors.keys()):
a={}
a['key']=net
a['name']=net
a['protocols']=[]
for protocol in mirrors[net].keys():
for protocol in list(mirrors[net].keys()):
b={}
b['key']=protocol
b['name']=protocol
@ -166,13 +166,13 @@ def downloads_redirect(version, net, protocol, domain, file):
}
if not protocol:
protocol = mirrors.keys()[randint(0, len(mirrors) - 1)]
protocol = list(mirrors.keys())[randint(0, len(mirrors) - 1)]
if not protocol in mirrors:
abort(404)
mirrors=mirrors[protocol]
if not domain:
domain = mirrors.keys()[randint(0, len(mirrors) - 1)]
domain = list(mirrors.keys())[randint(0, len(mirrors) - 1)]
if not domain in mirrors:
abort(404)
return render_template('downloads/redirect.html',

View File

@ -29,8 +29,8 @@ def we_are_frozen():
def module_path():
encoding = sys.getfilesystemencoding()
if we_are_frozen():
return os.path.dirname(unicode(sys.executable, encoding))
return os.path.dirname(unicode(__file__, encoding))
return os.path.dirname(str(sys.executable, encoding))
return os.path.dirname(str(__file__, encoding))
class HighlightExtension(Extension):

View File

@ -12,7 +12,7 @@
import os
import sys
import os.path
import StringIO
import io
from pygments.formatter import Formatter
from pygments.token import Token, Text, STANDARD_TYPES
@ -27,11 +27,11 @@ __all__ = ['I2PHtmlFormatter', 'TextSpecFormatter']
_escape_html_table = {
ord('&'): u'&amp;',
ord('<'): u'&lt;',
ord('>'): u'&gt;',
ord('"'): u'&quot;',
ord("'"): u'&#39;',
ord('&'): '&amp;',
ord('<'): '&lt;',
ord('>'): '&gt;',
ord('"'): '&quot;',
ord("'"): '&#39;',
}
kinds = {
@ -459,7 +459,7 @@ class I2PHtmlFormatter(Formatter):
"""
if arg is None:
arg = ('cssclass' in self.options and '.'+self.cssclass or '')
if isinstance(arg, basestring):
if isinstance(arg, str):
args = [arg]
else:
args = list(arg)
@ -473,7 +473,7 @@ class I2PHtmlFormatter(Formatter):
return ', '.join(tmp)
styles = [(level, ttype, cls, style)
for cls, (style, ttype, level) in self.class2style.iteritems()
for cls, (style, ttype, level) in self.class2style.items()
if cls and style]
styles.sort()
lines = ['%s { %s } /* %s */' % (prefix(cls), style, repr(ttype)[6:])
@ -511,8 +511,8 @@ class I2PHtmlFormatter(Formatter):
cssfilename = os.path.join(os.path.dirname(filename),
self.cssfile)
except AttributeError:
print >>sys.stderr, 'Note: Cannot determine output file name, ' \
'using current directory as base for the CSS file name'
print('Note: Cannot determine output file name, ' \
'using current directory as base for the CSS file name', file=sys.stderr)
cssfilename = self.cssfile
# write CSS file only if noclobber_cssfile isn't given as an option.
try:
@ -521,7 +521,7 @@ class I2PHtmlFormatter(Formatter):
cf.write(CSSFILE_TEMPLATE %
{'styledefs': self.get_style_defs('body')})
cf.close()
except IOError, err:
except IOError as err:
err.strerror = 'Error writing CSS file: ' + err.strerror
raise
@ -540,7 +540,7 @@ class I2PHtmlFormatter(Formatter):
yield 0, DOC_FOOTER
def _wrap_tablelinenos(self, inner):
dummyoutfile = StringIO.StringIO()
dummyoutfile = io.StringIO()
lncount = 0
for t, line in inner:
if t:
@ -884,7 +884,7 @@ class TextSpecFormatter(Formatter):
else:
outfile.write(value)
for ref in refs.values():
for ref in list(refs.values()):
if enc:
outfile.write(ref.encode(enc))
else:

View File

@ -56,7 +56,7 @@ class Pagination(object):
def iter_pages(self, left_edge=2, left_current=2,
right_current=5, right_edge=2):
last = 0
for num in xrange(1, self.pages + 1):
for num in range(1, self.pages + 1):
if num <= left_edge or \
(num > self.page - left_current - 1 and \
num < self.page + right_current) or \

View File

@ -197,7 +197,7 @@ LEGACY_RELEASES_MAP={
'0.9.8': (2013, 9, 30),
'0.9.8.1': (2013, 10, 2),
'0.9.9': (2013, 12, 7),
'0.9.10': (2014, 01, 22),
'0.9.10': (2014, 0o1, 22),
}
def legacy_show(f):
@ -232,5 +232,6 @@ def legacy_release(version):
else:
return legacy_show('release-%s' % version)
def legacy_blog(lang, (year, month, day), title):
def legacy_blog(lang, xxx_todo_changeme, title):
(year, month, day) = xxx_todo_changeme
return redirect(url_for('blog_post', lang=lang, slug=('%d/%02d/%02d/%s' % (year, month, day, title))), 301)

View File

@ -54,7 +54,7 @@ def get_meetings_ids(num=0):
# iterate over all files
for f in v[2]:
# ignore all non-.rst files
print("Meeting file found", f)
print(("Meeting file found", f))
if not f.endswith('.rst'):
continue
try:

View File

@ -33,7 +33,7 @@
<img src="{{ url_for('static',
filename='images/firefox57.connectionsettings.png') }}" alt="{{ _('Firefox57
Connection Settings') }}" title="{{ _('Firefox57 Connection Settings') }}">
<p>{% trans -%} Finally, go to the address <em>about:config</em> and find the property media.peerConnection.ice.proxy_only. Ensure that this setting is True. Now find the property keyword.enabled, and set it to False.{%- endtrans %}</p>
<p>{% trans -%} Finally, go to the address <em>about:config</em> and find the property media.peerConnection.ice.proxy_only. Ensure that this setting is True. {%- endtrans %}</p>
<img src="{{ url_for('static',
filename='images/firefox.webrtc.png') }}" alt="{{ _('Firefox57
PeerConnection Settings') }}" title="{{ _('Firefox57 PeerConnection Settings') }}">

View File

@ -12,7 +12,7 @@
<li><a href="#debian">Knoppix</a></li>
</ul>
{% trans gtitlab='https://i2pgit.org/I2P_Developers/i2p.i2p/' -%}
{% trans gtitlab='https://i2pgit.org/i2p-hackers/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>.
@ -86,11 +86,13 @@ part of <a href="#Post-install_work">starting I2P</a> and configuring it for you
<h2 id="debian">{{ _('Instructions for Debian') }}</h2>
<p><b>NOTICE:</b>
Our old Debian repos <a href="https://deb.i2p2.de/">deb.i2p2.de</a> and
<a href="http://deb.i2p2.no/">deb.i2p2.no</a> are EOL.
Please follow <a href="https://deb.i2p.net">these instructions</a>
to update to the new repository, <code>deb.i2p.net</code>.
<p><b>WARNING:</b>
Our Debian repos <a href="https://deb.i2p2.de/">deb.i2p2.de</a> and
<a href="http://deb.i2p2.no/">deb.i2p2.no</a> are currently down, and probably will not be back soon.
Please follow <a href="https://i2pforum.net/viewtopic.php?p=2855">these instructions</a>
to use the Ubuntu PPA as a workaround.
We will announce any updates here and on <a href="https://i2pforum.net/">i2pforum.net</a>.
We apologize for the inconvenience.
</p>
<em>{% trans -%}Currently supported architectures{%- endtrans %}: amd64, i386, armhf, arm64, powerpc, ppc64el, s390x</em>
@ -114,7 +116,7 @@ user to root with <code>su</code> or by prefixing each command with <code>sudo</
<pre>
<code>
# Use this command on Debian Bullseye or newer only.
echo "deb [signed-by=/usr/share/keyrings/i2p-archive-keyring.gpg] https://deb.i2p.net/ $(lsb_release -sc) main" \
echo "deb [signed-by=/usr/share/keyrings/i2p-archive-keyring.gpg] https://deb.i2p2.de/ $(lsb_release -sc) main" \
| sudo tee /etc/apt/sources.list.d/i2p.list
</code>
</pre>
@ -122,7 +124,7 @@ user to root with <code>su</code> or by prefixing each command with <code>sudo</
<pre>
<code>
# Use this command on Debian Downstreams like LMDE or ParrotOS only.
echo "deb [signed-by=/usr/share/keyrings/i2p-archive-keyring.gpg] https://deb.i2p.net/ $(dpkg --status tzdata | grep Provides | cut -f2 -d'-') main" \
echo "deb [signed-by=/usr/share/keyrings/i2p-archive-keyring.gpg] https://deb.i2p2.de/ $(dpkg --status tzdata | grep Provides | cut -f2 -d'-') main" \
| sudo tee /etc/apt/sources.list.d/i2p.list
</code>
</pre>
@ -130,7 +132,7 @@ user to root with <code>su</code> or by prefixing each command with <code>sudo</
<pre>
<code>
# Use this command on Debian Buster or older only.
echo "deb https://deb.i2p.net/ $(lsb_release -sc) main" \
echo "deb https://deb.i2p2.de/ $(lsb_release -sc) main" \
| sudo tee /etc/apt/sources.list.d/i2p.list
</code>
</pre>
@ -138,7 +140,7 @@ user to root with <code>su</code> or by prefixing each command with <code>sudo</
<pre>
<code>
# Use this command on Debian Buster or older only.
echo "deb https://deb.i2p.net/ $(dpkg --status tzdata | grep Provides | cut -f2 -d'-') main" \
echo "deb https://deb.i2p2.de/ $(dpkg --status tzdata | grep Provides | cut -f2 -d'-') main" \
| sudo tee /etc/apt/sources.list.d/i2p.list
</code>
</pre>

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_Developers/i2p.firefox/-/issues/2" -%}
{% trans issueurl="https://i2pgit.org/i2p-hackers/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
@ -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 = 'def95180e5783686f68dcf2958cfa693f17a91da53a97f8ae75c98529c4e23a8' -%}
{% 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_Developers/i2p.firefox">{% trans -%}Gitlab Repository{%- endtrans %}</a></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>
@ -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_Developers/i2p.firefox/issues">{% trans -%}Gitlab Repository{%- endtrans %}</a></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

View File

@ -45,7 +45,7 @@ start an installer, "double-click" the downloaded .exe file.
{%- set name = 'Windows' -%}
{%- set icon = 'images/download/windows.png' -%}
{%- set filename = 'I2P-Easy-Install-Bundle-%s.exe' -%}
{%- set hash = 'a8e7e02b00428a150d8287774879c3babd4f0eeede7b691403dc283c05bda750' -%}
{%- set hash = 'def95180e5783686f68dcf2958cfa693f17a91da53a97f8ae75c98529c4e23a8' -%}
{% call package_outer('windows', name, icon) %}
<div class = "file">
@ -87,7 +87,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_Developers/i2p.firefox">{% trans -%}Gitlab Repository{%- endtrans %}</a></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>
@ -97,7 +97,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_Developers/i2p.firefox/issues">{% trans -%}Gitlab Repository{%- endtrans %}</a></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

View File

@ -57,14 +57,13 @@ If you would like to try the latest experimental I2P projects, visit the <a href
{%- endtrans %}</p>
<div class="file">
<p></p>
<a class="default" href="{{ get_url('downloads_macos') }}">{% trans %}Here is a helpful guide to installing I2P for Mac OS using a separate Java installation and the classic installer.{% endtrans %}</a>
<a class="default" href="{{ get_url('downloads_mac') }}">{% trans %}Here is a helpful guide to installing I2P for Mac OS using a separate Java installation and the classic installer.{% endtrans %}</a>
</div>
{% endcall %}
<h5>{%- trans %}I2P for Linux{%- endtrans %}</h5>
{% call package('unix') %}
<p>{% trans i2pversion=ver() -%} The most reliable way to launch the installer is from a terminal like this:
<code>java -jar i2pinstall_{{ i2pversion }}.jar</code>. This will launch the GUI installer. Depending on how your computer is set up, you may be able to start the installer by double-clicking the &quot;i2pinstall_{{ i2pversion }}.jar&quot; file
or right-clicking the file and selecting &quot;Open with Java&quot;. Unfortunately, this behaviour is difficult to predict. {%- endtrans %}</p>

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_Developers/i2p-jpackage-mac">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<div><a href="https://i2pgit.org/i2p-hackers/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_Developers/i2p-jpackage-mac/issues">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
<div><a href="https://i2pgit.org/i2p-hackers/i2p-jpackage-mac/issues">{% trans -%}Gitlab Repository{%- endtrans %}</a></div>
{% endblock %}

View File

@ -1,16 +1,16 @@
{% set i2pinstall_windows_hash = 'fe106319dcf5972b7c833150292cb72ae6a764cf18929f043dfb9f10340ee782' %}
{% set i2pinstall_jar_hash = 'fee438e9f42345eeef3f5255842bbcf725eb01f1f84589791a525cd45143555b' %}
{% set i2psource_hash = '03989319e186d9b06ed96ea0efa6ac95af1bc57af956d7f5f06f52f8da64fcd7' %}
{% set i2pupdate_hash = '1b79b2593bbe60e08da3f84411d48a5f1fe0c8cfd934f1c90d2fece436c1f2b5' %}
{% set i2p_android_hash = '13b6e3c35756605e8e65804ab91cb34521c819fcfaebafb348eba5d40bed6699' %}
{% set i2pinstall_windows_hash = '2081f8415013c80daa6b69b6f16f2ebf10aa20ee3cace20936e0268b2e816a3f' %}
{% set i2pinstall_jar_hash = '977ebce33001345731de6fe0b623f59a867de6fa6a6c46d8ad686e306310b28d' %}
{% set i2psource_hash = 'a0a8fb08e9c72eaef22f155b9c9aa0ea90fb331d2bbcf76f82649f0b9efe5f5b' %}
{% set i2pupdate_hash = '59b569dc17fad0e30e246048a3c275e403b308024eb88fda29ae83294bdbe8e6' %}
{% set i2p_android_hash = '272acf543c4489dc3775c07c42eb91710b4ed377c78aff605e3d44e73fad5110' %}
{% set i2p_macnative_hash = '18cb22cfcc3cbe0cec150e89a394d1a35703cb508ed627ef48084b7ba7c90dde' %}
{% set i2p_windows_subver = '' %}
{% set i2p_macosx_launcher_version = '1.9.0' %}
{% set i2p_android_version = '2.9.0' %}
{% set i2p_android_version = '2.2.1' %}
{% set i2p_android_version_kytv = '0.9.22' %}
{% set i2p_android_version_fdroid = '2.6.0' %}
{% set i2p_android_version_fdroid = '2.2.1' %}
{% macro package_outer(type, name, icon) -%}
@ -80,8 +80,8 @@
{%- if type == 'android' %}
<!-- do not use url_for here -->
<h3>{% trans %}Download I2P for {% endtrans %}{{name}}</h3>
<a class="default" href="https://files.i2p-projekt.de/{{ i2p_android_version }}/app.apk">{% trans %}Outside I2P{% endtrans %} ({{ i2p_android_version }})</a>
<a class="sig" href="https://files.i2p-projekt.de/{{ i2p_android_version }}/app.apk.asc">sig</a>
<a class="default" href="https://download.i2p2.no/android/current/app.apk">{% trans %}Outside I2P{% endtrans %} ({{ i2p_android_version }})</a>
<a class="sig" href="https://download.i2p2.no/android/current/app.apk.asc">sig</a>
<!-- do not use i2pconv here -->
<!--<a class="default" href="http://update.killyourtv.i2p/i2p.apk">{% trans %}Inside I2P{% endtrans %} ({{ i2p_android_version_kytv }})</a> -->
<a class="default" href="https://play.google.com/store/apps/details?id=net.i2p.android">Google Play ({{ i2p_android_version }})</a>

View File

@ -31,35 +31,6 @@
#
# Proposed new sections: application privacy, data anonymization, ...
#
@inproceedings {abdo,
author = {Jacques Bou Abdo and Liaquat Hossain},
title = {Modeling the Invisible Internet},
booktitle = {Complex Networks and their Applications XII},
year = {2024},
url = {https://link.springer.com/chapter/10.1007/978-3-031-53472-0_30},
publisher = {Springer},
month = {February},
www_section = traffic,
}
@techreport{stickland2021,
title = {Foundations of Rigorous Cyber Experimentation},
author = {Michael Stickland and Justin D. Li and Laura Swiler and Thomas Tarman},
institution = {Sandia National Laboratories},
year = {2021},
month = {September},
url = {https://www.osti.gov/servlets/purl/1854751/},
www_section = traffic,
}
@phdthesis{yu2021,
title = {Research and implementation of bridge technology in I2P anonymous system},
author = {Yu Chih-Wei},
school = {Beijing University of Posts and Telecommunications},
year = {2021},
url = {https://www.zhangqiaokeyan.com/academic-degree-domestic_mphd_thesis/020318030805.html},
www_section = comm,
}
@article {qu2020,
author = {QU Yun-xuan and WANG Yi-jun and XUE Zhi},
@ -291,16 +262,6 @@ on our factors and measure the level of anonymity.}},
www_section = comm,
}
@inproceedings{jeong2016,
title = {A Longitudinal Analysis of .i2p Leakage in the Public DNS Infrastructure},
author = {Seong Hoon Jeong and Ah Reum Kang and Joongheon Kim and Huy Kang Kim2 and Aziz Mohaisen},
booktitle = {SIGCOMM 2016 August 22-26, Florianopolis, Brazil},
year = {2016},
month = {August},
www_pdf_url = {https://www.cs.ucf.edu/~mohaisen/doc/sigcomm16.pdf},
www_section = comm,
}
#
# Actually a bachelors thesis but there's no @ for that
#

View File

@ -1,6 +1,6 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Presentations on I2P') }}{% endblock %}
{% block lastupdated %}2024-09{% endblock %}
{% block lastupdated %}2022-03{% endblock %}
{% block content %}
<p>{% trans papers=site_url('papers') -%}
Following are links to presentations, videos, and tutorials about I2P. Links to research papers on I2P are available <a href="{{ papers }}">here</a>.
@ -139,25 +139,6 @@ Andrew Savchenko (bircoph), FOSDEM, Brussel, February 4, 2018
idk
{%- endtrans %}</li>
<li>
I2P, blockchain and the application (FOSDEM 2021)
<a href="https://odysee.com/@diva.exchange:d/diva-exchange-fosdem-21:c">video</a>
February 7, 2021
</li>
<li>
Private, fully distributed exchange (DEX), Monero and I2P research results
<a href="https://odysee.com/@diva.exchange:d/monerokon2022:0">video</a>
MoneroKon 2022 Lisbon
July 5, 2022
</li>
<li>
DNS for I2P (FOSDEM 2023)
<a href="https://odysee.com/@diva.exchange:d/diva-dns-i2p-fosdem2023:2">video</a>
February 12, 2023
</li>
</ul>
@ -283,33 +264,6 @@ Opt Out Podcast Season 2 Episode 10
March 6, 2022
</li>
<li>
I2P and DIVA.EXCHANGE - Interview with Konrad
(<a href="https://odysee.com/@diva.exchange:d/i2p-diva-exchange-2022-09-26:6">video</a>)
September 26, 2022
</li>
<li>
Interview with Sadie on I2P and the Free Internet
(<a href="https://www.diva.exchange/en/privacy/i2p-and-the-free-internet-interview-with-a-community-member/">interview</a>)
February 2024
</li>
<li>
Interview with Phillip on I2P Network Reliability
(<a href="https://www.diva.exchange/en/privacy/i2p-network-reliability-is-on-the-radar-of-the-academic-community/">interview</a>)
March 2024
</li>
<li>
Interview with IDK on I2P Development
(<a href="https://www.diva.exchange/en/privacy/i2p-interview-with-the-developer-idk-part-1/">interview part 1</a>)
July 2024;
(<a href="https://www.diva.exchange/en/privacy/i2p-interview-with-the-developer-idk-part-2/">interview part 2</a>)
September 2024
</li>
</ul>
<h2>{{ _('Other') }}</h2>

View File

@ -1,6 +1,5 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Strict Countries') }}{% endblock %}
{% block lastupdated %}2024-07{% endblock %}
{% block content %}
<p>{% trans -%}This implementation of I2P (the Java implementation distributed on this site)
includes a "Strict Countries List" which we use to decide how routers should behave
@ -17,14 +16,14 @@ guidance is to include countries with a Civil Liberties (CL) score of 16 or less
Freedom score of 39 or less (not free).{%- endtrans %}</p>
<h4>{% trans -%}Hidden Mode Summary{%- endtrans %}</h4>
<p>{% trans -%}When a router is placed into hidden mode, three key things change about its behavior.
<p>{% trans -%}When a router is placed into hidden mode, three key things change about it's behavior.
It will no longer publish a routerInfo to the NetDB, it will no longer accept
participating tunnels, and it will reject direct connections to routers in the same
country that it is in. These defenses make the routers more difficult to enumerate
reliably, and prevent them from running afoul of restrictions on routing traffic for
others.{%- endtrans %}</p>
<h4>{% trans -%}Strict Countries List as of 2024{%- endtrans %}</h4>
<h4>{% trans -%}Strict Countries List as of 2020{%- endtrans %}</h4>
<pre><code>
/* Afghanistan */ "AF",
/* Azerbaijan */ "AZ",

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_Developers/i2p.www/issues' -%}
<p>{% trans trac='https://i2pgit.org/i2p-hackers/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_Developers/i2p.www/issues' -%}
<p>{% trans comparison=site_url('comparison'), trac='https://i2pgit.org/i2p-hackers/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_Developers/i2p.www/issues' -%}
<p>{% trans trac='https://i2pgit.org/i2p-hackers/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_Developers/i2p.www/issues' -%}
<p>{% trans trac='https://i2pgit.org/i2p-hackers/i2p.www/issues' -%}
You may contribute an analysis by entering a
<a href="{{ trac }}">new issue on Github</a>.
{%- endtrans %}</p>

View File

@ -1,20 +1,18 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('BOB - Basic Open Bridge') }}{% endblock %}
{% block lastupdated %}2025-05{% endblock %}
{% block lastupdated %}2022-06{% endblock %}
{% block content %}
<h2>Warning - Deprecated</h2>
<p>Not for use by new applications.
BOB, as specified here, supports the DSA-SHA1 signature type only.
BOB supports the DSA-SHA1 signature type only.
BOB will not be extended to support new signature types or other advanced features.
New applications should use <a href="{{ site_url('docs/api/samv3') }}">SAM V3</a>.
</p><p>
BOB support was removed from Java I2P new installs as of release 1.7.0 (2022-02).
BOB is not supported in Java I2P new installs as of release 1.7.0 (2022-02).
It will still work in Java I2P originally installed as version 1.6.1 or earlier,
even after updates, but it is unsupported and may break at any time.
BOB is still supported by i2pd as of 2025-05, but applications
BOB is still supported by i2pd as of 2022-06, but applications
should still migrate to SAMv3 for the reasons above.
See <a href="https://i2pd.readthedocs.io/en/latest/devs/i2pd-specifics/">the i2pd documentation</a>
for any extensions to the API documented here that are supported by i2pd.
</p>
<p>

View File

@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Datagrams{% endtrans %}{% endblock %}
{% block lastupdated %}2025-04{% endblock %}
{% block accuratefor %}0.9.66{% endblock %}
{% block lastupdated %}{% trans %}February 2019{% endtrans %}{% endblock %}
{% block accuratefor %}0.9.39{% endblock %}
{% block content %}
<h2>{% trans %}Datagram Overview{% endtrans %}</h2>
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
@ -35,30 +35,30 @@ the 'streamr' tunnel types, and udpTunnel classes.
{%- endtrans %}</p>
<h3>{% trans %}Datagram Length{% endtrans %}</h3>
<p>
<p>{% trans -%}
The application designer should carefully consider the tradeoff of repliable vs. non-repliable
datagrams. Also, the datagram size will affect reliability, due to tunnel fragmentation into 1KB
tunnel messages. The more message fragments, the more likely that one of them will be dropped
by an intermediate hop. Messages larger than a few KB are not recommended.
Over about 10 KB, the delivery probablility drops dramatically.
</p>
<a href="{{ site_url('docs/spec/datagrams') }}">{% trans -%}
See the Datagrams Specification page.
{%- endtrans %}</a>
Messages over 16 KB cannot be delivered over NTCP, dropping delivery chances even more.
{%- endtrans %}</p>
<p>
Also note that the various overheads added by lower layers, in particular
garlic messages, place a large burden on intermittent messages
<p>{% trans elgamalaes=site_url('docs/how/elgamal-aes') -%}
Also note that the various overheads added by lower layers, in particular asymmetric
<a href="{{ elgamalaes }}">ElGamal/AES</a>, place a large burden on intermittent messages
such as used by a Kademlia-over-UDP application. The implementations are currently tuned
for frequent traffic using the streaming library.
</p>
for frequent traffic using the streaming library. There are a high number
of session tags delivered, and a short session tag lifetime, for example.
There are currently no configuration parameters available within I2CP to tune
the ElGamal Session Tag parameters.
{%- endtrans %}</p>
<h3>{% trans %}I2CP Protocol Number and Ports{% endtrans %}</h3>
<p>{% trans -%}
The standard I2CP protocol number for signed (repliable) datagrams is PROTO_DATAGRAM (17).
The standard I2CP protocol number for datagrams is PROTO_DATAGRAM (17).
Applications may or may not choose to set the
protocol in the I2CP header. The default is implementation-dependent.
protocol in the I2CP header. It is not set by default.
It must be set to demultiplex datagram and streaming traffic received on the same Destination.
{%- endtrans %}</p>
@ -75,8 +75,7 @@ There is no method within the datagram API to specify whether it is non-repliabl
or repliable. The application should be designed to expect the appropriate type.
The I2CP protocol number or port should be used by the application to
indicate datagram type.
The I2CP protocol numbers PROTO_DATAGRAM (signed, also known as Datagram1), PROTO_DATAGRAM_RAW,
PROTO_DATAGRAM2, and PROTO_DATAGRAM3 are defined in the
The I2CP protocol numbers PROTO_DATAGRAM (signed) and PROTO_DATAGRAM_RAW are defined in the
<a href="{{ i2psession }}">I2PSession API</a>
for this purpose. A common design pattern in client/server datagram applications is to
use signed datagrams for a request which includes a nonce, and use a raw datagram
@ -87,10 +86,6 @@ for the reply, returning the nonce from the request.
PROTO_DATAGRAM = 17
</li><li>
PROTO_DATAGRAM_RAW = 18
</li><li>
PROTO_DATAGRAM2 = 19
</li><li>
PROTO_DATAGRAM3 = 20
</li></ul>
<p>{% trans i2psession='http://'+i2pconv('idk.i2p/javadoc-i2p')+'/net/i2p/client/I2PSession.html',
@ -105,7 +100,6 @@ as implemented in
<p>{% trans i2cp=site_url('docs/protocol/i2cp') -%}
Data integrity is assured by the gzip CRC-32 checksum implemented in
<a href="{{ i2cp }}#format">the I2CP layer</a>.
Authenticated datagrams (Datagram1 and Datagram2) also ensure integrity.
There is no checksum field in the datagram protocol.
{%- endtrans %}</p>

View File

@ -1,9 +1,8 @@
{% extends "global/layout.html" %}
{% block title %}SAM V1 Specification{% endblock %}
{% block lastupdated %}2025-03{% endblock %}
{% block lastupdated %}May 2015{% endblock %}
{% block accuratefor %}0.9.20{% endblock %}
{% block content %}
<h2>Warning - Deprecated - Unsupported - Use <a href="samv3.html">SAMv3</a></h2>
<p>Specified below is version 1 of a simple client protocol for interacting with
I2P.
Newer alternatives:

View File

@ -1,10 +1,9 @@
{% extends "global/layout.html" %}
{% block title %}SAM V2 Specification{% endblock %}
{% block lastupdated %}2025-03{% endblock %}
{% block lastupdated %}May 2015{% endblock %}
{% block accuratefor %}0.9.20{% endblock %}
{% block content %}
<h2>Warning - Deprecated - Unsupported - Use <a href="samv3.html">SAMv3</a></h2>
<p>Specified below is version 2 of a simple client protocol for interacting with I2P.
<p>Specified below is a simple client protocol for interacting with I2P.
</p>
<p>
SAM V2 was introduced in I2P release 0.6.1.31.

View File

@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}SAM V3{% endblock %}
{% block lastupdated %}2025-04{% endblock %}
{% block accuratefor %}API 0.9.66{% endblock %}
{% block lastupdated %}2023-11{% endblock %}
{% block accuratefor %}API 0.9.59{% endblock %}
{% block content %}
<p>SAM is a simple client protocol for interacting with I2P.
SAM is the recommended protocol for non-Java applications to connect to the I2P network,
@ -77,16 +77,7 @@ Do your own research.
<td>yes</td>
<td>yes</td>
<td>yes</td>
<td><a href="https://github.com/eyedeekay/sam3">github.com/eyedeekay/sam3</a></td>
</tr>
<tr class="even">
<td>onramp</td>
<td>Go</td>
<td>3.3</td>
<td>yes</td>
<td>yes</td>
<td>yes</td>
<td><a href="https://github.com/eyedeekay/onramp">github.com/eyedeekay/onramp</a></td>
<td><a href="https://bitbucket.org/eyedeekay/sam3">bitbucket.org/eyedeekay/sam3</a></td>
</tr>
<tr class="odd">
<td>txi2p</td>
@ -158,7 +149,7 @@ Do your own research.
<td>yes</td>
<td>yes</td>
<td>yes</td>
<td><a href="https://notabug.org/villain/mooni2p">notabug.org/villain/mooni2p</a></td>
<td><a href="https://notabug.org/l-n-s/mooni2p">notabug.org/l-n-s/mooni2p</a></td>
</tr>
<tr class="even">
<td>haskell-network-anonymous-i2p</td>
@ -233,13 +224,13 @@ Do your own research.
<td><a href="https://github.com/syvita/solitude">github.com/syvita/solitude</a></td>
</tr>
<tr class="even">
<td>Samty</td>
<td>i2pSAM-Qt</td>
<td>C++</td>
<td>3.1</td>
<td>yes</td>
<td>no</td>
<td>no</td>
<td><a href="https://notabug.org/acetone/samty">notabug.org/acetone/samty</a></td>
<td>yes</td>
<td>yes</td>
<td><a href="https://notabug.org/acetone/i2pSAM-Qt">notabug.org/acetone/i2pSAM-Qt</a></td>
</tr>
<tr class="odd">
<td>bitcoin</td>
@ -261,7 +252,7 @@ To implement a basic TCP-only, peer-to-peer application, the client must support
<li> HELLO VERSION MIN=3.1 MAX=3.1 <br> Needed for all of the remaining ones
<li> DEST GENERATE SIGNATURE_TYPE=7 <br> To generate our private key and destination
<li> NAMING LOOKUP NAME=... <br> To convert .i2p addresses to destinations
<li> SESSION CREATE STYLE=STREAM ID=... DESTINATION=... i2cp.leaseSetEncType=4,0<br> Needed for STREAM CONNECT and STREAM ACCEPT
<li> SESSION CREATE STYLE=STREAM ID=... DESTINATION=... <br> Needed for STREAM CONNECT and STREAM ACCEPT
<li> STREAM CONNECT ID=... DESTINATION=... <br> To make outgoing connections
<li> STREAM ACCEPT ID=... <br> To accept incoming connections
</ul>
@ -269,7 +260,6 @@ To implement a basic TCP-only, peer-to-peer application, the client must support
<h2>General Guidance for Developers</h2>
<h3>Application Design</h3>
<p>
SAM sessions (or inside I2P, tunnel pools or sets of tunnels) are designed to be long-lived.
Most applications will only need one session, created at startup and closed on exit.
@ -283,9 +273,7 @@ Also, please ensure your application settings
will result in your users contributing more resources to the network than they consume.
I2P is a peer-to-peer network, and the network cannot survive if a popular application
drives the network into permanent congestion.
</p>
<h3>Compatibility and Testing</h3>
<p>
</p><p>
The Java I2P and i2pd router implementations are independent and have minor differences
in behavior, feature support, and defaults.
Please test your application with the latest version of both routers.
@ -306,20 +294,8 @@ See below.
For more guidance to developers on ensuring your application uses only the resources it needs, please see
<a href="{{ site_url('docs/applications/embedding') }}">our guide to bundling I2P with your application</a>.
</p>
<h3>Signature and Encryption Types</h3>
<p>
I2P supports multiple signature and encryption types.
For backward compatibility, SAM defaults to old and inefficient types, so all clients should
specify newer types.
</p><p>
The signature type is specified in the DEST GENERATE and SESSION CREATE (for transient) commands.
All clients should set SIGNATURE_TYPE=7 (Ed25519).
</p><p>
The encryption type is specified in the SESSION CREATE command.
Multiple encryption types are allowed.
Clients should set either i2cp.leaseSetEncType=4 (for ECIES-X25519 only)
or i2cp.leaseSetEncType=4,0 (for ECIES-X25519 and ElGamal, if compatibility is required).
</p>
<h2>Version 3 Changes</h2>
@ -433,18 +409,14 @@ As of SAM 3.2, optional authentication user/password parameters are supported in
and may be required by the bridge.
</p><p>
I2P communications can take several distinct forms:
I2P communications can take three distinct forms:
<ul><li>
<a href="{{ site_url('docs/api/streaming') }}">Virtual streams</a>
</li><li>
<a href="{{ site_url('docs/spec/datagrams') }}#repliable">Repliable and authenticated datagrams</a> (messages with a FROM field)
</li><li>
</lil><li>
<a href="{{ site_url('docs/spec/datagrams') }}#repliable">Repliable datagrams</a> (messages with a FROM field)
</lil><li>
<a href="{{ site_url('docs/spec/datagrams') }}#raw">Anonymous datagrams</a> (raw anonymous messages)
</li><li>
<a href="{{ site_url('docs/spec/datagrams') }}#datagram2">Datagram2</a> (a new repliable and authenticated format)
</li><li>
<a href="{{ site_url('docs/spec/datagrams') }}#datagram3">Datagram3</a> (a new repliable but unauthenticated format)
</li></ul>
</lil></ul>
</p><p>
I2P communications are supported by I2P sessions, and each I2P
session is bound to an address (called destination). An I2P session
@ -669,18 +641,18 @@ received through other forms are answered with an error message) :
<pre>
-&gt; SESSION CREATE
STYLE={STREAM,DATAGRAM,RAW,DATAGRAM2,DATAGRAM3} # See below for DATAGRAM2/3
STYLE={STREAM,DATAGRAM,RAW}
ID=$nickname
DESTINATION={$privkey,TRANSIENT}
[SIGNATURE_TYPE=value] # SAM 3.1 or higher only, for DESTINATION=TRANSIENT only, default DSA_SHA1
[PORT=$port] # Required for DATAGRAM* RAW, invalid for STREAM
[HOST=$host] # Optional for DATAGRAM* and RAW, invalid for STREAM
[PORT=$port] # Required for DATAGRAM and RAW, invalid for STREAM
[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
[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
[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
[option=value]* # I2CP and streaming options
</pre>
@ -870,7 +842,7 @@ depending on signature type.
<b>NOTE:</b>
Since about 2014 (SAM v3.1), Java I2P has also supported hostnames and b32 addresses for the $destination, but this was previously undocumented.
Hostnames and b32 addresses are now officially supported by Java I2P as of release 0.9.48.
The i2pd router supports hostnames and b32 addresses as of release 2.38.0 (0.9.50).
The i2pd router will support hostnames and b32 addresses as of release 2.38.0 (0.9.50).
For both routers, "b32" support includes support extended "b33" addresses for blinded destinations.
</p>
@ -1136,19 +1108,15 @@ SAMv3 provides mechanisms to send and receive datagrams over local datagram sock
Some SAMv3 implementations also support the older v1/v2 way of sending/receiving
datagrams over the SAM bridge socket. Both are documented below.
</p><p>
I2P supports four types of datagrams:
I2P supports two types of datagrams:
</p>
<ul><li>
Repliable and authenticated datagrams are prefixed with the destination of the sender,
"Repliable" datagrams are prefixed with the destination of the sender,
and contain the signature of the sender, so the receiver
may verify that the sender's destination was not spoofed,
and may reply to the datagram.
The new Datagram2 format is also repliable and authenticated.
</li><li>
The new Datagram3 format is repliable but not authenticated.
The sender information is unverified.
</li><li>
Raw datagrams do not contain the destination of the sender or a signature.
"Raw" datagrams do not contain the destination of the sender or a signature.
</li></ul>
<p>
Default I2CP ports are defined for both repliable and raw datagrams.
@ -1255,7 +1223,7 @@ message:
<pre>
&lt;- DATAGRAM RECEIVED
DESTINATION=$destination # See notes below for Datagram3 format
DESTINATION=$destination
SIZE=$numBytes
FROM_PORT=nnn # SAM 3.2 or higher only
TO_PORT=nnn # SAM 3.2 or higher only
@ -1283,7 +1251,7 @@ CREATE command with PORT and HOST options:
<pre>
-&gt; SESSION CREATE
STYLE={DATAGRAM,RAW,DATAGRAM2,DATAGRAM3} # See below for DATAGRAM2/3
STYLE={DATAGRAM,RAW}
ID=$nickname
DESTINATION={$privkey,TRANSIENT}
PORT=$port
@ -1306,9 +1274,8 @@ CREATE command with PORT and HOST options:
The binary format is specified in <a href="http://{{ i2pconv('idk.i2p/javadoc-i2p') }}/net/i2p/data/PrivateKeyFile.html">Private Key File</a>.
</p><p>
Offline signatures are supported for RAW, DATAGRAM2, and DATAGRAM3 datagrams,
but not for DATAGRAM.
See the SESSION CREATE section above and the DATAGRAM2/3 section below for details.
Offline signatures are only supported for RAW datagrams.
See the SESSION CREATE section above for details.
</p><p>
$host is the hostname or IP address of the datagram server to
@ -1327,13 +1294,12 @@ configuration if not interpreted by the SAM bridge (e.g.
outbound.length=0). These options <a href="#options">are documented below</a>.
</p><p>
Forwarded repliable datagrams are always prefixed with the base64 destination,
except for Datagram3, see below.
Forwarded repliable datagrams are always prefixed with the destination.
When a repliable datagram arrives, the bridge sends to the specified host:port
a UDP packet containing the following data:
<pre>
$destination # See notes below for Datagram3 format
$destination
FROM_PORT=nnn # SAM 3.2 or higher only
TO_PORT=nnn # SAM 3.2 or higher only
\n
@ -1429,54 +1395,6 @@ the forwarded raw datagram will be prepended with a header line as follows:
For an alternate method of sending anonymous datagrams, see <a href="#dgsend">RAW SEND</a>.
</p>
<h4>Datagram 2/3</h4>
<p>
Datagram 2/3 are new formats specified in early 2025.
No known implementations currently exist.
Check implementation documentation for current status.
See <a href="{{ site_url('docs/spec/datagrams') }}">the specification</a> for more information.
</p><p>
There are no current plans to increase the SAM version to indicate Datagram 2/3 support.
This may be problematic as implementations may wish to support Datagram 2/3
but not SAM v3.3 features.
Any version change is TBD.
</p><p>
Both Datagram2 and Datagram3 are repliable. Only Datagram2 is authenticated.
</p><p>
Datagram2 is identical to repliable datagrams from a SAM perspective..
Both are authenticated.
Only the I2CP format and signature are different, but this is not visible
to SAM clients.
Datagram2 also supports offline signatures, so it may be used
by offline-signed destinations.
</p><p>
The intention is for Datagram2 to replace Repliable datagrams
for new applications that do not require backward-compatibility.
Datagram2 provides replay protection that is not present for Repliable datagrams.
If backward-compatibility is required, an application may support
both Datagram2 and Repliable may be supported on the same
session with SAM 3.3 PRIMARY sessions.
</p><p>
Datagram3 is repliable but not authenticated.
The 'from' field in the I2CP format is a hash, not a destination.
The $destination as sent from the SAM server to the client
will be a 44-byte base64 hash.
To convert it to a full destination for reply,
base64-decode it to 32 bytes binary, then base32-encode it to 52 characters
and append ".b32.i2p" for a NAMING LOOKUP.
As usual, clients should maintain their own cache to avoid repeated NAMING LOOKUPs.
</p><p>
Application designers should use extreme caution and consider the security implications
of unauthenticated datagrams.
</p>
<h4>V3 Datagram MTU Considerations</h4>
<p>
@ -1523,10 +1441,6 @@ These commands do <i>not</i> support the ID parameter. The datagrams are
sent to the most recently created DATAGRAM- or RAW-style session,
as appropriate. Support for the ID parameter may be added in a future release.
</p><p>
DATAGRAM2 and DATAGRAM3 formats are <i>not</i> supported
in the V1/V2 compatible way.
<h3 id="primary">SAM PRIMARY Sessions (V3.3 and higher)</h3>
@ -1603,10 +1517,10 @@ Using the same control socket on which the PRIMARY session was created:
<pre>
-&gt; SESSION ADD
STYLE={STREAM,DATAGRAM,RAW,DATAGRAM2,DATAGRAM3} # See above for DATAGRAM2/3
STYLE={STREAM,DATAGRAM,RAW}
ID=$nickname # must be unique
[PORT=$port] # Required for DATAGRAM* and RAW, invalid for STREAM
[HOST=$host] # Optional for DATAGRAM* and RAW, invalid for STREAM
[PORT=$port] # Required for DATAGRAM and RAW, invalid for STREAM
[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
@ -1615,8 +1529,8 @@ Using the same control socket on which the PRIMARY session was created:
[LISTEN_PROTOCOL=nnn] # For inbound traffic for STYLE=RAW only.
# Default is the PROTOCOL value; 6 (streaming) is disallowed
[HEADER={true,false}] # 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
[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
[option=value]* # I2CP and streaming options
</pre>
@ -1693,7 +1607,6 @@ bridge for name resolution:
<pre>
NAMING LOOKUP
NAME=$name
[OPTIONS=true] # Default false, as of router API 0.9.66
</pre>
</p><p>
@ -1705,7 +1618,6 @@ which is answered by
NAME=$name
[VALUE=$destination]
[MESSAGE="$message"]
[OPTION:optionkey="$optionvalue"] # As of router API 0.9.66
</pre>
@ -1737,35 +1649,6 @@ However, in some implementations, a .b32.i2p lookup which is uncached and requir
a network query may fail, as no client tunnels are available for the lookup.
</p>
<h4>Name Lookup Options</h4>
<p>
NAMING LOOKUP is extended as of router API 0.9.66 to support service lookups.
Support may vary by implementation.
See proposal 167 for additional information.
</p><p>
NAMING LOOKUP NAME=example.i2p OPTIONS=true requests the options mapping in the reply.
NAME may be a full base64 destination when OPTIONS=true.
</p><p>
If the destination lookup was successful and options were present in the leaseset,
then in the reply, following the destination,
will be one or more options in the form of OPTION:key=value.
Each option will have a separate OPTION: prefix.
All options from the leaseset will be included, not just service record options.
For example, options for parameters defined in the future may be present.
Example:
</p><p>
NAMING REPLY RESULT=OK NAME=example.i2p VALUE=base64dest OPTION:_smtp._tcp="1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p"
</p><p>
Keys containing '=', and keys or values containing a newline,
are considered invalid and the key/value pair will be removed from the reply.
If there are no options found in the leaseset, or if the leaseset was version 1,
then the response will not include any options.
If OPTIONS=true was in the lookup, and the leaseset is not found, a new result value LEASESET_NOT_FOUND will be returned.
</p>
<h4>Destination Key Generation</h4>
</p><p>
@ -1923,25 +1806,8 @@ their meaning:
KEY_NOT_FOUND The naming system can't resolve the given name
PEER_NOT_FOUND The peer cannot be found on the network
TIMEOUT Timeout while waiting for an event (e.g. peer answer)
LEASESET_NOT_FOUND See Name Lookup Options above. As of router API 0.9.66.
</pre>
<p>
Different implementations may not be consistent in which RESULT is returned
in various scenarios.
<p>
Most responses with a RESULT, other than OK, will also include a MESSAGE with additional information.
The MESSAGE will generally be helpful in debugging problems.
However, MESSAGE strings are implementation-dependent,
may or may not be translated by the SAM server to the current locale,
may contain internal implementation-specific information such as exceptions,
and are subject to change without notice.
While SAM clients may choose to expose MESSAGE strings to users,
they should not make programmatic decisions based on those strings,
as that will be fragile.
<h3 id="options">Tunnel, I2CP, and Streaming Options</h3>
<p>

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 %}2022-04{% endblock %}
{% block accuratefor %}0.9.53{% endblock %}
{% block content %}
<h2>{% trans %}Overview{% endtrans %}</h2>
@ -330,9 +330,10 @@ As of release {{ release }}.
<tr><td>i2p.streaming.maxWindowSize</td><td>128</td></tr>
<tr><td>i2p.streaming.profile</td><td>1 (bulk)</td><td>
1=bulk; 2=interactive; see important notes <a href="#profile">below</a>.
</td></tr>
<tr><td>i2p.streaming.profile</td><td>1 (bulk)</td><td>{% trans -%}
(2=interactive not supported)
This doesn't currently do anything, but setting it to a value other than 1 will cause an error.
{%- endtrans %}</td></tr>
<tr><td>i2p.streaming.readTimeout</td><td>-1</td><td>{% trans -%}
How long to block on read, in milliseconds. Negative means indefinitely.
@ -533,29 +534,6 @@ Streaming may be configured to disable sending pongs with the configuration i2p.
{%- endtrans %}</p>
<h3 id="profile">i2p.streaming.profile Notes</h3>
<p>
This option supports two values; 1=bulk and 2=interactive.
The option provides a hint to the streaming library and/or router as to
the traffic pattern that is expected.
</p><p>
"Bulk" means to optimize for high bandwidth, possibly at the expense of latency.
This is the default.
"Interactive" means to optimize for low latency, possibly at the expense of bandwidth or efficiency.
Optimization strategies, if any, are implementation-dependent, and may include changes
outside of the streaming protocol.
</p><p>
Through API version 0.9.63, Java I2P would return an error for any value other than 1 (bulk) and the tunnel would fail to start.
As of API 0.9.64, Java I2P ignores the value.
Through API version 0.9.63, i2pd ignored this option; it is implemented in i2pd as of API 0.9.64.
</p><p>
While the streaming protocol includes a flag field to pass the profile setting to the
other end, this is not implemented in any known router.
</p>
<h3 id="sharing">{% trans %}Control Block Sharing{% endtrans %}</h3>
<p>{% trans -%}
The streaming lib supports "TCP" Control Block sharing.

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 %}2023-01{% endblock %}
{% block accuratefor %}0.9.57{% endblock %}
{% block content %}
<p>{% trans -%}
@ -58,19 +58,6 @@ For most low- to medium-bandwidth and low- to medium-connection counts, 3 is suf
Please specify the tunnel quantity in the SESSION CREATE message
to get consistent performance with the Java I2P and i2pd routers.
</p><p>
I2P supports multiple signature and encryption types.
For compatibility, I2P defaults to old and inefficient types, so all clients should
specify newer types.
</p><p>
If using SAM, the signature type is specified in the DEST GENERATE and SESSION CREATE (for transient) commands.
All clients should set SIGNATURE_TYPE=7 (Ed25519).
</p><p>
The encryption type is specified in the SAM SESSION CREATE command or in i2cp options.
Multiple encryption types are allowed.
Some trackers support ECIES-X25519, some support ElGamal, and some support both.
Clients should set i2cp.leaseSetEncType=4,0 (for ECIES-X25519 and ElGamal)
so that they may connect to both.
</p><p>
DHT support requires SAM v3.3 PRIMARY and SUBSESSIONS for TCP and UDP over the same session.
This will require substantial development effort on the client side, unless the client is written in Java.
i2pd does not currently support SAM v3.3.
@ -121,10 +108,7 @@ the tracker should probably decode and reject bad Base64 when announced.
The default response type is non-compact. Clients may request a compact response with
the parameter compact=1. A tracker may, but is not required to, return
a compact response when requested.
{%- endtrans %}
Note: 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>
{%- endtrans %}</p>
<p>{% trans -%}
Developers of new I2P clients

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_Developers/i2p.i2p</code></pre>
<pre><code>git remote set-url origin git@127.0.0.1:i2p-hackers/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_Developers/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-hackers/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_Developers/i2p.i2p</code></pre></li>
<pre><code>git remote add upstream git@127.0.0.1:i2p-hackers/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_Developers/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-hackers/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

@ -79,12 +79,12 @@ alt="{{ _('Configure port') }}" title="{{ _('Pidgin Step Four') }}">
alt="{{ _('Add a server') }}" title="{{ _('XChat Step One') }}">
<p>{% trans %}Create a new network named "Irc2P" to configure for I2P IRC. Click
the "Edit" button on the right-hand side. Make sure you disable TLS and SSL inside I2P.{% endtrans %}</p>
the "Edit" button on the right-hand side.{% endtrans %}</p>
<img src="{{ url_for('static', filename='images/irc/xchat-irc-1.png') }}"
alt="{{ _('Add a server') }}" title="{{ _('XChat Step Two') }}">
<p>{% trans %}Change the value in "Servers" from the default to `localhost/6668`,
<p>{% trans %}Change the value in "Servers" from the default to `localhost/6669`,
and configure the default channels you want to join. I suggest #i2p and #i2p-dev
{% endtrans %}</p>

View File

@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}The Network Database{% endtrans %}{% endblock %}
{% block lastupdated %}2025-03{% endblock %}
{% block accuratefor %}0.9.65{% endblock %}
{% block lastupdated %}2023-11{% endblock %}
{% block accuratefor %}0.9.59{% endblock %}
{% block content %}
<h2>{% trans %}Overview{% endtrans %}</h2>
@ -56,16 +56,14 @@ to be present:
<li><b>M</b>: {% trans amount='48 - 64 KBps' %}{{ amount }} shared bandwidth{% endtrans %}</li>
<li><b>N</b>: {% trans amount='64 - 128 KBps' %}{{ amount }} shared bandwidth{% endtrans %}</li>
<li><b>O</b>: {% trans amount='128 - 256 KBps' %}{{ amount }} shared bandwidth{% endtrans %}</li>
<li><b>P</b>: {% trans amount='256 - 2000 KBps' %}{{ amount }} shared bandwidth{% endtrans %} (as of release 0.9.20, see note below)</li>
<li><b>P</b>: {% trans amount='256 - 2000 KBps' %}{{ amount }} shared bandwidth{% endtrans %} (as of release 0.9.20)</li>
<li><b>R</b>: {% trans %}Reachable{% endtrans %}</li>
<li><b>U</b>: {% trans %}Unreachable{% endtrans %}</li>
<li><b>X</b>: {% trans amount='2000 KBps' %}Over {{ amount }} shared bandwidth{% endtrans %} (as of release 0.9.20, see note below)</li>
<li><b>X</b>: {% trans amount='2000 KBps' %}Over {{ amount }} shared bandwidth{% endtrans %} (as of release 0.9.20)</li>
</ul>
"Shared bandwidth" == (share %) * min(in bw, out bw)
<br>
For compatibility with older routers, a router may publish multiple bandwidth letters, for example "PO".
<br>
Note: the boundary between the P and X bandwidth classes may be either 2000 or 2048 KBps, implementor's choice.
</li>
<li><b>netId</b> = 2
({% trans %}Basic network compatibility - A router will refuse to communicate with a peer having a different netId{% endtrans %})
@ -531,34 +529,7 @@ Routing keys are never sent on-the-wire in any I2NP message, they are only used
determination of distance.
{%- endtrans %}</p>
<h2 id="segmentation">{% trans %}Network Database Segmentation - Sub-Databases{% endtrans %}</h2>
<p>{% trans -%}Traditionally Kademlia-style DHT's are not concerned with preserving the unlinkability of information stored on any particular node in the DHT.
For example, a piece of information may be stored to one node in the DHT, then requested back from that node unconditionally.
Within I2P and using the netDb, this is not the case, information stored in the DHT may only be shared under certain known circumstances where it is "safe" to do so.
This is to prevent a class of attacks where a malicious actor can try to associate a client tunnel with a router by sending a store to a client tunnel, then requesting it back directly from the suspected "Host" of the client tunnel.
{%- endtrans %}</p>
<h3>{% trans %}Segmentation Structure{% endtrans %}</h3>
<p>{% trans -%}I2P routers can implement effective defenses against the attack class provided a few conditions are met.
A network database implementation should be able to keep track of whether a database entry was recieved down a client tunnel or directly.
If it was recieved down a client tunnel, then it should also keep track of which client tunnel it was recieved through, using the client's local destination.
If the entry was recieved down multiple client tunnels, then the netDb should keep track of all destinations where the entry was observed.
It should also keep track of whether an entry was recieved as a reply to a lookup, or as a store.
{%- endtrans %}</p>
<p>{% trans -%}In both the Java and C++ implementations, this achieved by using a single "Main" netDb for direct lookups and floodfill operations first.
This main netDb exists in the router context.
Then, each client is given it's own version of the netDb, which is used to capture database entries sent to client tunnels and respond to lookups sent down client tunnels.
We call these "Client Network Databases" or "Sub-Databases" and they exist in the client context.
The netDb operated by the client exists for the lifetime of the client only and contains only entries that are communicated with the client's tunnels.
This makes it impossible for entries sent down client tunnels to overlap with entries sent directly to the router.
{%- endtrans %}</p>
<p>{% trans -%}Additionally, each netDb needs to be able to remember if a database entry was recieved because it was sent to one of our destinations, or because it was requested by us as part of a lookup.
If a database entry it was recieved as a store, as in some other router sent it to us, then a netDb should respond to requests for the entry when another router looks up the key.
However, if it was recieved as a reply to a query, then the netDb should only reply to a query for the entry if the entry had already been stored to the same destination.
A client should never answer queries with an entry from the main netDb, only it's own client network database.
{%- endtrans %}</p>
<p>{% trans -%}These strategies should be taken and used combined so that both are applied.
In combination, they "Segment" the netDb and secure it against attacks.
{%- endtrans %}</p>
<h2 id="delivery">{% trans %}Storage, Verification, and Lookup Mechanics{% endtrans %}</h2>
@ -613,13 +584,7 @@ The floodfill router replies with a
with the Message ID set to the value of the Reply Token.
{%- endtrans %}</p>
<p>In some circumstances, a router may also send the RouterInfo DatabaseStoreMessage out
an exploratory tunnel; for example, due to connection limits, connection incompatibility,
or a desire to hide the actual IP from the floodfill.
The floodfill may not accept such a store in times of overload or based
on other criteria; whether to explicitly declare non-direct store of a RouterInfo illegal is a topic
for further study.
</p>
<h3>{% trans %}LeaseSet Storage to Floodfills{% endtrans %}</h3>
@ -642,13 +607,6 @@ This message is sent back to one of the client's inbound tunnels.
<h3>{% trans %}Flooding{% endtrans %}</h3>
<p>
Like any router, a floodfill uses various criteria to validate the LeaseSet or RouterInfo before storing it locally.
These criteria may be adaptive and dependent on current conditions including current load, netdb size,
and other factors.
All validation must be done before flooding.
</p>
<p>{% trans floodsize=3 -%}
After a floodfill router receives a DatabaseStoreMessage containing a
valid RouterInfo or LeaseSet which is newer than that previously stored in its
@ -669,14 +627,6 @@ as this is a direct connection, so there are no intervening routers
The other routers do not reply or re-flood, as the Reply Token is zero.
{%- endtrans %}</p>
<p>
Floodfills must not flood via tunnels; the DatabaseStoreMessage must be sent over a direct connection.
</p>
<p>
Floodfills must never flood an expired LeaseSet or a RouterInfo published more than one hour ago.
</p>
<h3 id="lookup">{% trans %}RouterInfo and LeaseSet Lookup{% endtrans %}</h3>
<p>{% trans i2np=site_url('docs/protocol/i2np') -%}

View File

@ -1,16 +1,8 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Peer Profiling and Selection{% endtrans %}{% endblock %}
{% block lastupdated %}2024-02{% endblock %}
{% block accuratefor %}0.9.62{% endblock %}
{% block lastupdated %}{% trans %}July 2010{% endtrans %}{% endblock %}
{% block accuratefor %}0.8{% endblock %}
{% block content %}
<h2>NOTE</h2>
This page describes the Java I2P implementation of peer profiling and selection as of 2010.
While still broadly accurate, some details may no longer be correct.
We continue to evolve banning, blocking, and selection strategies to address newer threats, attacks, and network conditions.
The current network has multiple router implementations with various versions.
Other I2P implementations may have completely different profiling and selection strategies,
or may not use profiling at all.
<h2>{% trans %}Overview{% endtrans %}</h2>
<h3>{% trans %}Peer Profiling{% endtrans %}</h3>

View File

@ -1,7 +1,5 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}I2P: A scalable framework for anonymous communication{% endtrans %}{% endblock %}
{% block lastupdated %}2025-01{% endblock %}
{% block accuratefor %}0.9.65{% endblock %}
{% block content_nav %}
<ul>
<li><a href="#intro">{% trans %}Introduction{% endtrans %}</a></li>
@ -15,40 +13,10 @@
<li><a href="#op.crypto">{% trans %}Cryptography{% endtrans %}</a></li>
</ul>
</li>
<li>
<a href="#future">{% trans %}Future{% endtrans %}</a>
<ul>
<li><a href="#future.restricted">{% trans %}Restricted Routes{% endtrans %}</a></li>
<li><a href="#future.variablelatency">{% trans %}Variable Latency{% endtrans %}</a></li>
</ul>
</li>
<li>
<a href="#similar">{% trans %}Similar Networks{% endtrans %}</a>
<ul>
<li><a href="#similar.tor">{% trans %}Tor{% endtrans %}</a></li>
<li><a href="#similar.freenet">{% trans %}Freenet{% endtrans %}</a></li>
</ul>
</li>
<li>
<a href="#app">{% trans %}Application Layer{% endtrans %}</a>
<ul>
<li><a href="#app.streaming">{% trans %}Streaming{% endtrans %}</a></li>
<li><a href="#app.naming">{% trans %}Naming and Addressbook{% endtrans %}</a></li>
<li><a href="#app.i2psnark">{% trans %}I2PSnark{% endtrans %}</a></li>
<li><a href="#app.i2ptunnel">{% trans %}I2PTunnel{% endtrans %}</a></li>
<li><a href="#app.i2pmail">{% trans %}I2P Email{% endtrans %}</a></li>
</ul>
</li>
</ul>
{% endblock %}
{% block content %}
<p>
NOTE: This document was originally written by jrandom in 2003.
While we strive to keep it current, some information may be obsolete or incomplete.
The transport and cryptography sections are current as of 2025-01.
</p>
<h1 id="intro">{% trans %}Introduction{% endtrans %}</h1>
<p>{% trans -%}
I2P is a scalable, self organizing, resilient packet switched anonymous
@ -62,16 +30,20 @@ anonymity set of users already running on top of I2P.
<p>{% trans -%}
Applications available already provide the full range of typical Internet activities -
<b>anonymous</b> web browsing, web hosting, chat, file sharing, e-mail,
blogging and content syndication, as well as several other applications under development.
blogging and content syndication, newsgroups, as well as several other applications under development.
{%- endtrans %}</p>
<ul>
<li>{% trans %}Web browsing: using any existing browser that supports using a proxy.{% endtrans %}</li>
<li>{% trans %}Chat: IRC and other protocols{% endtrans %}</li>
<li>{% trans %}Chat: IRC, Jabber, <a href="#app.i2pmessenger">I2P-Messenger</a>.{% endtrans %}</li>
<li>{% trans -%}
File sharing: <a href="#app.i2psnark">I2PSnark</a> and other applications
File sharing: <a href="#app.i2psnark">I2PSnark</a>, <a href="#app.robert">Robert</a>, <a href="#app.imule">iMule</a>,
<a href="#app.i2phex">I2Phex</a>, <a href="#app.pybit">PyBit</a>, <a href="#app.i2pbt">I2P-bt</a>
and others.
{%- endtrans %}</li>
<li>{% trans %}E-mail: <a href="#app.i2pmail">susimail</a> and other applications{% endtrans %}</li>
<li>{% trans %}Blog: using any local web server, or available plugins{% endtrans %}</li>
<li>{% trans %}E-mail: <a href="#app.i2pmail">susimail</a> and <a href="#app.i2pbote">I2P-Bote</a>.{% endtrans %}</li>
<li>{% trans %}Blog: using e.g. the pebble plugin or the distributed blogging software <a href="#app.syndie">Syndie</a>.{% endtrans %}</li>
<li>{% trans %}Distributed Data Store: Save your data redundantly in the Tahoe-LAFS cloud over I2P.{% endtrans %}</li>
<li>{% trans %}Newsgroups: using any newsgroup reader that supports using a proxy.{% endtrans %}</li>
</ul>
<p>{% trans -%}
@ -143,7 +115,6 @@ and an end point. Messages can be sent only in one way. To send messages back,
another tunnel is required.
{%- endtrans %}</p>
<div class="box" style="text-align:center;">
<br /><br />
<img src="{{ url_for('static', filename='images/tunnels.png') }}" alt="{{ _('Inbound and outbound tunnel schematic') }}" title="{{ _('Inbound and outbound tunnel schematic') }}" />
<br /><br />
{% trans %}Figure 1: Two types of tunnels exist: inbound and outbound.{% endtrans %}
@ -197,10 +168,8 @@ She can then send a build message to the first hop, requesting the construction
that router to send the construction message onward, until the tunnel has been constructed.
{%- endtrans %}</p>
<div class="box" style="text-align:center;">
<br /><br />
<img src="{{ url_for('static', filename='images/netdb_get_routerinfo_1.png') }}" alt="{{ _('Request information on other routers') }}" title="{{ _('Request information on other routers') }}" />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br /><br />
<img src="{{ url_for('static', filename='images/netdb_get_routerinfo_2.png') }}" alt="{{ _('Build tunnel using router information') }}" title="{{ _('Build tunnel using router information') }}" />
<br /><br />
{% trans %}Figure 2: Router information is used to build tunnels.{% endtrans %}
@ -223,7 +192,6 @@ recent LeaseSet with the message so that Bob doesn't need to do a netDb lookup
for it when he wants to reply, but this is optional.
{%- endtrans %}</p>
<div class="box" style="text-align:center;">
<br /><br />
<img src="{{ url_for('static', filename='images/netdb_get_leaseset.png') }}" alt="{{ _('Connect tunnels using LeaseSets') }}" title="{{ _('Connect tunnels using leaseSets') }}" />
<br /><br />
{% trans %}Figure 3: LeaseSets are used to connect outbound and inbound tunnels.{% endtrans %}
@ -362,12 +330,10 @@ but a basic explanation is available below.
{%- endtrans %}</p>
<p>{% trans -%}
All I2P routers contain a local netDb, but not all routers participate in the DHT
or respond to leaseset lookups.
Those routers that do participate in the DHT and respond to leaseset lookups
are called 'floodfills'.
Routers may be manually configured as floodfills, or automatically become floodfill
if they have enough capacity and meet other criteria for reliable operation.
A percentage of I2P users are appointed as 'floodfill peers'.
Currently, I2P installations that have a lot of bandwidth and are fast enough,
will appoint themselves as floodfill as soon as the number of existing floodfill routers
drops too low.
{%- endtrans %}</p>
<p>{% trans netdb=site_url('docs/how/network-database') -%}
@ -404,7 +370,7 @@ Some additional remarks are also important.
<p>{% trans -%}
One could only want specific people to be able to reach a destination.
This is possible by not publishing the destination in the netDb. You will however have to transmit the destination by other means.
This is supported by 'encrypted leaseSets'. These leaseSets can only be decoded by people with access to the decryption key.
An alternative are the 'encrypted leaseSets'. These leaseSets can only be decoded by people with access to the decryption key.
{%- endtrans %}</p>
</li>
<li>
@ -414,16 +380,16 @@ Bootstrapping the netDb is quite simple. Once a router manages to receive a sing
it can query that router for references to other routers in the network.
Currently, a number of users post their routerInfo files to a website to make this information available.
I2P automatically connects to one of these websites to gather routerInfo files and bootstrap.
I2P calls this bootstrap process "reseeding".
{%- endtrans %}</p>
</li>
<li>
<b>{% trans %}Lookup scalability:{% endtrans %}</b>
<p>{% trans -%}
Lookups in the I2P network are iterative, not recursive.
If a lookup from a floodfill fails, the lookup will be repeated to the next-closest floodfill.
The floodfill does not recursively ask another floodfill for the data.
Iterative lookups are scalable to large DHT networks.
Lookups in the I2P network are not forwarded to other netDb routers.
Currently, this is not a major problem, since the network is not very large.
However, as the network grows, not all routerInfo and leaseSet files will be present
on each netDb router. This will cause a deterioration of the percentage of successful lookups.
Because of this, refinements to the netDb will be done in the next releases.
{%- endtrans %}</p>
</li>
</ul>
@ -437,29 +403,15 @@ communicate with other routers aren't critical - three separate protocols
have been used at different points to provide those bare necessities.
{%- endtrans %}</p>
<p>{% trans ntcp=site_url('docs/transport/ntcp'), ssu=site_url('docs/transport/ssu'), ntcp2=spec_url('ntcp2'), ssu2=spec_url('ssu2') -%}
I2P currently supports two transport protocols,
<a href="{{ ntcp2 }}">NTCP2</a> over TCP, and <a href="{{ ssu2 }}">SSU2</a> over UDP.
These have replaced the previous versions of the protocols,
<a href="{{ ntcp }}">NTCP</a> and <a href="{{ ssu }}">SSU</a>, which are now deprecated.
Both protocols support both IPv4 and IPv6.
By supporting both TCP and UDP transports, I2P can effectively traverse most firewalls,
including those intended to block traffic in restrictive censorship regimes.
NTCP2 and SSU2 were designed to use modern encryption standards,
improve traffic identification resistance,
increase efficiency and security,
and make NAT traversal more robust.
Routers publish each supported transport and IP address in the network database.
Routers with access to public IPv4 and IPv6 networks will usually publish
four addresses, one for each combination of NTCP2/SSU2 with IPv4/IPv6.
<p>{% trans ssu=site_url('docs/transport/ssu') -%}
I2P started with a TCP-based protocol which
has since been disabled. Then, to accommodate the need for high degree communication
(as a number of routers will end up speaking with many others), I2P moved
from a TCP based transport to a <a href="{{ ssu }}">UDP-based one</a> - "Secure
Semireliable UDP", or "SSU".
{%- endtrans %}</p>
<p>{% trans ssu=site_url('docs/transport/ssu'), ssu2=spec_url('ssu2') -%}
<a href="{{ ssu2 }}">SSU2</a> supports and extends the goals of SSU.
SSU2 has many similarities to other modern UDP-based protocols such as Wireguard and QUIC.
In addition to the reliable transport of network messages over UDP,
SSU2 provides specialized facilities for peer-to-peer, cooperative
IP address detection, firewall detection, and NAT traversal.
<p>{% trans ssu=site_url('docs/transport/ssu') -%}
As described in the <a href="{{ ssu }}">SSU spec</a>:
{%- endtrans %}</p>
@ -473,11 +425,14 @@ sufficient for home users. In addition, it should support techniques for address
network obstacles, like most NATs or firewalls.
{%- endtrans %}</blockquote>
<p>{% trans ntcp2=spec_url('ntcp2') -%}
NTCP2 supports and extends the goals of NTCP.
It provides an efficient and fully encrypted transport of network messages over TCP,
and resistance to traffic identification,
using modern encryption standards.
<p>{% trans ntcp=site_url('docs/transport/ntcp') -%}
Following the introduction of SSU, after issues with congestion collapse
appeared, a new NIO-based TCP transport called <a href="{{ ntcp }}">NTCP</a>
was implemented. It is enabled by default for outbound connections only. Those
who configure their NAT/firewall to allow inbound connections and specify
the external host and port (dyndns/etc is ok) on /config.jsp can receive inbound
connections. As NTCP is NIO based, so it doesn't suffer from the 1 thread
per connection issues of the old TCP transport.
{%- endtrans %}</p>
<p>{% trans -%}
@ -488,51 +443,28 @@ Transports may reply with different bids, depending on whether there is already
an established connection to the peer.
{%- endtrans %}</p>
<p>{% trans -%}
The bid (priority) values are implementation-dependent and
may vary based on traffic conditions, connection counts, and other factors.
Routers also publish their transport preferences for inbound connections in the network database
as transport "costs" for each transport and address.
<p>{% trans ntcp=site_url('docs/transport/ntcp') -%}
The current implementation ranks NTCP as the highest-priority transport
for outbound connections in most situations. SSU is enabled for both outbound
and inbound connections. Your firewall and your I2P router must be configured
to allow inbound NTCP connections. For further information see the <a href="{{ ntcp }}">NTCP
page</a>.
{%- endtrans %}</p>
<h2 id="op.crypto">{% trans %}Cryptography{% endtrans %}</h2>
<p>{% trans -%}
I2P uses cryptography at several protocol layers for encryption, authentication, and verification.
The major protocol layers are: transports, tunnel build messages, tunnel layer encryption,
network database messages, and end-to-end (garlic) messages.
I2P's original design used a small set of cryptographic primitives that at the time were considered secure.
These included ElGamal asymmetric encryption, DSA-SHA1 signatures,
AES256/CBC symmetric encryption, and SHA-256 hashes.
As available computing power increased and cryptographic research evolved substantially
over the years, I2P needed to upgrade its primitives and protocols.
Therefore, we added a concept of "encryption types" and "signature types",
and extended our protocols to include these identifiers and indicate support.
This allows us to periodically update and extend the network support for
modern cryptography and future-proof the network for new primitives,
without breaking backward compatibility or requiring a "flag day" for network updates.
Some signature and encryption types are also reserved for experimental use.
{%- endtrans %}</p>
<p>{% trans -%}
The current primitives used in most protocol layers are X25519 key exchange, EdDSA signatures,
ChaCha20/Poly1305 authenticated symmetric encryption, and SHA-256 hashes.
AES256 is still used for tunnel layer encryption.
These modern protocols are used for the vast majority of network communication
Older primitives including ElGamal, ECDSA, and DSA-SHA1 continue to be supported by most implementations
for backward compatibility when communicating with older routers.
Some old protocols have been deprecated and/or removed completely.
In the near future we will begin research on a migration to post-quantum (PQ)
or hybrid-PQ encryption and signatures to maintain our robust security standards.
{%- endtrans %}</p>
<p>{% trans -%}
These cryptographic primitives are combined together to
A bare minimum set of cryptographic primitives are combined together to
provide I2P's layered defenses against a variety of adversaries. At the lowest
level, inter-router communication is protected by the transport layer security.
<a href="#op.tunnels">Tunnel</a> messages passed over the transports
have their own layered encryption.
Various other messages are passed along inside "garlic messages", which are also encrypted.
level, inter router communication is protected by the transport layer security
- SSU encrypts each packet with AES256/CBC with both an explicit IV and MAC
(HMAC-MD5-128) after agreeing upon an ephemeral session key through a 2048bit
Diffie-Hellman exchange, station-to-station authentication with the other
router's DSA key, plus each network message has their own hash for local integrity
checking. <a href="#op.tunnels">Tunnel</a> messages passed over the transports
have their own layered AES256/CBC encryption with an explicit IV and verified
at the tunnel endpoint with an additional SHA256 hash. Various other messages
are passed along inside "garlic messages", which are encrypted with ElGamal/AES+SessionTags
(explained below).
{%- endtrans %}</p>
<h3 id="op.garlic">{% trans %}Garlic messages{% endtrans %}</h3>
@ -544,10 +476,10 @@ into a garlic message whenever the message would otherwise be passing in clearte
through a peer who should not have access to the information - for instance,
when a router wants to ask another router to participate in a tunnel, they
wrap the request inside a garlic, encrypt that garlic to the receiving router's
public key, and forward it through a tunnel. Another example
2048bit ElGamal public key, and forward it through a tunnel. Another example
is when a client wants to send a message to a destination - the sender's router
will wrap up that data message (alongside some other messages) into a garlic,
encrypt that garlic to the public key published in the recipient's
encrypt that garlic to the 2048bit ElGamal public key published in the recipient's
leaseSet, and forward it through the appropriate tunnels.
{%- endtrans %}</p>
@ -568,17 +500,11 @@ not currently used in the existing implementation.
<p>{% trans -%}
As an unreliable, unordered, message based system, I2P uses a simple combination
of asymmetric and symmetric encryption algorithms to provide data confidentiality
and integrity to garlic messages. The original combination was referred
and integrity to garlic messages. As a whole, the combination is referred
to as ElGamal/AES+SessionTags, but that is an excessively verbose way to describe
the simple use of 2048bit ElGamal, AES256, SHA256 and 32 byte nonces.
While this protocol is still supported, most of the network has migrated to
a new protocol, ECIES-X25519-AEAD-Ratchet.
This protocol combines X25519, ChaCha20/Poly1305, and a synchronized PRNG
to generate the 32 byte nonces.
Both protocols will be briefly described below.
{%- endtrans %}</p>
<h4 id="op.elg">ElGamal/AES+SessionTags</h4>
<p>{% trans -%}
The first time a router wants to encrypt a garlic message to another router,
they encrypt the keying material for an AES256 session key with ElGamal and
@ -620,50 +546,24 @@ drop the ones previously assumed to be properly delivered, reverting back
to the full expensive ElGamal encryption.
{%- endtrans %}</p>
<h4 id="op.ratchet">ECIES-X25519-AEAD-Ratchet</h4>
<p>{% trans -%}
ElGamal/AES+SessionTags required substantial overhead in a number of ways.
CPU usage was high because ElGamal is quite slow.
Bandwidth was excessive because large numbers of session tags had to be delivered in advance,
and because ElGamal public keys are very large.
Memory usage was high due to the requirement to store large amounts of session tags.
Reliability was hampered by lost session tag delivery.
{%- endtrans %}</p>
<p>{% trans -%}
ECIES-X25519-AEAD-Ratchet was designed to address these issues.
X25519 is used for key exchange.
ChaCha20/Poly1305 is used for authenticated symmetric encryption.
Encryption keys are "double ratcheted" or rotated periodically.
Session tags are reduced from 32 bytes to 8 bytes and are generated with a PRNG.
The protocol has many similarities to the signal protocol used in Signal and WhatsApp.
This protocol provides substantially lower overhead in CPU, RAM, and bandwidth.
{%- endtrans %}</p>
<p>{% trans -%}
The session tags are generated from a deterministic synchronized PRNG running
at both ends of the session to generate session tags and session keys.
The PRNG is a HKDF using a SHA-256 HMAC, and is seeded from the X25519 DH result.
Session tags are never transmitted in advance; they are only included with the message.
The receiver stores a limited number of session keys, indexed by session tag.
The sender does not need to store any session tags or keys because they
are not sent in advance; they may be generated on-demand.
By keeping
One alternative is to transmit only a single session tag, and from that,
seed a deterministic PRNG for determining what tags to use or expect. By keeping
this PRNG roughly synchronized between the sender and recipient (the recipient
precomputes a window of the next e.g. 50 tags), the overhead of periodically
bundling a large number of tags is removed.
bundling a large number of tags is removed, allowing more options in the space/time
tradeoff, and perhaps reducing the number of ElGamal encryptions necessary.
However, it would depend upon the strength of the PRNG to provide the necessary
cover against internal adversaries, though perhaps by limiting the amount
of times each PRNG is used, any weaknesses can be minimized. At the moment,
there are no immediate plans to move towards these synchronized PRNGs.
{%- endtrans %}</p>
<h1 id="future">{% trans %}Future{% endtrans %}</h1>
<p>{% trans -%}
I2P's protocols are efficient on most platforms, including cell phones,
and secure for most threat models. However, there
While I2P is currently functional and sufficient for many scenarios, there
are several areas which require further improvement to meet the needs of those
facing powerful state-sponsored adversaries, and to meet the threats of
continued cryptographic advances and ever-increasing computing power.
Two possible features, restricted routes and variable latency,
were propsed by jrandom in 2003. While we no longer plan to
implement these features, they are described below.
facing more powerful adversaries as well as substantial user experience optimization.
{%- endtrans %}</p>
<h2 id="future.restricted">{% trans %}Restricted route operation{% endtrans %}</h2>
@ -684,7 +584,7 @@ Restricted route operation, where there are limits to what peers are reachable
directly, has several different functional and anonymity implications, dependent
upon how the restricted routes are handled. At the most basic level, restricted
routes exist when a peer is behind a NAT or firewall which does not allow
inbound connections. This was largely addressed by integrating
inbound connections. This was largely addressed in I2P 0.6.0.6 by integrating
distributed hole punching into the transport layer, allowing people behind
most NATs and firewalls to receive unsolicited connections without any configuration.
However, this does not limit the exposure of the peer's IP address to routers
@ -710,7 +610,8 @@ tunnel gateway. The concept of 'client routers' simply extends the restricted
route by not publishing any router addresses. Such a router would not even
need to publish their routerInfo in the netDb, merely providing their self
signed routerInfo to the peers that it contacts (necessary to pass the router's
public keys).
public keys). Both levels of restricted route operation are planned for I2P
2.0.
{%- endtrans %}</p>
<p>{% trans -%}
@ -725,20 +626,6 @@ of using a hostile peer to get connected is small enough, or trusted (and
perhaps temporary) peers are used instead.
{%- endtrans %}</p>
<p>{% trans -%}
Restricted routes are complex, and the overall goal has been largely abandoned.
Several related improvements have greatly reduced the need for them.
We now support UPnP to automatically open firewall ports.
We support both IPv4 and IPv6.
SSU2 improved address detection, firewall state determination, and cooperative NAT hole punching.
SSU2, NTCP2, and address compatibility checks ensure that tunnel hops can connect
before the tunnel is built.
GeoIP and country identification allow us to avoid peers in countries with restrictive firewalls.
Support for "hidden" routers behind those firewalls has improved.
Some implementations also support connections to peers on overlay networks such as Yggdrasil.
{%- endtrans %}</p>
<h2 id="future.variablelatency">{% trans %}Variable latency{% endtrans %}</h2>
<p>{% trans -%}
Even though the bulk of I2P's initial efforts have been on low latency communication,
@ -758,14 +645,20 @@ or, most likely, to a remote client destination.
{%- endtrans %}</p>
<p>{% trans -%}
The goal of variable latency services requires substantial resources
for store-and-forward mechanisms to support it.
These mechanisms can and are supported in various messaging applications,
such as i2p-bote.
At the network level, alternative networks such as Freenet provide these services.
We have decided not to pursue this goal at the I2P router level.
There are a substantial number of ways to exploit this capacity for high
latency comm in I2P, but for the moment, doing so has been scheduled for the
I2P 3.0 release. In the meantime, those requiring the anonymity that high
latency comm can offer should look towards the application layer to provide
it.
{%- endtrans %}</p>
<h2 id="future.open">{% trans %}Open questions{% endtrans %}</h2>
<ul>
<li>{% trans %}How to get rid of the timing constraint?{% endtrans %}</li>
<li>{% trans %}Can we deal with the sessionTags more efficiently?{% endtrans %}</li>
<li>{% trans %}What, if any, batching/mixing strategies should be made available on the tunnels?{% endtrans %}</li>
<li>{% trans %}What other tunnel peer selection and ordering strategies should be available?{% endtrans %}</li>
</ul>
<h1 id="similar">{% trans %}Similar systems{% endtrans %}</h1>
@ -781,8 +674,6 @@ two in particular are pulled out here - Tor and Freenet.
<p>{% trans comparisons=site_url('comparison') -%}
See also the <a href="{{ comparisons }}">Network Comparisons Page</a>.
Note that these descriptions were written by jrandom in 2003 and
may not currently be accurate.
{%- endtrans %}</p>
<h2 id="similar.tor">Tor</h2>
@ -833,6 +724,11 @@ in a tunnel is important, as an adversary would otherwise be able to mount
a series of powerful predecessor, intersection, and traffic confirmation attacks.
{%- endtrans %}</p>
<p>{% trans -%}
Tor's support for a second tier of "onion proxies" does offer a non-trivial
degree of anonymity while requiring a low cost of entry, while I2P will not
offer this topology until <a href="#future.restricted">2.0</a>.
{%- endtrans %}</p>
<p>{% trans -%}
On the whole, Tor and I2P complement each other in their focus - Tor works
@ -878,6 +774,20 @@ Freenet team will pursue efforts in that direction, if not simply reusing
(or helping to improve, as necessary) existing mixnets like I2P or Tor.
{%- endtrans %}</p>
<p>{% trans -%}
It is worth mentioning that there has recently been discussion and work
by the Freenet developers on a "globally scalable darknet" using restricted
routes between peers of various trust. While insufficient information has
been made publicly available regarding how such a system would operate for
a full review, from what has been said the anonymity and scalability claims
seem highly dubious. In particular, the appropriateness for use in hostile
regimes against state level adversaries has been tremendously overstated,
and any analysis on the implications of resource scarcity upon the scalability
of the network has seemingly been avoided. Further questions regarding susceptibility
to traffic analysis, trust and other topics do exist, but a more in-depth
review of this "globally scalable darknet" will have to wait until the Freenet
team makes more information available.
{%- endtrans %}</p>
<h1 id="app">Appendix A: Application layer</h1>
<p>{% trans -%}
@ -981,6 +891,24 @@ systems can plug into, allowing end users to drive what sort of naming tradeoffs
they prefer.
{%- endtrans %}</p>
<h2 id="app.syndie">Syndie</h2>
<p><i>{% trans -%}
The old Syndie bundled with I2P has been replaced by the new Syndie which
is distributed separately. For more information see the <a href="http://syndie.i2p2.de/">Syndie</a>
pages.
{%- endtrans %}</i></p>
<p>{% trans -%}
Syndie is a safe, anonymous blogging / content publication / content aggregation
system. It lets you create information, share it with others, and read posts
from those you're interested in, all while taking into consideration your
needs for security and anonymity. Rather than building its own content distribution
network, Syndie is designed to run on top of existing networks, syndicating
content through I2P Sites, Tor hidden services, Freenet freesites, normal websites,
usenet newsgroups, email lists, RSS feeds, etc. Data published with Syndie
is done so as to offer pseudonymous authentication to anyone reading or archiving
it.
{%- endtrans %}</p>
<h2 id="app.i2ptunnel">I2PTunnel</h2>
<p><i>{% trans dev='mihi' -%}Developed by: {{ dev }}{%- endtrans %}</i></p>
@ -1027,6 +955,25 @@ POP3 and SMTP destinations (which in turn are simply "server" instances pointing
at POP3 and SMTP servers), as well as "client" tunnels pointing at I2P's CVS
server, allowing anonymous development. At times people have even run "client"
proxies to access the "server" instances pointing at an NNTP server.
{%- endtrans %}</p>
<h2 id="app.i2pbt">i2p-bt</h2>
<p><i>{% trans dev='duck, et al' -%}Developed by: {{ dev }}{%- endtrans %}</i></p>
<p>{% trans -%}
i2p-bt is a port of the mainline python BitTorrent client to run both the
tracker and peer communication over I2P. Tracker requests are forwarded through
the eepproxy to I2P Sites specified in the torrent file while tracker responses
refer to peers by their destination explicitly, allowing i2p-bt to open up
a <a href="#app.streaming">streaming lib</a> connection to query them for
blocks.
{%- endtrans %}</p>
<p>{% trans -%}
In addition to i2p-bt, a port of bytemonsoon has been made to I2P, making
a few modifications as necessary to strip any anonymity-compromising information
from the application and to take into consideration the fact that IPs cannot
be used for identifying peers.
{%- endtrans %}</p>
<h2 id="app.i2psnark">I2PSnark</h2>
@ -1040,6 +987,40 @@ href="http://www.klomp.org/snark/">Snark</a> client
Bundled with the I2P install, I2PSnark offers a simple anonymous BitTorrent
client with multitorrent capabilities, exposing all of the functionality through
a plain HTML web interface.
{%- endtrans %}</p>
<h2 id="app.robert">Robert</h2>
<p><i>{% trans dev='sponge' -%}Developed by: {{ dev }}{%- endtrans %}</i></p>
<p>{% trans bob=i2pconv('bob.i2p') -%}
Robert is a Bittorrent client written in Python.
It is hosted on <a href="http://{{ bob }}/Robert.html">http://{{ bob }}/Robert.html</a> <!-- TODO: expand -->
{%- endtrans %}</p>
<h2 id="app.pybit">PyBit</h2>
<p><i>{% trans dev='Blub' -%}Developed by: {{ dev }}{%- endtrans %}</i></p>
<p>{% trans pybit='http://'+i2pconv('echelon.i2p')+'/pybit/' -%}
PyBit is a Bittorrent client written in Python.
It is hosted on <a href="{{ pybit }}">{{ pybit }}</a> <!-- TODO: expand -->
{%- endtrans %}</p>
<h2 id="app.i2phex">I2Phex</h2>
<p><i>{% trans dev='sirup' -%}Developed by: {{ dev }}{%- endtrans %}</i></p>
<p>{% trans -%}
I2Phex is a fairly direct port of the Phex Gnutella filesharing client to
run entirely on top of I2P. While it has disabled some of Phex's functionality,
such as integration with Gnutella webcaches, the basic file sharing and chatting
system is fully functional.
{%- endtrans %}</p>
<h2 id="app.imule">iMule</h2>
<p><i>{% trans dev='mkvore' -%}Developed by: {{ dev }}{%- endtrans %}</i></p>
<p>{% trans -%}
iMule is a fairly direct port of the aMule filesharing client
running entirely inside I2P.
{%- endtrans %}</p>
<h2 id="app.i2pmail">I2Pmail/susimail</h2>
@ -1059,9 +1040,27 @@ to delivery through the mail.i2p outproxies, which are separate from the mail.i2
SMTP and POP3 servers - both the outproxies and inproxies communicate with
the mail.i2p SMTP and POP3 servers through I2P itself, so compromising those
non-anonymous locations does not give access to the mail accounts or activity
patterns of the user.
patterns of the user. At the moment the developers work on a decentralized
mailsystem, called "v2mail". More information can be found on the I2P Site
<a href="http://{{ postman }}/">{{ postman }}</a>.
{%- endtrans %}</p>
<h2 id="app.i2pbote">I2P-Bote</h2>
<p><i>{% trans dev='HungryHobo' -%}Developed by: {{ dev }}{%- endtrans %}</i></p>
<p>{% trans -%}
I2P-Bote is a distributed e-mail application. It does not use the traditional
e-mail concept of sending an e-mail to a server and retrieving it from a server.
Instead, it uses a Kademlia Distributed Hash Table to store mails.
One user can push a mail into the DHT, while another can request the e-mail from the DHT.
And all the mails sent within the I2P-Bote network are automatically encrypted end-to-end. <br>
Furthermore, I2P-Bote offers a remailer function on top of I2P, for increased high-latency anonymity.
{%- endtrans %}</p>
<h2 id="app.i2pmessenger">I2P-Messenger</h2>
<p>{% trans -%}
I2P-Messenger is an end-to-end encrypted serverless communication application.
For communication between two users, they need to give each other their destination keys, to allow the other to connect.
It supports file transfer and has a search for other users, based on Seedless.
{%- endtrans %}</p>
{% endblock %}

View File

@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Index to Technical Documentation{% endtrans %}{% endblock %}
{% block lastupdated %}2025-06{% endblock %}
{% block accuratefor %}0.9.67{% endblock %}
{% block lastupdated %}2022-08{% endblock %}
{% block accuratefor %}0.9.55{% 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_Developers/i2p.www/issues' -%}
<p>{% trans trac='https://i2pgit.org/i2p-hackers/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>.
@ -122,7 +122,6 @@ 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>
@ -257,7 +256,7 @@ ancient (str4d)
</li><li>
<a href="http://{{ i2pconv('zzz.i2p') }}/">{{ _('Developer forum inside I2P') }}</a>
</li><li>
<a href="https://i2pgit.org/I2P_Developers/i2p.i2p/issues">{{ _('Bug tracker') }}</a>
<a href="https://i2pgit.org/i2p-hackers/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

@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Naming and Address Book{% endtrans %}{% endblock %}
{% block lastupdated %}2025-01{% endblock %}
{% block accuratefor %}0.9.65{% endblock %}
{% block lastupdated %}2023-11{% endblock %}
{% block accuratefor %}0.9.59{% endblock %}
{% block content %}
<h2 id="overview">{% trans %}Overview{% endtrans %}</h2>
@ -168,39 +168,18 @@ Otherwise, it forwards the request to a configured HTTP outproxy.
Thus, in practice, all HTTP (I2P Site) hostnames must end in the pseudo-Top Level Domain '.i2p'.
{%- endtrans %}</p>
<p>{% trans i2ptld='https://datatracker.ietf.org/doc/draft-grothoff-iesg-special-use-p2p-names/',
rfc6761='http://tools.ietf.org/html/rfc6761' -%}
We have <a href="{{ i2ptld }}">applied to reserve the .i2p TLD</a>
following the procedures specified in <a href="{{ rfc6761 }}">RFC 6761</a>.
{%- endtrans %}</p>
<p>{% trans -%}
If the router fails to resolve the hostname, the HTTP proxy returns
an error page to the user with links to several "jump" services.
See below for details.
{%- endtrans %}</p>
<h2 id="alt">.i2p.alt Domain</h2>
We previously <a href="https://datatracker.ietf.org/doc/draft-grothoff-iesg-special-use-p2p-names/">applied to reserve the .i2p TLD</a>
following the procedures specified in <a href="https://www.rfc-editor.org/rfc/rfc6761.html">RFC 6761</a>.
However, this application and all others were rejected, and RFC 6761 was declared a "mistake".
</p>
<p>
After many years of work by the GNUnet team and others, the .alt domain was reserved as a special-use TLD
in <a href="https://www.rfc-editor.org/rfc/rfc9476.html">RFC 9476</a> as of late 2023.
While there are no official registrars sanctioned by IANA, we have registered the .i2p.alt domain
with the primary unofficial registrar <a href="https://gana.gnunet.org/dot-alt/dot_alt.html">GANA</a>.
This does not prevent others from using the domain, but it should help discourage it.
</p>
<p>
One benefit to the .alt domain is that, in theory, DNS resolvers will not forward .alt requests
once they update to comply with RFC 9476, and that will prevent DNS leaks.
For compatibility with .i2p.alt hostnames, I2P software and services should be updated to handle
these hostnames by stripping off the .alt TLD.
These updates are scheduled for the first half of 2024.
</p>
<p>
At this time, there are no plans to make .i2p.alt the preferred form for display and interchange of I2P hostnames.
This is a topic for further research and discussion.
</p>
<h2 id="addressbook">{% trans %}Address Book{% endtrans %}</h2>
<h3>{% trans %}Incoming Subscriptions and Merging{% endtrans %}</h3>
@ -300,15 +279,7 @@ Base32 hostnames (*.b32.i2p) are reserved for base 32 use and so are not allowed
<li>{% trans -%}
Certain hostnames reserved for project use are not allowed
(proxy.i2p, router.i2p, console.i2p, mail.i2p, *.proxy.i2p, *.router.i2p, *.console.i2p, *.mail.i2p, and others)
{%- endtrans %}</li>
<li>{% trans -%}
Hostnames starting with 'www.' are discouraged and are rejected by some registration services.
Some addressbook implementations automatically strip 'www.' prefixes from lookups.
So registring 'www.example.i2p' is unnecessary,
and registering a different destination for 'www.example.i2p' and 'example.i2p'
will make 'www.example.i2p' unreachable for some users.
(proxy.i2p, router.i2p, console.i2p, *.proxy.i2p, *.router.i2p, *.console.i2p, and others)
{%- endtrans %}</li>
<li>{% trans -%}

View File

@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Ports Used by I2P{% endtrans %}{% endblock %}
{% block lastupdated %}2024-02{% endblock %}
{% block accuratefor %}0.9.62{% endblock %}
{% block lastupdated %}2022-08{% endblock %}
{% block accuratefor %}0.9.55{% endblock %}
{% block content %}
<p>{% trans -%}
@ -11,7 +11,7 @@ and some typical related applications.
{%- endtrans %}</p>
<p>{% trans faq=site_url('faq') -%}
Note that many of these are not installed or enabled by default.
Note that many of these are not enabled by default.
There is more information in <a href="{{ faq }}#ports">the FAQ</a>.
See also the documentation for individual plugins.
Plugin authors please add any ports you use here.
@ -22,8 +22,7 @@ in the 767x range.
<table>
<tr><th>Port</th><th>Usage</th></tr>
<tr><td>123</td><td>SNTP</td></tr>
<tr><td>1488</td><td>XD client web UI (old)</td>
<tr><td>1776</td><td>XD client web UI (new)</td>
<tr><td>1488</td><td>XD client web UI</td>
<tr><td>1900</td><td>UPnP SSDP UDP multicast listener</td>
<tr><td>2827</td><td>BOB Bridge</td></tr>
<tr><td>3456</td><td>Tahoe-LAFS-Controller Plugin</td></tr>
@ -35,7 +34,6 @@ in the 767x range.
<tr><td>6667</td><td>IRC Proxy (alt)</td></tr>
<tr><td>6668</td><td>IRC Proxy</td></tr>
<tr><td>6669</td><td>IRC Proxy (alt)</td></tr>
<tr><td>7070</td><td>i2pd console</td></tr>
<tr><td>7644</td><td>HTTP Proxy (I2P Browser mode)</td></tr>
<tr><td>7647</td><td>Console (I2P Browser mode)</td></tr>
<tr><td>7650</td><td>I2PControl Plugin</td></tr>
@ -46,7 +44,7 @@ in the 767x range.
<tr><td>7655</td><td>SAM Bridge (UDP)</td></tr>
<tr><td>7656</td><td>SAM Bridge (TCP)</td></tr>
<tr><td>7657</td><td>Router Console</td></tr>
<tr><td>7658</td><td>I2P Site (Jetty)</td></tr>
<tr><td>7658</td><td>I2P Site</td></tr>
<tr><td>7659</td><td>SMTP Proxy</td></tr>
<tr><td>7660</td><td>POP3 Proxy</td></tr>
<tr><td>7661</td><td>Pebble Plugin</td></tr>
@ -59,7 +57,6 @@ in the 767x range.
<tr><td>7668</td><td>I2P Site SSL</td></tr>
<tr><td>7669</td><td>Garlic Farm</td></tr>
<tr><td>7670</td><td>Git SSH</td></tr>
<tr><td>7672</td><td>Railroad Plugin</td></tr>
<tr><td></td><td><i>{% trans %}recommended spot for new plugins/applications{% endtrans %}</i></td></tr>
<tr><td>7680</td><td>don't use - Windows Delivery Optimization</td></tr>
<tr><td>8002</td><td>I2PSnark (standalone install only)</td></tr>

View File

@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}I2CP{% endblock %}
{% block lastupdated %}2025-04{% endblock %}
{% block accuratefor %}0.9.66{% endblock %}
{% block lastupdated %}2023-10{% endblock %}
{% block accuratefor %}0.9.59{% endblock %}
{% block content %}
<p>{% trans -%}
The I2P Client Protocol (I2CP) exposes a strong separation of concerns between
@ -63,15 +63,13 @@ through an internal JVM interface.
{%- endtrans %}</p>
<p>{% trans commonstructures=site_url('docs/spec/common-structures') -%}
Some router and client implementations may also support external connections over SSL,
as configured by the i2cp.SSL=true option.
The router also supports external connections over SSL.
While SSL is not the default, it is strongly recommended for any traffic that may
be exposed to the open Internet. The authorization user/password (if any), the
<a href="{{ commonstructures }}#type_PrivateKey">Private Key</a> and
<a href="{{ commonstructures }}#type_SigningPrivateKey">Signing Private Key</a> for the
<a href="{{ commonstructures }}#struct_Destination">Destination</a>
are all transmitted in-the-clear unless SSL is enabled.
Some router and client implementations may also support external connections over domain sockets.
{%- endtrans %}</p>
<h2>{% trans %}I2CP Protocol Specification{% endtrans %}</h2>
@ -729,7 +727,7 @@ See proposal 123.
<td>
The base 64 of the client name (ignored, UI use only),
followed by a ':', followed by the base 64 of the private
key to use for PSK per-client auth. nnn starts with 0.
key to use for PSK per-client auth. nnn starts with 0
See proposal 123.
</td>
</tr>
@ -760,21 +758,6 @@ See proposals 123, 144, and 145.
<td>{% trans %}For encrypted leasesets. Base 64 SessionKey (44 characters){% endtrans %}</td>
</tr>
<tr>
<td>i2cp.leaseSetOption.nnn
<td>0.9.66</td>
<td>srvKey=srvValue
<td>&nbsp;
<td>&nbsp;
<td>
A service record to be placed in the LeaseSet2 options.
Example:
"_smtp._tcp=1 86400 0 0 25 ...b32.i2p"
nnn starts with 0.
See proposal 167.
</td>
</tr>
<tr>
<td>i2cp.leaseSetPrivateKey
<td>0.9.18</td>

View File

@ -1,7 +1,7 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Protocol Stack{% endtrans %}{% endblock %}
{% block lastupdated %}2024-01{% endblock %}
{% block accuratefor %}0.9.61{% endblock %}
{% block lastupdated %}2021-12{% endblock %}
{% block accuratefor %}0.9.52{% endblock %}
{% block content %}
<p>{% trans docs=site_url('docs') -%}
@ -86,7 +86,8 @@ However, each of these layers adds additional functionality, to allow applicatio
<br />
<a href="{{ site_url('docs/api/i2ptunnel') }}">I2PTunnel</a>
<br />
<a href="{{ site_url('docs/api/samv3') }}">SAMv3</a>
<a href="{{ site_url('docs/api/sam') }}">SAM</a>/<a href="{{ site_url('docs/api/samv2') }}">SAMv2</a>/<a href="{{ site_url('docs/api/samv3') }}">SAMv3</a>(*),
<a href="{{ site_url('docs/api/bob') }}">BOB</a>
</li>
<li>
{% trans %}<b>I2P Application Proxy Layer:</b> proxy systems.{% endtrans %}

View File

@ -1,18 +1,12 @@
{% extends "global/layout.html" %}
{% block title %}{% trans %}Secure Semireliable UDP{% endtrans %} (SSU){% endblock %}
{% block lastupdated %}2025-01{% endblock %}
{% block accuratefor %}0.9.64{% endblock %}
{% block lastupdated %}2022-07{% endblock %}
{% block accuratefor %}0.9.54{% endblock %}
{% block content %}
<p>
<b>DEPRECATED</b> - SSU has been replaced by SSU2.
SSU support was removed from i2pd in release 2.44.0 (API 0.9.56) 2022-11.
SSU support was removed from Java I2P in release 2.4.0 (API 0.9.61) 2023-12.
</p>
<p>{% trans transports=site_url('docs/transport'), ntcp=site_url('docs/transport/ntcp'), ntcp2=site_url('docs/spec/ntcp2') -%}
SSU (also called "UDP" in much of the I2P documentation and user interfaces)
was one of two <a href="{{ transports }}">transports</a> implemented in I2P.
is one of two <a href="{{ transports }}">transports</a> currently implemented in I2P.
The other is <a href="{{ ntcp2 }}">NTCP2</a>.
Support for <a href="{{ ntcp }}">NTCP</a> has been removed.
{%- endtrans %}</p>

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_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>
<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>
</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

@ -1,6 +1,6 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Developer Guidelines and Coding Style') }}{% endblock %}
{% block lastupdated %}2025-03{% endblock %}
{% block lastupdated %}2022-01{% endblock %}
{% block content %}
<p>{% trans newdevs=site_url('get-involved/guides/new-developers') -%}
Read the <a href="{{ newdevs }}">new developers guide</a> first.
@ -34,8 +34,8 @@ the checkin deadline for a release.
<h3>{{ _('Release Cycle') }}</h3>
<p>
The normal release cycle is 10-16 weeks, four releases a year.
Following are the approximate deadlines within a typical 13-week cycle.
The normal release cycle is 6-12 weeks.
Following are the approximate deadlines within a typical 8-week cycle.
Actual deadlines for each release are set by the release manager after consultation with the full team.
</p>
@ -87,8 +87,8 @@ Check in some small changes and see how it goes.
<li>{% trans -%}
Test your changes before checking them in.
If you prefer the checkin-before-test development model,
use your own development branch in your own account,
and create an MR once the work is done.
use your own development branch
and propagate back to i2p.i2p once it is working well.
Do not break the build. Do not cause regressions.
In case you do (it happens), please do not vanish for a long period after
you push your change.
@ -99,30 +99,17 @@ to know whether your change was tested or not, add a checkin comment to history.
and increment the build revision in RouterVersion.java.
{%- endtrans %}</li>
<li>{% trans -%}
Do not check in major changes into the main i2p.i2p branch late in the release cycle.
If a project will take you more than a couple days, create your own branch in git,
in your own account, and do the development there so you do not block releases.
Ensure that you 'git pull' to the latest revision before you check in and push.
If you inadvertently diverge, merge and push as soon as possible.
Don't routinely make others merge for you.
{%- endtrans %}</li>
<li>{% trans -%}
Do not check in major changes into the main i2p.i2p branch late in the release cycle.
If a project will take you more than a couple days, create your own branch in git
and do the development there so you do not block releases.
{%- endtrans %}</li>
<li>
For big changes (generally speaking, more than 100 lines, or touching more than three files),
check it into a new branch on your own gitlab account, create an MR, and assign a reviewer.
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_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>
<li>
Do development in a transparent fashion and with the community in mind.
Checkin often. Checkin or merge into the main branch
as frequently as possible, given the guidelines above.
If you are working on some big project in your own branch/account,
let people know so they may follow along and review/test/comment.
</li>
</ul>
<h3>{{ _('Coding Style') }}</h3>
<ul>
<li>{% trans -%}
@ -290,7 +277,7 @@ Include the license and source information in the checkin comment.
<h3>{{ _('Bugs') }}</h3>
<ul>
<li>{% trans trac=i2pconv('git.idk.i2p') -%}
<li>{% trans trac=i2pconv('trac.i2p2.i2p') -%}
Managing issues are everybody's job, please help.
Monitor {{ Gitlab }} for issues you can help with.
Comment on, fix, and close issues if you can.

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_Developers/i2p.i2p.git</code>
<code>git clone https://i2pgit.org/i2p-hackers/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_Developers/i2p.i2p/issues' -%}
<p>{% trans todo=site_url('get-involved/todo'), trac='https://i2pgit.org/i2p-hackers/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

@ -26,6 +26,16 @@ Optional:
<li>IPv6</li>
</ul>
<p>{% trans -%}
When your setup is complete and ready for testing, we will need the HTTPS URL,
the SSL public key certificate (only if selfsigned), and the su3 public key certificate.
After testing is complete, these will be added to the hardcoded entries in the Java and C++ routers in the next release,
and you will start seeing traffic.
We also will need your email address so we may continue to contact you about reseed administration issues.
The email will not be made public but will be known to the other reseed operators.
You should expect that your nick or name and its association with that URL or IP will become public.
{%- endtrans %}</p>
<h3>{% trans %}Information Required{% endtrans %}</h3>
<p>{% trans -%}

View File

@ -1,6 +1,6 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('How to Set up a Reseed Server') }}{% endblock %}
{% block lastupdated %}2024-12{% endblock %}
{% block lastupdated %}2023-01{% endblock %}
{% block content %}
<h2>{% trans %}General Information{% endtrans %}</h2>
@ -140,11 +140,11 @@ zzz.i2p
. {% trans %}These will allow I2P users to authenticate your reseed services and secure the I2P network.{% endtrans %}
</p>
<p>
Contact us via email zzz at mail.i2p.
Provide us with details about your new reseed server:
{% trans %}Contact us via email zzz at mail.i2p (alternatively, post in the reseed section on the zzz.i2p forum)
Provide us with details about your new reseed server:{% endtrans %}
<ul>
<li>{% trans %}Reseed website URL{% endtrans %}</li>
<li>Public SSL certificate (only required if selfsigned)</li>
<li>{% trans %}Public SSL certificate{% endtrans %}</li>
<li>{% trans %}Public reseed su3 certificate{% endtrans %}</li>
<li>{% trans %}Your contact email{% endtrans %}</li>
<li>{% trans %}A statement that you agree to the privacy policy above{% endtrans %}</li>

View File

@ -1,6 +1,6 @@
{% extends "global/layout.html" %}
{% block title %} {{ _('Roadmap') }}{% endblock %}
{% block lastupdated %}2025-04{% endblock %} {% block content %}
{% block lastupdated %}2022-11{% 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.
@ -9,386 +9,40 @@
For details and discussion on specific items, search on gitlab or zzz.i2p. For contents of past releases, see the release notes. For other project goals, see the meeting notes.
</p>
<p>
We do not maintain separate unstable and stable branches or releases. We have a single, stable release path. Our typical release cycle is about 13 weeks.
We do not maintain separate unstable and stable branches or releases. We have a single, stable release path. Our normal release cycle is 13 weeks, with releases in February, May, August, and November.
</p>
<p>
Older releases are at the bottom of the page.
</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.4.0">2.4.0 (API 0.9.60)</h2>
<p><b>Target release: September 2023</b></p>
<ul>
<li>
UDP tracker support (prop. 160)
NetDB context management
</li>
<li>
Implement LS service record parameter (prop. 167)
</li>
<li>
Continue work on PQ (prop. 169);
Start checking in MLKEM parts of PQ (prop. 169)
</li>
<li>
Tunnel build bandwidth parameters (prop. 168)
Part 2 (handling)
</li>
<li>
Continue work on per-tunnel throttling
</li>
<li>
Stat/graph subsystem cleanup and make prometheus-friendly
</li>
<li>
Tomcat update
</li>
</ul>
<h2 id="2.9.0">2.9.0 (API 0.9.66)</h2>
<p><b>Released: June 2, 2025</b></p>
<ul>
<li>
Netdb map
</li>
<li>
Implement Datagram2, Datagram3 (prop. 163)
</li>
<li>
Start work on LS service record parameter (prop. 167)
</li>
<li>
Start work on PQ (prop. 169)
</li>
<li>
Continue work on per-tunnel throttling
</li>
<li>
Tunnel build bandwidth parameters (prop. 168)
Part 1 (sending)
</li>
<li>
Use /dev/random for PRNG by default on Linux
</li>
<li>
Remove redundant LS render code
</li>
<li>
Display changelog in HTML
</li>
<li>
Reduce HTTP server thread usage
</li>
<li>
Fix auto-floodfill enrollment
</li>
<li>
Wrapper update to 3.5.60
</li>
</ul>
<h2 id="2.8.2">2.8.2 (API 0.9.65)</h2>
<p><b>Released: March 29, 2025</b></p>
<ul>
<li>
Fix SHA256 corruption bug
</li>
</ul>
<h2 id="2.8.1">2.8.1 (API 0.9.65)</h2>
<p><b>Released: March 17, 2025</b></p>
<ul>
<li>
Fix installer failure on Java 21+
</li>
<li>
Fix "loopback" bug
</li>
<li>
Fix tunnel tests for outbound client tunnels
</li>
<li>
Fix installing to paths with spaces
</li>
<li>
Update outdated Docker container and container libraries
</li>
<li>
Console notification bubbles
</li>
<li>
SusiDNS sort-by-latest
</li>
<li>
Use SHA256 pool in Noise
</li>
<li>
Console dark theme fixes and improvements
</li>
<li>
.i2p.alt support
</li>
</ul>
<h2 id="2.8.0">2.8.0 (API 0.9.65)</h2>
<p><b>Released: February 3, 2025</b></p>
<ul>
<li>
RouterInfo publishing improvements
</li>
<li>
Improve SSU2 ACK efficiency
</li>
<li>
Improve SSU2 handling of dup relay messages
</li>
<li>
Faster / variable lookup timeouts
</li>
<li>
LS expiration improvements
</li>
<li>
Change symmetric NAT cap
</li>
<li>
Enforce POST in more forms
</li>
<li>
SusiDNS dark theme fixes
</li>
<li>
Bandwidth test cleanups
</li>
<li>
New Gan Chinese translation
</li>
<li>
Add Kurdish option to UI
</li>
<li>
New Jammy build to handle Jetty API change
</li>
<li>
Izpack 5.2.3
</li>
<li>
rrd4j 3.10
</li>
</ul>
<h2 id="2.7.0">2.7.0 (API 0.9.64)</h2>
<p><b>Released: October 8, 2024</b></p>
<ul>
<li>
i2ptunnel HTTP server reduce thread usage
</li>
<li>
Generic UDP Tunnels in I2PTunnel
</li>
<li>
Browser Proxy in I2PTunnel(Proposal 166)
</li>
<li>
Website Migration
</li>
<li>
Fix for tunnels going yellow
</li>
<li>
Console /netdb refactoring
</li>
</ul>
<h2 id="2.6.1">2.6.1 (API 0.9.63)</h2>
<p><b>Released: August 6, 2024</b></p>
<ul>
<li>
Fix iframe size issues in console
</li>
<li>
Convert graphs to SVG
</li>
<li>
Bundle translation status report in console
</li>
</ul>
<h2 id="2.6.0">2.6.0 (API 0.9.63)</h2>
<p><b>Released: July 19, 2024</b></p>
<ul>
<li>
Reduce memory usage for netdb
</li>
<li>
Continue removing SSU1 code
</li>
<li>
Fix i2psnark temp file leaks and stalls
</li>
<li>
More efficient PEX in i2psnark
</li>
<li>
JS refresh of graphs in console
</li>
<li>
Graph rendering improvements
</li>
<li>
Susimail JS search
</li>
<li>
More efficient handling of messages at OBEP
</li>
<li>
More efficient lookup of local destinations in I2CP
</li>
<li>
Fix JS variable scoping issues and concurrency
</li>
</ul>
<h2 id="2.5.2">2.5.2 (API 0.9.62)</h2>
<p><b>Released: May 15, 2024</b></p>
<ul>
<li>
HTTP truncation fix
</li>
<li>
Publish G cap if symmetric natted
</li>
<li>
rrd4j 3.9.1-preview
</li>
</ul>
<h2 id="2.5.1">2.5.1 (API 0.9.62)</h2>
<p><b>Released: May 6, 2024</b></p>
<ul>
<li>
NetDB DDoS mitigations
</li>
<li>
Add Tor blocklist
</li>
<li>
susimail fixes
</li>
<li>
susimail search
</li>
<li>
Continue removing SSU1 code
</li>
<li>
Tomcat 9.0.88
</li>
</ul>
<h2 id="2.5.0">2.5.0 (API 0.9.62)</h2>
<p><b>Released: April 8, 2024</b></p>
<ul>
<li>
Console iframe improvements
</li>
<li>
Redesign i2psnark bandwidth limiter
</li>
<li>
Javascript drag-and-drop for i2psnark and susimail
</li>
<li>
i2ptunnel SSL error handling improvements
</li>
<li>
i2ptunnel persistent HTTP connection support
</li>
<li>
Start removing SSU1 code
</li>
<li>
SSU2 relay tag request handling improvements
</li>
<li>
SSU2 peer test fixes
</li>
<li>
susimail initial loading speedup
</li>
<li>
susimail javascript markdown for plain text emails
</li>
<li>
susimail HTML email support
</li>
<li>
susimail fixes and improvements
</li>
<li>
tunnnel peer selection adjustments
</li>
<li>
Update RRD4J to 3.9
</li>
<li>
Update gradlew to 8.5
</li>
</ul>
<h2 id="2.4.0">2.4.0 (API 0.9.61)</h2>
<p><b>Released: December 18, 2023</b></p>
<ul>
<li>
NetDB context management/Segmented NetDB
Streaming replay fix
</li>
<li>
Handle congestion capabilities by deprioritizing overloaded routers
</li>
<li>
"Install Plugin from File" command-line option
</li>
<li>
Generic UDP Tunnels in HSM
</li>
<li>
Revive Android helper library
</li>
<li>
i2psnark local torrent file selector
</li>
<li>
NetDB lookup handler fixes
</li>
<li>
Disable SSU1
</li>
<li>
Ban routers publishing in the future
</li>
<li>
SAM fixes
</li>
<li>
susimail fixes
</li>
<li>
UPnP fixes
Website Migration
</li>
</ul>
<h2 id="2.3.0">2.3.0 (API 0.9.59)</h2>
<p><b>Released: June 28, 2023</b></p>
<p><b>Target release: June 2023</b></p>
<ul>
<li>
Tunnel peer selection improvements
@ -410,16 +64,8 @@
</li>
</ul>
<h2 id="2.2.1">2.2.1 (API 0.9.58)</h2>
<p><b>Released: April 12, 2023</b></p>
<ul>
<li>
Packaging fixes
</li>
</ul>
<h2 id="2.2.0">2.2.0 (API 0.9.58)</h2>
<p><b>Released: March 13, 2023</b></p>
<p><b>Target release: April 2023</b></p>
<ul>
<li>
Tunnel peer selection improvements

View File

@ -1,12 +1,14 @@
{% extends "global/layout.html" %}
{% block title %}{{ _('Vulnerability Response Process') }}{% endblock %}
{% block lastupdated %}2023-04{% endblock %}
{% block lastupdated %}2020-06{% endblock %}
{% block content_id %}vrp{% endblock %}
{% block content %}
<p>{% trans %}
This process is subject to change. Please refer to this page for the current VRP.
{%- endtrans %}</p>
<p>{% trans %}This page was last updated April 2023.{%- endtrans %}</p>
<p>{% trans %}Researchers: during your study and network testing, we ask that you refrain from the following: - Performing active exploits or Denial of Service attacks on the
I2P network - Performing social engineering on I2P team and community members - Performing any physical or electronic attempts against I2P property and/or data
centers{%- endtrans %}</p>

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_Developers/i2p.www/issues' -%}
<p>{% trans trac='https://i2pgit.org/i2p-hackers/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>.
@ -55,6 +55,7 @@ If you find any inaccuracies in the documents linked below, please
Current specifications: These may eventually be migrated to the new format.
<ul>
<li><a href="{{ site_url('docs/how/elgamal-aes') }}">{{ _('ElGamal/AES+SessionTags') }}</a></li>
<li><a href="{{ site_url('docs/api/i2pcontrol') }}">I2PControl</a></li>
<li><a href="{{ site_url('docs/api/samv3') }}">SAM v3</a></li>
<li><a href="{{ site_url('docs/applications/bittorrent') }}">{{ _('Bittorrent') }}</a></li>
@ -64,14 +65,8 @@ Current specifications: These may eventually be migrated to the new format.
Obsolete specifications:
<ul>
<li><a href="{{ site_url('docs/transport/ntcp') }}">NTCP</a></li>
<li><a href="{{ site_url('docs/api/bob') }}">BOB</a></li>
<li><a href="{{ site_url('docs/how/elgamal-aes') }}">{{ _('ElGamal/AES+SessionTags') }}</a></li>
<li><a href="{{ site_url('docs/transport/ntcp') }}">NTCP 1</a></li>
<li><a href="{{ site_url('docs/api/sam') }}">SAM v1</a></li>
<li><a href="{{ site_url('docs/api/samv2') }}">SAM v2</a></li>
<li><a href="{{ site_url('docs/transport/ssu') }}">SSU 1 (overview)</a></li>
<li><a href="{{ spec_url('ssu') }}">SSU 1 (spec)</a></li>
<li><a href="{{ spec_url('tunnel-creation') }}">Tunnel Creation (ElGamal)</a></li>
</ul>
{% endblock %}

View File

@ -3,8 +3,8 @@ Common structures Specification
===============================
.. meta::
:category: Design
:lastupdated: 2025-06
:accuratefor: 0.9.67
:lastupdated: 2023-01
:accuratefor: 0.9.57
.. contents::
@ -84,24 +84,15 @@ 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]_
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
================ ================= ====== =====
======= ============== ====== =====
Type Length (bytes) Since Usage
======= ============== ====== =====
ElGamal 256 All Router Identities and Destinations
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]_
======= ============== ====== =====
JavaDoc: http://{{ i2pconv('idk.i2p/javadoc-i2p') }}/net/i2p/data/PublicKey.html
@ -125,21 +116,15 @@ 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]_
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
================ ================== ====== =====
======= ============== ====== =====
Type Length (bytes) Since Usage
======= ============== ====== =====
ElGamal 256 All Router Identities and Destinations
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]_
======= ============== ====== =====
JavaDoc: http://{{ i2pconv('idk.i2p/javadoc-i2p') }}/net/i2p/data/PrivateKey.html
@ -176,12 +161,12 @@ Certificate of a Destination. The default type is DSA_SHA1. As of release
====================== ============== ====== =====
Type Length (bytes) Since Usage
====================== ============== ====== =====
DSA_SHA1 128 Deprecated for Router Identities as of 09.58; discouraged for Destinations
ECDSA_SHA256_P256 64 0.9.12 Deprecated Older Destinations
ECDSA_SHA384_P384 96 0.9.12 Deprecated Rarely used for Destinations
ECDSA_SHA512_P521 132 0.9.12 Deprecated Rarely used for Destinations
RSA_SHA256_2048 256 0.9.12 Deprecated Offline signing, never used for Router Identities or Destinations
RSA_SHA384_3072 384 0.9.12 Deprecated Offline signing, never used for Router Identities or Destinations
DSA_SHA1 128 Legacy Router Identities and Destinations
ECDSA_SHA256_P256 64 0.9.12 Recent Destinations
ECDSA_SHA384_P384 96 0.9.12 Rarely used for Destinations
ECDSA_SHA512_P521 132 0.9.12 Rarely used for Destinations
RSA_SHA256_2048 256 0.9.12 Offline signing, never used for Router Identities or Destinations
RSA_SHA384_3072 384 0.9.12 Offline signing, never used for Router Identities or Destinations
RSA_SHA512_4096 512 0.9.12 Offline signing, never used for Router Identities or Destinations
EdDSA_SHA512_Ed25519 32 0.9.15 Recent Router Identities and Destinations
EdDSA_SHA512_Ed25519ph 32 0.9.25 Offline signing, never used for Router Identities or Destinations
@ -216,12 +201,12 @@ As of release 0.9.12, other types may be supported, depending on context.
====================== ============== ====== =====
Type Length (bytes) Since Usage
====================== ============== ====== =====
DSA_SHA1 20 Deprecated for Router Identities as of 09.58; discouraged for Destinations
ECDSA_SHA256_P256 32 0.9.12 Deprecated Older Destinations
ECDSA_SHA384_P384 48 0.9.12 Deprecated Rarely used for Destinations
ECDSA_SHA512_P521 66 0.9.12 Deprecated Rarely used for Destinations
RSA_SHA256_2048 512 0.9.12 Deprecated Offline signing, never used for Router Identities or Destinations
RSA_SHA384_3072 768 0.9.12 Deprecated Offline signing, never used for Router Identities or Destinations
DSA_SHA1 20 Legacy Router Identities and Destinations
ECDSA_SHA256_P256 32 0.9.12 Recent Destinations
ECDSA_SHA384_P384 48 0.9.12 Rarely used for Destinations
ECDSA_SHA512_P521 66 0.9.12 Rarely used for Destinations
RSA_SHA256_2048 512 0.9.12 Offline signing, never used for Router Identities or Destinations
RSA_SHA384_3072 768 0.9.12 Offline signing, never used for Router Identities or Destinations
RSA_SHA512_4096 1024 0.9.12 Offline signing, never used for Router Identities or Destinations
EdDSA_SHA512_Ed25519 32 0.9.15 Recent Router Identities and Destinations
EdDSA_SHA512_Ed25519ph 32 0.9.25 Offline signing, never used for Router Identities or Destinations
@ -257,12 +242,12 @@ depending on context.
====================== ============== ====== =====
Type Length (bytes) Since Usage
====================== ============== ====== =====
DSA_SHA1 40 Deprecated for Router Identities as of 09.58; discouraged for Destinations
ECDSA_SHA256_P256 64 0.9.12 Deprecated Older Destinations
ECDSA_SHA384_P384 96 0.9.12 Deprecated Rarely used for Destinations
ECDSA_SHA512_P521 132 0.9.12 Deprecated Rarely used for Destinations
RSA_SHA256_2048 256 0.9.12 Deprecated Offline signing, never used for Router Identities or Destinations
RSA_SHA384_3072 384 0.9.12 Deprecated Offline signing, never used for Router Identities or Destinations
DSA_SHA1 40 Legacy Router Identities and Destinations
ECDSA_SHA256_P256 64 0.9.12 Recent Destinations
ECDSA_SHA384_P384 96 0.9.12 Rarely used for Destinations
ECDSA_SHA512_P521 132 0.9.12 Rarely used for Destinations
RSA_SHA256_2048 256 0.9.12 Offline signing, never used for Router Identities or Destinations
RSA_SHA384_3072 384 0.9.12 Offline signing, never used for Router Identities or Destinations
RSA_SHA512_4096 512 0.9.12 Offline signing, never used for Router Identities or Destinations
EdDSA_SHA512_Ed25519 64 0.9.15 Recent Router Identities and Destinations
EdDSA_SHA512_Ed25519ph 64 0.9.25 Offline signing, never used for Router Identities or Destinations
@ -372,9 +357,8 @@ specifying the size of the certificate payload, then that many bytes.
Notes
`````
* For `Router Identities`_, the Certificate is always NULL through version
0.9.15. As of 0.9.16, a Key Certificate is used to specify the
key types. As of 0.9.48, X25519 encryption public key types
are allowed. See below.
0.9.15. As of 0.9.16, a Key Certificate may be used to specify the signing
public key type. See below.
* For `Garlic Cloves`_, the Certificate is always NULL, no others are currently
implemented.
@ -401,11 +385,11 @@ The following certificate types are defined:
Type Type Code Payload Length Total Length Notes
======== ========= ============== ============ =====
Null 0 0 3
HashCash 1 varies varies Deprecated, unused. Payload contains an ASCII colon-separated hashcash string.
Hidden 2 0 3 Deprecated, unused. Hidden routers generally do not announce that they are hidden.
Signed 3 40 or 72 43 or 75 Deprecated, unused. Payload contains a 40-byte DSA signature,
HashCash 1 varies varies Experimental, unused. Payload contains an ASCII colon-separated hashcash string.
Hidden 2 0 3 Experimental, unused. Hidden routers generally do not announce that they are hidden.
Signed 3 40 or 72 43 or 75 Experimental, unused. Payload contains a 40-byte DSA signature,
optionally followed by the 32-byte Hash of the signing Destination.
Multiple 4 varies varies Deprecated, unused. Payload contains multiple certificates.
Multiple 4 varies varies Experimental, unused. Payload contains multiple certificates.
Key 5 4+ 7+ Since 0.9.12. See below for details.
======== ========= ============== ============ =====
@ -433,57 +417,40 @@ Excess Signing Public Key Data 0+
Excess Crypto Public Key Data 0+
================================== ======
Warning: The key type order is the opposite of what you may expect;
the Signing Public Key Type is first.
The defined Signing Public Key types are:
====================== =========== ======================= ====== =====
Type Type Code Total Public Key Length Since Usage
====================== =========== ======================= ====== =====
DSA_SHA1 0 128 0.9.12 Deprecated for Router Identities as of 0.9.58; discouraged for Destinations
ECDSA_SHA256_P256 1 64 0.9.12 Deprecated Older Destinations
ECDSA_SHA384_P384 2 96 0.9.12 Deprecated Rarely if ever used for Destinations
ECDSA_SHA512_P521 3 132 0.9.12 Deprecated Rarely if ever used for Destinations
RSA_SHA256_2048 4 256 0.9.12 Deprecated Offline only; never used in Key Certificates for Router Identities or Destinations
RSA_SHA384_3072 5 384 0.9.12 Deprecated Offline only; never used in Key Certificates for Router Identities or Destinations
DSA_SHA1 0 128 0.9.12 Legacy Router Identities and Destinations, never explicitly set
ECDSA_SHA256_P256 1 64 0.9.12 Older Destinations
ECDSA_SHA384_P384 2 96 0.9.12 Rarely if ever used for Destinations
ECDSA_SHA512_P521 3 132 0.9.12 Rarely if ever used for Destinations
RSA_SHA256_2048 4 256 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations
RSA_SHA384_3072 5 384 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations
RSA_SHA512_4096 6 512 0.9.12 Offline only; never used in Key Certificates for Router Identities or Destinations
EdDSA_SHA512_Ed25519 7 32 0.9.15 Recent Router Identities and Destinations
EdDSA_SHA512_Ed25519ph 8 32 0.9.25 Offline only; never used in Key Certificates for Router Identities or Destinations
reserved (GOST) 9 64 Reserved, see [Prop134]_
reserved (GOST) 10 128 Reserved, see [Prop134]_
reserved (GOST) 9 64 Reserved, see proposal 134
reserved (GOST) 10 128 Reserved, see proposal 134
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 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
================ =========== ======================= ====== =====
======== =========== ======================= =====
Type Type Code Total Public Key Length Usage
======== =========== ======================= =====
ElGamal 0 256 All Router Identities and Destinations
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
======== =========== ======================= =====
When a Key Certificate is not present, the preceeding 384 bytes in the
Destination or RouterIdentity are defined as the 256-byte ElGamal PublicKey
@ -531,11 +498,6 @@ Notes
* Implementers are cautioned to prohibit excess data in Key Certificates.
The appropriate length for each certificate type should be enforced.
* A KEY certificate with types 0,0 (ElGamal,DSA_SHA1) is allowed but discouraged.
It is not well-tested and may cause issues in some implementations.
Use a NULL certificate in the canonical representation of a
(ElGamal,DSA_SHA1) Destination or RouterIdentity, which will be 4 bytes shorter
than using a KEY certificate.
.. _type-Mapping:
@ -549,12 +511,7 @@ A set of key/value mappings or properties
Contents
````````
A 2-byte size Integer followed by a series of String=String; pairs.
WARNING: Most uses of Mapping are in signed structures, where the
Mapping entries must be sorted by key, so the signature is immutable.
Failure to sort by key will result in signature failures!
A 2-byte size Integer followed by a series of String=String; pairs
.. raw:: html
@ -594,7 +551,7 @@ Notes
* The encoding allows duplicate keys, however in any usage where the mapping is
signed, duplicates may cause a signature failure.
* Mappings contained in I2NP messages (e.g. in a RouterAddress or RouterInfo)
* Mappings contained in I2NP messages (i.e. in a RouterAddress or RouterInfo)
must be sorted by key so that the signature will be invariant. Duplicate keys
are not allowed.
@ -666,10 +623,11 @@ A PublicKey_ followed by a SigningPublicKey_ and then a Certificate_.
padding :: random data
length -> 0 bytes or as specified in key certificate
public_key length + padding length + signing_key length == 384 bytes
padding length + signing_key length == 128 bytes
signing__key :: `SigningPublicKey` (partial or full)
length -> 128 bytes or as specified in key certificate
padding length + signing_key length == 128 bytes
certificate :: `Certificate`
length -> >= 3 bytes
@ -1180,13 +1138,6 @@ Notes
* Maximum actual expires time is about 660 (11 minutes) for
LeaseSet2_ and 65535 (the full 18.2 hours) for MetaLeaseSet_.
* LeaseSet_ (1) did not have a 'published' field, so versioning required
a search for the earliest lease. LeaseSet2 adds a 'published' field
with a resolution of one second. Routers should rate-limit sending
new leasesets to floodfills to a rate much slower than once a second (per destination).
If this is not implemented, then the code must ensure that each new leaseset
has a 'published' time at least one second later than the one before, or else
floodills will not store or flood the new leaseset.
.. _struct-LeaseSet2:
@ -1280,7 +1231,7 @@ by the Destination_'s SigningPrivateKey_ or the transient key.
length -> 2 bytes
encryption_key :: `PublicKey`
length -> keylen bytes
length -> 256 bytes
num :: `Integer`
length -> 1 byte
@ -1297,77 +1248,6 @@ by the Destination_'s SigningPrivateKey_ or the transient key.
{% endhighlight %}
Encryption Key Preference
`````````````````````````
For published (server) leasesets, the encryption keys are in order of server preference,
most-preferred first. If clients support more than one encryption type, it is recommended
that they honor the server preference and select the first supported type as the
encryption method to use to connect to the server.
Generally, the newer (higher-numbered) key types are more secure or efficient and
are preferred, so the keys should be listed in reverse order of key type.
However, clients may, implementation-dependent, select based on their preference instead,
or use some method to determine the "combined" preference. This may be useful as
a configuration option, or for debugging.
The key order in unpublished (client) leasesets effectively does not matter, because
connections will usually not be attempted to unpublished clients.
Unless this order is used to determine a combined preference, as described above.
Options
```````
As of API 0.9.66, a standard format for service record options
is defined. See proposal 167 for details.
Options other than service records, using a different format,
may be defined in the future.
LS2 options MUST be sorted by key, so the signature is invariant.
Service record options are defined as follows:
- serviceoption := optionkey optionvalue
- optionkey := _service._proto
- service := The symbolic name of the desired service. Must be lower case. Example: "smtp".
Allowed chars are [a-z0-9-] and must not start or end with a '-'.
Standard identifiers from [REGISTRY]_ or Linux /etc/services must be used if defined there.
- proto := The transport protocol of the desired service. Must be lower case, either "tcp" or "udp".
"tcp" means streaming and "udp" means repliable datagrams.
Protocol indicators for raw datagrams and datagram2 may be defined later.
Allowed chars are [a-z0-9-] and must not start or end with a '-'.
- optionvalue := self | srvrecord[,srvrecord]*
- self := "0" ttl port [appoptions]
- srvrecord := "1" ttl priority weight port target [appoptions]
- ttl := time to live, integer seconds. Positive integer. Example: "86400".
A minimum of 86400 (one day) is recommended, see Recommendations section below for details.
- priority := The priority of the target host, lower value means more preferred. Non-negative integer. Example: "0"
Only useful if more than one record, but required even if just one record.
- weight := A relative weight for records with the same priority. Higher value means more chance of getting picked. Non-negative integer. Example: "0"
Only useful if more than one record, but required even if just one record.
- port := The I2CP port on which the service is to be found. Non-negative integer. Example: "25"
Port 0 is supported but not recommended.
- target := The hostname or b32 of the destination providing the service. A valid hostname as in [NAMING]_. Must be lower case.
Example: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b32.i2p" or "example.i2p".
b32 is recommended unless the hostname is "well known", i.e. in official or default address books.
- appoptions := arbitrary text specific to the application, must not contain " " or ",". Encoding is UTF-8.
Examples:
In LS2 for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b32.i2p, pointing to one SMTP server:
"_smtp._tcp" "1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p"
In LS2 for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b32.i2p, pointing to two SMTP servers:
"_smtp._tcp" "1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p,86400 1 0 25 cccccccccccccccccccccccccccccccccccccccccccc.b32.i2p"
In LS2 for bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p, pointing to itself as a SMTP server:
"_smtp._tcp" "0 999999 25"
Notes
`````
* The public key of the destination was used for the old I2CP-to-I2CP
@ -1390,10 +1270,6 @@ Notes
* The key length is provided for each key, so that floodfills and clients
may parse the structure even if not all encryption types are known or supported.
* See note on the 'published' field in LeaseSet2Header_
* The options mapping, if the size is greater than one, must be sorted by key, so the signature is invariant.
JavaDoc: http://{{ i2pconv('idk.i2p/javadoc-i2p') }}/net/i2p/data/LeaseSet2.html
@ -1575,8 +1451,6 @@ Notes
destination, or the transient signing public key, if an offline signature
is included in the leaseset2 header.
* See note on the 'published' field in LeaseSet2Header_
JavaDoc: http://{{ i2pconv('idk.i2p/javadoc-i2p') }}/net/i2p/data/MetaLeaseSet.html
@ -1701,10 +1575,6 @@ Notes
* See proposal 123 for notes on using offline signatures
with encrypted leasesets.
* See note on the 'published' field in LeaseSet2Header_
(same issue, even though we do not use the LeaseSet2Header format here)
.. _EncryptedLeaseSet: {{ site_url('docs/spec/encryptedleaseset') }}
JavaDoc: http://{{ i2pconv('idk.i2p/javadoc-i2p') }}/net/i2p/data/EncryptedLeaseSet.html
@ -1909,9 +1779,6 @@ References
.. [ECIES]
{{ spec_url('ecies') }}
.. [ECIES-HYBRID]
{{ spec_url('ecies-hybrid') }}
.. [ECIES-ROUTERS]
{{ spec_url('ecies-routers') }}
@ -1930,21 +1797,9 @@ References
.. [I2NP]
{{ site_url('docs/protocol/i2np', True) }}
.. [NAMING]
{{ site_url('docs/naming', True) }}
.. [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
.. [SSU]
{{ site_url('docs/transport/ssu', True) }}

View File

@ -3,8 +3,8 @@ Low-level Cryptography Specification
====================================
.. meta::
:category: Design
:lastupdated: 2025-05
:accuratefor: 0.9.66
:lastupdated: 2020-09
:accuratefor: 0.9.47
.. contents::
@ -12,18 +12,6 @@ Low-level Cryptography Specification
Overview
========
NOTE: MOSTLY OBSOLETE -
See the following documents for current specifications:
- {{ spec_url('ecies') }}
- {{ spec_url('encryptedleaseset') }}
- {{ spec_url('ntcp2') }}
- {{ spec_url('red25519') }}
- {{ spec_url('ssu2') }}
- {{ spec_url('tunnel-creation-ecies') }}
This page specifies the low-level details of the cryptography in I2P.
There are several cryptographic algorithms in use within I2P.
@ -51,10 +39,11 @@ of ElGamal asymmetric encryption and AES symmetric encryption.
Newer protocols NTCP2 and ECIES-X25519-AEAD-Ratchet
use a combination of X25519 key exchange and ChaCha20/Poly1305 symmetric encryption.
- ECIES-X25519-AEAD-Ratchet has replaced ElGamal/AES+SessionTags.
- NTCP2 has replaced NTCP.
- SSU2 has replaced SSU.
- X25519 tunnel creation has replaced ElGamal tunnel creation.
- ECIES-X25519-AEAD-Ratchet design and implementation are complete,
and will replace ElGamal/AES+SessionTags in late 2020.
- SSU2, using X25519 and ChaCha20/Poly1305, is scheduled for design in late 2020
to replace SSU in 2021.
Asymmetric Encryption

View File

@ -3,8 +3,8 @@ Datagram Specification
======================
.. meta::
:category: Protocols
:lastupdated: 2025-04
:accuratefor: 0.9.66
:lastupdated: February 2019
:accuratefor: 0.9.39
.. contents::
@ -14,139 +14,11 @@ Overview
See [DATAGRAMS]_ for an overview of the Datagrams API.
The following types are defined. The standard protocol numbers
are listed, however any other protocol numbers may be used other than
the streaming protocol number (6), application-specific.
========= ======== ========== ============== ================== =====
Type Protocol Repliable? Authenticated? Replay Prevention? As Of
========= ======== ========== ============== ================== =====
Raw 18 no no no
Datagram1 17 yes yes no
Datagram2 19 yes yes yes 0.9.66
Datagram3 20 yes no no 0.9.66
========= ======== ========== ============== ================== =====
Support for Datagram2 and Datagram3 in various router and library implementations
is TBD. Check the documentation for those implementations.
Datagram Type Identification
----------------------------
The four datagram types do not share a common header with the protocol
version in the same place. Packets cannot be identified by type
based on their content. When using multiple types on the same session,
or a single type together with streaming, applications must use
protocol numbers and/or I2CP/SAM ports to route incoming packets to the
right place. Using standard protocol numbers will make this easier.
Leaving the protocol number unset (0 or PROTO_ANY), even for a datagram-only
application, is not recommended as it increases the chance of routing
errors and makes upgrades to a multi-protocol application harder.
Version fields in Datagram 2 and 3 are provided only as
an additional check for routing errors and future changes.
Application Design
------------------
All uses of datagrams are application-specific.
As authenticated datagrams carry substantial overhead,
a typical application uses both authenticated and non-authenticated datagrams.
A typical design is to send single authenticated datagram
containing a token from the client to the server.
The server replies with an unauthenticated datagram containing the same token.
Any subsequent communication, before token timeout, uses raw datagrams.
Applications send and receive datagrams using protocol and port numbers
via the I2CP API [I2CP]_ or SAMv3 [SAMv3]_.
Datagrams are, of course, unreliable. Applications must design for unreliable
delivery. Within I2P, delivery is reliable hop-to-hop
if the next hop is reachable, as the NTCP2 and SSU2
transports provide reliablity. However, end-to-end delivery is
not reliable, as I2NP messages may be dropped within any hop due
to queue limits, expirations, timeouts, bandwidth limits,
or unreachable next-hops.
Datagram Size
-------------
The nominal size limit for I2NP messages, including datagrams, is 64 KB.
Garlic and tunnel message overhead reduce somewhat.
However, all I2NP messages must be fragmented into 1 KB tunnel messages.
The drop probability of a n KB I2NP message is the exponential function of
the drop probability of a single tunnel message, p ** n.
As fragmentation results in a burst of tunnel messages,
actual drop probability is much higher than the exponential
function would imply, due to queue limits and active queue management
(AQM, CoDel or similar) in router implementations.
Recommended typical max size to ensure reliable delivery is a few KB,
or at the most 10 KB.
With careful analysis of overhead sizes at all protocol layers (except transport),
developers should set a max payload size
that will fit precisely in one, two, or three tunnel messages.
This will maximize efficiency and reliability.
Overhead at various layers includes the gzip header,
I2NP header, garlic message header, garlic encryption,
tunnel message header, tunnel message fragmentation headers,
and others.
See streaming MTU calculations in Proposal 144 [Prop144]_
and ConnectionOptions.java in the Java I2P source for examples.
SAM Considerations
------------------
Applications send and receive datagrams using protocol and port numbers
via the I2CP API or SAM. Specifying protocol and port numbers
via SAM requires SAM v3.2 or higher.
Using both datagrams and streaming (UDP and TCP) on the same SAM session (tunnels)
requires SAM v3.3 or higher.
Using multiple datagram types on the same SAM session (tunnels)
requires SAM v3.3 or higher.
SAM v3.3 is only supported by the Java I2P router at this time.
SAM support for Datagram2 and Datagram3 in various router and library implementations
is TBD. Check the documentation for those implementations.
Note that sizes over a typical 1500 byte network MTU will prohibit
SAM applications from transporting unfragmented packets to/from
the SAM server, if the application and server are on separate computers.
Typically, this is not the case, they are both on localhost,
where the MTU is 65536 or higher.
If a SAM application is expected to be separated on a different
computer from the server, max payload for a repliable datagram is
slightly under 1 KB.
PQ Considerations
-----------------
If the MLDSA portion of the Post-Quantum proposal [Prop169]_ is implemented,
overhead will increase substantially.
The size of a destination + signature will increase from 391 + 64 = 455 bytes
to a minimum of 3739 for MLDSA44 and a maximum of 7226 for MLDSA87.
The practical effects of this are to be determined.
Datagram3, with authentication provided by the router, may be a solution.
.. _raw:
Raw (Non-Repliable) Datagrams
=============================
Non-Repliable Datagrams
=======================
Non-repliable datagrams have no 'from' address and are not authenticated. They
are also called "raw" datagrams. Strictly speaking, they are not "datagrams"
@ -155,10 +27,6 @@ However, SAM and the I2PTunnel classes support "raw datagrams".
The standard I2CP protocol number for raw datagrams is PROTO_DATAGRAM_RAW (18).
The format is not specified here, it is defined by the application.
For completeness, we include a picture of the format below.
Format
------
@ -169,22 +37,22 @@ Format
| payload...
+----+----+----+----+----//
length: 0 - about 64 KB (see notes)
length: 0 - unlimited (see notes)
{% endhighlight %}
Notes
-----
The practical length is limited by both overhead at various layers and reliability.
The practical length is limited by lower layers of protocols - the tunnel
message spec [TUNMSG]_ limits messages to about 61.2 KB and the transports
[TRANSPORT]_ currently limit messages to about 32 KB, although this may be
raised in the future.
.. _repliable:
Datagram1 (Repliable)
=====================
Repliable Datagrams
===================
Repliable datagrams contain a 'from' address and a signature. These add at
least 427 bytes of overhead.
@ -236,7 +104,7 @@ Format
The signature may be verified by the signing public key of $from
payload :: The data
Length: 0 to about 63 KB (see notes)
Length: 0 to ~31.5 KB (see notes)
Total length: Payload length + 427+
{% endhighlight %}
@ -244,7 +112,9 @@ Format
Notes
-----
* The practical length is limited by both overhead at various layers and reliability.
* The practical length is limited by lower layers of protocols - the transports
[TRANSPORT]_ currently limit messages to about 32 KB, so the data length here
is limited to about 31.5 KB.
* See important notes about the reliability of large datagrams [DATAGRAMS]_. For
best results, limit the payload to about 10 KB or less.
@ -255,241 +125,12 @@ Notes
for LS2 (proposal 123). A new protocol with flags must be defined for that.
.. _datagram2:
Datagram2
=========
The Datagram2 format is as specified in Proposal 163 [Prop163]_.
The I2CP protocol number for Datagram2 is 19.
Datagram2 is intended as a replacement for Datagram1.
It adds the following features to Datagram1:
- Replay prevention
- Offline signature support
- Flags and options fields for extensibility
Note that the signature calculation algorithm for Datagram2
is substantially different than for Datagram1.
Format
------
.. raw:: html
{% highlight lang='dataspec' -%}
+----+----+----+----+----+----+----+----+
| |
~ from ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| flags | options (optional) |
+----+----+ +
~ ~
~ ~
+----+----+----+----+----+----+----+----+
| |
~ offline_signature (optional) ~
~ expires, sigtype, pubkey, offsig ~
| |
+----+----+----+----+----+----+----+----+
| |
~ payload ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| |
~ signature ~
~ ~
| |
+----+----+----+----+----+----+----+----+
from :: a `Destination`
length: 387+ bytes
The originator and (unless offline signed) signer of the datagram
flags :: (2 bytes)
Bit order: 15 14 ... 3 2 1 0
Bits 3-0: Version: 0x02 (0 0 1 0)
Bit 4: If 0, no options; if 1, options mapping is included
Bit 5: If 0, no offline sig; if 1, offline signed
Bits 15-6: unused, set to 0 for compatibility with future uses
options :: (2+ bytes if present)
If flag indicates options are present, a `Mapping`
containing arbitrary text options
offline_signature ::
If flag indicates offline keys, the offline signature section,
as specified in the Common Structures Specification,
with the following 4 fields. Length: varies by online and offline
sig types, typically 102 bytes for Ed25519
This section can, and should, be generated offline.
expires :: Expires timestamp
(4 bytes, big endian, seconds since epoch, rolls over in 2106)
sigtype :: Transient sig type (2 bytes, big endian)
pubkey :: Transient signing public key (length as implied by sig type),
typically 32 bytes for Ed25519 sig type.
offsig :: a `Signature`
Signature of expires timestamp, transient sig type,
and public key, by the destination public key,
length: 40+ bytes, as implied by the Signature type, typically
64 bytes for Ed25519 sig type.
payload :: The data
Length: 0 to about 61 KB (see notes)
signature :: a `Signature`
Signature type must match the signing public key type of $from
(if no offline signature) or the transient sigtype
(if offline signed)
length: 40+ bytes, as implied by the Signature type, typically
64 bytes for Ed25519 sig type.
The `Signature` of the payload and other fields as specified below.
The signature is verified by the signing public key of $from
(if no offline signature) or the transient pubkey
(if offline signed)
{% endhighlight %}
Total length: minimum 433 + payload length;
typical length for X25519 senders and without offline signatures:
457 + payload length.
Note that the message will typically be compressed with gzip at the I2CP layer,
which will result in significant savings if the from destination is compressible.
Note: The offline signature format is the same as in the Common Structures spec [Common]_ and [Streaming]_.
Signatures
----------
The signature is over the following fields.
- Prelude: The 32-byte hash of the target destination (not included in the datagram)
- flags
- options (if present)
- offline_signature (if present)
- payload
In repliable datagram, for the DSA_SHA1 key type, the signature was over the
SHA-256 hash of the payload, not the payload itself; here, the signature is
always over the fields above (NOT the hash), regardless of key type.
ToHash Verification
-------------------
Receivers must verify the signature (using their destination hash)
and discard the datagram on failure, for replay prevention.
.. _datagram3:
Datagram3
=========
The Datagram3 format is as specified in Proposal 163 [Prop163]_.
The I2CP protocol number for Datagram3 is 20.
Datagram3 is intended as an enhanced version of raw datagrams.
It adds the following features to raw datagrams:
- Repliability
- Flags and options fields for extensibility
Datagram3 is NOT authenticated.
In a future proposal, authentication may be provided by
the router's ratchet layer, and authentication status
would be passed to the client.
Format
------
.. raw:: html
{% highlight lang='dataspec' -%}
+----+----+----+----+----+----+----+----+
| |
~ fromhash ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| flags | options (optional) |
+----+----+ +
~ ~
~ ~
+----+----+----+----+----+----+----+----+
| |
~ payload ~
~ ~
| |
+----+----+----+----+----+----+----+----+
fromhash :: a `Hash`
length: 32 bytes
The originator of the datagram
flags :: (2 bytes)
Bit order: 15 14 ... 3 2 1 0
Bits 3-0: Version: 0x03 (0 0 1 1)
Bit 4: If 0, no options; if 1, options mapping is included
Bits 15-5: unused, set to 0 for compatibility with future uses
options :: (2+ bytes if present)
If flag indicates options are present, a `Mapping`
containing arbitrary text options
payload :: The data
Length: 0 to about 61 KB (see notes)
{% endhighlight %}
Total length: minimum 34 + payload length.
References
==========
.. [Common]
{{ spec_url('common-structures') }}
.. [DATAGRAMS]
{{ site_url('docs/api/datagrams', True) }}
.. [I2CP]
{{ site_url('docs/protocol/i2cp', True) }}
.. [Prop144]
{{ proposal_url('144') }}
.. [Prop163]
{{ proposal_url('163') }}
.. [Prop169]
{{ proposal_url('163') }}
.. [SAMv3]
{{ site_url('docs/api/samv3') }}
.. [Streaming]
{{ spec_url('streaming') }}
.. [TRANSPORT]
{{ site_url('docs/transport', True) }}

View File

@ -1,833 +0,0 @@
===================================
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 Router Messages
=============================
.. meta::
:category: Protocols
:lastupdated: 2025-03
:accuratefor: 0.9.65
:lastupdated: 2021-01
:accuratefor: 0.9.49
.. contents::
@ -271,7 +271,7 @@ This is the same as specified in [Tunnel-Creation-ECIES]_ and [Prop152]_ for tun
//chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
plaintext = 464 byte build request record
ad = h

View File

@ -3,26 +3,25 @@ ECIES-X25519-AEAD-Ratchet
=========================
.. meta::
:category: Protocols
:lastupdated: 2025-06
:accuratefor: 0.9.67
:lastupdated: 2020-11
:accuratefor: 0.9.47
.. contents::
Note
====
Network deployment complete.
Network deployment and testing in progress.
Subject to minor revisions.
See [Prop144]_ for the original proposal, including background discussion and additional information.
The following features are not implemented as of 0.9.66:
The following features are not implemented as of 0.9.46:
- MessageNumbers, Options, and Termination blocks
- Protocol-layer responses
- Zero static key
- Multicast
For the MLKEM PQ Hybrid version of this protocol, see [ECIES-HYBRID]_.
Overview
@ -183,44 +182,6 @@ Bound sessions are similar to the Noise IK pattern.
{% endhighlight %}
Security Properties
```````````````````
Using Noise terminology, the establishment and data sequence is as follows:
(Payload Security Properties from [Noise]_ )
.. raw:: html
{% highlight lang='text' %}
IK(s, rs): Authentication Confidentiality
<- s
...
-> e, es, s, ss 1 2
<- e, ee, se 2 4
-> 2 5
<- 2 5
{% endhighlight %}
Differences From XK
```````````````````
IK handshakes have several differences from XK handshakes used
in [NTCP2]_ and [SSU2]_.
- Four total DH operations compared to three for XK
- Sender authentication in first message: The payload is authenticated
as belonging to the owner of the sender's public key, although
the key could have been compromised (Authentication 1)
XK requires another round trip before Alice is authenticated.
- Full forward secrecy (Confidentiality 5) after the second message.
Bob may send a payload immediately after the second message with
full forward secrecy.
XK requires another round trip for full forward secrecy.
In summary, IK allows 1-RTT delivery of the response payload from Bob to Alice
with full forward secrecy, however the request payload is not forward-secret.
Sessions
--------
@ -931,7 +892,7 @@ This is the "e" message pattern:
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, flags/static key section, ad)
@ -975,7 +936,7 @@ This is the "ss" message pattern:
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
@ -995,7 +956,7 @@ KDF for Payload Section (without Alice static key)
Note that this is a Noise "N" pattern, but we use the same "IK" initializer
as for bound sessions.
New Session messages can not be identified as containing Alice's static key or not
New Session essages can not be identified as containing Alice's static key or not
until the static key is decrypted and inspected to determine if it contains all zeros.
Therefore, the receiver must use the "IK" state machine for all
New Session messages.
@ -1180,7 +1141,7 @@ KDF for Reply Key Section Encrypted Contents
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
@ -2182,13 +2143,10 @@ a single frame, but it is not prohibited.
DateTime
````````
An expiration.
Assists in replay prevention.
Assists in reply prevention.
Bob must validate that the message is recent, using this timestamp.
Bob must implement a Bloom filter or other mechanism to prevent replay attacks,
if the time is valid.
Bob may also use an earlier replay detection check for a duplicate ephemeral key
(either pre- or post-Elligator2 decode) to detect and drop recent duplicate NS messages
before decryption.
Generally included in New Session messages only.
.. raw:: html
@ -3041,24 +2999,8 @@ non-mod-16 padding, things will need to be done differently.
Retransmissions and State Transistions
--------------------------------------
The ratchet layer does not do retransmissions, and with two exceptions,
does not use timers for tranmssions. Timers are also required
for tagset timeout.
Transmission timers are used only for sending NSR and for
replying with an ES when a received ES contains an ACK request.
Recommended timeout is one second. In almost all cases, the
higher layer (datagram or streaming) will reply, forcing
a NSR or ES, and the timer may be cancelled.
If the timer does fire, send an empty payload with the NSR or ES.
Ratchet-layer Responses
````````````````````````
Protocol-layer Responses
-------------------------
Initial implementations rely on bidirectional traffic at the higher layers.
That is, the implementations assume that traffic in the opposite direction
@ -3070,7 +3012,7 @@ such that there is no higher-layer traffic to generate a timely response.
Receipt of NS and NSR messages require a response;
receipt of ACK Request and Next Key blocks also require a response.
Implementations should start a timer when one of these
A sophisticated implementation may start a timer when one of these
messages is received which requires a response,
and generate an "empty" (no Garlic Clove block) response
at the ECIES layer
@ -3081,130 +3023,6 @@ responses to NS and NSR messages, to shift the traffic to
the efficient ES messages as soon as possible.
NS Binding For NSR
``````````````````
At the ratchet layer, as Bob, Alice is only known by static key.
The NS message is authenticated ([Noise]_ IK sender authentication 1).
However, this is not sufficient for the ratchet layer to be able to send anything
to Alice, as network routing requires a full Destination.
Before the NSR may be sent, Alice's full Destination must be discovered either
by the ratchet layer or a higher-layer repliable protocol,
either repliable [Datagrams]_ or [Streaming]_.
After finding the Leaseset for that Destination, that Leaseset
will contain the same static key as contained in the NS.
Typically, the higher layer will respond, forcing a network database
lookup of Alice's Leaseset by Alice's Destination Hash.
That Leaseset will almost always be found locally, because the
NS contained a Garlic Clove block, containing a Database Store message,
containing Alice's Leaseset.
For Bob to be prepared to send a ratchet-layer NSR, and to bind
the pending session to Alice's Destination, Bob should
"capture" the Destination while processing the NS payload.
If a Database Store message is found containing a Leaseset
with a key matching the static key in the NS,
the pending session is now bound to that Destination,
and Bob knows where to send any NSR if the response timer expires.
This is the recommended implementation.
An alternative design is to maintain a cache or database
where the static key is mapped to a Destination.
The security and practicality of this approach
is a topic for further study.
Neither this specification nor others strictly require that
every NS contains Alice's Leaseset.
However, in practice, it should.
The recommended ES tagset sender timeout (8 minutes)
is shorter than the maximum Leaseset timeout (10 minutes),
so there could be a small window where the previous session
has expired, Alice thinks that Bob
still has her valid Leaseset, and does not send a new Leaseset
with the new NS. This is a topic for further study.
Multiple NS Messages
````````````````````
If no NSR response is received before the higher layer (datagram or streaming)
sends more data, possibly as a retransmission, Alice must compose a new NS, using a new ephemeral key.
Do not reuse the ephemeral key from any previous NS.
Alice must maintain the additional handshake state and derived receive tagset,
to receive NSR messages in reply to any NSR that was sent.
Implementations may limit the total number of NS messages sent,
or the rate of NS message sending,
either by queueing or dropping higher layer messages before they are sent.
In certain situations, when under high load, or under certain attack scenarios,
it may be appropriate for Bob to queue, drop, or limit apparent NS messages without attempting to decrypt,
to avoid a resource exhaustion attack.
For each NS received, Bob generates an NSR outbund tagset, sends an NSR, does a split(),
and generates the inbound and outbound ES tagsets.
However, Bob does not send any ES messages until the first ES message
on the corresponding inbound tagset is received. After that, Bob may discard
all handshake states and tagsets for any other NS received or NSR sent, or allow
them to expire shortly. Do not use NSR tagsets for ES messages.
It is a topic for further study if Bob may choose to speculatively send ES messages immediately after
the NSR, even before receiving the first ES from Alice.
In certain scenarios and traffic patterns, this could save substantial
bandwidth and CPU.
This strategy may be based on heuristics such as traffic patterns,
percentage of ESs received on the first session's tagset, or other data.
Multiple NSR Messages
`````````````````````
For each NS message received, until an ES message is received, Bob must reply
with a new NSR, either due to higher layer traffic being sent, or NSR send timer expiration.
Each NSR uses the handshake state and tagset corresponding to the incoming NS.
Bob must maintain the handshake state and tagest for all NS messages received, until
an ES message is received.
Implementations may limit the total number of NSR messages sent,
or the rate of NSR message sending,
either by queueing or dropping higher layer messages before they are sent.
These may be limited either when caused by incoming NS messages, or
additional higher layer outbound traffic.
In certain situations, when under high load, or under certain attack scenarios,
it may be appropriate for Alice to queue, drop, or limit NSR messages
without attempting to decrypt, to avoid a resource exhaustion attack.
These limits may be either total across all sessions, per session, or both.
Once Alice receives an NSR, Alice does a split() to derive the ES session keys.
Alice should set a timer, and send an empty ES message if the higher layer does
not send any traffic, typically within one second.
The other inbound NSR tagsets may be removed soon or allowed
to expire, but Alice should keep them for a short while, to
decrypt any other NSR messages that are received.
Replay Prevention
-----------------
Bob must implement a Bloom filter or other mechanism to prevent NS replay attacks,
if the included DateTime is recent, and reject NS messages where the
DateTime is too old.
Bob may also have use an earlier replay detection check for a duplicate ephemeral key
(either pre- or post-Elligator2 decode) to detect and drop recent duplicate NS messages
before decryption.
NSR and ES messages have inherent replay prevention because the
session tag is one-time-use.
Garlic messages also have replay prevention if the router implements
a router-wide Bloom filter based on I2NP message ID.
@ -3252,12 +3070,6 @@ References
.. [CRYPTO-ELG]
{{ site_url('docs/how/cryptography', True) }}#elgamal
.. [ECIES-HYBRID]
{{ spec_url('ecies-hybrid') }}
.. [Datagrams]
{{ spec_url('datagrams') }}
.. [Elligator2]
https://elligator.cr.yp.to/elligator-20130828.pdf
https://www.imperialviolet.org/2013/12/25/elligator.html
@ -3329,12 +3141,6 @@ References
.. [SSU]
{{ site_url('docs/transport/ssu', True) }}
.. [SSU2]
{{ spec_url('ssu2') }}
.. [Streaming]
{{ spec_url('streaming') }}
.. [STS]
Diffie, W.; van Oorschot P. C.; Wiener M. J., Authentication and
Authenticated Key Exchanges

View File

@ -3,8 +3,8 @@ Encrypted LeaseSet Specification
================================
.. meta::
:category: Protocols
:lastupdated: 2025-05
:accuratefor: 0.9.66
:lastupdated: June 2019
:accuratefor: 0.9.41
.. contents::

View File

@ -3,8 +3,8 @@ Access Filter Format Specification
==================================
.. meta::
:category: Formats
:lastupdated: 2025-05
:accuratefor: 0.9.66
:lastupdated: April 2019
:accuratefor: 0.9.40
.. contents::

View File

@ -3,8 +3,8 @@ GeoIP File Specification
========================
.. meta::
:category: Formats
:lastupdated: 2025-05
:accuratefor: 0.9.66
:lastupdated: December 2013
:accuratefor: 0.9.9
.. contents::
@ -12,12 +12,6 @@ GeoIP File Specification
Overview
========
NOTE: OBSOLETE - We now support three formats, in order of preference:
- Maxmind geoip2 (GeoLite2-Country.mmdb) bundled with all installs except Debian packages and Android
- Maxmind geoip1 (GeoIP.dat) in the Debian geoip-database package
- The IPv4 Tor format (geoip.txt) and the custom IPv6 format (geoipv6.dat.gz) documented below, still supported but unused.
This page specifies the format of the various GeoIP files,
used by the router to look up a country for an IP.

View File

@ -3,8 +3,8 @@ I2CP Specification
==================
.. meta::
:category: Protocols
:lastupdated: 2025-04
:accuratefor: 0.9.66
:lastupdated: 2023-10
:accuratefor: 0.9.59
.. contents::
@ -12,21 +12,13 @@ I2CP Specification
Overview
========
This is the specification of the I2P Control Protocol (I2CP), the low-level interface
This page specified the I2P Control Protocol (I2CP), which is the interface
between clients and the router. Java clients will use the I2CP client API,
which implements this protocol.
which implements this protocol. Non-Java clients will most likely use a
higher-layer protocol such as SAM or BOB.
There are no known non-Java implementations of a client-side library
that implements I2CP. Additionally, socket-oriented (streaming) applications would need
an implementation of the streaming protocol, but there are no non-Java libraries for that either.
Therefore, non-Java clients should instead use the higher-layer protocol SAM [SAMv3]_,
for which libraries exist in several languages.
This is a low-level protocol supported both internally and externally
by the Java I2P router.
The protocol is only serialized if the client and router are not in the same
JVM; otherwise, I2CP message Java objects are passed via an internal JVM interface.
I2CP is also supported externally by the C++ router i2pd.
JVM; otherwise, I2CP message objects are passed via an internal JVM interface.
More information is on the I2CP Overview page [I2CP]_.
@ -46,9 +38,8 @@ It also appears that there are some provisions for a single client to talk to
multiple routers over separate connections. This is also untested, and probably
not useful.
There is no way for a session to be maintained
It does not appear that there is currently a way for a session to be maintained
after a disconnect, or to be recovered on a different I2CP connection.
When the socket is closed, the session is destroyed.
Example Message Sequences
@ -150,7 +141,7 @@ Existing session, with i2cp.fastReceive=true (as of 0.9.4)
Message Payload Message <---------------------
{% endhighlight %}
Existing session, with i2cp.fastReceive=false (DEPRECATED)
Existing session, with i2cp.fastReceive=false
.. raw:: html
@ -213,6 +204,13 @@ responses. DestLookup and DestReply do not contain Session IDs; use the newer
HostLookup and HostReply instead. GetBandwidthLimts and BandwidthLimits do not
contain session IDs, however the response is not session-specific.
Support for multiple sessions is preliminary and subject to change. Support
may not be complete in other parts of the API and user interface, particularly
streaming and i2ptunnel. Current support is primarily for clients (i.e.
Destinations that do not publish their leaseset or accept incoming
connections), and is incomplete and untested for servers. Future releases may
provide additional features and options.
.. _notes:
@ -237,10 +235,6 @@ below.
============== ======================
Version Required I2CP Features
============== ======================
0.9.66 Host lookup/reply extensions (see proposal 167)
0.9.62 MessageStatus message Loopback error code
0.9.43 BlindingInfo message supported
Additional HostReply message failure codes
@ -452,7 +446,7 @@ Message Types
=============================== ========= ==== =====
BandwidthLimitsMessage_ R -> C 23 0.7.2
BlindingInfoMessage_ C -> R 42 0.9.43
CreateLeaseSetMessage_ C -> R 4 deprecated
CreateLeaseSetMessage_ C -> R 4
CreateLeaseSet2Message_ C -> R 41 0.9.39
CreateSessionMessage_ C -> R 1
DestLookupMessage_ C -> R 34 0.7
@ -465,11 +459,11 @@ HostLookupMessage_ C -> R 38 0.9.11
HostReplyMessage_ R -> C 39 0.9.11
MessagePayloadMessage_ R -> C 31
MessageStatusMessage_ R -> C 22
ReceiveMessageBeginMessage_ C -> R 6 deprecated
ReceiveMessageEndMessage_ C -> R 7 deprecated
ReceiveMessageBeginMessage_ C -> R 6
ReceiveMessageEndMessage_ C -> R 7
ReconfigureSessionMessage_ C -> R 2 0.7.1
ReportAbuseMessage_ bidir. 29 deprecated
RequestLeaseSetMessage_ R -> C 21 deprecated
ReportAbuseMessage_ bidir. 29
RequestLeaseSetMessage_ R -> C 21
RequestVariableLeaseSetMessage_ R -> C 37 0.9.7
SendMessageMessage_ C -> R 5
SendMessageExpiresMessage_ C -> R 36 0.7.1
@ -501,11 +495,9 @@ Contents
Notes
`````
The client limits may be the only values set, and may be the
actual router limits, or a percentage of the router limits, or specific to
the particular client, implementation-dependent.
All the values labeled as router limits may be 0, implementation-dependent.
As of release 0.7.2.
Currently, the client limits are the only values set, and are actually the
router limits. All the values labeled as router limits are always 0. As of
release 0.7.2.
.. _msg-BlindingInfo:
@ -602,11 +594,6 @@ Notes
CreateLeaseSetMessage
---------------------
DEPRECATED. Cannot be used for LeaseSet2, offline keys, non-ElGamal encryption types,
multiple encryption types, or encrypted LeaseSets.
Use CreateLeaseSet2Message with all routers 0.9.39 or higher.
Description
```````````
This message is sent in response to a RequestLeaseSetMessage_ or
@ -661,7 +648,7 @@ Contents
1. `Session ID`_
2. One byte type of lease set to follow.
- Type 1 is a [LeaseSet]_ (deprecated)
- Type 1 is a [LeaseSet]_
- Type 3 is a [LeaseSet2]_
- Type 5 is a [EncryptedLeaseSet]_
- Type 7 is a [MetaLeaseSet]_
@ -889,24 +876,7 @@ Contents
2. 4 byte [Integer]_ request ID
3. 4 byte [Integer]_ timeout (ms)
4. 1 byte [Integer]_ request type
5. SHA-256 [Hash]_ or host name [String]_ or [Destination]_
Request types:
==== =================== =======
Type Lookup key (item 5) As of
==== =================== =======
0 Hash
1 host name String
2 Hash 0.9.66
3 host name String 0.9.66
4 Destination 0.9.66
==== =================== =======
Types 2-4 request that the options mapping from the LeaseSet
be returned in the HostReply message.
See proposal 167.
5. SHA-256 [Hash]_ or host name [String]_
Notes
`````
@ -919,6 +889,8 @@ Notes
the future it may also be useful for remote naming service lookups. The value
may be not be honored for local host name lookups, which should be fast.
* The request type is 0 for Hash and 1 for host name.
* Base 32 host name lookup is supported but it is preferred to convert it to a
Hash first.
@ -943,44 +915,8 @@ Contents
- 3: Private key required (as of 0.9.43)
- 4: Lookup password and private key required (as of 0.9.43)
- 5: Leaseset decryption failure (as of 0.9.43)
- 6: Leaseset lookup failure (as of 0.9.66)
- 7: Lookup type unsupported (as of 0.9.66)
4. [Destination]_, only present if result code is zero,
except may also be returned for lookup types 2-4.
See below.
5. [Mapping]_, only present if result code is zero,
only returned for lookup types 2-4.
As of 0.9.66. See below.
Responses for lookup types 2-4
``````````````````````````````
Proposal 167 defines additional lookup types that
return all options from the leaseset, if present.
For lookup types 2-4, the router must fetch the leaseset,
even if the lookup key is in the address book.
If successful, the HostReply will contain the options Mapping
from the leaseset, and includes it as item 5 after the destination.
If there are no options in the Mapping, or the leaseset was version 1,
it will still be included as an empty Mapping (two bytes: 0 0).
All options from the leaseset will be included, not just service record options.
For example, options for parameters defined in the future may be present.
The returned Mapping may or may not be sorted, implementation-dependent.
On leaseset lookup failure, the reply will contain a new error code 6 (Leaseset lookup failure)
and will not include a mapping.
When error code 6 is returned, the Destination field may or may not be present.
It will be present if a hostname lookup in the address book was successful,
or if a previous lookup was successful and the result was cached,
or if the Destination was present in the lookup message (lookup type 4).
If a lookup type is not supported,
the reply will contain a new error code 7 (lookup type unsupported).
4. [Destination]_, only present if result code is zero.
Notes
`````
@ -993,9 +929,6 @@ Notes
As of 0.9.43, the additional failure codes 2-5 were defined
to support extended errors for "b33" lookups.
See proposals 123 and 149 for additional information.
As of 0.9.66, the additional failure codes 6-7 were defined
to support extended errors for type 2-4 lookups.
See proposal 167 for additional information.
.. _msg-MessagePayload:
@ -1050,16 +983,13 @@ router implementation uses the guaranteed status codes, not the best effort
codes.
As of router version 0.9.5, additional status codes are defined, however they
are not necessarily implemented. See [MSM-JAVADOCS]_ for details.
For outgoing messages, the codes 1, 2, 4, and 6 indicate success; all others are failures.
Returned failure codes may vary and are implementation-specific.
All status codes:
are not necessarily implemented. See [MSM-JAVADOCS]_ for details. All status
codes:
=========== ============= ====================== ==========================================================
Status Code As Of Release Name Description
=========== ============= ====================== ==========================================================
0 Available DEPRECATED. For incoming messages only. All other status codes below
0 Available For incoming messages only. All other status codes below
are for outgoing messages.
The included size is the size in bytes of the available
@ -1165,11 +1095,6 @@ Status Code As Of Release Name Description
This is a guaranteed failure.
23 0.9.62 Loopback Denied The message was attempted to be sent from and to
the same destination or session.
This is a guaranteed failure.
=========== ============= ====================== ==========================================================
When status = 1 (accepted), the nonce matches the nonce in the
@ -1181,8 +1106,6 @@ success or failure notification. Otherwise, the nonce may be ignored.
ReceiveMessageBeginMessage
--------------------------
DEPRECATED. Not supported by i2pd.
Description
```````````
Request the router to deliver a message that it was previously notified of.
@ -1209,8 +1132,6 @@ This is unused in "fast receive" mode, which is the default as of release
ReceiveMessageEndMessage
------------------------
DEPRECATED. Not supported by i2pd.
Description
```````````
Tell the router that delivery of a message was completed successfully and that
@ -1261,19 +1182,11 @@ Notes
changes here will not be recognized by the router. Changes to tunnel options
inbound.* and outbound.* are always recognized.
* In general, the router should merge the updated config with the current config,
so the updated config only needs to contain the new or changed options.
However, because of the merge, options may not be removed in this manner;
they must be set explicitly to the desired default value.
.. _msg-ReportAbuse:
ReportAbuseMessage
------------------
DEPRECATED, UNUSED, UNSUPPORTED
Description
```````````
Tell the other party (client or router) that they are under attack, potentially
@ -1302,21 +1215,12 @@ ReportAbuseMessage_, but neither has a handler for the message when received.
RequestLeaseSetMessage
----------------------
DEPRECATED. Not supported by i2pd. Not sent by Java I2P to clients version
0.9.7 or higher (2013-07). Use RequestVariableLeaseSetMessage.
Description
```````````
Request that a client authorize the inclusion of a particular set of inbound
tunnels. Sent from Router to Client. The client responds with a
CreateLeaseSetMessage_.
The first of these messages sent on a session is a signal to the client
that tunnels are built and ready for traffic. The router must not
send the first of these messages until at least one inbound AND one outbound tunnel
have been built. Clients should timeout and destroy the session if the first
of these messages is not received after some time (recommended: 5 minutes or more).
Contents
````````
1. `Session ID`_
@ -1330,9 +1234,9 @@ Contents
Notes
`````
This requests a [LeaseSet]_ with all [Lease]_ entries set to expire at the same time.
This requests a [LeaseSet]_ with all [Leases]_ set to expire at the same time.
For client versions 0.9.7 or higher, RequestVariableLeaseSetMessage_ is
used.
preferred.
.. _msg-RequestVariableLeaseSet:
@ -1346,17 +1250,11 @@ tunnels.
Sent from Router to Client. The client responds with a CreateLeaseSetMessage_ or CreateLeaseSet2Message_.
The first of these messages sent on a session is a signal to the client
that tunnels are built and ready for traffic. The router must not
send the first of these messages until at least one inbound AND one outbound tunnel
have been built. Clients should timeout and destroy the session if the first
of these messages is not received after some time (recommended: 5 minutes or more).
Contents
````````
1. `Session ID`_
2. 1 byte [Integer]_ number of tunnels
3. That many [Lease]_ entries
3. That many [Leases]_
Notes
`````
@ -1505,7 +1403,6 @@ Bit 8
Bits 7-4
Low tag threshold. If there are less than this many tags available, send
more. This is advisory and does not force tags to be delivered.
For ElGamal only. Ignored for ECIES-Ratchet.
=========== =============
Field value Tag threshold
@ -1531,7 +1428,6 @@ Field value Tag threshold
Bits 3-0
Number of tags to send if required. This is advisory and does not force
tags to be delivered.
For ElGamal only. Ignored for ECIES-Ratchet.
=========== ============
Field value Tags to send
@ -1563,11 +1459,8 @@ Description
```````````
Instruct the client as to the status of its session.
Sent from Router to Client, in response to a CreateSessionMessage_,
Sent from Router to Client, possibly in response to a CreateSessionMessage_,
ReconfigureSessionMessage_, or DestroySessionMessage_.
In all cases, including in response to CreateSessionMessage_,
the router should respond immediately (do not wait for tunnels to be built).
Contents
````````
@ -1661,6 +1554,7 @@ References
.. [Integer]
{{ ctags_url('Integer') }}
.. [Leases]
.. [Lease]
{{ ctags_url('Lease') }}
@ -1688,9 +1582,6 @@ References
.. [RouterIdentity]
{{ ctags_url('RouterIdentity') }}
.. [SAMv3]
{{ site_url('docs/api/samv3') }}
.. [Signature]
{{ ctags_url('Signature') }}

View File

@ -3,8 +3,8 @@ I2NP Specification
==================
.. meta::
:category: Protocols
:lastupdated: 2025-04
:accuratefor: 0.9.66
:lastupdated: 2023-10
:accuratefor: 0.9.59
.. contents::
@ -45,18 +45,6 @@ below.
============== ================================================================
API Version Required I2NP Features
============== ================================================================
0.9.66 LeaseSet2 service record options (see proposal 167)
0.9.65 Tunnel build bandwidth parameters (see proposal 168)
0.9.59 Minimum peers will build tunnels through, as of 0.9.63
Minimum floodfill peers will send DSM to, as of 0.9.63
0.9.58 Minimum peers will build tunnels through, as of 0.9.62
ElGamal Routers deprecated
0.9.55 SSU2 transport support (if published in router info)
0.9.51 Short tunnel build messages for ECIES-X25519 routers
@ -158,23 +146,12 @@ Common header to all I2NP messages, which contains important information like a
Contents
````````
There are three separate formats used, depending on context;
one standard format, and two short format.
The standard 16 byte format contains
1 byte [Integer]_ specifying the type of this message, followed by a 4 byte
[Integer]_ specifying the message-id. After that there is an expiration
[Date]_, followed by a 2 byte [Integer]_ specifying the length of the message
payload, followed by a [Hash]_, which is truncated to the first byte. After
that the actual message data follows.
The short formats use a 4 byte expiration in seconds instead of an
8 byte expiration in milliseconds.
The short formats do not contain a checksum or size,
those are provided by the encapsulations, depending on context.
.. raw:: html
{% highlight lang='dataspec' %}
@ -186,13 +163,13 @@ Standard (16 bytes):
| size |chks|
+----+----+----+----+----+----+----+----+
Short (SSU, 5 bytes) (obsolete):
Short (SSU, 5 bytes):
+----+----+----+----+----+
|type| short_expiration |
+----+----+----+----+----+
Short (NTCP2, SSU2, and ECIES-Ratchet Garlic Cloves, 9 bytes):
Short (NTCP2 and SSU2, 9 bytes):
+----+----+----+----+----+----+----+----+
|type| msg_id | short_expira-
@ -261,9 +238,6 @@ Notes
BuildRequestRecord
------------------
DEPRECATED, only used in the current network when a tunnel contains an ElGamal router.
See [TUNNEL-CREATION-ECIES]_.
Description
```````````
One Record in a set of multiple records to request the creation of one hop in
@ -441,9 +415,6 @@ Notes
BuildResponseRecord
-------------------
DEPRECATED, only used in the current network when a tunnel contains an ElGamal router.
See [TUNNEL-CREATION-ECIES]_.
Description
```````````
One Record in a set of multiple records with responses to a build request.
@ -525,11 +496,6 @@ See [TUNNEL-CREATION-ECIES]_.
GarlicClove
-----------
Warning: This is the format used for garlic cloves within ElGamal-encrypted garlic messages [CRYPTO-ELG]_.
The format for ECIES-AEAD-X25519-Ratchet garlic messages and garlic cloves
is significantly different; see [ECIES]_ for the specification.
.. raw:: html
{% highlight lang='dataspec' %}
@ -586,25 +552,17 @@ Notes
* The Clove ID is generally set to a random number on transmit and is checked
for duplicates on receive (same message ID space as top-level Message IDs)
.. _struct-GarlicCloveDeliveryInstructions:
Garlic Clove Delivery Instructions
----------------------------------
This is the format used for both ElGamal-encrypted [CRYPTO-ELG]_
and ECIES-AEAD-X25519-Ratchet encrypted [ECIES]_ garlic cloves.
This specification is for Delivery Instructions inside Garlic Cloves only.
Note that "Delivery Instructions" are also used inside Tunnel Messages, where
the format is significantly different. See the Tunnel Message documentation
[TMDI]_ for details. Do NOT use the following specification for Tunnel Message
Delivery Instructions!
Session key and delay are unused and never present, so the three
possible lengths are 1 (LOCAL), 33 (ROUTER and DESTINATION), and 37 (TUNNEL) bytes.
.. raw:: html
{% highlight lang='dataspec' %}
@ -684,8 +642,8 @@ Garlic_ 11
TunnelData_ 18
TunnelGateway_ 19
Data_ 20
TunnelBuild_ 21 deprecated
TunnelBuildReply_ 22 deprecated
TunnelBuild_ 21
TunnelBuildReply_ 22
VariableTunnelBuild_ 23 0.7.12
VariableTunnelBuildReply_ 24 0.7.12
ShortTunnelBuild_ 25 0.9.51
@ -978,11 +936,6 @@ Contents
Reply Encryption
````````````````
NOTE: ElGamal routers are deprecated as of API 0.9.58.
As the recommended minimum floodfill version to query is now 0.9.58,
implementations need not implement encryption for ElGamal floodfill routers.
ElGamal destinations are still supported.
Flag bit 4 is used in combination with bit 1 to determine the reply encryption mode.
Flag bit 4 must only be set when sending to routers with version 0.9.46 or higher.
See proposals 154 and 156 for details.
@ -1011,7 +964,6 @@ reply_key, tags, and reply_tags are not present.
ElG to ElG
``````````````
Supported as of 0.9.7.
Deprecated as of 0.9.58.
ElG destination sends a lookup to a ElG router.
Requester key generation:
@ -1047,7 +999,6 @@ reply_key ::
ECIES to ElG
``````````````
Supported as of 0.9.46.
Deprecated as of 0.9.58.
ECIES destination sends a lookup to a ElG router.
The reply_key and reply_tags fields are redefined for an ECIES-encrypted reply.
@ -1245,21 +1196,9 @@ Notes
* The returned peer hashes are not necessarily closer to the key than the
router being queried.
For replies to regular lookups, this facilitates discovery of new floodfills
and "backwards" searching (further-from-the-key) for robustness.
* The key for an exploration lookup is usually generated randomly.
Therefore, the response's non-floodfill peer_hashes may be selected using an
optimized algorithm, such as providing peers that are close to the key but not
necessarily the closest in the entire local network database, to avoid an
inefficient sort or search of the entire local database.
Other strategies such as caching may also be appropriate.
This is implementation-dependent.
* Typical number of hashes returned: 3
* Recommended maximum number of hashes to return: 16
* The lookup key, peer hashes, and from hash are "real" hashes, NOT routing
keys.
@ -1306,18 +1245,11 @@ Notes
"arrival time" is set to the current network-wide ID, which is 2 (i.e.
0x0000000000000002).
.. _msg-Garlic:
Garlic
------
Warning: This is the format used for ElGamal-encrypted garlic messages [CRYPTO-ELG]_.
The format for ECIES-AEAD-X25519-Ratchet garlic messages and garlic cloves
is significantly different; see [ECIES]_ for the specification.
Description
```````````
Used to wrap multiple encrypted I2NP Messages
@ -1529,8 +1461,6 @@ Notes
TunnelBuild
-----------
DEPRECATED, use VariableTunnelBuild_
.. raw:: html
{% highlight lang='dataspec' %}
@ -1574,8 +1504,6 @@ Notes
TunnelBuildReply
----------------
DEPRECATED, use VariableTunnelBuildReply_
.. raw:: html
{% highlight lang='dataspec' %}
@ -1710,7 +1638,7 @@ OutboundTunnelBuildReply
Description
```````````
Sent from the outbound endpoint of a new tunnel to the originator.
Sent from the outbound gateway of a new tunnel to the originator.
As of API version 0.9.51, for ECIES-X25519 routers only.
.. raw:: html

View File

@ -3,8 +3,8 @@ NTCP 2
======
.. meta::
:category: Transports
:lastupdated: 2025-05
:accuratefor: 0.9.66
:lastupdated: 2022-12
:accuratefor: 0.9.56
.. contents::
@ -110,7 +110,7 @@ Alice Bob
{% endhighlight %}
Using Noise terminology, the establishment and data sequence is as follows:
(Payload Security Properties from [Noise]_ )
(Payload Security Properties)
.. raw:: html
@ -368,7 +368,7 @@ Noise content: Alice's ephemeral key X
Noise payload: 16 byte option block
Non-noise payload: Random padding
(Payload Security Properties from [Noise]_ )
(Payload Security Properties)
.. raw:: html
@ -574,10 +574,6 @@ Notes
set a random timeout (range TBD) and then read a random number of bytes (range TBD),
before closing the socket.
- Bob may do a fast MSB check for a valid key (X[31] & 0x80 == 0) before
attempting decryption. If the high bit is set, implement probing resistance
as for AEAD failures.
- DoS Mitigation: DH is a relatively expensive operation. As with the previous NTCP protocol,
routers should take all necessary measures to prevent CPU or connection exhaustion.
Place limits on maximum active connections and maximum connection setups in progress.
@ -707,7 +703,7 @@ Noise content: Bob's ephemeral key Y
Noise payload: 16 byte option block
Non-noise payload: Random padding
(Payload Security Properties from [Noise]_ )
(Payload Security Properties)
.. raw:: html
@ -996,7 +992,7 @@ Noise content: Alice's static key
Noise payload: Alice's RouterInfo and random padding
Non-noise payload: none
(Payload Security Properties from [Noise]_ )
(Payload Security Properties)
.. raw:: html
@ -1271,7 +1267,7 @@ Types include date/time, I2NP message, options, termination, and padding.
Note: Bob may, but is not required, to send his RouterInfo to Alice as
his first message to Alice in the data phase.
(Payload Security Properties from [Noise]_ )
(Payload Security Properties)
.. raw:: html
@ -1387,14 +1383,6 @@ Raw contents
{% endhighlight %}
Notes
`````
- As the receiver must get the entire frame to check the MAC,
it is recommended that the sender limit frames to a few KB
rather than maximizing the frame size.
This will minimize latency at the receiver.
Unencrypted data
````````````````

View File

@ -5,7 +5,7 @@ ECIES-X25519-AEAD-Ratchet
:author: zzz, chisana, orignal
:created: 2018-11-22
:thread: http://zzz.i2p/topics/2639
:lastupdated: 2025-03-05
:lastupdated: 2020-11-12
:status: Closed
:target: 0.9.46
:implementedin: 0.9.46
@ -1109,7 +1109,7 @@ This is the "e" message pattern:
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, flags/static key section, ad)
@ -1153,7 +1153,7 @@ This is the "ss" message pattern:
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
@ -1173,7 +1173,7 @@ KDF for Payload Section (without Alice static key)
Note that this is a Noise "N" pattern, but we use the same "IK" initializer
as for bound sessions.
New Session messages can not be identified as containing Alice's static key or not
New Session essages can not be identified as containing Alice's static key or not
until the static key is decrypted and inspected to determine if it contains all zeros.
Therefore, the receiver must use the "IK" state machine for all
New Session messages.
@ -1358,7 +1358,7 @@ KDF for Reply Key Section Encrypted Contents
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, ZEROLEN, ad)

View File

@ -5,7 +5,7 @@ ECIES Tunnels
:author: chisana, zzz, orignal
:created: 2019-07-04
:thread: http://zzz.i2p/topics/2737
:lastupdated: 2025-03-05
:lastupdated: 2021-03-21
:status: Closed
:target: 0.9.48
:implementedin: 0.9.48
@ -700,7 +700,7 @@ Failing to use unique keys opens an attack vector for colluding hops to confirm
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
plaintext = 464 byte build request record
ad = h

View File

@ -5,7 +5,7 @@ ECIES Routers
:author: zzz, orignal
:created: 2020-09-01
:thread: http://zzz.i2p/topics/2950
:lastupdated: 2025-03-05
:lastupdated: 2021-07-31
:status: Closed
:target: 0.9.51
@ -331,7 +331,7 @@ This is the same as specified in [Tunnel-Creation-ECIES]_ and [Prop152]_ for tun
//chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
plaintext = 464 byte build request record
ad = h

View File

@ -5,8 +5,8 @@ SSU2
:author: eyedeekay, orignal, zlatinb, zzz
:created: 2021-09-12
:thread: http://zzz.i2p/topics/2612
:lastupdated: 2025-03-05
:status: Closed
:lastupdated: 2022-12-19
:status: Open
:target: 0.9.56
.. contents::
@ -39,7 +39,7 @@ Connection Migration 0.9.55+ dev 0.9.56 2022-11
Immediate ACK flag 0.9.55+ dev 0.9.56 2022-11
Key Rotation 0.9.57 2023-02 0.9.58 2023-05
Disable SSU 1 (i2pd) 0.9.56 2022-11
Disable SSU 1 (Java I2P) 0.9.58 2023-05 0.9.61 2023-12
Disable SSU 1 (Java I2P) 0.9.58 2023-05 0.9.59 2023-08
========================== ===================== ====================
Basic Session includes the handshake and data phase.
@ -2852,7 +2852,7 @@ Before header encryption:
Short Header
`````````````
The short header is 16 bytes. It is used for Session Created and for Data messages.
Unauthenticated messages such as Session Request, Retry, and Peer Test will
Uauthenticated messages such as Session Request, Retry, and Peer Test will
always use the long header.
16 bytes is required, because
@ -3463,7 +3463,7 @@ KDF for Session Request
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
@ -3764,7 +3764,7 @@ KDF for Session Created and Session Confirmed part 1
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
@ -4044,7 +4044,7 @@ This is the "se" message pattern:
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
@ -6717,7 +6717,7 @@ An additional packet count limit may be useful as well to prevent
buffer overflow in the kernel or in middleboxes, implementation dependent,
although this may add significant complexity.
If per-session and/or total packet output is bandwidth-limited and/or paced,
this may mitigate the need for packet count limiting.
this may mitigate the need for packet count ilmiting.

View File

@ -5,9 +5,9 @@ UDP Trackers
:author: zzz
:created: 2022-01-03
:thread: http://zzz.i2p/topics/1634
:lastupdated: 2025-06-09
:lastupdated: 2022-12-19
:status: Open
:target: 0.9.68
:target: 0.9.58
.. contents::
@ -18,36 +18,6 @@ Overview
This proposal is for implemention of UDP trackers in I2P.
Change History
--------------
A preliminary proposal for UDP trackers in I2P was posted on our bittorrent spec page [SPEC]_
in May 2014; this predated our formal proposal process, and it was never implemented.
This proposal was created in early 2022 and simplifies the 2014 version.
As this proposal relies on repliable datagrams, it was put on hold once we
started working on the Datagram2 proposal [Prop163]_ in early 2023.
That proposal was approved in April 2025.
The 2023 version of this proposal specified two modes, "compatibility" and "fast".
Further analysis revealed that the fast mode would be insecure, and would also
be inefficient for clients with a large number of torrents.
Further, BiglyBT indicated a preference for compatibility mode.
This mode will be easier to implement for any tracker or client supporting
standard [BEP15]_.
While the compatibility mode is more complex to implement from-scratch
on the client size, we do have preliminary code for it started in 2023.
Therefore, the current version here is further simplified to remove fast mode,
and remove the term "compatibility". The current version switches to
the new Datagram2 format, and adds references to the UDP announce extenstion
protocol [BEP41]_.
Also, a connection ID lifetime field is added to the connect response,
to extend the efficiency gains of this protocol.
Motivation
==========
@ -57,6 +27,10 @@ we need to make trackers and announces more efficient so that trackers are not o
Bittorrent proposed UDP trackers in BEP 15 [BEP15]_ in 2008, and the vast majority
of trackers on clearnet are now UDP-only.
A preliminary proposal for UDP trackers in I2P was posted on our bittorrent spec page [SPEC]_
in May 2014; this predated our formal proposal process, and it was never implemented.
This proposal simplifies the 2014 version.
It is difficult to calculate the bandwidth savings of datagrams vs. streaming protocol.
A repliable request is about the same size as a streaming SYN, but the payload
is about 500 bytes smaller because the HTTP GET has a huge 600 byte
@ -67,27 +41,19 @@ for a tracker's outbound traffic.
Additionally, there should be implementation-specific memory reductions,
as datagrams require much less in-memory state than a streaming connection.
Post-Quantum encryption and signatures as envisioned in [Prop169]_ will substantially
increase the overhead of encrypted and signed structures, including destinations,
leasesets, streaming SYN and SYN ACK. It is important to minimize this
overhead where possible before PQ crypto is adopted in I2P.
Design
============
This proposal uses repliable datagram2, repliable datagram3, and raw datagrams,
This proposal uses both repliable 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:
The message flow in [BEP15]_ is as follows:
.. raw:: html
@ -103,127 +69,66 @@ Client Tracker
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.
This connection ID expires in one minute at the client, and in two minutes at the tracker.
This is not necessary in I2P because of repliable datagrams.
I2P will use the same message flow as BEP 15,
We propose two mechanisms for I2P, compatibility mode and fast mode.
Compatibility Mode
-------------------------
In compatibility mode, we keep 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 Req. -------------> (Repliable)
<-------------- Connect Resp. (Raw)
Announce Req. -------------> (Repliable Datagram3)
Announce Req. -------------> (Raw)
<-------------- Announce Resp. (Raw)
Announce Req. -------------> (Repliable Datagram3)
Announce Req. -------------> (Raw)
<-------------- 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.
This mode is also useful if the client plans to send multiple announces
within one minute to a single tracker, as only the connect
message must be repliable.
Tracker/Client support
----------------------
For an integrated application (router and client in one process, for example i2psnark, and the ZzzOT Java plugin),
or for an I2CP-based application (for example BiglyBT),
it should be straightforward to implement and route the streaming and datagram traffic separately.
ZzzOT and i2psnark are expected to be the first tracker and client to implement this proposal.
Non-integrated trackers and clients are discussed below.
Trackers
````````
There are four known I2P tracker implementations:
- zzzot, an integrated Java router plugin, running at opentracker.dg2.i2p and several others
- tracker2.postman.i2p, running presumably behind a Java router and HTTP Server tunnel
- The old C opentracker, ported by zzz, with UDP support commented out
- The new C opentracker, ported by r4sas, running at opentracker.r4sas.i2p and possibly others,
running presumably behind a i2pd router and HTTP Server tunnel
For an external tracker application that currently uses an HTTP server tunnel to receive
announce requests, the implementation could be quite difficult.
A specialized tunnel could be developed to translate datagrams to local HTTP requests/responses.
Or, a specialized tunnel that handles both HTTP requests and datagrams could be designed
that would forward the datagrams to the external process.
These design decisions will depend heavily on the specific router and tracker implementations,
and are outside the scope of this proposal.
Clients
```````
External SAM-based torrent clients such as qbittorrent and other libtorrent-based clients
would require SAM v3.3 [SAMv3]_ which is not supported by i2pd.
This is also required for DHT support, and is complex enough that no known
SAM torrent client has implemented it.
No SAM-based implementations of this proposal are expected soon.
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
I2P Fast Mode
-------------------------
This design maintains compatibility with [BEP15]_ as much as possible
to limit changes required in existing clients and trackers.
In fast mode, we omit the connect phase, as it is not required to prevent address spoofing.
This significantly simplifies the client-side implementation.
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.
.. raw:: html
{% highlight %}
Client Tracker
Announce Req. -------------> (Repliable)
<-------------- Announce Resp. (Raw)
{% endhighlight %}
This mode omits a round-trip, but requires every announce request to be repliable.
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.
The primary goal of an announce protocol is to impose a cost on address spoofing.
In compatibility mode, 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 proposal does not support blinded destinations,
but may be extended to do so. See below.
However, in fast mode, the destination and leaseset could be fake.
Multiple fake destinations and leasesets can be rapidly generated without
actually building tunnels. The Announce Request messages could then be sent out
any tunnel.
@ -231,57 +136,15 @@ Issues
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.
Repliable datagrams use I2CP protocol 17; raw datagrams use I2CP protocol 18.
Requests may be repliable or raw. Responses are always raw.
Connect Request
```````````````
-----------------
Client to tracker.
16 bytes. Must be repliable Datagram2. Same as in [BEP15]_. No changes.
16 bytes. Must be repliable. Same as in [BEP15]_.
.. raw:: html
@ -296,10 +159,10 @@ Offset Size Name Value
Connect Response
````````````````
-----------------
Tracker to client.
16 or 18 bytes. Must be raw. Same as in [BEP15]_ except as noted below.
16 bytes. Must be raw. Same as in [BEP15]_.
.. raw:: html
@ -309,64 +172,68 @@ 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.
98 bytes. Same as in [BEP15]_ except as noted below.
The connection_id is as received in the connect response.
If preceded by a connect request/response, must be raw,
with the connection_id received in the connect response.
If NOT preceded by a connect request/response, must be repliable,
and the connection_id is ignored.
.. raw:: html
{% highlight %}
Offset Size Name Value
0 64-bit integer connection_id
8 32-bit integer action 1 // announce
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
80 32-bit integer event 0 // 0: none; 1: completed; 2: started; 3: stopped
84 32-bit integer IP address 0 // default
88 32-bit integer key
92 32-bit integer num_want -1 // default
92 32-bit integer num_want -1 // default
96 16-bit integer port
98 varies options optional // As specified in BEP 41
98 TBD additional data TBD
{% endhighlight %}
Changes from [BEP15]_:
- connection_id is ignored if repliable
- IP address is ignored
- key is ignored
- port is probably ignored
- The options section, if present, is as defined in [BEP41]_
- Explicitly indidate that the protocol is extensible,
with possible additional data starting at port 98.
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.
20+ bytes. Must be raw. Same as in [BEP15]_ except as noted below.
@ -379,68 +246,74 @@ Offset Size Name Value
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
20 16-bit integer count of hashes to follow
22 32 * n 32-byte hash binary hashes
...
22 + 32 * n TBD additional data TBD
{% endhighlight %}
Changes from [BEP15]_:
- Add a hash count before the hashes, so that the response format
is extensible with additional data after the hashes.
- 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.
- Explicitly indidate that the protocol is extensible,
with possible additional data starting after the hashes
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;
I2P datagrams have a very large maximum size of about 16 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.
to about 50.
Scrape
``````
----------
Scrape request/response from [BEP15]_ is not required by this proposal,
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.
The scrape request is always repliable (unless there is a previous connect request/response)
and 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.
Error response from [BEP15]_ is not required by this proposal,
but may be implemented if desired, no changes required.
The error response is always raw.
.. raw:: html
{% highlight %}
Announce URL
------------
Offset Size Name Value
0 32-bit integer action 3 // error
4 32-bit integer transaction_id
8 string message
As in clearnet, UDP announce URLs are of the form "udp://host:port/path".
The path is ignored and may be empty.
If the ":port" part is omitted, use an I2CP port of 0.
{% endhighlight %}
Issues
=======
- Repliable datagrams do not support offline signatures.
That requires a separate proposal.
- This proposal does not support blinded destinations,
but may be extended to do so. See below.
- This proposal offers two modes at the client's option.
An existing clearnet tracker such as "opentracker" would require more modifications
to support the fast mode. There is no way in the announce URL to indicate
support for only one mode.
- Compatibility mode may not be necessary, pending feedback from BiglyBT and
other developers. However, it would still save a lot of bandwidth
if it is used for several announces within a minute.
Repliable announces are about 450 bytes larger than raw announces.
Extensions
=============
@ -448,39 +321,36 @@ 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.
The announce response is modified to include a count of peer hashes,
so that the response may be easily extended with additional information.
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.
blinded 35-byte address to the end of the announce request, or define a new blinded announce request message.
The set of blinded 35-byte peer addresses could be added to the end of the announce reply.
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 wihout existing BEP 15 support should implement
fast mode only, as it is much simpler.
Clients with existing BEP 15 support should require only small modifications.
Evaluate both fast and compatibility modes and choose
whatever is best for the existing code base.
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.
Trackers will never send a repliable datagram 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.
@ -490,32 +360,27 @@ 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 must implement both compatibility mode and fast mode.
Trackers with existing BEP 15 support should require only small modifications.
This proposal differs from the 2014 proposal, in that the tracker
must support reception of repliable datagram2 and datagram3 on the same port.
must support reception of repliable and raw datagrams 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.
For an integrated application (router and client in one process, for example the ZzzOT Java plugin),
it should be straightforward to implement and route the streaming and datagram traffic separately.
For an external tracker application that currently uses an HTTP server tunnel to receive
announce requests, the implementation could be quite difficult.
A specialized tunnel could be developed to translate datagrams to local HTTP requests/responses.
Or, a specialized tunnel that handles both HTTP requests and datagrams could be designed
that would forward the datagrams to the external process.
These design decisions will depend heavily on the specific router and tracker implementations,
and are outside the scope of this proposal.
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)``
Migration
@ -546,20 +411,8 @@ References
.. [BEP15]
http://www.bittorrent.org/beps/bep_0015.html
.. [BEP41]
http://www.bittorrent.org/beps/bep_0041.html
.. [DATAGRAMS]
{{ spec_url('datagrams') }}
.. [Prop163]
{{ proposal_url('163') }}
.. [Prop169]
{{ proposal_url('169') }}
.. [SAMv3]
{{ site_url('docs/api/samv3') }}
.. [SPEC]
{{ site_url('docs/applications/bittorrent', True) }}

View File

@ -2,395 +2,135 @@
Datagram2 Protocol
===================================
.. meta::
:author: zzz, orignal, drzed, eyedeekay
:author: zzz
:created: 2023-01-24
:thread: http://zzz.i2p/topics/3540
:lastupdated: 2025-04-16
:status: Closed
:target: 0.9.67
:lastupdated: 2023-01-24
:status: Open
:target: 0.9.60
.. contents::
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.
Check implementation documentation for status.
Overview
========
Pulled out from [Prop123]_ as a separate proposal.
Pulled out from [Prop123]_ as a separate proposal. Copied from [Prop123]_:
Offline signatures cannot be verified in the repliable datagram processing.
Needs a flag to indicate offline signed but there's no place to put a flag.
Will require a completely new I2CP protocol number and format,
Will require a completely new protocol number and format.
to be added to the [DATAGRAMS]_ specification.
Let's call it "Datagram2".
Goals
=====
- Add support for offline signatures
- Add replay resistance
- Add flavor without signatures
- Add flags and options fields for extensibility
Non-Goals
=========
Full end-to-end protocol support for congestion control, etc.
That would be build on top of, or an alternative to, Datagram2, which is a low-level protocol.
It would not make sense to design a high-performance protocol solely atop
Datagram2, because of the from field and signature overhead.
Any such protocol should do an initial handshake with Datagram2 and then
switch to RAW datagrams.
Motivation
==========
Left over from LS2 work otherwise completed in 2019.
The first application to use Datagram2 is expected to be
bittorrent UDP announces, as implemented in i2psnark and zzzot,
see [Prop160]_.
Repliable Datagram Spec
========================
For reference,
following is a review of the specification for repliable datagrams,
copied from [Datagrams]_.
The standard I2CP protocol number for repliable datagrams is PROTO_DATAGRAM (17).
.. raw:: html
{% highlight lang='dataspec' -%}
+----+----+----+----+----+----+----+----+
| from |
+ +
| |
~ ~
~ ~
| |
+ +
| |
| |
+----+----+----+----+----+----+----+----+
| signature |
+ +
| |
+ +
| |
+ +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| payload...
+----+----+----+----//
from :: a `Destination`
length: 387+ bytes
The originator and signer of the datagram
signature :: a `Signature`
Signature type must match the signing public key type of $from
length: 40+ bytes, as implied by the Signature type.
For the default DSA_SHA1 key type:
The DSA `Signature` of the SHA-256 hash of the payload.
For other key types:
The `Signature` of the payload.
The signature may be verified by the signing public key of $from
payload :: The data
Length: 0 to about 31.5 KB (see notes)
Total length: Payload length + 423+
{% endhighlight %}
Design
======
- Define new protocol 19 - Repliable datagram with options.
- Define new protocol 20 - Repliable datagram without signature.
- Add flags field for offline signatures and future expansion
- Move signature after the payload for easier processing
- New signature specification different from repliable datagram or streaming, so that
signature verification will fail if interpreted as repliable datagram or streaming.
This is accomplished by moving the signature after the payload,
and by including the destination hash in the signature function.
- Add replay prevention for datagrams, as was done in [Prop164]_ for streaming.
- Add section for arbitrary options
- Reuse offline signature format from [Common]_ and [Streaming]_.
- Offline signature section must be before the variable-length
payload and signature sections, as it specifies the length
of the signature.
Define new protocol 19 - Repliable datagram with options.
New signature specification.
Specification
=============
Protocol
--------
The new I2CP protocol number for Datagram2 is 19.
Add it as PROTO_DATAGRAM2 to [I2CP]_.
The new I2CP protocol number for Datagram3 is 20.
Add it as PROTO_DATAGRAM2 to [I2CP]_.
Datagram2 Format
----------------
Add Datagram2 to [DATAGRAMS]_ as follows:
Format
-------
Preliminary, copied from [Prop123]_:
.. raw:: html
{% highlight lang='dataspec' -%}
+----+----+----+----+----+----+----+----+
| |
~ from ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| flags | options (optional) |
+----+----+ +
~ ~
~ ~
+----+----+----+----+----+----+----+----+
| |
~ offline_signature (optional) ~
~ expires, sigtype, pubkey, offsig ~
| |
+----+----+----+----+----+----+----+----+
| |
~ payload ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| |
~ signature ~
~ ~
| |
+----+----+----+----+----+----+----+----+
{% highlight %}
From (387+ bytes)
from :: a `Destination`
length: 387+ bytes
The originator and (unless offline signed) signer of the datagram
Flags (2 bytes)
Bit order: 15 14 ... 3 2 1 0
Bit 0: If 0, no offline keys; if 1, offline keys
Bits 1-15: set to 0 for compatibility with future uses
If flag indicates offline keys, the offline signature section:
flags :: (2 bytes)
Bit order: 15 14 ... 3 2 1 0
Bits 3-0: Version: 0x02 (0 0 1 0)
Bit 4: If 0, no options; if 1, options mapping is included
Bit 5: If 0, no offline sig; if 1, offline signed
Bits 15-6: unused, set to 0 for compatibility with future uses
Expires timestamp
(4 bytes, big endian, seconds since epoch, rolls over in 2106)
options :: (2+ bytes if present)
If flag indicates options are present, a `Mapping`
containing arbitrary text options
Transient sig type (2 bytes, big endian)
offline_signature ::
If flag indicates offline keys, the offline signature section,
as specified in the Common Structures Specification,
with the following 4 fields. Length: varies by online and offline
sig types, typically 102 bytes for Ed25519
This section can, and should, be generated offline.
Transient signing public key (length as implied by sig type)
expires :: Expires timestamp
(4 bytes, big endian, seconds since epoch, rolls over in 2106)
Signature of expires timestamp, transient sig type,
and public key, by the destination public key,
length as implied by destination public key sig type.
This section can, and should, be generated offline.
sigtype :: Transient sig type (2 bytes, big endian)
pubkey :: Transient signing public key (length as implied by sig type),
typically 32 bytes for Ed25519 sig type.
offsig :: a `Signature`
Signature of expires timestamp, transient sig type,
and public key, by the destination public key,
length: 40+ bytes, as implied by the Signature type, typically
64 bytes for Ed25519 sig type.
payload :: The data
Length: 0 to about 61 KB (see notes)
signature :: a `Signature`
Signature type must match the signing public key type of $from
(if no offline signature) or the transient sigtype
(if offline signed)
length: 40+ bytes, as implied by the Signature type, typically
64 bytes for Ed25519 sig type.
The `Signature` of the payload and other fields as specified below.
The signature is verified by the signing public key of $from
(if no offline signature) or the transient pubkey
(if offline signed)
Payload
Signature
{% endhighlight %}
Total length: minimum 433 + payload length;
typical length for X25519 senders and without offline signatures:
457 + payload length.
Note that the message will typically be compressed with gzip at the I2CP layer,
which will result in significant savings if the from destination is compressible.
Note: The offline signature format is the same as in the Common Structures spec [Common]_ and [Streaming]_.
Signatures
----------
The signature is over the following fields.
TBD
- Prelude: The 32-byte hash of the target destination (not included in the datagram)
- flags
- options (if present)
- offline_signature (if present)
- payload
Prelude: "DatagramProtocol" ?
In repliable datagram, for the DSA_SHA1 key type, the signature was over the
SHA-256 hash of the payload, not the payload itself; here, the signature is
always over the fields above (NOT the hash), regardless of key type.
ToHash Verification
-------------------
Receivers must verify the signature (using their destination hash)
and discard the datagram on failure, for replay prevention.
Datagram3 Format
----------------
Add Datagram3 to [DATAGRAMS]_ as follows:
.. raw:: html
{% highlight lang='dataspec' -%}
+----+----+----+----+----+----+----+----+
| |
~ fromhash ~
~ ~
| |
+----+----+----+----+----+----+----+----+
| flags | options (optional) |
+----+----+ +
~ ~
~ ~
+----+----+----+----+----+----+----+----+
| |
~ payload ~
~ ~
| |
+----+----+----+----+----+----+----+----+
fromhash :: a `Hash`
length: 32 bytes
The originator of the datagram
flags :: (2 bytes)
Bit order: 15 14 ... 3 2 1 0
Bits 3-0: Version: 0x03 (0 0 1 1)
Bit 4: If 0, no options; if 1, options mapping is included
Bits 15-5: unused, set to 0 for compatibility with future uses
options :: (2+ bytes if present)
If flag indicates options are present, a `Mapping`
containing arbitrary text options
payload :: The data
Length: 0 to about 61 KB (see notes)
{% endhighlight %}
Total length: minimum 34 + payload length.
SAM
---
Add STYLE=DATAGRAM2 and STYLE=DATAGRAM3 to the SAMv3 specification.
Update the information on offline signatures.
Overhead
--------
This design adds 2 bytes of overhead to repliable datagrams for flags.
This is acceptable.
Add STYLE=DATAGRAM2
Security Analysis
=================
Including the target hash in the signature should be effective at preventing replay attacks.
The Datagram3 format lacks signatures, so the sender cannot be verified,
and replay attacks are possible. Any required validation must be done at the application layer,
or by the router at the ratchet layer.
Notes
=====
- The practical length is limited by lower layers of protocols - the tunnel
message spec [TUNMSG]_ limits messages to about 61.2 KB and the transports
[TRANSPORT]_ currently limit messages to about 64 KB, so the data length here
is limited to about 61 KB.
- See important notes about the reliability of large datagrams [API]_. For
best results, limit the payload to about 10 KB or less.
Compatibility
===============
None. Applications must be rewritten to route Datagram2 I2CP messages
based on protocol and/or port.
Datagram2 messages that are misrouted and interpreted as
Repliable datagram or streaming messages will fail based on signature, format, or both.
None
Migration
=========
Each UDP application must separately detect support and migrate.
The most prominent UDP application is bittorrent.
Bittorrent
----------
Bittorrent DHT: Needs extension flag probably,
e.g. i2p_dg2, coordinate with BiglyBT
Bittorrent UDP Announces [Prop160]_: Design in from the beginning.
Coordindate with BiglyBT, i2psnark, zzzot
Bittorrent UDP Announces [Prop160]_: Design in from the beginning?
Coorindate with BiglyBT, i2psnark, zzzot
Others
------
Bote: Unlikely
Bote: Unlikely to migrate, not actively maintained
Streamr: Nobody's using it, no migration planned
Streamr: Just switch, nobody's using it
SAM UDP apps: None known
@ -398,20 +138,11 @@ SAM UDP apps: None known
References
==========
.. [API]
{{ site_url('docs/api/datagrams', True) }}
.. [BT-SPEC]
{{ site_url('docs/applications/bittorrent', True) }}
.. [Common]
{{ spec_url('common-structures') }}
.. [DATAGRAMS]
{{ spec_url('datagrams') }}
.. [I2CP]
{{ site_url('docs/protocol/i2cp', True) }}
{{ spec_url('i2cp') }}
.. [Prop123]
{{ proposal_url('123') }}
@ -419,15 +150,5 @@ References
.. [Prop160]
{{ proposal_url('160') }}
.. [Prop164]
{{ proposal_url('164') }}
.. [Streaming]
{{ spec_url('streaming') }}
.. [TRANSPORT]
{{ site_url('docs/transport', True) }}
.. [TUNMSG]
{{ spec_url('tunnel-message') }}#notes
.. [BT-SPEC]
{{ site_url('docs/applications/bittorrent', True) }}

View File

@ -1,202 +0,0 @@
===========================
I2P proposal #165: SSU2 fix
===========================
.. meta::
:author: weko, orignal, the Anonymous, zzz
:created: 2024-01-19
:thread: http://i2pforum.i2p/viewforum.php?f=13
:lastupdated: 2024-11-17
:status: Open
:target: 0.9.62
.. contents::
Proposal by weko, orignal, the Anonymous and zzz.
Overview
--------
This document suggests changes to SSU2 following an attack on I2P that exploited vulnerabilities in SSU2. The primary goal is to enhance security and prevent Distributed Denial of Service (DDoS) attacks and de-anonymization attempts.
Threat model
------------
An attacker creates new fake RIs (router doesnt exist): is regular RI,
but he puts address, port, s and i keys from real Bobs router, then he
floods the network. When we are trying to connect to this (as we think
real) router, we, as Alice can connect to this address, but we cant be
sure what done it with real Bobs RI. This is possible and was used for
a Distributed Denial of Service attack (make big amount of such RIs and
flood the network), also this can make de-anon attacks easier by framing
good routers and do not framing attackers routers, if we ban IP with
many RIs (instead better distrubute tunnel building to this RIs as to
one router).
Potential fixes
---------------
1. Fix with support for old (before the change) routers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _overview-1:
Overview
^^^^^^^^
A workaround to support SSU2 connections with old routers.
Behavivor
^^^^^^^^^
Bobs router profile should have verified flag, its false by default
for all new routers (with no profile yet). When verified flag is
false, we never do connections with SSU2 as Alice to Bob - we cant be
sure in RI. If Bob connected to us (Alice) with NTCP2 or SSU2 or we
(Alice) connected to Bob with NTCP2 once (we can verify Bobs
RouterIdent in these cases) - flag is set to true.
Problems
^^^^^^^^
So, there is a problem with fake SSU2-only RI flood: we cant verify it
by ourselves and are forced to wait when the real router will make
connections with us.
2. Verify RouterIdent during connection creation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _overview-2:
Overview
^^^^^^^^
Add “RouterIdent” block for SessionRequest and SessionCreated.
Possible format of RouterIdent block
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1 byte flags, 32 bytes RouterIdent. Flag_0: 0 if receivers RouterIdent;
1 if senders RouterIdent
Behavior
^^^^^^^^
Alice (should(1), can(2)) send in payload RouterIdent block Flag_0 = 0
and Bobs RouterIdent. Bob (should(3), can(4)) check if is it his
RouterIdent, and if not: terminate the session with “Wrong RouterIdent”
reason, if it is his RouterIdent: send RI block with 1 in Flag_0 and
Bobs RouterIdent.
With (1) Bob does not support old routers. With (2) Bob supports old
routers, but can be a victim of DDoS from routers that are trying to
make connection with fake RIs. With (3) Alice does not support old
routers. With (4) Alice supports old routers and is using a hybrid
scheme: Fix 1 for old routers and Fix 2 for new routers. If RI says new
version, but while in the connection we didnts recieve the RouterIdent
block - terminate and remove RI.
.. _problems-1:
Problems
^^^^^^^^
An attacker can mask his fake routers as old, and with (4) we are
waiting for verified as in fix 1 anyways.
Notes
^^^^^
Instead of 32 byte RouterIdent, we can probably use 4 byte
siphash-of-the-hash, some HKDF or something else, which must be
sufficient.
3. Bob sets i = RouterIdent
~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _overview-3:
Overview
^^^^^^^^
Bob uses his RouterIdent as i key.
.. _behavior-1:
Behavior
^^^^^^^^
Bob (should(1), can(2)) uses his own RouterIdent as i key for SSU2.
Alice with (1) connects only if i = Bobs RouterIdent. Alice with (2)
uses the hybrid scheme (fix 3 and 1): if i = Bobs RouterIdent, we can
make the connection, otherwise we should verify it first (see fix 1).
With (1) Alice does not support old routers. With (2) Alice supports old
routers.
.. _problems-2:
Problems
^^^^^^^^
An attacker can mask his fake routers as old, and with (2) we are
waiting for verified as in fix 1 anyways.
.. _notes-1:
Notes
^^^^^
To save on RI size, better add handling if i key isnt specified. If it
is, then i = RouterIdent. In that case, Bob does not support old
routers.
4. Add one more MixHash to KDF of SessionRequest
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _overview-4:
Overview
^^^^^^^^
Add MixHash(Bob's ident hash) to NOISE state of "SessionRequest" message, e.g.
h = SHA256 (h || Bob's ident hash).
It must be last MixHash used as ad for ENCYPT or DECRYPT.
Additional SSU2 header flag "Verify Bob's ident" = 0x02 must be introduced.
.. _behavior-4:
Behavior
^^^^^^^^
- Alice adds MixHash with Bob's ident hash from Bob's RouterInfo and use it as ad for ENCRYPT and sets "Verify Bob's ident" flag
- Bob checks "Verify Bob's ident" flag and adds MixHash with own ident hash and use it ad as for DECRYPT. Is AEAD/Chacha20/Poly1305 fails, Bob closes the session.
Compatibity with older routers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Alice must check Bob's router version and if it satisfies miminal version supporting this proposal add this MixHash and set "Verify Bob's ident" flag. If router is older, Alice doesn't add MixHash and doesn't set "Verify Bob's ident" flag.
- Bob checks "Verify Bob's ident" flag and adds this MixHash if it's set. Older router don't set this flag and this MixHash shouldn't be added.
.. _problems-4:
Problems
^^^^^^^^
- An attacker can claim fake routers with older version. At some point olders router should be used with precaution and after they got verified by other ways.
Backward compability
--------------------
Described in fixes.
Current status
--------------
i2pd: Fix 1.

View File

@ -1,285 +0,0 @@
===================================================
I2P proposal #166: Identity/Host Aware Tunnel Types
===================================================
.. meta::
:author: eyedeekay
:created: 2024-05-27
:thread: http://i2pforum.i2p/viewforum.php?f=13
:lastupdated: 2024-08-27
:status: Open
:target: 0.9.65
.. contents::
Proposal for a Host-Aware HTTP Proxy Tunnel Type
------------------------------------------------
This is a proposal to resolve the “Shared Identity Problem” in
conventional HTTP-over-I2P usage by introducing a new HTTP proxy tunnel
type. This tunnel type has supplemental behavior which is intended to
prevent or limit the utility of tracking conducted by potential hostile
hidden service operators, against targeted user-agents(browsers) and the
I2P Client Application itself.
What is the “Shared Identity” problem?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The “Shared Identity” problem occurs when a user-agent on a
cryptographically addressed overlay network shares a cryptographic
identity with another user-agent. This occurs, for instance, when a
Firefox and GNU Wget are both configured to use the same HTTP Proxy.
In this scenario, it is possible for the server to collect and store the
cryptographic address(Destination) used to reply to the activity. It can
treat this as a “Fingerprint” which is always 100% unique, because it is
cryptographic in origin. This means that the linkability observed by the
Shared Identity problem is perfect.
But is it a problem?
^^^^^^^^^^^^^^^^^^^^
The shared identity problem is a problem when user-agents that speak the
same protocol desire unlinkability. `It was first mentioned in the
context of HTTP in this Reddit
Thread <https://old.reddit.com/r/i2p/comments/579idi/warning_i2p_is_linkablefingerprintable/>`__,
with the deleted comments accessible courtesy of
`pullpush.io <https://api.pullpush.io/reddit/search/comment/?link_id=579idi>`__.
*At the time* I was one of the most active respondents, and *at the
time* I believed the issue was small. In the past 8 years, the situation
and my opinion of it have changed, I now believe the threat posed by
malicious destination correlation grows considerably as more sites are
in a position to “profile” specific users.
This attack has a very low barrier to entry. It only requires that a
hidden service operator operate multiple services. For attacks on
contemporary visits(visiting multiple sites at the same time), this is
the only requirement. For non-contemporary linking, one of those
services must be a service which hosts “accounts” which belong to a
single user who is targeted for tracking.
Currently, any service operator who hosts user accounts will be able to
correlate them with activity across any sites they control by exploiting
the Shared Identity problem. Mastodon, Gitlab, or even simple forums
could be attackers in disguise as long as they operate more than one
service and have an interest in creating a profile for a user. This
surveillance could be conducted for stalking, financial gain, or
intelligence-related reasons. Right now there are dozens of major
operators, who could carry out this attack and gain meaningful data from
it. We mostly trust them not to for now, but players who dont care
about our opinions could easily emerge.
This is directly related to a fairly basic form of profile-building on
the clear web where organizations can correlate interactions on their
site with interations on networks they control. On I2P, because the
cryptographic destination is unique, this technique can sometimes be
even more reliable, albeit without the additional power of geolocation.
The Shared Identity is not useful against a user who is using I2P solely
to obfuscate geolocation. It also cannot be used to break I2Ps routing.
It is only a problem of contextual identity management.
- It is impossible to use the Shared Identity problem to geolocate an
I2P user.
- It is impossible to use the Shared Identity problem to link I2P
sessions if they are not contemporary.
However, it is possible to use it to degrade the anonymity of an I2P
user in circumstances which are probably very common. One reason they
are common is becase we encourage the use of Firefox, a web browser
which supports “Tabbed” operation.
- It is *always* possible to produce a fingerprint from the Shared
Identity problem in *any* web browser which supports requesting
third-party resources.
- Disabling Javascript accomplishes **nothing** against the Shared
Identity problem.
- If a link can be established between non-contemporary sessions such
as by “traditional” browser fingerprinting, then the Shared Identity
can be applied transitively, potentially enabling a non-contemporary
linking strategy.
- If a link can be established between a clearnet activity and an I2P
identity, for instance, if the target is logged into a site with both
an I2P and a clearnet presence on both sides, the Shared Identity can
be applied transitively, potentially enabling complete
de-anonymization.
How you view the severity of the Shared Identity problem as it applies
to the I2P HTTP proxy depends on where you(or more to the point, a
“user” with potentially uninformed expectationss) think the “contextual
identity” for the application lies. There are several possibilities:
1. HTTP is both the Application and the Contextual Identity - This is
how it works now. All HTTP Applications share an identity.
2. The Process is the Application and the Contextual Identity - This is
how it works when an application uses an API like SAMv3 or I2CP,
where an application creates its identity and controls its
lifetime.
3. HTTP is the Application, but the Host is the Contextual Identity
-This is the object of this proposal, which treats each Host as a
potential “Web Application” and treats the threat surface as such.
Is it Solvable?
^^^^^^^^^^^^^^^
It is probably not possible to make a proxy which intelligently responds
to every possible case in which its operation could weaken the
anonymity of an application. However, it is possible to build a proxy
which intelligently responds to a specific application which behaves in
a predictable way. For instance, in modern Web Browsers, it is expected
that users will have multiple tabs open, where they will be interacting
with multiple web sites, which will be distinguished by hostname.
This allows us to improve upon the behavior of the HTTP Proxy for this
type of HTTP user-agent by making the behavior of the proxy match the
behavior of the user-agent by giving each host its own Destination when
used with the HTTP Proxy. This change makes it impossible to use the
Shared Identity problem to derive a fingerprint which can be used to
correlate client activity with 2 hosts, because the 2 hosts will simply
no longer share a return identity.
Description:
^^^^^^^^^^^^
A new HTTP Proxy will be created and added to Hidden Services
Manager(I2PTunnel). The new HTTP Proxy will operate as a “multiplexer”
of I2PSocketManagers. The multiplexer itself has no destination. Each
individual I2PSocketManager which becomes part of the multiplex has its own
local destination, and its own tunnel pool. I2PSocketManagerss are created
on-demand by the multiplexer, where the “demand” is the first visit to the
new host. It is possible to optimize the creation of the I2PSocketManagers
before inserting them into the multiplexer by creating one or more in advance
and storing them outside the multiplexer. This may improve performance.
An additional I2PSocketManager, with its own destination, is set up as the
carrier of an “Outproxy” for any site which does *not* have an I2P
Destination, for example any Clearnet site. This effectively makes all
Outproxy usage a single Contextual Identity, with the caveat that
configuring multiple Outproxies for the tunnel will cause the normal
“Sticky” outproxy rotation, where each outproxy only gets requests for a
single site. This is *almost* the equivalent behavior as isolating
HTTP-over-I2P proxies by destination, on the clear internet.
Resource Considerations:
''''''''''''''''''''''''
The new HTTP proxy requires additional resources compared to the
existing HTTP proxy. It will:
- Potentially build more tunnels and I2PSocketManagers
- Build tunnels more often
Each of these requires:
- Local computing resources
- Network resources from peers
Settings:
'''''''''
In order to minimize the impact of the increased resource usage, the
proxy should be configured to use as little as possible. Proxies which
are part of the multiplexer(not the parent proxy) should be configured
to:
- Multiplexed I2PSocketManagers build 1 tunnel in, 1 tunnel out in their
tunnel pools
- Multiplexed I2PSocketManagers take 3 hops by default.
- Close sockets after 10 minutes of inactivity
- I2PSocketManagers started by the Multiplexer share the lifespan of the
Multiplexer. Multiplexed tunnels are not “Destructed” until the
parent Multiplexer is.
Diagrams:
^^^^^^^^^
The diagram below represents the current operation of the HTTP proxy,
which corresponds to “Possibility 1.” under the “Is it a problem”
section. As you can see, the HTTP proxy interacts with I2P sites
directly using only one destination. In this scenario, HTTP is both the
application and the contextual identity.
.. code:: md
**Current Situation: HTTP is the Application, HTTP is the Contextual Identity**
__-> Outproxy <-> i2pgit.org
/
Browser <-> HTTP Proxy(one Destination)<->I2PSocketManager <---> idk.i2p
\__-> translate.idk.i2p
\__-> git.idk.i2p
The diagram below represents the operation of a host-aware HTTP proxy,
which corresponds to “Possibility 3.” under the “Is it a problem”
section. In this secenario, HTTP is the application, but the Host
defines the contextual identity, wherein each I2P site interacts with a
different HTTP proxy with a unique destination per-host. This prevents
operators of multiple sites from being able to distinguish when the same
person is visiting multiple sites which they operate.
.. code:: md
**After the Change: HTTP is the Application, Host is the Contextual Identity**
__-> I2PSocketManager(Destination A - Outproxies Only) <--> i2pgit.org
/
Browser <-> HTTP Proxy Multiplexer(No Destination) <---> I2PSocketManager(Destination B) <--> idk.i2p
\__-> I2PSocketManager(Destination C) <--> translate.idk.i2p
\__-> I2PSocketManager(Destination C) <--> git.idk.i2p
Status:
^^^^^^^
A working Java implementation of the host-aware proxy which conforms to
an older version of this proposal is available at idk's fork under the
branch: i2p.i2p.2.6.0-browser-proxy-post-keepalive Link in citations. It
is under heavy revision, in order to break down the changes into smaller
sections.
Implementations with varying capabilities have been written in Go using
the SAMv3 library, they may be useful for embedding in other Go
applications or for go-i2p but are unsuitable for Java I2P.
Additionally, they lack good support for working interactively with
encrypted leaseSets.
Addendum: ``i2psocks``
A simple application-oriented approach to isolating other types of
clients is possible without implementing a new tunnel type or changing
the existing I2P code by combining I2PTunnel existing tools which are
already widely available and tested in the privacy community. However,
this approach makes a difficult assumption which is not true for HTTP
and also not true for many other kinds of potentsial I2P clients.
Roughly, the following script will produce an application-aware SOCKS5
proxy and socksify the underlying command:
.. code:: sh
#! /bin/sh
command_to_proxy="$@"
java -jar ~/i2p/lib/i2ptunnel.jar -wait -e 'sockstunnel 7695'
torsocks --port 7695 $command_to_proxy
Addendum: ``example implementation of the attack``
`An example implementation of the Shared Identity attack on HTTP
User-Agents <https://github.com/eyedeekay/colluding_sites_attack/>`__
has existed for several years. An additional example is available in the
``simple-colluder`` subdirectory of `idks prop166
repository <https://git.idk.i2p/idk/i2p.host-aware-proxy>`__ These
examples are deliberately designed to demonstrate that the attack works
and would require modification(albeit minor) to be turned into a real
attack.
Citations:
''''''''''
https://old.reddit.com/r/i2p/comments/579idi/warning_i2p_is_linkablefingerprintable/
https://api.pullpush.io/reddit/search/comment/?link_id=579idi
https://github.com/eyedeekay/colluding_sites_attack/
https://en.wikipedia.org/wiki/Shadow_profile
https://github.com/eyedeekay/si-i2p-plugin/
https://github.com/eyedeekay/eeproxy/
https://geti2p.net/en/docs/api/socks
https://i2pgit.org/idk/i2p.www/-/compare/master...166-identity-aware-proxies?from_project_id=17
https://i2pgit.org/idk/i2p.i2p/-/tree/i2p.i2p.2.6.0-browser-proxy-post-keepalive?ref_type=heads

View File

@ -1,448 +0,0 @@
===================================
Service Records in LS2
===================================
.. meta::
:author: zzz, orignal, eyedeekay
:created: 2024-06-22
:thread: http://zzz.i2p/topics/3641
:lastupdated: 2025-04-03
:status: Closed
:target: 0.9.66
.. contents::
Status
======
Approved on 2nd review 2025-04-01; specs are updated; not yet implemented.
Overview
========
I2P lacks a centralized DNS system.
However, the address book, together with the b32 hostname system, allows
the router to look up full destinations and fetch lease sets, which contain
a list of gateways and keys so that clients may connect to that destination.
So, leasesets are somewhat like a DNS record. But there is currently no facility to
find out if that host supports any services, either on that destination or a different one,
in a manner similar to DNS SRV records [SRV]_ [RFC2782]_.
The first application for this may be peer-to-peer email.
Other possible applications: DNS, GNS, key servers, certificate authorities, time servers,
bittorrent, cryptocurrencies, other peer-to-peer applications.
Related Proposals and Alternatives
==================================
Service Lists
--------------
The LS2 proposal 123 [Prop123]_ defined 'service records' that indicated a destination
was participating in a global service. The floodfills would aggregate these records
into global 'service lists'.
This was never implemented due to complexity, lack of authentication,
security, and spamming concerns.
This proposal is different in that it provides lookup for a service for a specific destination,
not a global pool of destinations for some global service.
GNS
-----
GNS [GNS]_ proposes that everybody runs their own DNS server.
This proposal is complementary, in that we could use service records to specify
that GNS (or DNS) is supported, with a standard service name of "domain" on port 53.
Dot well-known
---------------
In [DOTWELLKNOWN]_ it is proposed that services be looked up via an HTTP request to
/.well-known/i2pmail.key. This requires that every service must have a related
website to host the key. Most users do not run websites.
One workaround is that we could presume that a service for a b32 address is actually
running on that b32 address. So that looking for the service for example.i2p requires
the HTTP fetch from http://example.i2p/.well-known/i2pmail.key, but
a service for aaa...aaa.b32.i2p does not require that lookup, it can just connect directly.
But there's an ambiguity there, because example.i2p can also be addressed by its b32.
MX Records
----------
SRV records are simply a generic version of MX records for any service.
"_smtp._tcp" is the "MX" record.
There is no need for MX records if we have SRV records, and MX records
alone do not provide a generic record for any service.
Design
======
Service records are placed in the options section in LS2 [LS2]_.
The LS2 options section is currently unused.
Not supported for LS1.
This is similar to the tunnel bandwidth proposal [Prop168]_,
which defines options for tunnel build records.
To lookup a service address for a specific hostname or b32, the router fetches the
leaseset and looks up the service record in the properties.
The service may be hosted on the same destination as the LS itself, or may reference
a different hostname/b32.
If the target destination for the service is different, the target LS must also
include a service record, pointing to itself, indicating that it supports the service.
The design does not require special support or caching or any changes in the floodfills.
Only the leaseset publisher, and the client looking up a service record,
must support these changes.
Minor I2CP and SAM extensions are proposed to facilitate retrieval of
service records by clients.
Specification
=============
LS2 Option Specification
---------------------------
LS2 options MUST be sorted by key, so the signature is invariant.
Defined as follows:
- serviceoption := optionkey optionvalue
- optionkey := _service._proto
- service := The symbolic name of the desired service. Must be lower case. Example: "smtp".
Allowed chars are [a-z0-9-] and must not start or end with a '-'.
Standard identifiers from [REGISTRY]_ or Linux /etc/services must be used if defined there.
- proto := The transport protocol of the desired service. Must be lower case, either "tcp" or "udp".
"tcp" means streaming and "udp" means repliable datagrams.
Protocol indicators for raw datagrams and datagram2 may be defined later.
Allowed chars are [a-z0-9-] and must not start or end with a '-'.
- optionvalue := self | srvrecord[,srvrecord]*
- self := "0" ttl port [appoptions]
- srvrecord := "1" ttl priority weight port target [appoptions]
- ttl := time to live, integer seconds. Positive integer. Example: "86400".
A minimum of 86400 (one day) is recommended, see Recommendations section below for details.
- priority := The priority of the target host, lower value means more preferred. Non-negative integer. Example: "0"
Only useful if more than one record, but required even if just one record.
- weight := A relative weight for records with the same priority. Higher value means more chance of getting picked. Non-negative integer. Example: "0"
Only useful if more than one record, but required even if just one record.
- port := The I2CP port on which the service is to be found. Non-negative integer. Example: "25"
Port 0 is supported but not recommended.
- target := The hostname or b32 of the destination providing the service. A valid hostname as in [NAMING]_. Must be lower case.
Example: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b32.i2p" or "example.i2p".
b32 is recommended unless the hostname is "well known", i.e. in official or default address books.
- appoptions := arbitrary text specific to the application, must not contain " " or ",". Encoding is UTF-8.
Examples
``````````
In LS2 for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b32.i2p, pointing to one SMTP server:
"_smtp._tcp" "1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p"
In LS2 for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b32.i2p, pointing to two SMTP servers:
"_smtp._tcp" "1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p,86400 1 0 25 cccccccccccccccccccccccccccccccccccccccccccc.b32.i2p"
In LS2 for bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p, pointing to itself as a SMTP server:
"_smtp._tcp" "0 999999 25"
Possible format for redirecting email (see below):
"_smtp._tcp" "1 86400 0 0 25 smtp.postman.i2p example@mail.i2p"
Limits
```````
The Mapping data structure format used for LS2 options limits keys and values to 255 bytes (not chars) max.
With a b32 target, the optionvalue is about 67 bytes, so only 3 records would fit.
Maybe only one or two with a long appoptions field, or up to four or five with a short hostname.
This should be sufficient; multiple records should be rare.
Differences from [RFC2782]_
````````````````````````````
- No trailing dots
- No name after the proto
- Lower case required
- In text format with comma-separated records, not binary DNS format
- Different record type indicators
- Additional appoptions field
Notes
`````
No wildcarding such as (asterisk), (asterisk)._tcp, or _tcp is allowed.
Each supported service must have its own record.
Service Name Registry
----------------------
Non-standard identifiers that are not listed in [REGISTRY]_ or Linux /etc/services
may be requested and added to the common structures specification [LS2]_.
Service-specific appoptions formats may also be added there.
I2CP Specification
------------------
The [I2CP]_ protocol must be extended to support service lookups.
Additional MessageStatusMessage and/or HostReplyMessage error codes related to service lookup
are required.
To make the lookup facility general, not just service record-specific,
the design is to support retrieval of all LS2 options.
Implementation: Extend HostLookupMessage to add request for
LS2 options for hash, hostname, and destination (request types 2-4).
Extend HostReplyMessage to add the options mapping if requested.
Extend HostReplyMessage with additional error codes.
Options mappings may be cached or negative cached for a short time on either the client or router side,
implementation-dependent. Recommended maximum time is one hour, unless the service record TTL is shorter.
Service records may be cached up to the TTL specified by the application, client, or router.
Extend the specification as follows:
Configuration options
`````````````````````
Add the following to [I2CP-OPTIONS]
i2cp.leaseSetOption.nnn
Options to be put in the leaseset. Only available for LS2.
nnn starts with 0. Option value contains "key=value".
(do not include quotes)
Example:
i2cp.leaseSetOption.0=_smtp._tcp=1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p
HostLookup Message
``````````````````
- Lookup type 2: Hash lookup, request options mapping
- Lookup type 3: Hostname lookup, request options mapping
- Lookup type 4: Destination lookup, request options mapping
For lookup type 4, item 5 is a Destination.
HostReply Message
``````````````````
For lookup types 2-4, the router must fetch the leaseset,
even if the lookup key is in the address book.
If successful, the HostReply will contain the options Mapping
from the leaseset, and includes it as item 5 after the destination.
If there are no options in the Mapping, or the leaseset was version 1,
it will still be included as an empty Mapping (two bytes: 0 0).
All options from the leaseset will be included, not just service record options.
For example, options for parameters defined in the future may be present.
On leaseset lookup failure, the reply will contain a new error code 6 (Leaseset lookup failure)
and will not include a mapping.
When error code 6 is returned, the Destination field may or may not be present.
It will be present if a hostname lookup in the address book was successful,
or if a previous lookup was successful and the result was cached,
or if the Destination was present in the lookup message (lookup type 4).
If a lookup type is not supported,
the reply will contain a new error code 7 (lookup type unsupported).
SAM Specification
------------------
The [SAMv3]_ protocol must be extended to support service lookups.
Extend NAMING LOOKUP as follows:
NAMING LOOKUP NAME=example.i2p OPTIONS=true requests the options mapping in the reply.
NAME may be a full base64 destination when OPTIONS=true.
If the destination lookup was successful and options were present in the leaseset,
then in the reply, following the destination,
will be one or more options in the form of OPTION:key=value.
Each option will have a separate OPTION: prefix.
All options from the leaseset will be included, not just service record options.
For example, options for parameters defined in the future may be present.
Example:
NAMING REPLY RESULT=OK NAME=example.i2p VALUE=base64dest OPTION:_smtp._tcp="1 86400 0 0 25 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.b32.i2p"
Keys containing '=', and keys or values containing a newline,
are considered invalid and the key/value pair will be removed from the reply.
If there are no options found in the leaseset, or if the leaseset was version 1,
then the response will not include any options.
If OPTIONS=true was in the lookup, and the leaseset is not found, a new result value LEASESET_NOT_FOUND will be returned.
Naming Lookup Alternative
==========================
An alternative design was considered, to support lookups of services
as a full hostname, for example _smtp._tcp.example.i2p,
by updating [NAMING]_ to specify handling of hostnames starting with '_'.
This was rejected for two reasons:
- I2CP and SAM changes would still be necessary to pass through the TTL and port information to the client.
- It would not be a general facility that could be used to retrieve other LS2
options that could be defined in the future.
Recommendations
================
Servers should specify a TTL of at least 86400, and the standard port for the application.
Advanced Features
==================
Recursive Lookups
----------------------
It may be desirable to support recursive lookups, where each successive leaseset
is checked for a service record pointing to another leaseset, DNS-style.
This is probably not necessary, at least in an initial implementation.
TODO
Application-specific fields
-----------------------------
It may be desirable to have application-specific data in the service record.
For example, the operator of example.i2p may wish to indicate that email should
be forwarded to example@mail.i2p. The "example@" part would need to be in a separate field
of the service record, or stripped from the target.
Even if the operator runs his own email service, he may wish to indicate that
email should be sent to example@example.i2p. Most I2P services are run by a single person.
So a separate field may be helpful here as well.
TODO how to do this in a generic way
Changes required for Email
------------------------------
Out of the scope of this proposal. See [DOTWELLKNOWN]_ for a discussion.
Implementation Notes
=====================
Caching of service records up to the TTL may be done by the router or the application,
implementation-dependent. Whether to cache persistently is also implementation-dependent.
Lookups must also lookup the target leaseset and verify it contains a "self" record
before returning the target destination to the client.
Security Analysis
=================
As the leaseset is signed, any service records within it are authenticated by the signing key of the destination.
The service records are public and visible to floodfills, unless the leaseset is encrypted.
Any router requesting the leaseset will be able to see the service records.
A SRV record other than "self" (i.e., one that points to a different hostname/b32 target)
does not require the consent of the targeted hostname/b32.
It's not clear if a redirection of a service to an arbitrary destination could facilitate some
sort of attack, or what the purpose of such an attack would be.
However, this proposal mitigates such an attack by requiring that the target
also publish a "self" SRV record. Implementers must check for a "self" record
in the leaseset of the target.
Compatibility
===============
LS2: No issues. All known implementations currently ignore the options field in LS2,
and correctly skip over a non-empty options field.
This was verified in testing by both Java I2P and i2pd during the development of LS2.
LS2 was implemented in 0.9.38 in 2016 and is well-supported by all router implementations.
The design does not require special support or caching or any changes in the floodfills.
Naming: '_' is not a valid character in i2p hostnames.
I2CP: Lookup types 2-4 should not be sent to routers below the minimum API version
at which it is supported (TBD).
SAM: Java SAM server ignores additional keys/values such as OPTIONS=true.
i2pd should as well, to be verified.
SAM clients will not get the additional values in the reply unless requested with OPTIONS=true.
No version bump should be necessary.
Migration
=========
Implementations may add support at any time, no coordination is needed,
except for an agreement on the effective API version for the I2CP changes.
SAM compatibility versions for each implementation will be documented in the SAM spec.
References
==========
.. [DOTWELLKNOWN]
http://i2pforum.i2p/viewtopic.php?p=3102
.. [I2CP]
{{ spec_url('i2cp') }}
.. [I2CP-OPTIONS]
{{ site_url('docs/protocol/i2cp', True) }}
.. [LS2]
{{ spec_url('common-structures') }}
.. [GNS]
http://zzz.i2p/topcs/1545
.. [NAMING]
{{ site_url('docs/naming', True) }}
.. [Prop123]
{{ proposal_url('123') }}
.. [Prop168]
{{ proposal_url('168') }}
.. [REGISTRY]
http://www.dns-sd.org/ServiceTypes.html
.. [RFC2782]
https://datatracker.ietf.org/doc/html/rfc2782
.. [SAMv3]
{{ site_url('docs/api/samv3') }}
.. [SRV]
https://en.wikipedia.org/wiki/SRV_record

View File

@ -1,200 +0,0 @@
===================================
Tunnel Bandwidth Parameters
===================================
.. meta::
:author: zzz
:created: 2024-07-31
:thread: http://zzz.i2p/topics/3652
:lastupdated: 2024-12-10
:status: Closed
:target: 0.9.65
.. contents::
NOTE
====
This proposal was approved and is now in the
[Tunnel-Creation-ECIES]_ specification as of API 0.9.65.
There are no known implementations yet; implementation dates / API versions are TBD.
Overview
========
As we have increased the performance of the network over the last several years
with new protocols, encryption types, and congestion control improvements,
faster applications such as video streaming are becoming possible.
These applications require high bandwidth at each hop in their client tunnels.
Participating routers, however, do not have any information about how much
bandwidth a tunnel will use when they get a tunnel build message.
They can only accept or reject a tunnel based on the current total bandwidth
used by all participating tunnels and the total bandwidth limit for participating tunnels.
Requesting routers also do not have any information on how much bandwidth
is available at each hop.
Also, routers currently have no way to limit inbound traffic on a tunnel.
This would be quite useful during times of overload or DDoS of a service.
This proposal addresses these issues by adding bandwidth parameters to
the tunnel build request and reply messages.
Design
======
Add bandwidth parameters to the records in ECIES tunnel build messages [Tunnel-Creation-ECIES]_
in the tunnel build options mapping field. Use short parameter names since the space available
for the options field is limited.
Tunnel build messages are fixed-size so this does not increase the
size of the messages.
Specification
=============
Update the ECIES tunnel build message specification [Tunnel-Creation-ECIES]_
as follows:
For both long and short ECIES build records:
Build Request Options
---------------------------
The following three options may be set in the tunnel build options mapping field of the record:
A requesting router may include any, all, or none.
- m := minimum bandwidth required for this tunnel (KBps positive integer as a string)
- r := requested bandwidth for this tunnel (KBps positive integer as a string)
- l := limit bandwidth for this tunnel; only sent to IBGW (KBps positive integer as a string)
Constraint: m <= r <= l
The participating router should reject the tunnel if "m" is specified and it cannot
provide at least that much bandwidth.
Request options are sent to each participant in the corresponding encrypted build request record,
and are not visible to other participants.
Build Reply Option
---------------------------
The following option may be set in the tunnel build reply options mapping field of the record,
when the response is ACCEPTED:
- b := bandwidth available for this tunnel (KBps positive integer as a string)
The participating router should include this if either "m" or "r" was specified
in the build request. The value should be at least that of the "m" value if specified,
but may be less or more than the "r" value if specified.
The participating router should attempt to reserve and provide at least this
much bandwidth for the tunnel, however this is not guaranteed.
Routers cannot predict conditions 10 minutes into the future, and
participating traffic is lower-priority than a router's own traffic and tunnels.
Routers may also over-allocate available bandwidth if necessary, and this is
probably desirable, as other hops in the tunnel could reject it.
For these reasons, the participating router's reply should be treated
as a best-effort commitment, but not a guarantee.
Reply options are sent to the requesting router in the corresponding encrypted build reply record,
and are not visible to other participants.
Implementation Notes
=====================
Bandwidth parameters are as seen at the participating routers at the tunnel layer,
i.e. the number of fixed-size 1 KB tunnel messages per second.
Transport (NTCP2 or SSU2) overhead is not included.
This bandwidth may be much more or less than the bandwidth seen at the client.
Tunnel messages contain substantial overhead, including overhead from higher layers
including ratchet and streaming. Intermittent small messages such as streaming acks
will be expanded to 1 KB each.
However, gzip compression at the I2CP layer may substantially reduce bandwidth.
The simplest implementation at the requesting router is to use
the average, minimum, and/or maximum bandwidths of current tunnels in the pool
to calculate the values to put in the request.
More complex algorithms are possible and are up to the implementer.
There are no current I2CP or SAM options defined for the client to tell the
router what bandwidth is required, and no new options are proposed here.
Options may be defined at a later date if necessary.
Implementations may use available bandwidth or any other data, algorithm, local policy,
or local configuration to calculate the bandwidth value returned in the
build response. Not specified by this proposal.
This proposal requires inbound gateways to implement per-tunnel
throttling if requested by the "l" option.
It does not require other participating hops to implement per-tunnel or global
throttling of any type, or specify a particular algorithm or implementation, if any.
This proposal also does not require client routers to throttle traffic
to the "b" value returned by the participating hop, and depending on application,
that may not be possible, particularly for inbound tunnels.
This proposal only affects tunnels created by the originator. There is no
method defined to request or allocate bandwidth for "far-end" tunnels created
by the the owner of the other end of an end-to-end connection.
Security Analysis
=================
Client fingerprinting or correlation may be possible based on requests.
The client (originating) router may wish to randomize the "m" and "r" values instead of sending
the same value to each hop; or send a limited set values that represent bandwidth "buckets",
or some combination of both.
Over-allocation DDoS: While it may be possible to DDoS a router now by building and
using a large number of tunnels through it, this proposal arguably makes it much easier,
by simply requesting one or more tunnels with large bandwidth requests.
Implementations can and should use one or more of the following strategies
to mitigate this risk:
- Overallocation of available bandwidth
- Limit per-tunnel allocation to some percentage of available bandwidth
- Limit rate of increase in allocated bandwidth
- Limit rate of increase in used bandwidth
- Limit allocated bandwidth for a tunnel if not used early in a tunnel's lifetime (use it or lose it)
- Tracking average bandwidth per tunnel
- Tracking requested vs. actual bandwidth used per tunnel
Compatibility
===============
No issues. All known implementations currently ignore the mapping field in build messages,
and correctly skip over a non-empty options field.
Migration
=========
Implementations may add support at any time, no coordination is needed.
As there is currently no API version defined where support for this proposal is required,
routers should check for a "b" response to confirm support.
References
==========
.. [Tunnel-Creation-ECIES]
{{ spec_url('tunnel-creation-ecies') }}

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,8 @@ SSU Protocol Specification
==========================
.. meta::
:category: Transports
:lastupdated: 2024-01
:accuratefor: 0.9.61
:lastupdated: 2022-06
:accuratefor: 0.9.54
.. contents::
@ -12,10 +12,6 @@ SSU Protocol Specification
Overview
========
DEPRECATED - SSU has been replaced by SSU2.
SSU support was removed from i2pd in release 2.44.0 (API 0.9.56) 2022-11.
SSU support was removed from Java I2P in release 2.4.0 (API 0.9.61) 2023-12.
See [SSU]_ for an overview of the SSU transport.

View File

@ -3,8 +3,8 @@ SSU2
======
.. meta::
:category: Transports
:lastupdated: 2025-04
:accuratefor: 0.9.65
:lastupdated: 2023-01
:accuratefor: 0.9.57
.. contents::
@ -13,7 +13,7 @@ SSU2
Status
========
Substantially complete. See [Prop159]_ for additional background and goals,
Testing in progress. See [Prop159]_ for additional background and goals,
including security analysis, threat models, a review of SSU 1 security and issues,
and excerpts of the QUIC specifications.
@ -40,7 +40,7 @@ Connection Migration 0.9.55+ dev 0.9.56 2022-11
Immediate ACK flag 0.9.55+ dev 0.9.56 2022-11
Key Rotation 0.9.57 2023-02 0.9.58 2023-05
Disable SSU 1 (i2pd) 0.9.56 2022-11
Disable SSU 1 (Java I2P) 0.9.58 2023-05 0.9.61 2023-12
Disable SSU 1 (Java I2P) 0.9.58 2023-05 0.9.59 2023-08
========================== ===================== ====================
Basic Session includes the handshake and data phase.
@ -464,7 +464,7 @@ Before header encryption:
Short Header
`````````````
The short header is 16 bytes. It is used for Session Created and for Data messages.
Unauthenticated messages such as Session Request, Retry, and Peer Test will
Uauthenticated messages such as Session Request, Retry, and Peer Test will
always use the long header.
16 bytes is required, because
@ -1075,7 +1075,7 @@ KDF for Session Request
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
@ -1375,7 +1375,7 @@ KDF for Session Created and Session Confirmed part 1
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
@ -1549,7 +1549,7 @@ Payload
- DateTime block
- Address block
- Relay Tag block (optional)
- New Token block (not recommended, see note)
- New Token block (optional)
- First Packet Number block (optional)
- Options block (optional)
- Termination block (not recommended, send in a retry message instead)
@ -1589,10 +1589,6 @@ Notes
- Bob sends a relay tag block if requested by Alice in the Session Request.
- New Token block is not recommended in Session Created, because Bob
should do validation of the Session Confirmed first. See
the Tokens section below.
Issues
``````
@ -1658,7 +1654,7 @@ This is the "se" message pattern:
chainKey = keydata[0:31]
// AEAD parameters
k = keydata[32:63]
k = keydata[32:64]
n = 0
ad = h
ciphertext = ENCRYPT(k, n, payload, ad)
@ -3864,12 +3860,9 @@ used as a keep-alive or to validate an IP/Port change.
Notes:
- A minimum data size of 8 bytes, containing random data,
is recommended but not required.
- The max size is not specified, but it should be well under
1280, because the PMTU during the path validation phase is 1280.
- Large challenge sizes are not recommended because they could
be a vector for packet amplification attacks.
A minimum data size of 8 bytes, containing random data,
is recommended but not required.
Path Response
@ -4223,9 +4216,7 @@ stores the values and associated IP and port (in-memory or persistently).
The generator may not generate an opaque value, for example,
using the SipHash (with a secret seed K0, K1) of the IP, port, and current hour or day,
to create tokens that do not need to be saved in-memory,
because this method makes it difficult to reject reused tokens and replay attacks.
However, it is a topic for further study if we may migrate to such a scheme,
as [WireGuard]_ does, using a 16-byte HMAC of a server secret and IP address.
because this method make it difficult to reject reused tokens and replay attacks.
Tokens may only be used once.
A token sent from Bob to Alice in a Retry message must be used immediately, and expires
@ -4234,8 +4225,7 @@ A token sent in a New Token block in an established session
may be used in a subsequent connection, and it
expires at the time specified in that block.
Expiration is specified by the sender; recommended values are
several minutes minimum, one or more hours maximum, depending on
desired maximum overhead of stored tokens.
one hour minimum, several hours maximum.
If a router's IP or port changes, it must delete all saved tokens
(both inbound and outbound) for the old IP or port, as they are no longer valid.
@ -4246,15 +4236,9 @@ A router may choose to limit token storage, and remove the oldest stored tokens
even if they have not expired.
New Token blocks may be sent from Alice to Bob or Bob to Alice.
They would typically be sent at least once, during or soon after session establishment.
Due to validation checks of the RouterInfo in the Session Confirmed message,
Bob should not send a New Token block in the Session Created message,
it may be sent with the ACK 0 and Router Info after the Session Confirmed is received
and validated.
As session lifetimes are often longer than token expiration,
the token should be resent before or after expiration with a new expiration time,
or a new token should be sent.
They would typically be sent once, during or soon after session establishment.
The token may be resent before or after expiration with a new expiration time,
or a new token may be sent.
Routers should assume that only the last token received is valid;
there is no requirement to store multiple inbound or outbound tokens for the same IP/port.
@ -4343,7 +4327,7 @@ An additional packet count limit may be useful as well to prevent
buffer overflow in the kernel or in middleboxes, implementation dependent,
although this may add significant complexity.
If per-session and/or total packet output is bandwidth-limited and/or paced,
this may mitigate the need for packet count limiting.
this may mitigate the need for packet count ilmiting.
@ -4784,9 +4768,9 @@ Message Contents
The Data messages should contain the following blocks.
Order is not specified except that Padding must be last:
- Path Challenge or Path Response block.
Path Challenge contains opaque data, recommended 8 bytes minimum.
Path Response contains the data from the Path Challenge.
- Path Validation or Path Response block.
Path Validation contains opaque data, recommended 8 bytes minimum.
Path Response contains the data from the Path Validation.
- Address block containing the recipient's apparent IP
- DateTime block
- ACK block
@ -4795,7 +4779,7 @@ Order is not specified except that Padding must be last:
It is not recommended to include any other blocks
(for example, I2NP) in the message.
It is allowed to include a Path Challenge block in the message
It is allowed to include a Path Validation block in the message
containing the Path Response, to initiate a validation
in the other direction.
@ -4933,8 +4917,8 @@ the other peer should initiate a path challenge in the other direction.
Use as Ping/Pong
-----------------
Path Challenge and Path Response blocks may be used at any time as Ping/Pong packets.
Reception of a Path Challenge block does not change any state at the receiver,
Path Validation and Path Response blocks may be used at any time as Ping/Pong packets.
Reception of a Path Validation block does not change any state at the receiver,
unless received from a different IP/port.
@ -5493,19 +5477,8 @@ are all in-session and are covered by the
data phase ACK and retransmission processes.
Relay Request, Relay Intro, and Relay Response blocks are ack-eliciting.
Note that usually, Charlie will respond immediately to a Relay Intro
with a Relay Response, which should include an ACK block.
In that case, no separate message with an ACK block is required.
Hole punch may be retransmitted, as in SSU 1.
Unlike I2NP messages, the Relay messages do not have unique identifiers,
so duplicates must be detected by the relay state machine, using the nonce.
Implementations may also need to maintain a cache of recently-used nonces,
so that received duplicates may be detected even after the state machine for that nonce has completed.
IPv4/v6
----------
All features of SSU 1 relay are supported, including those documented in
@ -6090,8 +6063,6 @@ Recommended Constants
- Max ACK ranges: 256?
- Max ACK depth: 512?
- Padding distribution: 0-15 bytes, or greater
- Data phase minimum retransmission timeout: 1 second, as in [RFC-6298]_
- See also [RFC-6298]_ for additional guidance on retransmission timers for the data phase.
Packet Overhead Analysis
@ -6127,22 +6098,6 @@ Total 1314
================== =========== ===== ====== ======= ====== =====
Issues and Future Work
======================
Tokens
------
We specify above that the token must be a randomly-generated 8 byte value,
not generate an opaque value such as a hash or HMAC of a server secret
and the IP, port, due to reuse attacks.
However, this requires temporary and (optionally) persistent storage of
delivered tokens.
[WireGuard]_ uses a 16-byte HMAC of a server secret and IP address,
and the server secret rotates every two minutes.
We should investigate something similar, with a longer server secret lifetime.
If we embed a timestamp in the token, that may be a solution, but
an 8-byte token may not be large enough for that.

Some files were not shown because too many files have changed in this diff Show More