java.lang.Object
net.i2p.data.i2np.BuildRequestRecord

public class BuildRequestRecordextends Object
A tunnel build request record, in one of three formats. The original 222-byte ElGamal format, the new 464-byte ECIES format, and the newest 154-byte ECIES format. See proposal 152 and 157 for details on the new formats.

Two formats were supported as of 0.9.48, three as of 0.9.51.

None of the readXXX() calls are cached. For efficiency, they should only be called once.

Original ElGamal format:

Holds the unencrypted 222-byte tunnel request record, with a constructor for ElGamal decryption and a method for ElGamal encryption. Iterative AES encryption/decryption is done elsewhere.

Cleartext:

bytes     0-3: tunnel ID to receive messages as
bytes    4-35: local router identity hash (Unused and no accessor here)
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-221: uninterpreted / random padding

Encrypted:

bytes    0-15: First 16 bytes of router hash
bytes  16-527: ElGamal encrypted block (discarding zero bytes at elg[0] and elg[257])

ECIES long record format, ref: proposal 152:

Holds the unencrypted 464-byte tunnel request record, with a constructor for ECIES decryption and a method for ECIES encryption. Iterative AES encryption/decryption is done elsewhere.

Cleartext:

bytes     0-3: tunnel ID to receive messages as, nonzero
bytes     4-7: next tunnel ID, nonzero
bytes    8-39: next router identity hash
bytes   40-71: AES-256 tunnel layer key
bytes  72-103: AES-256 tunnel IV key
bytes 104-135: AES-256 reply key
bytes 136-151: AES-256 reply IV
byte      152: flags
bytes 153-155: more flags, unused, set to 0 for compatibility
bytes 156-159: request time (in minutes since the epoch, rounded down)
bytes 160-163: request expiration (in seconds since creation)
bytes 164-167: next message ID
bytes   168-x: tunnel build options (Mapping)
bytes     x-x: other data as implied by flags or options
bytes   x-463: random padding

Encrypted:

bytes    0-15: Hop's truncated identity hash
bytes   16-47: Sender's ephemeral X25519 public key
bytes  48-511: ChaCha20 encrypted BuildRequestRecord
bytes 512-527: Poly1305 MAC

ECIES short record format, ref: proposal 157:

Holds the unencrypted 154-byte tunnel request record, with a constructor for ECIES decryption and a method for ECIES encryption. Iterative AES encryption/decryption is done elsewhere.

Cleartext:

bytes     0-3: tunnel ID to receive messages as, nonzero
bytes     4-7: next tunnel ID, nonzero
bytes    8-39: next router identity hash
byte       40: flags
bytes   41-42: more flags, unused, set to 0 for compatibility
byte       43: layer enc. type
bytes   44-47: request time (in minutes since the epoch, rounded down)
bytes   48-51: request expiration (in seconds since creation)
bytes   52-55: next message ID
bytes    56-x: tunnel build options (Mapping)
bytes     x-x: other data as implied by flags or options
bytes   x-153: random padding

Encrypted:

