Skip navigation

Common structures Specification

This page was last updated in February 2014 and is accurate for router version 0.9.11.

Common structures Specification

This document describes some data types common to all I2P protocols, like I2NP, I2CP, SSU, etc.

Index

Type
Boolean
Certificate
Date
Delivery Instructions
Destination
Hash
Integer
Lease
LeaseSet
Mapping
PrivateKey
PublicKey
RouterAddress
RouterIdentity
RouterInfo
SessionTag
Signature
SigningPrivateKey
SigningPublicKey
String
TunnelId

Integer

Description

Represents a non-negative integer.

Contents

1 to 8 bytes in network byte order representing an unsigned integer

Date

Description

The number of milliseconds since midnight on January 1, 1970 in the GMT timezone. If the number is 0, the date is undefined or null.

Contents

8 byte Integer

String

Description

Represents a UTF-8 encoded string.

Contents

1 or more bytes where the first byte is the number of bytes (not characters!) in the string and the remaining 0-255 bytes are the non-null terminated UTF-8 encoded character array. Length limit is 255 bytes (not characters). Length may be 0.

Boolean

Description

A boolean value, supporting null/unknown representation 0=false, 1=true, 2=unknown/null

Contents

1 byte Integer

Notes

Deprecated - unused

PublicKey

Description

This structure is used in ElGamal encryption, representing only the exponent, not the primes, which are constant and defined in the cryptography specification.

Contents

256 bytes

Javadoc

PrivateKey

Description

This structure is used in ElGamal decryption, representing only the exponent, not the primes which are constant and defined in the cryptography specification.

Contents

256 bytes

Javadoc

SessionKey

Description

This structure is used for AES256 encryption and decryption.

Contents

32 bytes

Javadoc

SigningPublicKey

Description

This structure is used for verifying signatures.

Contents

Key type and length are inferred from context or are specified in the Key Certificate of a Destination. The default type is DSA-160. As of release 0.9.12, other types may be supported, depending on context.

TypeLength (bytes)
DSA-160128
ECDSA-SHA256-P25664
ECDSA-SHA384-P38496
ECDSA-SHA512-P521132
RSA-SHA256-2048256
RSA-SHA384-3072384
RSA-SHA512-4096512

Javadoc

SigningPrivateKey

Description

This structure is used for creating signatures.

Contents

Key type and length are specified when created. The default type is DSA-160. As of release 0.9.12, other types may be supported, depending on context.

TypeLength (bytes)
DSA-16020
ECDSA-SHA256-P25632
ECDSA-SHA384-P38448
ECDSA-SHA512-P52166
RSA-SHA256-2048512
RSA-SHA384-3072768
RSA-SHA512-40961024

Javadoc

Signature

Description

This structure represents the signature of some data.

Contents

Signature type and length are inferred from the type of key used. The default type is DSA-160. As of release 0.9.12, other types may be supported, depending on context.

TypeLength (bytes)
DSA-16040
ECDSA-SHA256-P25664
ECDSA-SHA384-P38496
ECDSA-SHA512-P521132
RSA-SHA256-2048256
RSA-SHA384-3072384
RSA-SHA512-4096512

Javadoc

Hash

Description

Represents the SHA256 of some data.

Contents

32 bytes

Javadoc

Session Tag

Description

A random number

Contents

32 bytes

Javadoc

TunnelId

Description

Defines an identifier that is unique to each router in a tunnel.

Contents

4 byte Integer

Javadoc

Certificate

Description

A certificate is a container for various receipts or proof of works used throughout the I2P network.

Contents

1 byte Integer specifying certificate type, followed by a 2 Integer specifying the size of the certificate payload, then that many bytes.

+----+----+----+----+----+-//
|type| length  | payload
+----+----+----+----+----+-//

type :: Integer
        length -> 1 byte

        case 0 -> NULL
        case 1 -> HASHCASH
        case 2 -> HIDDEN
        case 3 -> SIGNED
        case 4 -> MULTIPLE
        case 5 -> KEY

length :: Integer
          length -> 2 bytes

payload :: data
           length -> $length bytes

Notes

  • For Router Identities, the Certificate is always NULL, no others are currently implemented.
  • For Garlic Cloves, the Certificate is always NULL, no others are currently implemented.
  • For Garlic Messages, the Certificate is always NULL, no others are currently implemented.
  • For Destinations, the Certificate may be non-NULL, however non-NULL certs are not widely used, and any checking is left to the application-level.

Certificate Types

The following certificate types are defined:

