Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
718 lines (616 sloc) 44.4 KB
I2P-Bote Technical Documentation
--------------------------------
1) Introduction
I2P-Bote is a serverless pseudonymous email exchange service for the I2P network. Emails are stored
encrypted in a Kademlia DHT formed by all I2P-bote nodes.
There is a web interface that lets the user send/read email and change settings.
An SMTP/POP interface to use with an email client is planned for the future.
Email can be sent through a number of other nodes (relays) for increased anonymity, or directly to a set
of storage nodes for faster delivery. Receiving email through relays is not yet implemented.
All nodes are created equal. There are no "supernodes" or designated relay/storage nodes.
Everybody acts as a potential relay and storage node. At some point in the
future, the maximum amount of disk space used for relayed/stored email packets will be user-configurable.
Before an email is sent, it is broken up into packets 30 kb or smaller and encrypted with the recipient's
public key. The packets are then stored in the DHT.
Email packets are stored redundantly in a Kademlia DHT (distributed hash table).
Stored email packets and relay packets are kept for at least 100 days, during which the recipient can
download them. If a node runs out of email storage space, and there are no old packets that can be deleted,
the node refuses storage requests.
Below is a diagram of how an email packet is routed from a sender to a recipient:
.-------. .-------. .--------.
| Relay | ----> | Relay | ----> | Storer | --------------------.
_ `-------' `-------' `--------' `\
/` |
/ |
.--------. / .-------. .-------. .--------. |
| Sender | -----> | Relay | ---> | Relay | ----> | Storer | -------------. |
`--------' \ `-------' `-------' `--------' `\ |
\ | |
_\/ | |
.-------. .-------. .--------. | |
| Relay | ----> | Relay | ----> | Storer | ------. | |
`-------' `-------' `--------' `\ | |
| | |
V V V
.--------------- Kademlia DHT -------------------------.
| .---------. |
| .---------. | Storage | |
| | Storage | .---------. | Node | |
| | Node | | Storage | `---------' |
| `---------' | Node | |
| `---------' .---------. |
| .---------. .---------. | Storage | |
| | Storage | | Storage | .---------. | Node | |
| | Node | | Node | | Storage | `---------' |
| `---------' `---------' | Node | |
| `---------' |
`------------------------------------------------------'
| | |
.-------. .-------. .---------. _' | |
| Relay | <----- | Relay | <---- | Fetcher | <---' | |
/ `-------' `-------' `---------' | |
/ | |
\/_ | |
.-----------. .-------. .-------. .---------. _' |
| Recipient | <---- | Relay | <--- | Relay | <---- | Fetcher | <----------' |
`-----------' _ `-------' `-------' `---------' |
|\ |
\ |
\ .-------. .-------. .---------. _'
| Relay | <----- | Relay | <---- | Fetcher | <-----------------'
`-------' `-------' `---------'
The number of relays for sending or retrieving an email is user-configurable.
For higher performance (but reduced anonymity), it is possible to use no relays and no storers/fetchers,
i.e. sender and recipient talk to the storage nodes directly. If both sender and recipient chose not to use
relays, the diagram looks like this:
.--------.
| Sender | ----------------------------.
`--------' `\
|
V
.--------------- Kademlia DHT -------------------------.
| .---------. |
| .---------. | Storage | |
| | Storage | .---------. | Node | |
| | Node | | Storage | `---------' |
| `---------' | Node | |
| `---------' .---------. |
| .---------. .---------. | Storage | |
| | Storage | | Storage | .---------. | Node | |
| | Node | | Node | | Storage | `---------' |
| `---------' `---------' | Node | |
| `---------' |
`------------------------------------------------------'
|
|
.-----------. _'
| Recipient | <-------------------------'
`-----------'
I2P-Bote uses base64 strings for addresses. They are called email destinations and can be between 86 and 512
characters long, depending on the type of encryption the user chooses (see 7.1)
The code is licensed under the GPL. The author can be reached via I2PMail at HungryHobo@mail.i2p,
or via I2P-Bote at:
hobo37SEJsEMfQHwcpVlvEgnrERGFz34GC1yjVyuRvl1QHnTi0UAoOtrLP~qkFY0oL59BBqj5sCep0RA8I5G8n
- either in German or English.
2. Kademlia
The Kademlia implementation used by I2P-Bote differs from standard Kademlia in several ways:
* Items can be deleted from the DHT
* No caching of DHT items because they are only retrieved once and then deleted
* I2P-Bote uses sibling lists (s-buckets) as suggested in the S/Kademlia paper
There are three types of data that is stored in the DHT: Email Packets, Index Packets, and Contacts.
Index packets contain the DHT keys of one or more email packets. The DHT key of an index packet is the
SHA-256 hash of the Email Destination the email packets are destined for.
To check for new email for a given Email Destination, I2P-Bote first queries the DHT for index packets for that
Email Destination, then queries the DHT for all email packet keys in the index packets. When a complete set of
email packets has been received, the email is reconstructed and placed in the inbox.
TODO Contacts
To delete an email packet, or an entry in an index packet, the delete request must contain the correct
verification code (the delete verification hash). The verification code is the SHA-256 hash of another block of
data called the delete authorization which is encrypted in the email packet. This means no third party can delete
the packet until the recipient has decrypted the packet and sent out a delete request containing the delete
authorization.
Note that once a delete request for a given email packet has been received by a node that is storing the
email packet, the node knows the delete authorization code and can propagate the delete request to other nodes
that don't know yet that the packet has been deleted.
To delete an index packet entry, a delete verification hash is required as well. It is the same hash as the one
for the email packet which the index packet entry points to.
3. Packet Types
As of release 0.2.5, the protocol version is 4. It is incompatible to earlier versions.
Version 4 clients will talk to higher versions. There will be at least one more protocol version at some point
in the future; this version will be backwards compatible to version 4.
All packets start with one byte for the packet type, followed by one byte for the packet version.
Strings in packets are UTF8 encoded.
3.1. Data Packets
These are always sent wrapped in a Communication Packet (see 3.2).
E denotes encrypted data.
For supported encryption and signature algorithms, see 7.1
Packet Type | Field | Data Type | Description
--------------------+-------+------------+------------------------------------------------------------------
Email Packet, | | | An email or email fragment, one recipient. Part of
encrypted | | | the packet is encrypted with the recipient's key.
| TYPE | 1 byte | Value = 'E'
| VER | 1 byte | Protocol version
| KEY | 32 bytes | DHT key of the packet, SHA-256 hash of LEN+DATA
| TIM | 4 bytes | The time the packet was stored on a storage node
| DV | 32 bytes | Delete verification hash, SHA-256 hash of DA
| ALG | 1 byte | ID number of the encryption algorithm used
| LEN | 2 bytes | Length of DA+DATA together
| DA | 32 bytes E | Delete authorization key, randomly generated
| DATA | byte[] E | An Unencrypted Email Packet
--------------------+-------+------------+------------------------------------------------------------------
Email Packet, | | | Storage format for the Incomplete Email Folder
unencrypted | | |
| TYPE | 1 byte | Value = 'U'
| VER | 1 byte | Protocol version
| MSID | 32 bytes | Message ID in binary format
| DA | 32 bytes | Delete authorization key, randomly generated
| FRID | 2 bytes | Fragment Index of this packet (0..NFR-1)
| NFR | 2 bytes | Number of fragments in the email
| MLEN | 2 bytes | Length of the MSG field
| MSG | byte[] | email content (MLEN bytes)
--------------------+-------+------------+------------------------------------------------------------------
Index Packet | | | Contains the DHT keys of one or more Email Packets, a
| | | Delete Verification Hash, and time stamp for each DHT key.
| TYPE | 1 byte | Value = 'I'
| VER | 1 byte | Protocol version
| DH | 32 bytes | SHA-256 hash of the recipient's email destination
| NP | 4 bytes | Number of entries in the packet
| KEY1 | 32 bytes | DHT key of the first Email Packet
| DV1 | 32 bytes | Delete verification hash for KEY1
| | | (SHA-256 hash of DA in the email packet)
| TIM1 | 4 bytes | The time the key KEY1 was added
| KEY2 | 32 bytes | DHT key of the second Email Packet
| DV2 | 32 bytes | Delete verification hash for KEY2
| | | (SHA-256 hash of DA in the email packet)
| TIM2 | 4 bytes | The time the key KEY2 was added
| ... | ... | ...
| KEYn | 32 bytes | DHT key of the n-th Email Packet
| DVn | 32 bytes | Delete verification hash for KEYn
| | | (SHA-256 hash of DA in the email packet)
| TIMn | 4 bytes | The time the key KEYn was added
--------------------+-------+------------+------------------------------------------------------------------
Deletion Info | | | Contains information about deleted DHT items, which can be
Packet | | | Email Packets or Index Packet entries.
| TYPE | 1 byte | Value = 'T'
| VER | 1 byte | Protocol version
| NP | 4 bytes | Number of entries in the packet
| KEY1 | 32 bytes | First DHT key
| DA1 | 32 bytes | Delete Authorization for KEY1
| TIM1 | 4 bytes | The time the key KEY1 was added
| KEY2 | 32 bytes | Second DHT key
| DA2 | 32 bytes | Delete Authorization for KEY2
| TIM2 | 4 bytes | The time the key KEY2 was added
| ... | ... | ...
| KEYn | 32 bytes | The n-th DHT key
| DAn | 32 bytes | Delete Authorization for KEYn
| TIMn | 4 bytes | The time the key KEYn was added
--------------------+-------+------------+------------------------------------------------------------------
Peer List | | | Response to a Find Close Peers Request or a Peer List Request
| TYPE | 1 byte | Value = 'P'
| VER | 1 byte | Protocol version
| NUMP | 2 bytes | Number of peers in the list
| P1 | 384 bytes | Destination key
| P2 | 384 bytes | Destination key
| ... | ... | ...
| Pn | 384 bytes | Destination key
--------------------+-------+------------+------------------------------------------------------------------
Directory Entry | | | A name/Email Destination mapping
(Contact.java) | TYPE | 1 byte | Value = 'C'
| VER | 1 byte | Protocol version
| KEY | 32 bytes | DHT key (SHA-256 hash of the UTF8-encoded name in lower case)
| DLEN | 2 bytes | Length of the DEST field
| DEST | byte[] | Email destination, 8 bit encoded (not base64)
| SALT | 4 bytes | A value such that scrypt(KEY|DEST|SALT) ends with a zero byte
| PLEN | 2 bytes | Length of PIC, max 7500
| PIC | byte[] | User picture in a browser-compatible format (JPG, PNG, GIF)
| COMP | 1 byte | Compression type for TEXT
| TLEN | 2 bytes | Length of the TEXT field, max 2000
| TEXT | byte[] | User defined text in UTF8
--------------------+-------+------------+------------------------------------------------------------------
3.2. Communication Packets
Communication packets are used for sending data between two I2P-Bote nodes.
They contain a data packet, see 3.1.
All Communication Packets start with a four-byte prefix, followed by one byte for the packet type,
one byte for the packet version, and a 32-byte Correlation ID.
Packet Type | Field | Data Type | Description
--------------------+-------+------------+------------------------------------------------------------------
Relay Request | | | A packet that tells the receiver to communicate with a peer,
| | | or peers, on behalf of the sender. It contains an I2P
| | | destination, a delay time, and a Communication Packet.
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'R'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID, used for responses
| HLEN | 2 bytes | HashCash length
| HK | byte[] | HashCash token (HLEN bytes)
| DLY | 4 bytes | Delay in seconds before sending
| NEXT | 384 bytes | Destination to forward the packet to
| RET | Ret. Chain | An empty or non-empty Return Chain
| DLEN | 2 bytes | Length of the DATA field in bytes
| DATA | byte[] E | Encrypted with the recipient's public key. Can contain another
| | | Relay Request, a Store Request, or a Deletion Query.
| PAD | byte[] | Optional padding
--------------------+-------+------------+------------------------------------------------------------------
Relay Return | | | Contains a Return Chain and a payload. The final destination
Request | | | is unknown to the sender or any of the hops.
(not implemented) | | | Used for responding to a relayed data packet.
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'K'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID, used for confirmation between two relay peers.
| | | A new correlation ID is set at every hop.
| RET | Ret. Chain | A non-empty Return Chain
| DLEN | 2 bytes | Length of the DATA field in bytes
| DATA | byte[] E | The payload. AES256-encrypted at every hop in the return chain.
--------------------+-------+------------+------------------------------------------------------------------
Return Chain | | | Not a packet itself, but part of a Relay (Return) Request
| RL1 | 2 bytes | Length of RET1. Zero means an empty return chain, nothing follows.
| RET1 | RL1 bytes | Hop 1 in the return chain. Contains a zero byte, followed by the
| | | hop's I2P destination and an AES key to encrypt the payload with.
| RL2 | 2 bytes E| Length of RET2.
| RET2 | RL2 bytes E| Hop 2 in the return chain. Contains a zero byte, followed by the
| | | hop's I2P destination and an AES key to encrypt the payload with.
| | | This field is encrypted with the PK of hop 2.
| RL3 | 2 bytes E| Length of RET3.
| RET3 | RL3 bytes E| Hop 3 in the return chain. Contains a zero byte, followed by the
| | | hop's I2P destination and an AES key to encrypt the payload with.
| | | This field is encrypted with the PKs of hops 3 and 2.
| ... | ... | ...
| RLn | 2 bytes E| Length of RETn.
| RETn | RLn bytes E| Last hop in the return chain. Contains a zero byte, followed by the
| | | hop's I2P destination and an AES key to encrypt the payload with.
| | | This field is encrypted with the PKs of hops n...2.
| RLn+1 | 2 bytes E| Length of RETn+1.
| RETn+1| RLn+1 byt E| Number of hops (>0) followed by all AES256 keys (one per hop)
| RLn+2 | 2 bytes | Value=0 to indicate this is the end of the return chain
--------------------+-------+------------+------------------------------------------------------------------
Fetch Request | | | Request to a chain end point to retrieve an Index Packet or
| | | Email Packet.
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'F'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID, used for responses
| DTYP | 1 byte | Type of data to retrieve
| KEY | 32 bytes | DHT key to look up
| KPR | 384 bytes | Email keypair of recipient
| RLEN | 2 bytes | Length of the RET field
| RET | byte[] | Relay packet, contains the return chain (RLEN bytes)
--------------------+-------+------------+------------------------------------------------------------------
Response Packet | | | Response to a Retrieve Request, Fetch Request,
| | | Find Close Peers Request, or a Peer List Request
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'N'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID of the request packet
| STA | 1 byte | Status code:
| | | 0 = OK
| | | 1 = General error
| | | 2 = No data found
| | | 3 = Invalid packet
| | | 4 = Invalid HashCash
| | | 5 = Not enough HashCash provided
| | | 6 = No disk space left
| DLEN | 2 bytes | Length of the DATA field; can be 0 if no payload
| DATA | byte[] | A Data Packet
--------------------+-------+------------+------------------------------------------------------------------
Peer List Request | | | A request for a list of
| | | high-reachability relay peers
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'A'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID, used for responses
--------------------+-------+------------+------------------------------------------------------------------
DHT Communication Packets
Packet Type | Field | Data Type | Description
--------------------+-------+------------+------------------------------------------------------------------
RetrieveRequest | | | A request to a peer to return a data item for a given DHT key
| | | and data type
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'Q'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID, used for responses
| DTYP | 1 byte | Type of data to retrieve:
| | | 'I' = Index Packet
| | | 'E' = Email Packet
| | | 'C' = Directory Entry
| KEY | 32 bytes | DHT key to look up
--------------------+-------+------------+------------------------------------------------------------------
Deletion Query | | | A request to a peer to return a Deletion Info Packet for a given
| | | Email Packet DHT key. If the Email Packet is not known to be
| | | deleted, no response is expected back.
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'L'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID, used for responses
| KEY | 32 bytes | DHT key to look up
--------------------+-------+------------+------------------------------------------------------------------
Store Request | | | DHT Store Request
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'S'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID, used for responses
| HLEN | 2 bytes | HashCash length
| HK | byte[] | HashCash token (HLEN bytes)
| DLEN | 2 bytes | Length of the DATA field
| DATA | byte[] | Data packet to store (DLEN bytes).
| | | Can be an Index Packet, Email Packet, or Email Destination.
--------------------+-------+------------+------------------------------------------------------------------
Email Packet | | | Request to delete an Email Packet by DHT key
Delete Request | | |
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'D'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID, used for responses
| KEY | 32 bytes | DHT key of the Email Packet to delete
| DA | 32 bytes | Delete Authorization (SHA-256 must equal DV in the email pkt)
--------------------+-------+------------+------------------------------------------------------------------
Index Packet | | | Request to remove one or more entries (Email Packet keys) from
Delete Request | | | an Index Packet
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'X'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID, used for responses
| DH | 32 bytes | The Email Destination hash of the Index Packet
| N | 1 byte | Number of entries in the packet
| DHT1 | 32 bytes | First DHT key to remove
| DA1 | 32 bytes | Delete Authorization (SHA-256 must equal DV in the email packet
| | | referenced by DHT1)
| DHT2 | 32 bytes | Second DHT key to remove
| DA2 | 32 bytes | Delete Authorization (SHA-256 must equal DV in the email packet
| | | referenced by DHT2)
| ... | ... | ...
| DHTn | 32 bytes | n-th DHT key to remove
| DAn | 32 bytes | Delete Authorization (SHA-256 must equal DV in the email packet
| | | referenced by DHTn)
--------------------+-------+------------+------------------------------------------------------------------
Find Close Peers | | | Request for k peers close to a key
| PFX | 4 bytes | Packet prefix, must be 0x6D 0x30 0x52 0xE9
| TYPE | 1 byte | Value = 'C'
| VER | 1 byte | Protocol version
| CID | 32 bytes | Correlation ID, used for responses
| KEY | 32 bytes | DHT key
--------------------+-------+------------+------------------------------------------------------------------
4. Protocols
4.1. Storing a DHT item via relays
I2P nodes involved: A=Sender, R1...Rn=Relays, S1...Sm=Storage Nodes
1) A onion-encrypts the Store Request with the public keys of all hops, resulting in a Relay Packet.
2) A sends the Relay Packet to R1.
3) R1 decrypts the packet, waits a random amount of time, and sends it to R2.
4) R2 confirms delivery with R1.
5) Repeat until packet arrives at Rn.
6) Rn decrypts the Relay Packet into an Email Packet.
7) Rn sends the packet to S1,...,Sm through a Kademlia STORE
4.2. Return Chains
In order to make it impossible for two non-adjacent nodes on the return chain to identify Relay
Return Request packets, the payload and the entire Return Chain are re-encrypted at every hop.
A new Correlation ID is generated at every hop.
Here is a simplified diagram of how a Relay Return Packet is sent from one hop to the next:
(A) The packet is received. HOP1 through HOP3 contain encrypted data (encrypted with the public key
for the receiving I2P node):
+------------------- Relay Return Request --------------------------+
| |
| .-----KEY1-----. |
| .---KEY1---. | .---KEY2---. | |
| .-KEY1-. | .-KEY2-. | | | .-KEY3-. | | .---------. |
| | HOP1 | | | HOP2 | | | | | HOP2 | | | | PAYLOAD | |
| `------’ | `------’ | | | `------’ | | `---------’ |
| `----------’ | `----------’ | |
| `--------------’ |
| |
+-------------------------------------------------------------------+
KEYx denotes a layer of encryption.
(B) The receiving node decrypts HOP1, HOP2, and HOP3. HOP1 is now in plain text. It contains the
destination of the next hop and an AES key.
+------------------- Relay Return Request --------------------------+
| |
| .-----KEY2-----. |
| .---KEY2---. | .---KEY3---. | |
| .------. | .------. | | | .------. | | .---------. |
| | HOP1 | | | HOP2 | | | | | HOP2 | | | | PAYLOAD | |
| `------’ | `------’ | | | `------’ | | `---------’ |
| `----------’ | `----------’ | |
| `--------------’ |
| |
+-------------------------------------------------------------------+
(C) HOP1 is replaced with random data and moved to the end of the chain. The payload is encrypted with
the AES key from HOP1:
+------------------- Relay Return Request --------------------------+
| |
| .-----KEY2-----. |
| .---KEY2---. | .---KEY3---. | |
| | .------. | | | .------. | | .------. .---AES---. |
| | | HOP2 | | | | | HOP2 | | | | HOP1 | | PAYLOAD | |
| | `------’ | | | `------’ | | `------’ `---------’ |
| `----------’ | `----------’ | |
| `--------------’ |
| |
+-------------------------------------------------------------------+
(D) The packet is sent to the next node in the chain.
4.3. Retrieving DHT items via relays (not implemented yet)
I2P nodes involved:
A=Address Owner
F=Fetcher
O1...On=Outbound Relays
I1...In=Inbound Relays,
S1...Sm=Storage Nodes
1) A builds a Relay Request containing a Retrieve Request and sends it to F via O1, O2, ..., On
as described in 4.1
2) F queries the DHT for the DHT item
3) F encrypts the DHT data with the public key for hop 1 of the return chain
4) F moves the (RL1,RET1) block of the return chain to the end (behind RETn+1)
5) F sends the results of steps 3) and 4) to I1
6) I1 decrypts all (RLx,RETx) blocks of the return chain and finds I2 and the AES key in the first block
7) I1 replaces (RL1,RET1) with random data that is encrypted with the PK for I2
8) I1 moves the (RL1,RET1) block of the return chain to the end (behind RETn+1)
9) I1 encrypts the payload with the AES key
10) I1 sends the results of steps 7) and 8) to I2
11) Repeat from 6) for I2, I3, ..., until the data reaches A (when the first byte of RET1 is non-zero)
12) A decrypts the (RL1,RET1) block which contains all AES keys
13) A decrypts the payload with the AES keys, starting from the last hop's key
14) The decrypted data contains the DHT data packet
4.4. Deleting an Email Packet
Every time a recipient receives an email packet directly from one or more storage nodes, it asks the
storage node(s) to delete the packet.
If the email packet is received through one or more relays, the recipient issues a delete request to
a (possibly different) relay endpoint, which entails an additional findClosestNodes lookup because the
endpoint has to find out which nodes are storing the packet.
The recipient also sends a delete request for index packet, asking the storage nodes to delete the DHT
key of the email packet. Each index packet node then removes the DHT key from the stored index packet,
and adds the DHT key to a list of deleted DHT keys it maintains for each index packet (plus the
delete verification hash).
The purpose of this is so a node that is about to replicate an email packet can find out if it missed
an earlier delete request for that packet, in which case the node "replicates" the delete request rather
than the packet itself.
This helps reduce storage space by removing old Email Packets from nodes that weren't online at the time
the delete request was sent initially.
4.5 Deleting an Index Packet Entry
Similar to deleting an email packet.
4.6. Replication
See comments at the beginning of src/i2p/bote/network/kademlia/ReplicateThread.java
5. Algorithms Used By Nodes Locally
5.1. Retrieving Email via relays
See also http://forum.i2p/viewtopic.php?p=19927#19927 ff.
1) Randomly choose a set of n relay nodes, R1...Rn (outgoing chain for request)
2) Randomly choose a set of m relay nodes, S1...Sm. (return chain / inbound mail chain)
- with Sm being the node closest to the receiver
and S1 the chain node closest to fetcher
3) Generate m+1 random 32-byte arrays (for XORing the return packets), X1...Xm+1
(This is done so the outgoing chain's endpoint or inbound first hop need
not know all inbound hops in order to perform hop-to-hop encryption. Each
hop will decrypt one 32-byte random array and encrypt the packet with it,
so it looks different at each hop without one node at the beginning
knowing all hops)
4) With Sm's public key, encrypt the local destination key and Xm+1
5) With Sm-1's public key, encrypt Sm's destination key, Xm, and the data from step 4)
6) With Sm-2's public key, encrypt Sm-1's destination key, Xm-1, and the data from step 5)
7) Repeat until the entire return chain, S1...Sm, has been onion-encrypted, and also include a
delay for each hop.
8) Add S1's destination key and X1 to the data from step 7)
9) Add the data (which is a Relay Packet) to a Retrieve Request packet.
10) Encrypt the resulting packet, using the public keys of relays Rn (Fetcher), Rn-1, ..., R1,
and add the destination key of the next relay each time. Also included is a delay for each relay.
11) Set a random Correlation ID on the packet at each layer
12) Add the packet to the relay packet folder.
13) When a reply packet is received, decrypt it first with the local node's private
decryption key, then with all the random keys X1...Xm+1.
6. Files
6.1. Identities file
Stores all email identities the local user has created. The file uses the
Java Properties format, and can be read into / written out from a Java
Properties object.
The following property keys are currently stored and recognized:
identity#.publicName - The public name of the identity, included in emails.
identity#.key - Base64 of the identity keys.
identity#.salt - Salt used to generate a fingerprint.
identity#.description - Description of the identity, only displayed locally.
identity#.picture - Base64 of byte[] containing picture data
identity#.text - Text associated with the identity.
identity#.published - Has the identity been published to the public addressbook?
(# is an integer index)
The base64 key contains two public keys (encryption+signing) and two private
keys.
The identities file can optionally contain the property key "default", with
its value set to an Email Destination (i.e. two public keys). If the
Email Destination matches one of the identities, that identity is used as
the default.
6.2. Included .jar files and third-party source code
bcprov-jdk15on-152.jar The BouncyCastle library and SecurityProvider.
mailapi-1.5.4.jar Part of JavaMail 1.5.4
lzma-9.20.jar An LZMA implementation from http://www.7-zip.org/sdk.html
ntruenc-1.2.jar An NTRU implementation from http://sf.net/projects/ntru/
(only the NTRUEncrypt part, not NTRUSign)
flexi-gmss-1.7p1.jar A stripped down and patched version of the FlexiProvider
sources (http://www.flexiprovider.de/), containing only the
classes needed for GMSS.
The patch consists of a modified de.flexiprovider.core.CoreRegistry
and de.flexiprovider.api.Registry and its purpose is to
reduce dependencies on classes not related to GMSS.
scrypt-1.4.0.jar An scrypt implementation from https://github.com/wg/scrypt/
7. Cryptography
7.1. Asymmetric encryption and signing
Supported encryption and signature algorithms:
ALG=1: ElGamal-2048 / DSA-1024 / AES-256 / SHA-256 (same as the I2P router uses)
ALG=2: ECDH-256 / ECDSA-256 / AES-256 / SHA-256
ALG=3: ECDH-521 / ECDSA-521 / AES-256 / SHA-512
ALG=4: NTRUEncrypt-1087 / GMSS-512 / AES-256 / SHA-512
7.2. Password Encryption
The identities file, the address book, and all email files are encrypted with AES-256.
To generate the AES key from the password, scrypt (http://www.tarsnap.com/scrypt.html) is used.
The file format is:
Field | #bytes | Description
-------+--------+------------------------------------------------------------------
SOF | 4 | Start of file, contains the characters "IBef"
VER | 1 | Format version, must be 1
N | 4 | scrypt CPU cost parameter
r | 4 | scrypt memory cost parameter
p | 4 | scrypt parallelization parameter
SALT | 32 | Salt for scrypt
IV | 32 | IV for AES
DATA | | The encrypted data
Parameters N through SALT are cached in a file named derivparams so all encrypted files
can use the same key derivation parameters. This makes decryption much faster because
the key only needs to be derived once per session.
7.3. Fingerprints For Directory Entries
TODO
H = scrypt(name, dest, zuf.wert); die letzten 8 Binärstellen von H müssen 0 sein
13*7+22+18 = 131
8. Development
8.1. Setting up Eclipse
Rough steps, may not be complete:
* Import the I2P-Bote sources as a new Eclipse project
* Add the I2P .jar dependencies
* Install Tomcat 6 if you don't have it yet.
(I didn't have any luck with Jetty 6 + the Jetty WTP Adaptor from
http://download.eclipse.org/jetty/updates/jetty-wtp/development)
* In the Servers view, click New -> Server, add a Tomcat 6 server and add I2P-Bote
to the list of webapps
* Make a few more servers containing I2P-Bote (don't forget to use different ports)
so you can run a small I2P-Bote network for testing
* Make a work dir for each server. I used the port numbers for the dir names.
* Comment out all lines in built-in-peers.txt and disable seedless so you get a closed network
* Start and stop all servers, then go to Debug Configurations (or Run Configurations)
and add the following to Arguments -> VM arumgents:
-Di2p.dir.config="/path/to/<work_dir>/i2pbote/" -Di2p.dir.app="/path/to/<work_dir>/i2pbote/"
where <work_dir> is the name you gave that work dir. Repeat for the other servers.
* Edit built-in-peers.txt and add the I2P destination from the first test server
* Create a file named logger.config in each work dir with the following contents:
logger.record.i2p.bote=DEBUG
logger.minimumOnScreenLevel=DEBUG
* Start two or more servers, go to http://localhost:<port>/i2p.i2p-bote/, and click "connect".
After a minute, it should say "connected" and you should see the other server(s) on network.jsp.
8.2. Transifex
To update translations from Transifex, run "tx pull". On Debian and its derivatives, tx can be
installed via "sudo apt-get install transifex-client". After installation, run "tx init" in
the project directory.
9. Glossary of Terms
Email Destination
As the name implies, an Email Destination is an identifier by which somebody can be reached via I2P-Bote.
An Email Destination is a Base64 string containing a public encryption key and a signature verification key.
Example of a 512-character Email Destination (ElGamal-2048/DSA-1024):
uQtdwFHqbWHGyxZN8wChjWbCcgWrKuoBRNoziEpE8XDt8koHdJiskYXeUyq7JmpG
In8WKXY5LNue~62IXeZ-ppUYDdqi5V~9BZrcbpvgb5tjuu3ZRtHq9Vn6T9hOO1fa
FYZbK-FqHRiKm~lewFjSmfbBf1e6Fb~FLwQqUBTMtKYrRdO1d3xVIm2XXK83k1Da
-nufGASLaHJfsEkwMMDngg8uqRQmoj0THJb6vRfXzRw4qR5a0nj6dodeBfl2NgL9
HfOLInwrD67haJqjFJ8r~vVyOxRDJYFE8~f9b7k3N0YeyUK4RJSoiPXtTBLQ2RFQ
gOaKg4CuKHE0KCigBRU-Fhhc4weUzyU-g~rbTc2SWPlfvZ6n0voSvhvkZI9V52X3
SptDXk3fAEcwnC7lZzza6RNHurSMDMyOTmppAVz6BD8PB4o4RuWq7MQcnF9znElp
HX3Q10QdV3omVZJDNPxo-Wf~CpEd88C9ga4pS~QGIHSWtMPLFazeGeSHCnPzIRYD
Example of a 86-character Email Destination (ECC-256):
1Lcvly8no5of6juJKxqy-xA-MStM2c2XKorepH1oqs5yKBkg9-ZcG4G4kZY1E~2672cMA806l9EicQLmlehB1m
Email Address
Email Addresses in I2P-Bote are shortcuts for Email Destinations.
Email Address <--> Email Destination mappings are stored in two places: the local address book and the
distributed address directory.
Email Identity
An Email Identity is an Email Destination plus a name you want to be known as when you use that identity.
Technically speaking, an Email Identity consists of four things:
* An Email Destination (i.e. two public keys)
* The two private keys for the Email Destination
* A public name which is shown to other people in emails
* A description which is not shown to anybody but you.
It helps you remember which Email Identity you use for which purpose.
An email identity is not required for sending emails (in that case only "Anonymous" can be selected in the
"sender" field).
I2P destination
The address of a I2P-Bote node on the I2P network. There is normally no need to know it.
I2P destinations and Email Destinations look similar, but are completely independent of each other.
You can’t perform that action at this time.