proposal 149

This commit is contained in:
zzz
2019-03-13 16:13:26 +00:00
parent 8eb0edcef0
commit 0dfef3ec7a
2 changed files with 185 additions and 24 deletions

View File

@ -1213,30 +1213,7 @@ Downsides of PSK client authorization
Encrypted LS with Base 32 Addresses
```````````````````````````````````
You can't use a traditional base 32 address for an encrypted LS2,
as it contains only the hash of the destination. It does not provide the non-blinded public key.
Therefore, a base 32 address alone is insufficient.
The client needs either the full destination (which contains the public key),
or the public key by itself.
If the client has the full destination in an address book, and the address book
supports reverse lookup by hash, then the public key may be retrieved.
So we need a new format that puts the public key instead of the hash into
a base32 address. This format must also contain the signature type of the
public key, and the signature type of the blinding scheme.
The total requirements are 32 + 2 + 2 = 36 bytes, requiring 58 characters in base 32.
.. raw:: html
{% highlight lang='text' %}
data = 32 byte pubkey || 2 byte unblinded sigtype || 2 byte blinded sigtype
address = Base32Encode(data) || ".b32.i2p"
{% endhighlight %}
We use the same ".b32.i2p" suffix as for traditional base 32 addresses.
Addresses for encrypted leasesets are identified by the 58 encoded characters
(36 decoded bytes), compared to 52 characters (32 bytes) for traditional base 32 addresses.
The five unused bits at the end of b32 must be 0.
See proposal 149.
You can't use an encrypted LS2 for bittorrent, because of compact announce replies which are 32 bytes.
The 32 bytes contain only the hash. There is no room for an indication that the

View File

@ -0,0 +1,184 @@
=====================
B32 for Encrypted LS2
=====================
.. meta::
:author: zzz
:created: 2019-03-13
:thread: http://zzz.i2p/topics/2682
:lastupdated: 2019-03-13
:status: Open
.. contents::
Overview
========
Standard Base 32 ("b32") addresses contain the hash of the destination.
This will not work for encrypted ls2 (proposal 123).
You can't use a traditional base 32 address for an encrypted LS2 (proposal 123),
as it contains only the hash of the destination. It does not provide the non-blinded public key.
Clients must know the destination's public key, sig type,
the blinded sig type, and an optional secret or private key
to fetch and decrypt the leaseset.
Therefore, a base 32 address alone is insufficient.
The client needs either the full destination (which contains the public key),
or the public key by itself.
If the client has the full destination in an address book, and the address book
supports reverse lookup by hash, then the public key may be retrieved.
So we need a new format that puts the public key instead of the hash into
a base32 address. This format must also contain the signature type of the
public key, and the signature type of the blinding scheme.
This proposal documents a new b32 format for these addresses.
While we have referred to this new format during discussions
as a "b33" address, the actual new format retains the usual ".b32.i2p" suffix.
Goals
=====
- Include both unblinded and blinded sigtypes to support future blinding schemes
- Support pubkeys larger than 32 bytes
- Ensure b32 chars are all or mostly random, especially at the beginning
(don't want all addresses to start with the same chars)
- Parseable
- Support "private" links that include blinding secret and/or per-client key
- Add checksum to detect typos
- Minimize length, maintain DNS label length less than 63 chars for normal usage
- Retain the usual ".b32.i2p" suffix.
Design
======
- New format will contain the unblinded public key, unblinded sig type,
and blinded sig type.
- Optionally contain a secret and/or private key, for private links only
- Use the existing ".b32.i2p" suffix, but with a longer length.
- Add a checksum.
- Addresses for encrypted leasesets are identified by 56 or more encoded characters
(35 or more decoded bytes), compared to 52 characters (32 bytes) for traditional base 32 addresses.
Specification
=============
Creation and encoding
---------------------
Construct a hostname of {56+ chars}.b32.i2p (35+ chars in binary) as follows:
.. raw:: html
{% highlight lang='text' %}
flag (1 byte)
bit 0: 0 for one-byte sigtypes, 1 for two-byte sigtypes
bit 1: 0 for no secret, 1 for appended secret
bit 2: 0 for no per-client auth, 1 for appended per-client privkey
bits 7-3: Unused, set to 0
public key sigtype (1 or 2 bytes as indicated in flags)
If 1 byte, the upper byte is assumed zero
blinded key sigtype (1 or 2 bytes as indicated in flags)
If 1 byte, the upper byte is assumed zero
public key
Number of bytes as implied by sigtype
optional secret (only if secret flag is set)
length of secret (1 byte)
secret (UTF-8 encoded)
optional auth private key (only if auth flag is set)
auth type (1 byte)
length of private key (1 byte)
private key
{% endhighlight %}
Post-processing and checksum:
.. raw:: html
{% highlight lang='text' %}
Construct the binary data as above.
Calculate checksum = Adler32(data[3:end])
data[0] ^= checksum[0]
data[1] ^= checksum[1]
data[2] ^= checksum[2]
hostname = Base32.encode(data) || ".b32.i2p"
{% endhighlight %}
Any unused bits at the end of the b32 must be 0.
There are no unused bits for a standard 56 character (35 byte) address.
Decoding and Verification
-------------------------
.. raw:: html
{% highlight lang='text' %}
strip the ".b32.i2p" from the hostname
data = Base32.decode(hostname)
Calculate checksum = Adler32(data[3:end])
flags = data[0] ^ checksum[0]
if 1 byte sigtypes:
pubkey sigtype = data[1] ^ checksum[1]
blinded sigtype = data[2] ^ checksum[2]
else (2 byte sigtypes) :
pubkey sigtype = data[1] ^ checksum[1] || data[2] ^ checksum[2]
blinded sigtype = data[3] || data[4]
parse the remainder based on the flags to get the public key,
optional secret, and optional auth privkey
{% endhighlight %}
Justification
=============
- XORing first 3 bytes with the hash provides a limited checksum capability,
and ensures that all base32 chars at the beginning are randomized.
Only a few flag and sigtype combinations are valid, so any typo is likely to create an invalid combination and will be rejected.
- In the usual case (1 byte sigtypes, no secret, no per-client auth),
the hostname will be {56 chars}.b32.i2p, decoding to 35 bytes, same as Tor.
- Tor 2-byte checksum has a 1/64K false negative rate. With 3 bytes, minus a few ignored bytes,
ours is approaching 1 in a million, since most flag/sigtype combinations are invalid.
Caching
=======
While outside the scope of this proposal, routers and/or clients must remember and cache
(probably persistently) the mapping of public key to destination, and vice versa.
Notes
=====
- Distinguish old from new flavors by length. Old b32 addresses are always {52 chars}.b32.i2p. New ones are {56+ chars}.b32.i2p
- Tor discussion thread: https://lists.torproject.org/pipermail/tor-dev/2017-January/011816.html
- Don't expect 2-byte sigtypes to ever happen, we're only up to 13. No need to implement now.
- Hostnames with secret and/or privkeys are for private sharing only and are low-security.
- New format can be used in jump links (and served by jump servers) if desired, just like b32.
Issues
======
- Is a checksum required? If we don't have a checksum, we still must xor the leading bytes with something to randomize the b32 chars.
- Any secret, private key, or public key longer than 32 bytes would
exceed the DNS max label length of 63 chars. Browsers probably do not care?
Migration
=========
No backward compatibility issues. Longer b32 addresses will fail to be converted
to 32-byte hashes in old software.