Class 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
     
    • Constructor Detail

      • 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 Detail

      • 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