Documentation
¶
Overview ¶
Package encrypted_leaseset implements the I2P EncryptedLeaseSet common data structure
Package encrypted_leaseset implements the I2P EncryptedLeaseSet common data structure
Package encrypted_leaseset implements the I2P EncryptedLeaseSet common data structure
Package encrypted_leaseset implements the I2P EncryptedLeaseSet common data structure
Index ¶
- Constants
- Variables
- func CreateBlindedDestination(dest destination.Destination, secret []byte, date time.Time) (destination.Destination, error)
- func DeriveSubcredential(destSigningPubKey []byte, sigTypeA uint16, blindedPubKey []byte, ...) [32]byte
- func EncryptInnerLeaseSet2(ls2 *lease_set2.LeaseSet2, subcredential [32]byte, published uint32) ([]byte, error)
- func VerifyBlindedSignature(blinded, original destination.Destination, alpha [32]byte) bool
- type EncryptedLeaseSet
- func NewEncryptedLeaseSet(sigType uint16, blindedPublicKey []byte, published uint32, ...) (*EncryptedLeaseSet, error)
- func NewEncryptedLeaseSetFromDestination(blindedDest destination.Destination, published uint32, expiresOffset uint16, ...) (*EncryptedLeaseSet, error)
- func ReadEncryptedLeaseSet(data []byte) (els EncryptedLeaseSet, remainder []byte, err error)
- func (els *EncryptedLeaseSet) BlindedPublicKey() []byte
- func (els *EncryptedLeaseSet) Bytes() ([]byte, error)
- func (els *EncryptedLeaseSet) DecryptInnerData(subcredential [32]byte) (*lease_set2.LeaseSet2, error)
- func (els *EncryptedLeaseSet) EncryptedInnerData() []byte
- func (els *EncryptedLeaseSet) ExpirationTime() time.Time
- func (els *EncryptedLeaseSet) Expires() uint16
- func (els *EncryptedLeaseSet) Flags() uint16
- func (els *EncryptedLeaseSet) HasOfflineKeys() bool
- func (els *EncryptedLeaseSet) InnerLength() uint16
- func (els *EncryptedLeaseSet) IsExpired() bool
- func (els *EncryptedLeaseSet) IsUnpublished() bool
- func (els *EncryptedLeaseSet) IsValid() bool
- func (els *EncryptedLeaseSet) OfflineSignature() *offline_signature.OfflineSignature
- func (els *EncryptedLeaseSet) Published() uint32
- func (els *EncryptedLeaseSet) PublishedTime() time.Time
- func (els *EncryptedLeaseSet) SigType() uint16
- func (els *EncryptedLeaseSet) Signature() sig.Signature
- func (els *EncryptedLeaseSet) Validate() error
- func (els *EncryptedLeaseSet) Verify() error
Constants ¶
const ( // ENCRYPTED_LEASESET_TYPE is the database store type identifier for EncryptedLeaseSet (type 5). // https://geti2p.net/spec/common-structures#encryptedleaseset ENCRYPTED_LEASESET_TYPE uint8 = 5 // ENCRYPTED_LEASESET_DBSTORE_TYPE is prepended to serialized data before signing/verification. ENCRYPTED_LEASESET_DBSTORE_TYPE byte = 0x05 // ENCRYPTED_LEASESET_MIN_SIZE is the minimum wire size in bytes: // sig_type(2) + blinded_key(32 min for Ed25519) + published(4) + expires(2) + // flags(2) + len(2) + encrypted(1 min) + signature(64 min for Ed25519) = 109 ENCRYPTED_LEASESET_MIN_SIZE int = 109 // ENCRYPTED_LEASESET_SIGTYPE_SIZE is the size of the sig_type field (2 bytes). ENCRYPTED_LEASESET_SIGTYPE_SIZE int = 2 // ENCRYPTED_LEASESET_PUBLISHED_SIZE is the size of the published timestamp field (4 bytes). ENCRYPTED_LEASESET_PUBLISHED_SIZE int = 4 // ENCRYPTED_LEASESET_EXPIRES_SIZE is the size of the expires offset field (2 bytes). ENCRYPTED_LEASESET_EXPIRES_SIZE int = 2 // ENCRYPTED_LEASESET_FLAGS_SIZE is the size of the flags field (2 bytes). ENCRYPTED_LEASESET_FLAGS_SIZE int = 2 // ENCRYPTED_LEASESET_INNER_LENGTH_SIZE is the size of the inner length field (2 bytes). ENCRYPTED_LEASESET_INNER_LENGTH_SIZE int = 2 // ENCRYPTED_LEASESET_FLAG_OFFLINE_KEYS indicates offline signature is present (bit 0). ENCRYPTED_LEASESET_FLAG_OFFLINE_KEYS uint16 = 1 << 0 // ENCRYPTED_LEASESET_FLAG_UNPUBLISHED indicates the lease set is not stored in netdb (bit 1). ENCRYPTED_LEASESET_FLAG_UNPUBLISHED uint16 = 1 << 1 // ENCRYPTED_LEASESET_RESERVED_FLAGS_MASK covers bits 15-2 which must be zero per spec. ENCRYPTED_LEASESET_RESERVED_FLAGS_MASK uint16 = 0xFFFC // ENCRYPTED_LEASESET_MAX_EXPIRES_OFFSET is the maximum expiration offset in seconds. ENCRYPTED_LEASESET_MAX_EXPIRES_OFFSET uint16 = 65535 // ENCRYPTED_LEASESET_TYPICAL_MAX_EXPIRES is a typical maximum (11 minutes). ENCRYPTED_LEASESET_TYPICAL_MAX_EXPIRES uint16 = 660 // ENCRYPTED_LEASESET_MIN_SIGNATURE_SIZE is the minimum signature size (Ed25519 = 64 bytes). ENCRYPTED_LEASESET_MIN_SIGNATURE_SIZE int = 64 // ENCRYPTED_LEASESET_MIN_ENCRYPTED_SIZE is the minimum encrypted inner data size: // outerSalt(32) + authType(1) + innerSalt(32) + plaintext(1 min) = 66 bytes. // Per the I2P spec, encrypted data uses a two-layer ChaCha20 scheme with 32-byte salts. ENCRYPTED_LEASESET_MIN_ENCRYPTED_SIZE int = 66 // ENCRYPTED_LEASESET_OUTER_SALT_SIZE is the size of the outer salt in the encrypted data (32 bytes). ENCRYPTED_LEASESET_OUTER_SALT_SIZE int = 32 // ENCRYPTED_LEASESET_INNER_SALT_SIZE is the size of the inner salt in the Layer 1 plaintext (32 bytes). ENCRYPTED_LEASESET_INNER_SALT_SIZE int = 32 // ENCRYPTED_LEASESET_AUTH_TYPE_NONE indicates no per-client authorization (type 0). ENCRYPTED_LEASESET_AUTH_TYPE_NONE byte = 0 // ENCRYPTED_LEASESET_AUTH_TYPE_DH indicates per-client DH authorization (type 1). // Not yet implemented. ENCRYPTED_LEASESET_AUTH_TYPE_DH byte = 1 // ENCRYPTED_LEASESET_AUTH_TYPE_PSK indicates per-client PSK authorization (type 2). // Not yet implemented. ENCRYPTED_LEASESET_AUTH_TYPE_PSK byte = 2 )
Variables ¶
var ( // ErrUnsupportedSignatureType indicates the destination signature type is not supported for blinding ErrUnsupportedSignatureType = oops.Errorf("signature type not supported for blinding (only Ed25519 supported)") // ErrInvalidSecret indicates the secret is invalid for blinding ErrInvalidSecret = oops.Errorf("invalid secret for blinding") // ErrBlindingFailed indicates the blinding operation failed ErrBlindingFailed = oops.Errorf("blinding operation failed") )
Functions ¶
func CreateBlindedDestination ¶
func CreateBlindedDestination(dest destination.Destination, secret []byte, date time.Time) (destination.Destination, error)
CreateBlindedDestination creates a blinded destination from an original destination, secret, and date. This is the core operation for EncryptedLeaseSet privacy.
The blinding process:
- Derives blinding factor (alpha) from secret and date using HKDF
- Blinds the Ed25519 signing public key: P' = P + [alpha]B
- Constructs a new destination with the blinded signing key
The blinded destination is deterministic (same secret + date = same blinded dest) and unlinkable to the original destination without knowing the secret.
Parameters:
- dest: Original destination to blind (must use Ed25519 signature type)
- secret: 32+ byte secret (typically from the destination's private key seed)
- date: Date for which to create the blinded destination (rotation period)
Returns:
- Blinded destination with same key certificate but blinded signing key
- Error if signature type unsupported, secret invalid, or blinding fails
Example:
// Create blinded destination for today
blindedDest, err := CreateBlindedDestination(originalDest, privateKeySeed, time.Now())
if err != nil {
return err
}
Security Notes:
- The secret MUST be kept confidential (compromise reveals original destination)
- Blinded destinations rotate daily (use same secret, different dates)
- Only Ed25519 signature types are supported (RedDSA SHA512 Ed25519)
Spec: I2P Proposal 123 - Encrypted LeaseSet
func DeriveSubcredential ¶ added in v0.1.5
func DeriveSubcredential(destSigningPubKey []byte, sigTypeA uint16, blindedPubKey []byte, sigTypeBlinded uint16) [32]byte
DeriveSubcredential computes the I2P subcredential for EncryptedLeaseSet encryption and decryption.
Per the I2P spec (https://geti2p.net/spec/encryptedleaseset §473–499):
A = destination's signing public key
stA = signature type of A, 2 bytes big-endian (e.g. 0x0007 for Ed25519, 0x000b for RedDSA)
stA' = signature type of the blinded key A', 2 bytes big-endian (0x000b for RedDSA)
keydata = A || stA || stA'
credential = H("credential", keydata)
subcredential = H("subcredential", credential || blindedPublicKey)
Parameters:
- destSigningPubKey: The unblinded destination signing public key bytes
- sigTypeA: Signature type of the unblinded key (e.g. 7 for Ed25519, 11 for RedDSA)
- blindedPubKey: The blinded signing public key from the EncryptedLeaseSet
- sigTypeBlinded: Signature type of the blinded key (always 11 for RedDSA)
The subcredential binds the encryption to knowledge of the destination, so only clients who know the original destination can decrypt.
func EncryptInnerLeaseSet2 ¶
func EncryptInnerLeaseSet2(ls2 *lease_set2.LeaseSet2, subcredential [32]byte, published uint32) ([]byte, error)
EncryptInnerLeaseSet2 encrypts a LeaseSet2 using the I2P spec's two-layer ChaCha20 encryption scheme (no per-client auth).
Encryption process:
- Serialize LeaseSet2 to bytes
- Generate random innerSalt, derive Layer 2 key, encrypt with ChaCha20
- Assemble Layer 1 plaintext: authType(0) || innerSalt || layer2Ciphertext
- Generate random outerSalt, derive Layer 1 key, encrypt with ChaCha20
- Return: outerSalt || layer1Ciphertext
Parameters:
- ls2: The LeaseSet2 to encrypt
- subcredential: 32-byte value from DeriveSubcredential()
- published: Published timestamp (seconds since epoch), must match the EncryptedLeaseSet's published field
func VerifyBlindedSignature ¶
func VerifyBlindedSignature(blinded, original destination.Destination, alpha [32]byte) bool
VerifyBlindedSignature verifies that a blinded destination was correctly derived from an original destination using the given blinding factor.
This verification checks: BlindedPubKey = OriginalPubKey + [alpha]B
Parameters:
- blinded: The blinded destination to verify
- original: The original destination
- alpha: The blinding factor used (32 bytes)
Returns:
- true if blinded destination matches the expected blinding of original
- false if verification fails or destinations don't match
Example:
// Verify blinded destination was created correctly
alpha, _ := kdf.DeriveBlindingFactor(secret, "2025-11-24")
if !VerifyBlindedSignature(blindedDest, originalDest, alpha) {
return errors.New("blinded destination verification failed")
}
Spec: I2P Proposal 123 - Encrypted LeaseSet
Types ¶
type EncryptedLeaseSet ¶
type EncryptedLeaseSet struct {
// contains filtered or unexported fields
}
EncryptedLeaseSet represents an encrypted I2P LeaseSet2 (Database Store Type 5).
Wire Format (I2P spec 0.9.67 — https://geti2p.net/spec/common-structures#encryptedleaseset):
sig_type (2 bytes) — Signing key type for the blinded public key blinded_public_key (variable) — Blinded signing public key (length from sig_type) published (4 bytes) — Timestamp in seconds since Unix epoch expires (2 bytes) — Expiration offset from published in seconds flags (2 bytes) — Bit 0: offline keys, Bit 1: unpublished, Bits 15‑2: reserved (0) [offline_signature] (variable) — Present only if flags bit 0 is set len (2 bytes) — Length of encrypted inner data encrypted_data (len bytes) — Encrypted LeaseSet2 structure signature (variable) — Signature by blinded key or transient key (length from sig_type)
NOTE: This structure does NOT use the LeaseSet2Header. There is no options mapping and no cookie in the cleartext wire format; those are internal to the encryption layer.
func NewEncryptedLeaseSet ¶
func NewEncryptedLeaseSet( sigType uint16, blindedPublicKey []byte, published uint32, expiresOffset uint16, flags uint16, offlineSig *offline_signature.OfflineSignature, encryptedInnerData []byte, signingKey interface{}, ) (*EncryptedLeaseSet, error)
NewEncryptedLeaseSet creates a spec-compliant EncryptedLeaseSet from raw fields.
Parameters:
- sigType: signing key type for the blinded public key (e.g., 7=Ed25519, 11=RedDSA)
- blindedPublicKey: the blinded signing public key bytes
- published: timestamp in seconds since Unix epoch
- expiresOffset: expiration offset in seconds from published (1‑65535)
- flags: flag bits (bit 0=offline, bit 1=unpublished, bits 15‑2 must be 0)
- offlineSig: optional offline signature (required if flags bit 0 set)
- encryptedInnerData: encrypted LeaseSet2 payload
- signingKey: Ed25519 private key ([64]byte, *Ed25519PrivateKey, or 64-byte []byte)
The signature is computed over: 0x05 || serialized_content (without the signature itself), using standard Ed25519 (no pre-hashing).
func NewEncryptedLeaseSetFromDestination ¶ added in v0.1.5
func NewEncryptedLeaseSetFromDestination( blindedDest destination.Destination, published uint32, expiresOffset uint16, flags uint16, offlineSig *offline_signature.OfflineSignature, encryptedInnerData []byte, signingKey interface{}, ) (*EncryptedLeaseSet, error)
NewEncryptedLeaseSetFromDestination creates an EncryptedLeaseSet from a blinded Destination. This convenience function extracts the sig_type and blinded signing public key from the Destination, then delegates to NewEncryptedLeaseSet.
func ReadEncryptedLeaseSet ¶
func ReadEncryptedLeaseSet(data []byte) (els EncryptedLeaseSet, remainder []byte, err error)
ReadEncryptedLeaseSet parses an EncryptedLeaseSet from its spec-compliant wire format.
Wire order: sig_type(2) | blinded_public_key(var) | published(4) | expires(2) | flags(2) | offline_signature | len(2) | encrypted_data(len) | signature(var)
func (*EncryptedLeaseSet) BlindedPublicKey ¶ added in v0.1.5
func (els *EncryptedLeaseSet) BlindedPublicKey() []byte
BlindedPublicKey returns a copy of the blinded signing public key.
func (*EncryptedLeaseSet) Bytes ¶
func (els *EncryptedLeaseSet) Bytes() ([]byte, error)
Bytes serializes the EncryptedLeaseSet to its spec-compliant wire format.
func (*EncryptedLeaseSet) DecryptInnerData ¶
func (els *EncryptedLeaseSet) DecryptInnerData(subcredential [32]byte) (*lease_set2.LeaseSet2, error)
DecryptInnerData decrypts the encrypted inner data using the I2P spec's two-layer ChaCha20 encryption scheme (no per-client auth).
Decryption process:
- Extract outerSalt (first 32 bytes, cleartext)
- Derive Layer 1 key: HKDF(outerSalt, subcredential||published, "ELS2_L1K")
- Decrypt Layer 1 → authType || innerSalt || layer2Ciphertext
- Verify authType == 0 (no per-client auth)
- Derive Layer 2 key: HKDF(innerSalt, subcredential||published, "ELS2_L2K")
- Decrypt Layer 2 → InnerLeaseSet2
Parameters:
- subcredential: 32-byte value from DeriveSubcredential()
func (*EncryptedLeaseSet) EncryptedInnerData ¶
func (els *EncryptedLeaseSet) EncryptedInnerData() []byte
EncryptedInnerData returns a copy of the encrypted inner data. Callers cannot mutate the internal state through the returned slice.
func (*EncryptedLeaseSet) ExpirationTime ¶
func (els *EncryptedLeaseSet) ExpirationTime() time.Time
ExpirationTime returns the absolute expiration time.
func (*EncryptedLeaseSet) Expires ¶
func (els *EncryptedLeaseSet) Expires() uint16
Expires returns the expiration offset in seconds from the published timestamp.
func (*EncryptedLeaseSet) Flags ¶
func (els *EncryptedLeaseSet) Flags() uint16
Flags returns the raw flags value.
func (*EncryptedLeaseSet) HasOfflineKeys ¶
func (els *EncryptedLeaseSet) HasOfflineKeys() bool
HasOfflineKeys returns true if the offline signature flag is set (bit 0).
func (*EncryptedLeaseSet) InnerLength ¶
func (els *EncryptedLeaseSet) InnerLength() uint16
InnerLength returns the length of the encrypted inner data.
func (*EncryptedLeaseSet) IsExpired ¶
func (els *EncryptedLeaseSet) IsExpired() bool
IsExpired checks if the EncryptedLeaseSet has expired.
func (*EncryptedLeaseSet) IsUnpublished ¶
func (els *EncryptedLeaseSet) IsUnpublished() bool
IsUnpublished returns true if the unpublished flag is set (bit 1).
func (*EncryptedLeaseSet) IsValid ¶
func (els *EncryptedLeaseSet) IsValid() bool
IsValid returns true if the EncryptedLeaseSet passes validation.
func (*EncryptedLeaseSet) OfflineSignature ¶
func (els *EncryptedLeaseSet) OfflineSignature() *offline_signature.OfflineSignature
OfflineSignature returns the optional offline signature structure.
func (*EncryptedLeaseSet) Published ¶
func (els *EncryptedLeaseSet) Published() uint32
Published returns the published timestamp (seconds since Unix epoch).
func (*EncryptedLeaseSet) PublishedTime ¶
func (els *EncryptedLeaseSet) PublishedTime() time.Time
PublishedTime returns the published timestamp as a Go time.Time.
func (*EncryptedLeaseSet) SigType ¶ added in v0.1.5
func (els *EncryptedLeaseSet) SigType() uint16
SigType returns the signing key type identifier.
func (*EncryptedLeaseSet) Signature ¶
func (els *EncryptedLeaseSet) Signature() sig.Signature
Signature returns the signature over the EncryptedLeaseSet data.
func (*EncryptedLeaseSet) Validate ¶
func (els *EncryptedLeaseSet) Validate() error
Validate checks internal consistency of the EncryptedLeaseSet.
func (*EncryptedLeaseSet) Verify ¶ added in v0.1.5
func (els *EncryptedLeaseSet) Verify() error
Verify verifies the cryptographic signature of the EncryptedLeaseSet.
Per the I2P specification, the signature covers: 0x05 || content_without_signature. The signing public key is the blinded public key, or the transient key if offline signatures are present.