TypeType CodePayload LengthTotal LengthNotes
Null003
HashCash1variesvaries Experimental, unused. Payload contains an ASCII colon-separated hashcash string.
Hidden203 Experimental, unused. Hidden routers generally do not announce that they are hidden.
Signed340 or 7243 or 75 Experimental, unused. Payload contains a 40-byte DSA signature, optionally followed by the 32-byte Hash of the signing Destination.
Multiple4variesvaries Experimental, unused. Payload contains multiple certificates.
Key54+7+ Since 0.9.12. See below for details.

Key Certificates

Key certificates are preliminary, and are scheduled to be introduced in release 0.9.12. Prior to that release, all PublicKeys were 256-byte ElGamal keys, and all SigningPublicKeys were 128-byte DSA-160 keys. A key certificate provides a mechanism to indicate the type of the PublicKey and SigningPublicKey in the Destination or RouterIdentity, and to package any key data in excess of the standard lengths.

By maintaining exactly 384 bytes before the certificate, and putting any excess key data inside the certificate, we maintain compatibility for any software that parses Destinations and RouterIdentities.

The key certificate payload contains:

DataLength
Signing Public Key Type2
Crypto Public Key Type2
Excess Signing Public Key Data0+
Excess Crypto Public Key Data0+

The defined Signing Key types are:

TypeType CodeTotal Public Key Length
DSA-1600128
ECDSA-SHA256-P256164
ECDSA-SHA384-P384296
ECDSA-SHA512-P5213132
RSA-SHA256-20484256
RSA-SHA384-30725384
RSA-SHA512-40966512

The defined Crypto Public Key types are:

TypeType CodeTotal Public Key Length
ElGamal0256

When a Key Certificate is not present, the preceeding 384 bytes in the Destination or RouterIdentity are defined as the 256-byte ElGamal PublicKey followed by the 128-byte DSA-160 SigningPublicKey. When a Key Certificate is present, the preceeding 384 bytes are redefined as follows:

  • Complete or first portion of Crypto Public Key
  • Random padding if the total lengths of the two keys are less than 384 bytes
  • Complete or first portion of Signing Public Key

The lengths and boundaries of the initial key data, the padding, and the excess key data portions in the certificates are not explicitly specified, but are derived from the lengths of the specified key types. If the total lengths of the Crypto and Signing Public Keys exceed 384 bytes, the remainder will be contained in the Key Certificate. If the Crypto Public Key length is not 256 bytes, the method for determining the boundary between the two keys is to be specified in a future revision of this document.

Example layouts using an ElGamal Crypto Public Key and the Signing Public Key type indicated:

Signing Key TypePadding LengthExcess Signing Key Data in Cert
DSA-16000
ECDSA-SHA256-P256640
ECDSA-SHA384-P384320
ECDSA-SHA512-P52104
RSA-SHA256-20480128
RSA-SHA384-30720256
RSA-SHA512-40960384

Javadoc

Mapping

Description

A set of key/value mappings or properties

Contents

A 2-byte size Integer followed by a series of String=String; pairs

+----+----+----+----+----+----+----+----+
|  size   |key_string (len + data) | =  |
+----+----+----+----+----+----+----+----+
| val_string (len + data)     | ;  | ...
+----+----+----+----+----+----+----+
size :: Integer
        length -> 2 bytes
        Total number of bytes that follow

key_string :: String
              A string (one byte length followed by UTF-8 encoded characters)

= :: A single byte containing '='

val_string :: String
              A string (one byte length followed by UTF-8 encoded characters)

; :: A single byte containing ';'

Notes

  • The encoding isn't optimal - we either need the '=' and ';' characters, or the string lengths, but not both
  • Some documentation says that the strings may not include '=' or ';' but this encoding supports them
  • Strings are defined to be UTF-8 but in the current implementation, I2CP uses UTF-8 but I2NP does not. For example, UTF-8 strings in a RouterInfo options mapping in a I2NP Database Store Message will be corrupted.
  • 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 (i.e. in a RouterAddress or RouterInfo) must be sorted by key so that the signature will be invariant. Duplicate keys are not allowed.
  • Mappings contained in an I2CP SessionConfig must be sorted by key so that the signature will be invariant. Duplicate keys are not allowed.
  • While it is application-dependent, keys and values are generally case-sensitive.
  • Key and value string length limits are 255 bytes (not characters) each, plus the length byte. Length byte may be 0.
  • Total length limit is 65535 bytes, plus the 2 byte size field, or 65537 total.