bytes    0-15: Hop's truncated identity hash
bytes   16-47: Sender's ephemeral X25519 public key
bytes  48-201: ChaCha20 encrypted BuildRequestRecord
bytes 202-217: Poly1305 MAC
  • Field Details

    • _data

      private final byte[] _data
      The raw record data.
    • _isEC

      private final boolean _isEC
      True if ECIES format, false if ElGamal.
    • _chachaReplyKey

      private SessionKey _chachaReplyKey
      ChaCha reply key for ECIES.
    • _chachaReplyAD

      private byte[] _chachaReplyAD
      ChaCha reply AD for ECIES.
    • _derivedLayerKey

      private SessionKey _derivedLayerKey
      Derived layer key for short records.
    • _derivedIVKey

      private SessionKey _derivedIVKey
      Derived IV key for short records.
    • _derivedGarlicKeys

      private MessageWrapper.OneTimeSession _derivedGarlicKeys
      Derived garlic keys for short OBEP records.
    • FLAG_UNRESTRICTED_PREV

      private static final int FLAG_UNRESTRICTED_PREV
      If set in the flag byte, any peer may send a message into this tunnel, but if not set, only the current predecessor may send messages in. This is only set on an inbound tunnel gateway.
      See Also:
    • FLAG_OUTBOUND_ENDPOINT

      private static final int FLAG_OUTBOUND_ENDPOINT
      If set in the flag byte, this is an outbound tunnel endpoint, which means that there is no 'next hop' and that the next hop fields contain the tunnel to which the reply message should be sent.
      See Also:
    • IV_SIZE

      public static final int IV_SIZE
      IV size in bytes.
      See Also:
    • PEER_SIZE

      public static final int PEER_SIZE
      We show 16 bytes of the peer hash outside the elGamal block.
      See Also:
    • DEFAULT_EXPIRATION_SECONDS

      private static final int DEFAULT_EXPIRATION_SECONDS
      Default life of the record - 10 minutes, stored in seconds.
      See Also:
    • EC_LEN

      private static final int EC_LEN
      Length of an X25519 public key, in bytes.
    • NULL_KEY

      private static final byte[] NULL_KEY
      An all-zero key, for records that carry none.
    • OFF_RECV_TUNNEL

      private static final int OFF_RECV_TUNNEL
      Offset for receive tunnel in ElGamal format.
      See Also:
    • OFF_OUR_IDENT

      private static final int OFF_OUR_IDENT
      Offset for local identity hash in ElGamal format.
      See Also:
    • OFF_SEND_TUNNEL

      private static final int OFF_SEND_TUNNEL
      Offset for send tunnel in ElGamal format.
      See Also:
    • OFF_SEND_IDENT

      private static final int OFF_SEND_IDENT
      Offset for send identity hash in ElGamal format.
      See Also:
    • OFF_LAYER_KEY

      private static final int OFF_LAYER_KEY
      Offset for layer key in ElGamal format.
      See Also:
    • OFF_IV_KEY

      private static final int OFF_IV_KEY
      Offset for IV key in ElGamal format.
      See Also:
    • OFF_REPLY_KEY

      public static final int OFF_REPLY_KEY
      Offset for reply key in ElGamal format.
      See Also:
    • OFF_REPLY_IV

      private static final int OFF_REPLY_IV
      Offset for reply IV in ElGamal format.
      See Also:
    • OFF_FLAG

      private static final int OFF_FLAG
      Offset for flags in ElGamal format.
      See Also:
    • OFF_REQ_TIME

      private static final int OFF_REQ_TIME
      Offset for request time in ElGamal format.
      See Also:
    • OFF_SEND_MSG_ID

      private static final int OFF_SEND_MSG_ID
      Offset for send message ID in ElGamal format.
      See Also:
    • PADDING_SIZE

      private static final int PADDING_SIZE
      Padding size for ElGamal format.
      See Also:
    • LENGTH

      private static final int LENGTH
      Record length for ElGamal format (222 bytes).
      See Also:
    • OFF_SEND_TUNNEL_EC

      private static final int OFF_SEND_TUNNEL_EC
      Offset for send tunnel in ECIES long format.
      See Also:
    • OFF_SEND_IDENT_EC

      private static final int OFF_SEND_IDENT_EC
      Offset for send identity hash in ECIES long format.
      See Also:
    • OFF_LAYER_KEY_EC

      private static final int OFF_LAYER_KEY_EC
      Offset for layer key in ECIES long format.
      See Also:
    • OFF_IV_KEY_EC

      private static final int OFF_IV_KEY_EC
      Offset for IV key in ECIES long format.
      See Also:
    • OFF_REPLY_KEY_EC

      public static final int OFF_REPLY_KEY_EC
      Offset for reply key in ECIES long format.
      See Also:
    • OFF_REPLY_IV_EC

      private static final int OFF_REPLY_IV_EC
      Offset for reply IV in ECIES long format.
      See Also:
    • OFF_FLAG_EC

      private static final int OFF_FLAG_EC
      Offset for flags in ECIES long format.
      See Also:
    • OFF_REQ_TIME_EC

      private static final int OFF_REQ_TIME_EC
      Offset for request time in ECIES long format.
      See Also:
    • OFF_EXPIRATION

      private static final int OFF_EXPIRATION
      Offset for expiration in ECIES long format.
      See Also:
    • OFF_SEND_MSG_ID_EC

      private static final int OFF_SEND_MSG_ID_EC
      Offset for send message ID in ECIES long format.
      See Also:
    • OFF_OPTIONS

      private static final int OFF_OPTIONS
      Offset for options in ECIES long format.
      See Also:
    • LENGTH_EC

      private static final int LENGTH_EC
      Record length for ECIES long format (464 bytes).
      See Also:
    • MAX_OPTIONS_LENGTH

      private static final int MAX_OPTIONS_LENGTH
      Maximum options length for ECIES long format.
      See Also:
    • OFF_FLAG_EC_SHORT

      private static final int OFF_FLAG_EC_SHORT
      Offset for flags in ECIES short format.
      See Also:
    • OFF_LAYER_ENC_TYPE

      private static final int OFF_LAYER_ENC_TYPE
      Offset for layer encryption type in ECIES short format.
      See Also:
    • OFF_REQ_TIME_EC_SHORT

      private static final int OFF_REQ_TIME_EC_SHORT
      Offset for request time in ECIES short format.
      See Also:
    • OFF_EXPIRATION_SHORT

      private static final int OFF_EXPIRATION_SHORT
      Offset for expiration in ECIES short format.
      See Also:
    • OFF_SEND_MSG_ID_EC_SHORT

      private static final int OFF_SEND_MSG_ID_EC_SHORT
      Offset for send message ID in ECIES short format.
      See Also:
    • OFF_OPTIONS_SHORT

      private static final int OFF_OPTIONS_SHORT
      Offset for options in ECIES short format.
      See Also:
    • LENGTH_EC_SHORT

      private static final int LENGTH_EC_SHORT
      Record length for ECIES short format (154 bytes).
      See Also:
    • MAX_OPTIONS_LENGTH_SHORT

      private static final int MAX_OPTIONS_LENGTH_SHORT
      Maximum options length for ECIES short format.
      See Also:
    • ZEROLEN

      private static final byte[] ZEROLEN
      Empty byte array for short record HKDF.
    • INFO_1

      private static final String INFO_1
      HKDF info string for reply key derivation.
      See Also:
    • INFO_2

      private static final String INFO_2
      HKDF info string for layer key derivation.
      See Also:
    • INFO_3

      private static final String INFO_3
      HKDF info string for IV key derivation.
      See Also:
    • INFO_4

      private static final String INFO_4
      HKDF info string for garlic key and tag derivation.
      See Also:
    • TEST

      private static final boolean TEST
      Test mode flag.
      See Also:
    • TESTKF

      private static KeyFactory TESTKF
      Test key factory.
  • Constructor Details

    • BuildRequestRecord

      public BuildRequestRecord(RouterContext ctx, PrivateKey ourKey, EncryptedBuildRecord encryptedRecord) throws DataFormatException
      Decrypts an encrypted build request record. Decrypt the data from the specified record, writing the decrypted record into this instance's data buffer

      Caller MUST check that first 16 bytes of our hash matches first 16 bytes of encryptedRecord before calling this. Not checked here.

      The ChaCha reply key and IV will be available via the getters after this call if ourKey is ECIES.

      Parameters:
      ctx - the router context
      ourKey - our private key to decrypt with
      encryptedRecord - the encrypted build record
      Throws:
      DataFormatException - on decrypt fail
    • BuildRequestRecord

      public BuildRequestRecord(I2PAppContext ctx, long receiveTunnelId, Hash peer, long nextTunnelId, Hash nextHop, long nextMsgId, SessionKey layerKey, SessionKey ivKey, SessionKey replyKey, byte[] iv, boolean isInGateway, boolean isOutEndpoint)
      Creates a new ElGamal build request record. Populate this instance with data. A new buffer is created to contain the data, with the necessary randomized padding.

      ElGamal only. ECIES constructor below.

      Parameters:
      ctx - the application context
      receiveTunnelId - tunnel the current hop will receive messages on
      peer - current hop's identity, unused, no read() method
      nextTunnelId - id for the next hop, or where we send the reply (if we are the outbound endpoint)
      nextHop - next hop's identity, or where we send the reply (if we are the outbound endpoint)
      nextMsgId - message ID to use when sending on to the next hop (or for the reply)
      layerKey - tunnel layer key to be used by the peer
      ivKey - tunnel IV key to be used by the peer
      replyKey - key to be used when encrypting the reply to this build request
      iv - iv to be used when encrypting the reply to this build request
      isInGateway - are we the gateway of an inbound tunnel?
      isOutEndpoint - are we the endpoint of an outbound tunnel?
    • BuildRequestRecord

      public BuildRequestRecord(I2PAppContext ctx, long receiveTunnelId, long nextTunnelId, Hash nextHop, long nextMsgId, SessionKey layerKey, SessionKey ivKey, SessionKey replyKey, byte[] iv, boolean isInGateway, boolean isOutEndpoint, Properties options)
      Creates a new ECIES long build request record. Populate this instance with data. A new buffer is created to contain the data, with the necessary randomized padding.

      ECIES long record only. ElGamal constructor above.

      Parameters:
      ctx - the application context
      receiveTunnelId - tunnel the current hop will receive messages on
      nextTunnelId - id for the next hop, or where we send the reply (if we are the outbound endpoint)
      nextHop - next hop's identity, or where we send the reply (if we are the outbound endpoint)
      nextMsgId - message ID to use when sending on to the next hop (or for the reply)
      layerKey - tunnel layer key to be used by the peer
      ivKey - tunnel IV key to be used by the peer
      replyKey - key to be used when encrypting the reply to this build request
      iv - iv to be used when encrypting the reply to this build request
      isInGateway - are we the gateway of an inbound tunnel?
      isOutEndpoint - are we the endpoint of an outbound tunnel?
      options - 296 bytes max when serialized
      Throws:
      IllegalArgumentException - if options too long
    • BuildRequestRecord

      public BuildRequestRecord(I2PAppContext ctx, long receiveTunnelId, long nextTunnelId, Hash nextHop, long nextMsgId, boolean isInGateway, boolean isOutEndpoint, Properties options)
      Creates a new ECIES short build request record. Populate this instance with data. A new buffer is created to contain the data, with the necessary randomized padding.

      ECIES short record only. ElGamal constructor above.

      Parameters:
      ctx - the application context
      receiveTunnelId - tunnel the current hop will receive messages on
      nextTunnelId - id for the next hop, or where we send the reply (if we are the outbound endpoint)
      nextHop - next hop's identity, or where we send the reply (if we are the outbound endpoint)
      nextMsgId - message ID to use when sending on to the next hop (or for the reply)
      isInGateway - are we the gateway of an inbound tunnel?
      isOutEndpoint - are we the endpoint of an outbound tunnel?
      options - 98 bytes max when serialized
      Throws:
      IllegalArgumentException - if options too long
  • Method Details

    • getData

      public byte[] getData()
      Returns the raw record data.
      Returns:
      222 (ElG) or 464 (ECIES) bytes, non-null
    • readReceiveTunnelId

      public long readReceiveTunnelId()
      Reads the tunnel ID this hop should receive messages on.
      Returns:
      the tunnel ID
    • readNextTunnelId

      public long readNextTunnelId()
      Reads the next hop's tunnel ID. What tunnel ID the next hop receives messages on. If this is the outbound tunnel endpoint, this specifies the tunnel ID to which the reply should be sent.
      Returns:
      the next tunnel ID
    • readNextIdentity

      public Hash readNextIdentity()
      Reads the next hop's identity hash. Read the next hop from the record. If this is the outbound tunnel endpoint, this specifies the gateway to which the reply should be sent.
      Returns:
      the next hop's identity hash, non-null
    • readLayerKey

      public SessionKey readLayerKey()
      Reads the tunnel layer encryption key. Tunnel layer encryption key that the current hop should use.
      Returns:
      the session key for layer encryption
    • readIVKey

      public SessionKey readIVKey()
      Reads the tunnel IV encryption key. Tunnel IV encryption key that the current hop should use.
      Returns:
      the session key for IV encryption
    • readReplyKey

      public SessionKey readReplyKey()
      Reads the reply encryption key. AES Session key that should be used to encrypt the reply. Not to be used for short ECIES records; use the ChaChaReplyKey instead.
      Returns:
      the session key for reply encryption
      Throws:
      IllegalStateException - for short ECIES records
    • readReplyIV

      public byte[] readReplyIV()
      Reads the reply IV. AES IV that should be used to encrypt the reply. Not to be used for short ECIES records.
      Returns:
      16 bytes IV data
      Throws:
      IllegalStateException - for short ECIES records
    • readIsInboundGateway

      public boolean readIsInboundGateway()
      Reads whether this hop is an inbound gateway. The current hop is the inbound gateway. If this is true, it means anyone can send messages to this tunnel, but if it is false, only the current predecessor can.
      Returns:
      true if inbound gateway, false otherwise
    • readIsOutboundEndpoint

      public boolean readIsOutboundEndpoint()
      Reads whether this hop is an outbound endpoint. The current hop is the outbound endpoint. If this is true, the next identity and next tunnel fields refer to where the reply should be sent.
      Returns:
      true if outbound endpoint, false otherwise
    • readRequestTime

      public long readRequestTime()
      Reads the request time. For ElGamal, time that the request was sent (ms), truncated to the nearest hour. For ECIES, time that the request was sent (ms), truncated to the nearest minute. This ignores leap seconds.
      Returns:
      the request time in milliseconds
    • readReplyMessageId

      public long readReplyMessageId()
      Reads the reply message ID. What message ID should we send the request to the next hop with. If this is the outbound tunnel endpoint, this specifies the message ID with which the reply should be sent.
      Returns:
      the reply message ID
    • readExpiration

      public long readExpiration()
      Reads the expiration time. The expiration in milliseconds from now.
      Returns:
      the expiration in milliseconds
    • readOptions

      public Properties readOptions()
      Reads the tunnel build options. ECIES only.
      Returns:
      the properties, or null for ElGamal or on error
    • readLayerEncryptionType

      public int readLayerEncryptionType()
      Reads the layer encryption type. ECIES short record only.
      Returns:
      the encryption type (0-255), or 0 for ElGamal or ECIES long record
    • readGarlicKeys

      public MessageWrapper.OneTimeSession readGarlicKeys()
      Reads the garlic keys for OBEP. ECIES short OBEP record only.
      Returns:
      the garlic keys, or null for ElGamal or ECIES long record or non-OBEP
    • encryptRecord

      public EncryptedBuildRecord encryptRecord(I2PAppContext ctx, PublicKey toKey, Hash toPeer)
      Encrypts the record using ElGamal. Encrypt the record to the specified peer. The result is formatted as:
      bytes 0-15: truncated SHA-256 of the current hop's identity (the toPeer parameter)
      bytes 15-527: ElGamal-2048 encrypted block
      
      ElGamal only.
      Parameters:
      ctx - the application context
      toKey - the public key to encrypt to
      toPeer - the peer's identity hash
      Returns:
      the encrypted build record, non-null
      Throws:
      IllegalArgumentException - if key type is not ElGamal
    • encryptECIESRecord

      public EncryptedBuildRecord encryptECIESRecord(RouterContext ctx, PublicKey toKey, Hash toPeer)
      Encrypts the record using ECIES. Encrypt the record to the specified peer. ECIES only. The ChaCha reply key and IV will be available via the getters after this call. For short records, derived keys will be available via readLayerKey(), readIVKey(), and readGarlicKeys() after this call. See class javadocs for format. See proposals 152 and 157.
      Parameters:
      ctx - the router context
      toKey - the public key to encrypt to
      toPeer - the peer's identity hash
      Returns:
      the encrypted build record, non-null
      Throws:
      IllegalArgumentException - if key type is not ECIES
      IllegalStateException - on encryption failure
    • getChaChaReplyKey

      public SessionKey getChaChaReplyKey()
      Returns the ChaCha reply key. Valid after calling encryptECIESRecord(RouterContext, PublicKey, Hash) or after the decrypting constructor with an ECIES private key. See proposal 152.
      Returns:
      the session key, or null if no ECIES encrypt/decrypt operation was performed
    • getChaChaReplyAD

      public byte[] getChaChaReplyAD()
      Returns the ChaCha reply AD (Associated Data). Valid after calling encryptECIESRecord() or after the decrypting constructor with an ECIES private key. See proposal 152.
      Returns:
      the AD data (32 bytes), or null if no ECIES encrypt/decrypt operation was performed
    • toString

      public String toString()
      Concise summary for log output: crypto type, hop role and tunnel IDs. No key material; no expiration (callers log elapsed or age deltas separately when relevant); no next-identity (callers print the peer hash in the message header). Starts with a newline and an asterisk for multi-line log entries.
      Overrides:
      toString in class Object
      Returns:
      a string representation
    • role

      static String role(boolean inboundGateway, boolean outboundEndpoint)
      The hop's role in the tunnel, in the plain words the logs use instead of the IBGW / OBEP shorthands.
      Parameters:
      inboundGateway - true if this hop receives the tunnel from the client
      outboundEndpoint - true if this hop forwards it to the final peer
      Returns:
      the role name, never null
    • toKeyString

      public String toKeyString()
      Key material for DEBUG-level build interop debugging only. Never log this at INFO or above. Starts with a newline and an asterisk for multi-line log entries.
      Returns:
      the key material dump, never null