{% extends "_layout.html" %} {% block title %}I2NP Specification{% endblock %} {% block content %}
The I2P Network Protocol (I2NP), which is sandwiched between I2CP and the various I2P transport protocols, manages the routing and mixing of messages between routers, as well as the selection of what transports to use when communicating with a peer for which there are multiple common transports supported.
{% filter escape %} +----+----+----+----+----+----+----+----+ |type| msg-id | expiration +----+----+----+----+----+----+----+----+ date | size |chks| +----+----+----+----+----+----+----+----+ | data ..... +----+---// {% endfilter %}
{% filter escape %} type: 1 byte identifies the message type(see table below) msg-id: 4 bytes uniquely identifies this message(for some time at least) expiration: 8 bytes date this message will expire size: 2 bytes length of the payload chks: 1 byte checksum of the payload TODO: algorithm data: $size bytes actual message contents {% endfilter %}
{% filter escape %} Cleartext: +----+----+----+----+----+----+----+----+ | receive tunnelId | local routerInfo | +----+----+----+----+ hash + | | + + | | + + | | + +----+----+----+----+ | | send tunnelId | +----+----+----+----+----+----+----+----+ | nexthop routerInfo hash | + + | | + + | | + + | | +----+----+----+----+----+----+----+----+ | AES256 tunnel layer key | + + | | + + | | + + | | +----+----+----+----+----+----+----+----+ | AES256 tunnel IV key | + + | | + + | | + + | | +----+----+----+----+----+----+----+----+ | AES256 reply key | + + | | + + | | + + | | +----+----+----+----+----+----+----+----+ | reply IV | + + | | +----+----+----+----+----+----+----+----+ |flag| request time | next msg-id +----+----+----+----+----+----+----+----+ | padding... +----+----+----+--// {% endfilter %}
{% filter escape %} * bytes 0-3: tunnel ID to receive messages as * bytes 4-35: local router identity hash * bytes 36-39: next tunnel ID * bytes 40-71: next router identity hash * bytes 72-103: AES-256 tunnel layer key * bytes 104-135: AES-256 tunnel IV key * bytes 136-167: AES-256 reply key * bytes 168-183: reply IV * byte 184: flags * bytes 185-188: request time (in hours since the epoch) * bytes 189-192: next message ID * bytes 193-222: uninterpreted / random padding Taken from i2p.i2p/router/java/src/net/i2p/data/i2np/BuildRequestRecord.java {% endfilter %}
Message | Type |
DatabaseStore | 1 |
DatabaseLookup | 2 |
DatabaseSearchReply | 3 |
DeliveryStatus | 10 |
Garlic | 11 |
TunnelData | 18 |
TunnelGateway | 19 |
Data | 20 |
TunnelBuild | 21 |
with reply token: +----+----+----+----+----+----+----+----+ | SHA256 Hash as key | + + | | + + | | + + | | +----+----+----+----+----+----+----+----+ |type| reply token | reply tunnel- +----+----+----+----+----+----+----+----+ Id | SHA256 of the gateway RouterInfo | +----+ + | | + + | | + + | | + +----+----+----+----+----+----+----+ | | data ... +----+--------\\ with reply token == 0: +----+----+----+----+----+----+----+----+ | SHA256 Hash as key | + + | | + + | | + + | | +----+----+----+----+----+----+----+----+ |type| reply token | data ... +----+-------------------+---------\\
key: 32 bytes SHA256 hash type: 1 byte type identifier mapping: 0 RouterInfo 1 LeaseSet reply token: 4 bytes TODO: find out what this does reply tunnelId: 4 bytes only included if reply token > 0 TODO: what this tunnel information is needed for reply gateway: 32 bytes Hash of the routerInfo entry to reach the gateway only included if reply token > 0 TODO: what this tunnel information is needed for data: rest of the message(could be anything)
{% filter escape %} if flag==TRUE +----+----+----+----+----+----+----+----+ | SHA256 hash as the key to look up | + + | | + + | | + + | | +----+----+----+----+----+----+----+----+ | SHA256 hash of the routerInfo | + who is asking + | | + + | | + + | | +----+----+----+----+----+----+----+----+ |flag| reply tunnelId |size | | +----+----+----+----+----+----+----+ + | SHA256 of $key1 to exclude | + + | | + + | | + +----+ | | | +----+----+----+----+----+----+----+ + | SHA256 of $key2 to exclude | .... {% endfilter %}
{% filter escape %} key: 32 bytes SHA256 hash of the object to lookup from: 32 bytes SHA256 hash of the routerInfo entry this request came from(and to which the reply should be sent) flag: 1 byte mapping: 0 FALSE => send reply directly 1 TRUE => send reply to some tunnel reply tunnelId: 2 bytes only included if flag==TRUE tunnelId of the tunnel to send the reply to size: 2 bytes number of peers to exclude from the lookup(TODO: whatever this means) excludedPeers: rest of the message are $size SHA256 hashes of 32 bytes each(total $size*32 bytes) {% endfilter %}
{% filter escape %} +----+----+----+----+----+----+----+----+ | SHA256 hash as query key | + + | | + + | | + + | | +----+----+----+----+----+----+----+----+ |num | peer hash $1 | +----+ + | | + + | | + + | | + +----+----+----+----+----+----+----+ | | | +----+.... $num peer hashes + +----+----+----+----+----+----+----+ | | from | +----+ + | | + + | | + + | | + +----+----+----+----+----+----+----+ | | +----+ {% endfilter %}Definition
{% filter escape %} key: 32 bytes SHA256 of the object being searched num: 1 byte number of peer hashes that follow peer hash: 32 bytes SHA256 of the RouterInfo that the other router thinks are close to the key $num entries from: 32 bytes SHA256 of the RouterInfo of the router this reply was sent from {% endfilter %}DeliveryStatus
{% filter escape %} +----+----+----+----+----+----+----+----+----+----+----+----+ |msg-id | arrival-time | +----+----+----+----+----+----+----+----+----+----+----+----+ {% endfilter %}Definition
{% filter escape %} msg-id: 4 bytes unique ID of the message we deliver the DeliveryStatus for(see common I2NP header for details) arrival-time: 8 bytes time the message was successfully delivered {% endfilter %}Garlic
{% filter escape %} +----+----+----+----+----+----+----+----+ |length | .... data +----+----+----+----+--\\ {% endfilter %}Definition
{% filter escape %} length: 4 bytes number of bytes that follow data: $length bytes $some data {% endfilter %}TunnelData
{% filter escape %} +----+----+----+----+----+----+----+----+ | tunnelId | data | +----+----+----+----+ | | | | | +----+----+----+----+----+----+----+----+ {% endfilter %}Definition
{% filter escape %} tunnelId: 4 bytes identifies the tunnel this message is directed at data: 1024 bytes payload data.. fixed to 1024 bytes {% endfilter %}TunnelGateway
{% filter escape %} +----+----+----+----+----+----+--\\----+ | tunnelId | length | data...| +----+----+----+----+----+----+--\\----+ {% endfilter %}Definition
{% filter escape %} tunnelId: 4 bytes identifies the tunnel this message is directed at length: 2 bytes length of the payload data: $length bytes actual payload of this message {% endfilter %}{% endblock %}Data
{% filter escape %} +----+----+----+----+----+---//--+ | length | data... | +----+----+----+----+----+---//--+ {% endfilter %}Definition
{% filter escape %} length: 4 bytes length of the payload data: $length bytes actual payload of this message {% endfilter %}TunnelBuild
{% filter escape %} ... {% endfilter %}