Javadoc

Common structure specification

RouterIdentity

Description

Defines the way to uniquely identify a particular router

Contents

PublicKey followed by SigningPublicKey and then a Certificate

+----+----+----+----+----+----+----+----+
| public_key                            |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| padding (optional)                    |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| signing_key                           |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| certificate                           |
+----+----+----+-//

public_key :: PublicKey (partial or full)
              length -> 256 bytes or as specified in key certificate

padding :: random data
              length -> 0 bytes or as specified in key certificate
              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

total length: 387+ bytes

Notes

  • The certificate for a RouterIdentity is currently unused and is always NULL.
  • Do not assume that RouterIdentities are always 387 bytes! They are 387 bytes plus the certificate length specified at bytes 385-386, which may be non-zero in a future release.
  • As of release 0.9.12, if the certificate is a Key Certificate, the boundaries of the key fields may vary. See the Key Certificate section above for details.

Javadoc

Destination

Description

A Destination defines a particular endpoint to which messages can be directed for secure delivery.

Contents

PublicKey followed by a SigningPublicKey and then a Certificate

+----+----+----+----+----+----+----+----+
| public_key                            |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| padding (optional)                    |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| signing_public_key                    |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| certificate
+----+----+----+-//

public_key :: PublicKey (partial or full)
              length -> 256 bytes or as specified in key certificate

padding :: random data
              length -> 0 bytes or as specified in key certificate
              padding length + signing_public_key length == 128 bytes

signing_public_key :: SigningPublicKey (partial or full)
              length -> 128 bytes or as specified in key certificate
              padding length + signing_public_key length == 128 bytes

certificate :: Certificate
               length -> >= 3 bytes

total length: 387+ bytes

Notes

  • The public key of the destination was used for the old i2cp-to-i2cp encryption which was disabled in version 0.6, it is currently unused except for the IV for LeaseSet encryption, which is deprecated. The public key in the LeaseSet is used instead.
  • Do not assume that Destinations are always 387 bytes! They are 387 bytes plus the certificate length specified at bytes 385-386, which may be non-zero.
  • As of release 0.9.12, if the certificate is a Key Certificate, the boundaries of the key fields may vary. See the Key Certificate section above for details.

Javadoc

Lease

Description

Defines the authorization for a particular tunnel to receive messages targeting a Destination.

Contents

SHA256 Hash of the RouterIdentity of the gateway router, then the TunnelId, and finally an end Date

+----+----+----+----+----+----+----+----+
| tunnel_gw                             |
+                                       +
|                                       |
+                                       +
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+
|     tunnel_id     |      end_date
+----+----+----+----+----+----+----+----+
                    |
+----+----+----+----+

tunnel_gw :: Hash of the RouterIdentity of the tunnel gateway
             length -> 32 bytes

tunnel_id :: TunnelId
             length -> 4 bytes

end_date :: Date
            length -> 8 bytes

Notes

  • Total size: 44 bytes

Javadoc

LeaseSet

Description

Contains all of the currently authorized Leases for a particular Destination, the PublicKey to which garlic messages can be encrypted, and then the public key that can be used to revoke this particular version of the structure. The LeaseSet is one of the two structures stored in the network database( the other being RouterInfo), and is keyed under the SHA256 of the contained Destination.

Contents

Destination, followed by a PublicKey for encryption, then a SigningPublicKey which can be used to revoke this version of the LeaseSet, then a 1 byte Integer specifying how many Lease structures are in the set, followed by the actual Lease structures and finally a Signature of the previous bytes signed by the Destination's SigningPrivateKey

+----+----+----+----+----+----+----+----+
| destination                           |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| encryption_key                        |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| signing_key                           |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
|num | Lease 0                          |
+----+                                  +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| Lease 1                               |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| Lease ($num-1)                        |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| signature                             |
+                                       +
|                                       |
+                                       +
|                                       |
+                                       +
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+

destination :: Destination
               length -> >= 387 bytes

encryption_key :: PublicKey
                  length -> 256 bytes

signing_key :: SigningPublicKey
               length -> 128 bytes or as specified in destination's key certificate

num :: Integer
       length -> 1 byte
       Number of leases to follow
       value: 0 <= num <= 16

leases :: [Lease]
          length -> $num*44 bytes

signature :: Signature
             length -> 40 bytes or as specified in destination's key certificate

