All Implemented Interfaces:
Serializable, DataStructure
Direct Known Subclasses:
LeaseSet2

public class LeaseSetextends DatabaseEntry
Defines the set of leases that a destination currently has available for routing messages.

LeaseSet is the fundamental routing structure in I2P, containing:

  • Destination: The service endpoint identity
  • Encryption Key: Public key for encrypting messages to the destination
  • Signing Key: Public key for verifying LeaseSet authenticity
  • Leases: List of tunnel endpoints and their validity periods
  • Signature: Cryptographic signature proving authenticity

Lease Structure:

  • Gateway: Router identity that hosts the tunnel endpoint
  • Tunnel ID: Unique identifier for the tunnel on the gateway
  • Expiration: Time when the lease becomes invalid

Encryption Support (Legacy):

  • ⚠️ SECURITY WARNING: Encryption is poorly designed and probably insecure
  • Not Recommended: Use modern alternatives like EncryptedLeaseSet
  • Limited Scope: Only encrypts gateway and tunnel ID data
  • No Indication: Encrypted leases appear identical to unencrypted ones
  • Keyring Required: Routers need desthash and key to decrypt

Encryption Process:

  • Client Side: Encryption performed in I2CP client
  • Router Side: Local router must decrypt for usage
  • Network: Encrypted form transmitted to floodfills
  • Access: Decrypted leases only available via getLease(int)

Usage:

  • Routing: Primary mechanism for message delivery in I2P
  • Load Balancing: Multiple leases provide redundancy and distribution
  • Mobility: Leases can be updated as endpoints change
  • Discovery: Published to network database for lookup

Security Considerations:

  • Signature Verification: Always verify LeaseSet signatures
  • Expiration Checking: Ensure leases are still valid
  • Encryption Avoidance: Legacy encryption should not be used
  • Modern Alternatives: Use LeaseSet2, EncryptedLeaseSet, or MetaLeaseSet

Migration Path:

  • LeaseSet2: Enhanced format with better security and features
  • EncryptedLeaseSet: Proper encryption with authentication
  • MetaLeaseSet: Advanced routing and load balancing
leases and the original leaseset signature.

Revocation (zero leases) isn't used anywhere. In addition: - A revoked leaseset has an EarliestLeaseDate of -1, so it will never be stored successfully. - Revocation of an encrypted leaseset will explode. - So having an included signature at all is pointless?

