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 Details

  • Constructor Details

    • BuildRequestRecord

      public BuildRequestRecord(RouterContext ctx, PrivateKey ourKey, EncryptedBuildRecord encryptedRecord) throws DataFormatException
      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.
      Throws:
      DataFormatException - on decrypt fail
      Since:
      0.9.48
    • 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)
      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:
      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?
      Since:
      0.9.18, was createRecord()
    • 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)
      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:
      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
      Since:
      0.9.48
    • BuildRequestRecord

      public BuildRequestRecord(I2PAppContext ctx, long receiveTunnelId, long nextTunnelId, Hash nextHop, long nextMsgId, boolean isInGateway, boolean isOutEndpoint, Properties options)
      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:
      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
      Since:
      0.9.51
  • Method Details

    • getData

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

      public long readReceiveTunnelId()
      what tunnel ID should this receive messages on
    • readNextTunnelId

      public long readNextTunnelId()
      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.
    • readNextIdentity

      public Hash readNextIdentity()
      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.
    • readLayerKey

      public SessionKey readLayerKey()
      Tunnel layer encryption key that the current hop should use
    • readIVKey

      public SessionKey readIVKey()
      Tunnel IV encryption key that the current hop should use
    • readReplyKey

      public SessionKey readReplyKey()
      AES Session key that should be used to encrypt the reply. Not to be used for short ECIES records; use the ChaChaReplyKey instead.
    • readReplyIV

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

      public boolean readIsInboundGateway()
      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.
    • readIsOutboundEndpoint

      public boolean readIsOutboundEndpoint()
      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.
    • readRequestTime

      public long readRequestTime()
      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.
    • readReplyMessageId

      public long readReplyMessageId()
      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.
    • readExpiration

      public long readExpiration()
      The expiration in milliseconds from now.
      Since:
      0.9.48
    • readOptions

      public Properties readOptions()
      ECIES only.
      Returns:
      null for ElGamal or on error
      Since:
      0.9.48
    • readLayerEncryptionType

      public int readLayerEncryptionType()
      ECIES short record only.
      Returns:
      0 for ElGamal or ECIES long record
      Since:
      0.9.51
    • readGarlicKeys

      public MessageWrapper.OneTimeSession readGarlicKeys()
      ECIES short OBEP record only.
      Returns:
      null for ElGamal or ECIES long record or non-OBEP
      Since:
      0.9.51
    • encryptRecord

      public EncryptedBuildRecord encryptRecord(I2PAppContext ctx, PublicKey toKey, Hash toPeer)
      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
      Returns:
      non-null
    • encryptECIESRecord

      public EncryptedBuildRecord encryptECIESRecord(RouterContext ctx, PublicKey toKey, Hash toPeer)
      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.
      Returns:
      non-null
      Since:
      0.9.48
    • getChaChaReplyKey

      public SessionKey getChaChaReplyKey()
      Valid after calling encryptECIESRecord() or after the decrypting constructor with an ECIES private key. See proposal 152.
      Returns:
      null if no ECIES encrypt/decrypt operation was performed
      Since:
      0.9.48
    • getChaChaReplyAD

      public byte[] getChaChaReplyAD()
      Valid after calling encryptECIESRecord() or after the decrypting constructor with an ECIES private key. See proposal 152.
      Returns:
      null if no ECIES encrypt/decrypt operation was performed
      Since:
      0.9.48
    • toString

      public String toString()
      Overrides:
      toString in class Object
      Since:
      0.9.24