Notes

  • The public key of the destination was used for the old i2cp-to-i2cp encryption which was disabled in version 0.6, it is currently unused.
  • The encryption key is used for end-to-end ElGamal/AES+SessionTag encryption. It is currently generated anew at every router startup, it is not persistent.
  • The signature may be verified using the signing public key of the destination.
  • The signing_key is currently unused. It was intended for LeaseSet revocation, which is unimplemented. It is currently generated anew at every router startup, it is not persistent. The signing key type is always the same as the destination's signing key type.
  • The earliest expiration of all the Leases is treated as the timestamp or version of the LeaseSet. Routers will generally not accept a store of a LeaseSet unless it is "newer" than the current one. Take care when publishing a new LeaseSet where the oldest Lease is the same as the oldest Lease in the previous LeaseSet. The publishing router should generally increment the expiration of the oldest Lease by at least 1 ms in that case.
  • Prior to release 0.9.7, when included in a DatabaseStore Message sent by the originating router, the router set all the published leases' expirations to the same value, that of the earliest lease. As of release 0.9.7, the router publishes the actual lease expiration for each lease. This is an implementation detail and not part of the structures specification.

Javadoc

RouterAddress

Description

This structure defines the means to contact a router through a transport protocol.

Contents

1 byte Integer defining the relative cost of using the address, where 0 is free and 255 is expensive, followed by the expiration Date after which the address should not be used, or if null, the address never expires. After that comes a String defining the transport protocol this router address uses. Finally there is a Mapping containing all of the transport specific options necessary to establish the connection, such as IP address, port number, email address, URL, etc.

+----+----+----+----+----+----+----+----+
|cost|           expiration
+----+----+----+----+----+----+----+----+
     |        transport_style           |
+----+----+----+----+-//-+----+----+----+
|                                       |
+                                       +
|               options                 |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+

cost :: Integer
        length -> 1 byte

        case 0 -> free
        case 255 -> expensive

expiration :: Date (must be all zeros, see notes below)
              length -> 8 bytes

              case null -> never expires

transport_style :: String
                   length -> 1-256 bytes

options :: Mapping

Notes

  • Cost is typically 5 or 6 for SSU, and 10 or 11 for NTCP.
  • Expiration is currently unused, always null (all zeroes). As of release 0.9.3, the expiration is assumed zero and not stored, so any non-zero expiration will fail in the RouterInfo signature verification. Implementing expiration (or another use for these bytes) will be a backwards-incompatible change. Routers MUST set this field to all zeros. As of release 0.9.12, a non-zero expiration field is again recognized, however we must wait several releases to use this field, until the vast majority of the network recognizes it.
  • The following options, while not required, are standard and expected to be present in most router addresses: "host" (an IPv4 or IPv6 address or host name) and "port".

Javadoc

RouterInfo

Description

Defines all of the data that a router wants to publish for the network to see. The RouterInfo is one of two structures stored in the network database(the other being LeaseSet, and is keyed under the SHA256 of the contained RouterIdentity.

Contents

RouterIdentity followed by the Date, when the entry was published

+----+----+----+----+----+----+----+----+
| router_ident                          |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| published                             |
+----+----+----+----+----+----+----+----+
|size| RouterAddress 0                  |
+----+                                  +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| RouterAddress 1                       |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+----+----+----+----+
| RouterAddress ($size-1)               |
+                                       +
|                                       |
~                                       ~
~                                       ~
|                                       |
+----+----+----+----+-//-+----+----+----+
|psiz| options                          |
+----+----+----+----+-//-+----+----+----+
| signature                             |
+                                       +
|                                       |
+                                       +
|                                       |
+                                       +
|                                       |
+                                       +
|                                       |
+----+----+----+----+----+----+----+----+

router_ident :: RouterIdentity
                length -> >= 387 bytes

published :: Date
             length -> 8 bytes

size :: Integer
        length -> 1 byte
        The number of RouterAddresses to follow, 0-255

addresses :: [RouterAddress]
             length -> varies

peer_size :: Integer
             length -> 1 byte
             The number of peer Hashes to follow, 0-255, unused, always zero
             value -> 0

options :: Mapping

signature :: Signature
             length -> 40 bytes

Notes

  • The peer_size Integer may be followed by a list of that many router hashes. This is currently unused. It was intended for a form of restricted routes, which is unimplemented.
  • The signature may be verified using the signing public key of the router_ident.
  • See the network database page for standard options that are expected to be present in all router infos.

Javadoc

Delivery Instructions

Tunnel Message Delivery Instructions are defined in the Tunnel Message Specification.

Garlic Message Delivery Instructions are defined in the I2NP Message Specification.