See Also:
  • Field Details

    • _destination

      protected Destination _destination
      Destination this LeaseSet is for.
    • _encryptionKey

      protected PublicKey _encryptionKey
      Encryption public key for the destination.
    • _signingKey

      protected SigningPublicKey _signingKey
      Revocation or blinded signing key. For LS1, the revocation key; for LS2, null except the blinded key for encrypted LS2.
    • _leases

      protected final List<Lease> _leases
      Leases must stay in the order received, or signature verification will fail.
    • _firstExpiration

      private long _firstExpiration
      Earliest expiration time among all leases. Cached because isCurrent(long) and getEarliestLeaseDate() are called frequently.
    • _lastExpiration

      protected long _lastExpiration
      Latest expiration time among all leases.
    • _decryptedLeases

      private List<Lease> _decryptedLeases
      Decrypted leases backing store.
    • _decrypted

      private boolean _decrypted
      Whether decryption was successful.
    • _checked

      protected boolean _checked
      Whether decryption has been attempted.
    • _byteified

      protected volatile byte[] _byteified
      Cached serialized byte array for performance.
    • MAX_LEASES

      public static final int MAX_LEASES
      Unlimited before 0.6.3; 6 as of 0.6.3; Increased in version 0.9.

      Leasesets larger than 6 should be used with caution, as each lease adds 44 bytes, and routers older than version 0.9 will not be able to connect as they will throw an exception in readBytes(InputStream). Also, the churn will be quite rapid, leading to frequent netdb stores and transmission on existing connections.

      However we increase it now in case some hugely popular eepsite arrives. Strategies elsewhere in the router to efficiently handle large leasesets are TBD.

      See Also:
    • DATA_LEN

      private static final int DATA_LEN
      Combined length of gateway hash and tunnel ID.
      See Also:
    • IV_LEN

      private static final int IV_LEN
      AES initialization vector length in bytes.
      See Also:
  • Constructor Details

    • LeaseSet

      public LeaseSet()
      Creates a new leaseset with default values.
  • Method Details

    • getDate

      public long getDate()
      Specified by:
      getDate in class DatabaseEntry
      Returns:
      milliseconds since the epoch of the earliest lease expiry
    • getKeysAndCert

      public KeysAndCert getKeysAndCert()
      Keys and certificate for this lease set.
      Specified by:
      getKeysAndCert in class DatabaseEntry
      Returns:
      KAC or null
    • getType

      public int getType()
      Lease set type for the network database.
      Specified by:
      getType in class DatabaseEntry
      Returns:
      KEY_TYPE_ROUTERINFO or KEY_TYPE_LEASESET or LS2 types
    • getDestination

      public Destination getDestination()
      Warning - will be null for LS2 EncryptedLeaseSets if not decrypted.
      Returns:
      Destination or null
    • setDestination

      public void setDestination(Destination dest)
      Destination for this leaseset.
      Parameters:
      dest - the destination this leaseset is published under
      Throws:
      IllegalStateException - if already signed
    • getEncryptionKey

      public PublicKey getEncryptionKey()
      Encryption public key.
      Returns:
      the encryption public key
    • getEncryptionKey

      public PublicKey getEncryptionKey(Set<EncType> supported)
      If more than one key, return the first supported one. If none supported, return null.
      Parameters:
      supported - what return types are allowed
      Returns:
      ElGamal key or null if ElGamal not in supported
    • setEncryptionKey

      public void setEncryptionKey(PublicKey encryptionKey)
      Encryption public key for this leaseset.
      Parameters:
      encryptionKey - the ElGamal or ECIES key tunnel build requests are encrypted to, matched to the receiver by the key type
      Throws:
      IllegalStateException - if already signed
    • getSigningKey

      public SigningPublicKey getSigningKey()
      The revocation key. Undeprecated as of 0.9.38, used for the blinded key in EncryptedLeaseSet.
      Returns:
      the revocation key for LS1, null for LS2 except blinded key for encrypted LS2
    • setSigningKey

      public void setSigningKey(SigningPublicKey key)
      The revocation key. Unused except for encrypted LS2. Must be the same type as the Destination's SigningPublicKey.
      Parameters:
      key - the revocation key, which must match the signing public key type of the destination or the leaseset cannot be verified
      Throws:
      IllegalArgumentException - if different type
    • setReceivedBy

      public void setReceivedBy(Hash localClient)
      Record the local client that received this leaseset.

      As of 0.9.65, no longer sets receivedAsReply to true.

      Overrides:
      setReceivedBy in class DatabaseEntry
      Parameters:
      localClient - may be null
    • addLease

      public void addLease(Lease lease)
      Adds a lease to this leaseset.
      Parameters:
      lease - the lease to add, which must have a gateway and, outside a meta LeaseSet2, a tunnel ID
      Throws:
      IllegalStateException - if already signed
    • getLeaseCount

      public int getLeaseCount()
      Number of leases in this leaseset.
      Returns:
      0-16 A LeaseSet with no leases is revoked.
    • getLease

      public Lease getLease(int index)
      Lease at the given index.
      Parameters:
      index - the lease index
      Returns:
      the decrypted lease when encrypted, otherwise the stored one
    • getEarliestLeaseDate

      public long getEarliestLeaseDate()
      Retrieve the end date of the earliest lease included in this leaseSet. This is the date that should be used in comparisons for leaseSet age - to determine which LeaseSet was published more recently (later earliestLeaseSetDate means it was published later)

      Warning - do not use this for version comparison for LeaseSet2. Use LeaseSet2.getPublished() instead.

      Returns:
      earliest end date of any lease in the set, or -1 if there are no leases
    • getLatestLeaseDate

      public long getLatestLeaseDate()
      Retrieve the end date of the latest lease included in this leaseSet. This is the date used in isCurrent().
      Returns:
      latest end date of any lease in the set, or 0 if there are no leases
    • verifySignature

      public boolean verifySignature()
      Verify that the signature matches the leaseset's destination's signing public key. As of 0.9.47, revocation is not checked.
      Overrides:
      verifySignature in class DatabaseEntry
      Returns:
      true only if the signature matches
    • isCurrent

      public boolean isCurrent(long fudge)
      Determine whether ANY lease is currently valid, at least within a given fudge factor.
      Parameters:
      fudge - milliseconds fudge factor to allow between the current time
      Returns:
      true if there are current leases, false otherwise
    • getBytes

      protected byte[] getBytes()
      Without the signature!
      Specified by:
      getBytes in class DatabaseEntry
      Returns:
      the raw payload data, or null on error (for example, if this is a RouterInfo, a DataFormatException is thrown instead)
    • readBytes

      public void readBytes(InputStream in) throws DataFormatException, IOException
      This does NOT validate the signature.
      Parameters:
      in - stream to read from
      Throws:
      IllegalStateException - if called more than once or Destination already set
      DataFormatException - if the data is improperly formatted
      IOException - if there was a problem reading the stream
    • writeBytes

      public void writeBytes(OutputStream out) throws DataFormatException, IOException
      This does NOT validate the signature.
      Parameters:
      out - stream to write to
      Throws:
      DataFormatException - if the data was incomplete or not yet ready to be written
      IOException - if there was a problem writing to the stream
    • size

      public int size()
      Number of bytes, NOT including signature.
      Returns:
      the size in bytes
    • equals

      public boolean equals(Object object)
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      The destination has enough randomness in it to use it by itself for speed.
      Overrides:
      hashCode in class Object
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • encrypt

      public void encrypt(SessionKey key)
      Encrypt the gateway and tunnel ID of each lease, leaving the expire dates unchanged. This adds an extra dummy lease, because AES data must be padded to 16 bytes. The fact that it is encrypted is not stored anywhere. Must be called after all the leases are in place, but before sign().
      Parameters:
      key - the session key whose first block is the AES key, with the remainder used to derive the initialization vector
    • encryp

      private void encryp(SessionKey key) throws DataFormatException, IOException
      Encrypts the lease set in seven steps.
      • Put the {Gateway Hash, TunnelID} pairs for all the leases in a buffer
      • Pad with random data to a multiple of 16 bytes
      • Use the first part of the dest's public key as an IV
      • Encrypt
      • Pad with random data to a multiple of 36 bytes
      • Add an extra lease
      • Replace the Hash and TunnelID in each Lease
      Parameters:
      key - the AES session key to encrypt the lease data with
      Throws:
      DataFormatException - if a lease's gateway or tunnel ID is not set
      IOException - if the lease data cannot be written
    • decrypt

      private void decrypt(SessionKey key) throws DataFormatException, IOException
      Decrypt the leases, except for the last one which is partially padding. Store the new decrypted leases in a backing store, and keep the original leases so that verify() still works and the encrypted leaseset can be sent on to others (via writeBytes(OutputStream)).
      Parameters:
      key - the AES session key to decrypt the lease data with
      Throws:
      DataFormatException - if there are fewer than two leases, or the data is invalid
      IOException - if the lease data cannot be read
    • isEncrypted

      private boolean isEncrypted()
      True if it was encrypted, and we decrypted it successfully.
      Returns:
      true if it was encrypted, and we decrypted it successfully. Decrypts on first call.