net.i2p.data.i2np

## Class BuildRequestRecord

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

-     public class BuildRequestRecord
      extends Object

  As of 0.9.48, supports two formats. As of 0.9.51, supports 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. 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 Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static int` | `IV_SIZE` IV size in bytes
    `static int` | `OFF_REPLY_KEY` Offset for reply key in ElGamal format
    `static int` | `OFF_REPLY_KEY_EC` Offset for reply key in ECIES long format
    `static int` | `PEER_SIZE` we show 16 bytes of the peer hash outside the elGamal block

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `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.
    `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.
    `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.
    `BuildRequestRecord(RouterContext ctx, PrivateKey ourKey, EncryptedBuildRecord encryptedRecord)` Decrypts an encrypted build request record.

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `EncryptedBuildRecord` | `encryptECIESRecord(RouterContext ctx, PublicKey toKey, Hash toPeer)` Encrypts the record using ECIES.
    `EncryptedBuildRecord` | `encryptRecord(I2PAppContext ctx, PublicKey toKey, Hash toPeer)` Encrypts the record using ElGamal.
    `byte[]` | `getChaChaReplyAD()` Returns the ChaCha reply AD (Associated Data).
    `SessionKey` | `getChaChaReplyKey()` Returns the ChaCha reply key.
    `byte[]` | `getData()` Returns the raw record data.
    `long` | `readExpiration()` Reads the expiration time.
    `MessageWrapper.OneTimeSession` | `readGarlicKeys()` Reads the garlic keys for OBEP.
    `boolean` | `readIsInboundGateway()` Reads whether this hop is an inbound gateway.
    `boolean` | `readIsOutboundEndpoint()` Reads whether this hop is an outbound endpoint.
    `SessionKey` | `readIVKey()` Reads the tunnel IV encryption key.
    `int` | `readLayerEncryptionType()` Reads the layer encryption type.
    `SessionKey` | `readLayerKey()` Reads the tunnel layer encryption key.
    `Hash` | `readNextIdentity()` Reads the next hop's identity hash.
    `long` | `readNextTunnelId()` Reads the next hop's tunnel ID.
    `Properties` | `readOptions()` Reads the tunnel build options.
    `long` | `readReceiveTunnelId()` Reads the tunnel ID this hop should receive messages on.
    `byte[]` | `readReplyIV()` Reads the reply IV.
    `SessionKey` | `readReplyKey()` Reads the reply encryption key.
    `long` | `readReplyMessageId()` Reads the reply message ID.
    `long` | `readRequestTime()` Reads the request time.
    `String` | `toString()` Returns a string representation of this record.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- - ### Field Detail

    - #### IV_SIZE

          public static final int IV_SIZE

      IV size in bytes
      See Also:
        Constant Field Values

    - #### OFF_REPLY_KEY

          public static final int OFF_REPLY_KEY

      Offset for reply key in ElGamal format
      See Also:
        Constant Field Values

    - #### OFF_REPLY_KEY_EC

          public static final int OFF_REPLY_KEY_EC

      Offset for reply key in ECIES long format
      See Also:
        Constant Field Values

    - #### PEER_SIZE

          public static final int PEER_SIZE

      we show 16 bytes of the peer hash outside the elGamal block
      See Also:
        Constant Field Values

  - ### Constructor Detail

    - #### 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,
                                    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

    - #### 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(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

  - ### Method Detail

    - #### 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

    - #### 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

    - #### 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

    - #### getChaChaReplyKey

          public SessionKey getChaChaReplyKey()

      Returns the ChaCha reply key. Valid after calling encryptECIESRecord() 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

    - #### getData

          public byte[] getData()

      Returns the raw record data.
      Returns:
        222 (ElG) or 464 (ECIES) bytes, non-null

    - #### readExpiration

          public long readExpiration()

      Reads the expiration time. The expiration in milliseconds from now.
      Returns:
        the expiration in milliseconds

    - #### 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

    - #### 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

    - #### 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

    - #### 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

    - #### 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

    - #### 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

    - #### 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

    - #### readOptions

          public Properties readOptions()

      Reads the tunnel build options. ECIES only.
      Returns:
        the properties, or null for ElGamal or on error

    - #### readReceiveTunnelId

          public long readReceiveTunnelId()

      Reads the tunnel ID this hop should receive messages on.
      Returns:
        the tunnel ID

    - #### 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

    - #### 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

    - #### 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

    - #### 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

    - #### toString

          public String toString()

      Returns a string representation of this record.
      Overrides:
        `toString` in class `Object`
      Returns:
        a string representation