java.lang.Object
net.i2p.data.DataStructureImpl
net.i2p.data.DatabaseEntry
net.i2p.data.LeaseSet
net.i2p.data.LeaseSet2
net.i2p.data.EncryptedLeaseSet
- All Implemented Interfaces:
Serializable, DataStructure
Implementation of EncryptedLeaseSet as specified in Proposal 123: New NetDb Entries.
EncryptedLeaseSet provides privacy and authentication enhancements over standard LeaseSet2:
- LeaseSet content is encrypted using authenticated encryption
- Supports per-client and group-based access control
- Uses blinded keys for enhanced privacy
- Requires authentication data for decryption
- Protects tunnel endpoints from unauthorized discovery
Key Features:
- Authentication Types: Supports DH, PSK, and no authentication
- Blinded Keys: Uses
LeaseSet.getSigningKey()for the blinded key (revocation key in super) - Encryption: Content encrypted with
ChaCha20-Poly1305 AEAD - Access Control: Fine-grained control over who can decrypt the LeaseSet
Usage:
- Services requiring restricted access to tunnel endpoints
- Private services with authenticated client access
- Situations where tunnel endpoint discovery must be controlled
Authentication Methods:
BlindData.AUTH_NONE- No authentication requiredBlindData.AUTH_DH- Diffie-Hellman key exchange authenticationBlindData.AUTH_PSK- Pre-shared key authentication
Implementation Status: PRELIMINARY - Subject to change as the proposal evolves.
- See Also:
Field Summary
FieldsModifier and TypeFieldDescriptionprivate HashCached calculated hash value.private SigningPrivateKeyAlpha signing private key.private intAuthorization type of this lease set.private PrivateKeyClient private key for decryption.private LeaseSet2Decrypted LeaseSet 2 instance.private byte[]Includes salt.private static HKDFCached HKDF for layer encryption/decryption.private static I2PAppContextThe context_hkdfwas built for, so a context change forces a rebuild.private final LogLogger instance.private intNumber of keys in the encrypted set.private StringSecret passphrase for decryption.private SigningPublicKeyTo decrypt with if we don't have the full destination.private static final intCombined client ID and cookie length.private static final intCookie length in bytes.private static final byte[]Credential ASCII bytes.private static final StringELS2 Diffie-Hellman key label.private static final StringELS2 pre-shared key label.private static final StringELS2 level 1 key label.private static final StringELS2 level 2 key label.private static final intClient identifier length in bytes.private static final intAES-GCM initialization vector length.private static final intMaximum encrypted data size.private static final intMinimum encrypted data size (salt + IV).private static final intSalt length in bytes.private static final byte[]Subcredential ASCII bytes.Fields inherited from class LeaseSet2
_expires, _flags, _offlineSignature, _options, _published, _transientExpires, _transientSigningPublicKeyModifier and TypeFieldDescriptionprotected longExpiration timestamp in ms (1-second resolution).protected intFlags for options, offline, unpublished, blinded.protected SignatureOffline signature.protected PropertiesOptions and statistics properties, may be null.protected longPublished timestamp in ms (1-second resolution).protected longTransient key expiration in ms.protected SigningPublicKeyTransient signing public key for offline signing.Fields inherited from class LeaseSet
_byteified, _checked, _destination, _encryptionKey, _lastExpiration, _leases, _signingKey, MAX_LEASESModifier and TypeFieldDescriptionprotected byte[]Cached serialized byte array for performance.protected booleanWhether decryption has been attempted.protected DestinationDestination this LeaseSet is for.protected PublicKeyEncryption public key for the destination.protected longLatest expiration time among all leases.Leases must stay in the order received, or signature verification will fail.protected SigningPublicKeyRevocation or blinded signing key.static final intUnlimited before 0.6.3; 6 as of 0.6.3; Increased in version 0.9.Fields inherited from class DatabaseEntry
_signature, KEY_TYPE_ENCRYPTED_LS2, KEY_TYPE_LEASESET, KEY_TYPE_LS2, KEY_TYPE_META_LS2, KEY_TYPE_ROUTERINFO, KEY_TYPE_SERVICE_LIST, KEY_TYPE_SERVICE_RECORDModifier and TypeFieldDescriptionprotected SignatureCryptographic signature.static final intEncrypted LeaseSet 2 type.static final intLeaseSet (v1) type.static final intLeaseSet 2 type.static final intMeta LeaseSet 2 type.static final intRouter info type.static final intService list type.static final intService record type.Constructor Summary
ConstructorsMethod Summary
Modifier and TypeMethodDescriptionprivate SigningPublicKeyblind(SigningPublicKey spk) Generate blinded pubkey from the unblinded pubkey in the destination, which must have been previously set.private voiddecrypt(PrivateKey csk) Throws IllegalStateException if not initialized.voidencrypt(int authType, List<? extends SimpleDataStructure> clientKeys) Throws IllegalStateException if not initialized.voidencrypt(SessionKey skey) Throws IllegalStateException if not initialized.booleanCompares this EncryptedLeaseSet with another object for equality.Leaseset or null if not decrypted.getEncryptionKey(Set<EncType> supported) If more than one key, return the first supported one.Null if not decrypted.getHash()This must be used instead of getDestination().getHash().private byte[]The HKDF input (no per-client auth).private byte[]getHKDFInput(I2PAppContext ctx, byte[] authcookie) The HKDF input (with per-client auth).getLease(int index) Null if not decrypted.int0-16, or 0 if not decrypted.protected SigningPublicKeyOverridden to return the blinded key so super.verifySignature()will work.private byte[]The subcredential.intgetType()Entry type for the network database.private static byte[]hash(I2PAppContext ctx, byte[] p, byte[] d) Hash with a personalization string.inthashCode()The destination has enough randomness in it to use it by itself for speed.private static HKDFhkdf(I2PAppContext ctx) Get the shared HKDF for a context.voidreadBytes(InputStream in) This does NOT validate the signature.protected voidOverridden because we have a blinded key, not a dest.protected voidOverridden because we have a blinded key, not a dest.voidsetClientPrivateKey(PrivateKey privKey) Must be set before verify for per-client auth.voidsetDestination(Destination dest) Overridden to set the blinded key.voidMust be set before sign or verify.voidOverridden to set the blinded key.voidsign(SigningPrivateKey key) Sign the structure using the supplied signing key.voidsign(SigningPrivateKey key, int authType, List<? extends SimpleDataStructure> clientKeys) Sign the structure using the supplied signing key.intsize()Number of bytes, NOT including signature.toString()Returns a string representation of this EncryptedLeaseSet.booleanOverridden because we have a blinded key, not a dest.booleanOverridden to decrypt if possible, and verify inner sig also.booleanverifySignature(PrivateKey clientKey) Decrypt if possible, and verify inner sig also.protected voidBeforeencrypt(SessionKey)is called, the inner leaseset.protected voidwriteHeader(OutputStream out) Overridden because we have a blinded key, not a dest.protected voidOverridden because we have a blinded key, not a dest.private voidx_decrypt(PrivateKey csk) Throws IllegalStateException if not initialized.Methods inherited from class LeaseSet2
addEncryptionKey, addLease, getBlindedHash, getBytes, getEncryptionKey, getExpires, getOption, getOptions, getPublished, getReceivedAsPublished, getTransientExpiration, getTransientSigningKey, isBlindedWhenPublished, isCurrent, isOffline, isUnpublished, offlineSign, setBlindedHash, setBlindedWhenPublished, setOfflineSignature, setOptions, setPublished, setUnpublished, verifyOfflineSignature, writeBody, writeBytesModifier and TypeMethodDescriptionvoidAdd an encryption key.voidMust be a Lease2.The original blinded hash, where this came from.protected byte[]getBytes()Without the signature!If more than one key, return the first supported one.longPublished expiration, as received.Option value for the given key.Leaseset options.longPublished timestamp, as received.booleanIf true, we received this LeaseSet by a remote peer publishing it to us, AND the unpublished flag is not set.longAbsolute time, not time from now.Transient public key for offline signing.booleanWhether the unencrypted LS, when published, will be blinded/encrypted.booleanisCurrent(long fudge) Determine whether the leaseset is currently valid, at least within a given fudge factor.booleanChecks if this leaseset uses offline keys.booleanTrue if unpublished.static SignatureofflineSign(long expires, SigningPublicKey transientSPK, SigningPrivateKey priv) Generate a Signature to pass toLeaseSet2.setOfflineSignature(long, SigningPublicKey, Signature).voidsetBlindedHash(Hash bh) Blinded hash, if known at creation.voidMark the unencrypted LS to be blinded/encrypted when published.booleansetOfflineSignature(long expires, SigningPublicKey transientSPK, Signature offlineSig) Destination must be previously set.voidsetOptions(Properties options) Configure a set of options or statistics that the router can expose.voidsetPublished(long now) Published timestamp.voidMarks this leaseset as unpublished.protected booleanVerify the offline signature with the given key.protected voidwriteBody(OutputStream out) Without sig.voidwriteBytes(OutputStream out) Including sig.Methods inherited from class LeaseSet
getDate, getDestination, getEarliestLeaseDate, getKeysAndCert, getLatestLeaseDate, getSigningKey, setEncryptionKey, setReceivedByModifier and TypeMethodDescriptionlonggetDate()Same asLeaseSet.getEarliestLeaseDate().Warning - will be null for LS2 EncryptedLeaseSets if not decrypted.longRetrieve the end date of the earliest lease included in this leaseSet.Keys and certificate for this lease set.longRetrieve the end date of the latest lease included in this leaseSet.The revocation key.voidsetEncryptionKey(PublicKey encryptionKey) Encryption public key for this leaseset.voidsetReceivedBy(Hash localClient) Record the local client that received this leaseset.Methods inherited from class DatabaseEntry
getReceivedAsReply, getReceivedBy, getRoutingKey, getSignature, isLeaseSet, isLeaseSet, isRouterInfo, setReceivedAsPublished, setReceivedAsReply, setSignature, validateRoutingKeyModifier and TypeMethodDescriptionbooleanIf true, we received this LeaseSet by searching for it Default false.The Hash of the local client that received this LS, null if the router or unknown.Routing key for the structure using the current modifier in the RoutingKeyGenerator.Retrieve the proof that the identity stands behind the info here.booleanConvenience method, is the type any variant of leaseset?static booleanisLeaseSet(int type) Convenience method, is the type any variant of leaseset?booleanConvenience method, is the type any variant of router info?voidMarks this entry as received via published mode.voidMarks this entry as received via reply.voidsetSignature(Signature signature) Configure the proof that the entity stands behind the info here.booleanValidates the routing key for this entry.Methods inherited from class DataStructureImpl
calculateHash, fromBase64, fromByteArray, read, toBase64, toByteArrayModifier and TypeMethodDescriptionCalculate the SHA256 value of this object (useful for a few scenarios).voidfromBase64(String data) Load the structure from the provided base64 string.voidfromByteArray(byte[] data) Loads structure from the data providedprotected intread(InputStream in, byte[] target) Repeated reads until buffer is full or IOException is thrown.toBase64()Render the structure into modified base 64 notation.byte[]Convert the structure to a byte array.
Field Details
_encryptedData
private byte[] _encryptedDataIncludes salt._decryptedLS2
Decrypted LeaseSet 2 instance.__calculatedHash
Cached calculated hash value._alpha
Alpha signing private key._unblindedSPK
To decrypt with if we don't have the full destination._secret
Secret passphrase for decryption._clientPrivateKey
Client private key for decryption._log
Logger instance._authType
private int _authTypeAuthorization type of this lease set._numKeys
private int _numKeysNumber of keys in the encrypted set.MIN_ENCRYPTED_SIZE
private static final int MIN_ENCRYPTED_SIZEMinimum encrypted data size (salt + IV).- See Also:
MAX_ENCRYPTED_SIZE
private static final int MAX_ENCRYPTED_SIZEMaximum encrypted data size.- See Also:
SALT_LEN
CREDENTIAL
private static final byte[] CREDENTIALCredential ASCII bytes.SUBCREDENTIAL
private static final byte[] SUBCREDENTIALSubcredential ASCII bytes.ELS2L1K
ELS2L2K
ELS2_DH
ELS2_PSK
IV_LEN
ID_LEN
COOKIE_LEN
CLIENT_LEN
private static final int CLIENT_LENCombined client ID and cookie length.- See Also:
_hkdf
Cached HKDF for layer encryption/decryption. HKDF is stateless (it only holds the context, and the context's HMAC256Generator is itself thread-safe), so one instance per context is reusable by all client threads and saves an allocation per encrypt/decrypt._hkdfCtx
The context_hkdfwas built for, so a context change forces a rebuild.
Constructor Details
EncryptedLeaseSet
public EncryptedLeaseSet()Creates a new EncryptedLeaseSet with default values.
Method Details
hkdf
Get the shared HKDF for a context. The cached instance is rebuilt if the context differs, so a context swap never leaves a HKDF bound to a stale one. A racy double build is harmless, as both instances are equivalent.- Parameters:
ctx- the app context- Returns:
- the shared HKDF, never null
getDecryptedLeaseSet
Leaseset or null if not decrypted.- Returns:
- leaseset or null if not decrypted.
setSecret
Must be set before sign or verify. Must be called beforesetDestination(Destination)or setSigningKey(), or alpha will be wrong.- Parameters:
secret- null or "" for none (default)
setClientPrivateKey
Must be set before verify for per-client auth.- Parameters:
privKey- non-null
getType
getLeaseCount
public int getLeaseCount()0-16, or 0 if not decrypted.- Overrides:
getLeaseCountin classLeaseSet- Returns:
- 0-16, or 0 if not decrypted.
getLease
getEncryptionKeys
Null if not decrypted.- Overrides:
getEncryptionKeysin classLeaseSet2- Returns:
- null if not decrypted.
getEncryptionKey
If more than one key, return the first supported one. If none supported, return null.- Overrides:
getEncryptionKeyin classLeaseSet2- Parameters:
supported- what return types are allowed- Returns:
- first supported key or null
setDestination
Overridden to set the blinded key.setSecret(String)MUST be called before this for non-null secret, or alpha will be wrong.- Overrides:
setDestinationin classLeaseSet- Parameters:
dest- non-null, must be EdDSA_SHA512_Ed25519 or RedDSA_SHA512_Ed25519- Throws:
IllegalStateException- if already signedIllegalArgumentException- if not EdDSA
setSigningKey
Overridden to set the blinded key. setSecret() MUST be called before this for non-null secret, or alpha will be wrong.- Overrides:
setSigningKeyin classLeaseSet2- Parameters:
spk- unblinded key non-null, must be EdDSA_SHA512_Ed25519 or RedDSA_SHA512_Ed25519- Throws:
IllegalStateException- if already signedIllegalArgumentException- if not EdDSA
blind
Generate blinded pubkey from the unblinded pubkey in the destination, which must have been previously set.- Parameters:
spk- the unblinded signing public key from the destination- Returns:
- the blinded public key
getSigningPublicKey
Overridden to return the blinded key so super.verifySignature()will work.- Overrides:
getSigningPublicKeyin classDatabaseEntry- Returns:
- SPK or null
readBytes
This does NOT validate the signature.- Specified by:
readBytesin interfaceDataStructure- Overrides:
readBytesin classLeaseSet2- Parameters:
in- stream to read from- Throws:
IllegalStateException- if called more than once or Destination already setDataFormatException- if the data is improperly formattedIOException- if there was a problem reading the stream
writeBytesWithoutSig
Beforeencrypt(SessionKey)is called, the inner leaseset. After encrypt() is called, the encrypted data. Without sig. This does NOT validate the signature.- Overrides:
writeBytesWithoutSigin classLeaseSet2- Parameters:
out- the stream to write the header and body to- Throws:
DataFormatException- if the destination or encryption key is unsetIOException- if the stream cannot be written
verifyOfflineSignature
public boolean verifyOfflineSignature()Overridden because we have a blinded key, not a dest.- Overrides:
verifyOfflineSignaturein classLeaseSet2- Returns:
- true if valid
readHeader
Overridden because we have a blinded key, not a dest.- Overrides:
readHeaderin classLeaseSet2- Parameters:
in- the input stream- Throws:
DataFormatException- if the data is invalidIOException- if there is an error reading
writeHeader
Overridden because we have a blinded key, not a dest.- Overrides:
writeHeaderin classLeaseSet2- Parameters:
out- the output stream- Throws:
DataFormatException- if the data is invalidIOException- if there is an error writing
readOfflineBytes
Overridden because we have a blinded key, not a dest.- Overrides:
readOfflineBytesin classLeaseSet2- Parameters:
in- the input stream- Throws:
DataFormatException- if the data is invalidIOException- if there is an error reading
writeOfflineBytes
Overridden because we have a blinded key, not a dest.- Overrides:
writeOfflineBytesin classLeaseSet2- Parameters:
out- the output stream- Throws:
DataFormatException- if the data is invalidIOException- if there is an error writing
size
getHash
This must be used instead of getDestination().getHash().Overridden because we have a blinded key, not a dest. This is the hash of the signing public key type and the signing public key. Throws IllegalStateException if not initialized.
- Overrides:
getHashin classDatabaseEntry- Returns:
- the hash of the signing public key's type and key, not the destination hash
- Throws:
IllegalStateException- if the signing key is not set
encrypt
Throws IllegalStateException if not initialized.- Overrides:
encryptin classLeaseSet2- Parameters:
skey- unused in this implementation- Throws:
IllegalStateException- if the lease set is already encrypted or not signed
encrypt
Throws IllegalStateException if not initialized. Ref: proposal 123.- Parameters:
authType- 0, 1, or 3, seeBlindDataclientKeys- The client's X25519 public or private keys, null if unused- Throws:
IllegalStateException- if already encrypted, not signed, or the inner layer cannot be written
decrypt
Throws IllegalStateException if not initialized.- Parameters:
csk- PrivateKey for DH or PSK, or null if none- Throws:
IllegalStateException- if this object holds no encrypted dataDataFormatException- if the per-client auth entry is missing or unusable, or the decrypted data is not a valid LeaseSetIOException- if the decrypted inner LeaseSet cannot be read
x_decrypt
Throws IllegalStateException if not initialized.- Parameters:
csk- PrivateKey for DH or PSK, or null if none- Throws:
IllegalStateException- if this object holds no encrypted dataDataFormatException- if the per-client auth type or entry is missing or unusable, or the decrypted data is not a valid LeaseSetIOException- if the decrypted inner LeaseSet cannot be read
getHKDFInput
The HKDF input (no per-client auth).- Parameters:
ctx- the context supplying the router and client keys used to derive the subcredential- Returns:
- 36 bytes
getHKDFInput
The HKDF input (with per-client auth).- Parameters:
ctx- the context supplying the keys used to derive the subcredentialauthcookie- 32 bytes- Returns:
- 68 bytes
getSubcredential
The subcredential.- Parameters:
ctx- the context supplying the hash used to derive it- Returns:
- 32 bytes
- Throws:
IllegalStateException- if we don't have it
hash
Hash with a personalization string.- Parameters:
ctx- the context supplying the SHA implementationp- the personalization string prepended to the datad- the data to hash- Returns:
- 32 bytes
sign
Sign the structure using the supplied signing key. Overridden because we sign the inner, then blind and encrypt and sign the outer.- Overrides:
signin classLeaseSet2- Parameters:
key- the signing key- Throws:
IllegalStateException- if already signedDataFormatException- if signing fails
sign
public void sign(SigningPrivateKey key, int authType, List<? extends SimpleDataStructure> clientKeys) throws DataFormatException Sign the structure using the supplied signing key. Overridden because we sign the inner, then blind and encrypt and sign the outer.- Parameters:
key- the signing keyauthType- 0, 1, or 3, see BlindDataclientKeys- X25519 public keys for DH, private keys for PSK- Throws:
IllegalStateException- if already signedDataFormatException- if the inner bytes cannot be serialized, or the blinded key is not one of the supported signing key types
verifySignature
public boolean verifySignature()Overridden to decrypt if possible, and verify inner sig also.Must call setDestination() prior to this if attempting decryption. Must call setClientKey() prior to this if attempting decryption.
- Overrides:
verifySignaturein classLeaseSet2- Returns:
- true if the signature is valid, false if it does not verify
verifySignature
Decrypt if possible, and verify inner sig also.Must call setDestination() prior to this if attempting decryption.
- Parameters:
clientKey- PrivateKey for DH or PSK, or null if none- Returns:
- true if the signature is valid, false if it does not verify
equals
hashCode
toString