mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-07-17 13:54:33 -04:00
Added constructors and readers
-NewLeaseSet() -NewLeaseSetFromBytes() -ReadLease() -NewLeaseFromBytes()
This commit is contained in:
@ -1,7 +1,14 @@
|
||||
// Package lease implements the I2P lease common data structure
|
||||
package lease
|
||||
|
||||
import . "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
. "github.com/go-i2p/go-i2p/lib/common/data"
|
||||
"github.com/go-i2p/go-i2p/lib/util/logger"
|
||||
"github.com/sirupsen/logrus"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Sizes in bytes of various components of a Lease
|
||||
const (
|
||||
@ -47,6 +54,9 @@ end_date :: Date
|
||||
// Lease is the represenation of an I2P Lease.
|
||||
//
|
||||
// https://geti2p.net/spec/common-structures#lease
|
||||
|
||||
var log = logger.GetGoI2PLogger()
|
||||
|
||||
type Lease [LEASE_SIZE]byte
|
||||
|
||||
// TunnelGateway returns the tunnel gateway as a Hash.
|
||||
@ -73,13 +83,76 @@ func (lease Lease) Date() (date Date) {
|
||||
// The remaining bytes after the specified length are also returned.
|
||||
// Returns a list of errors that occurred during parsing.
|
||||
func ReadLease(data []byte) (lease Lease, remainder []byte, err error) {
|
||||
// TODO: stub
|
||||
log.WithField("input_length", len(data)).Debug("Reading Lease from bytes")
|
||||
|
||||
if len(data) < LEASE_SIZE {
|
||||
err = errors.New("error parsing lease: not enough data")
|
||||
log.WithFields(logrus.Fields{
|
||||
"data_length": len(data),
|
||||
"required_length": LEASE_SIZE,
|
||||
}).Error("Failed to read lease: insufficient data")
|
||||
return
|
||||
}
|
||||
|
||||
copy(lease[:], data[:LEASE_SIZE])
|
||||
remainder = data[LEASE_SIZE:]
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"tunnel_id": lease.TunnelID(),
|
||||
"expiration": lease.Date().Time(),
|
||||
"remainder_length": len(remainder),
|
||||
}).Debug("Successfully read Lease")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// NewLease creates a new *NewLease from []byte using ReadLease.
|
||||
// Returns a pointer to KeysAndCert unlike ReadLease.
|
||||
func NewLease(data []byte) (lease *Lease, remainder []byte, err error) {
|
||||
// TODO: stub
|
||||
// NewLease creates a new Lease with the provided parameters.
|
||||
func NewLease(tunnelGateway Hash, tunnelID uint32, expirationTime time.Time) (*Lease, error) {
|
||||
log.Debug("Creating new Lease")
|
||||
|
||||
var lease Lease
|
||||
|
||||
// Gateway hash
|
||||
copy(lease[:LEASE_HASH_SIZE], tunnelGateway[:])
|
||||
|
||||
// Convert and copy tunnel ID
|
||||
tunnelIDBytes := make([]byte, LEASE_TUNNEL_ID_SIZE)
|
||||
binary.BigEndian.PutUint32(tunnelIDBytes, tunnelID)
|
||||
copy(lease[LEASE_HASH_SIZE:LEASE_HASH_SIZE+LEASE_TUNNEL_ID_SIZE], tunnelIDBytes)
|
||||
|
||||
// Convert and copy expiration date
|
||||
millis := expirationTime.UnixNano() / int64(time.Millisecond)
|
||||
dateBytes := make([]byte, DATE_SIZE)
|
||||
binary.BigEndian.PutUint64(dateBytes, uint64(millis))
|
||||
copy(lease[LEASE_HASH_SIZE+LEASE_TUNNEL_ID_SIZE:], dateBytes)
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"tunnel_id": tunnelID,
|
||||
"expiration": expirationTime,
|
||||
}).Debug("Successfully created new Lease")
|
||||
|
||||
return &lease, nil
|
||||
}
|
||||
|
||||
// NewLeaseFromBytes creates a new *Lease from []byte using ReadLease.
|
||||
// Returns a pointer to Lease unlike ReadLease.
|
||||
func NewLeaseFromBytes(data []byte) (lease *Lease, remainder []byte, err error) {
|
||||
log.WithField("input_length", len(data)).Debug("Creating Lease from bytes")
|
||||
|
||||
var l Lease
|
||||
l, remainder, err = ReadLease(data)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to read Lease from bytes")
|
||||
return nil, remainder, err
|
||||
}
|
||||
|
||||
lease = &l
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"tunnel_id": lease.TunnelID(),
|
||||
"expiration": lease.Date().Time(),
|
||||
"remainder_length": len(remainder),
|
||||
}).Debug("Successfully created Lease from bytes")
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -406,3 +406,154 @@ func (lease_set LeaseSet) OldestExpiration() (earliest Date, err error) {
|
||||
log.WithField("oldest_expiration", earliest.Time()).Debug("Found oldest expiration in LeaseSet")
|
||||
return
|
||||
}
|
||||
|
||||
func NewLeaseSet(
|
||||
destination Destination,
|
||||
encryptionKey crypto.PublicKey,
|
||||
signingKey crypto.SigningPublicKey,
|
||||
leases []Lease,
|
||||
signingPrivateKey crypto.SigningPrivateKey,
|
||||
) (LeaseSet, error) {
|
||||
log.Debug("Creating new LeaseSet")
|
||||
|
||||
// Validate inputs
|
||||
if len(leases) > 16 {
|
||||
return nil, errors.New("invalid lease set: more than 16 leases")
|
||||
}
|
||||
|
||||
// Build LeaseSet data
|
||||
data := make([]byte, 0)
|
||||
|
||||
// Add Destination
|
||||
data = append(data, destination.KeysAndCert.Bytes()...)
|
||||
|
||||
// Add encryption key
|
||||
data = append(data, encryptionKey.Bytes()...)
|
||||
|
||||
// Add signing key
|
||||
data = append(data, signingKey.Bytes()...)
|
||||
|
||||
// Add lease count
|
||||
leaseCount, err := NewIntegerFromInt(len(leases), 1)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to create lease count")
|
||||
return nil, err
|
||||
}
|
||||
data = append(data, leaseCount.Bytes()...)
|
||||
|
||||
// Add leases
|
||||
for _, lease := range leases {
|
||||
data = append(data, lease[:]...)
|
||||
}
|
||||
|
||||
// Create signature for all data up to this point
|
||||
signer, err := signingPrivateKey.NewSigner()
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to create signer")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
signature, err := signer.Sign(data)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to sign LeaseSet")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add signature
|
||||
data = append(data, signature...)
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"destination_length": len(destination.KeysAndCert.Bytes()),
|
||||
"encryption_key_length": len(encryptionKey.Bytes()),
|
||||
"signing_key_length": len(signingKey.Bytes()),
|
||||
"lease_count": len(leases),
|
||||
"total_length": len(data),
|
||||
}).Debug("Successfully created new LeaseSet")
|
||||
|
||||
return LeaseSet(data), nil
|
||||
}
|
||||
|
||||
// NewLeaseSetFromBytes creates a LeaseSet from raw byte data.
|
||||
func NewLeaseSetFromBytes(data []byte) (LeaseSet, error) {
|
||||
log.WithField("data_length", len(data)).Debug("Creating LeaseSet from bytes")
|
||||
|
||||
// Basic size validation
|
||||
minSize := LEASE_SET_PUBKEY_SIZE + LEASE_SET_SPK_SIZE + 1 + LEASE_SET_SIG_SIZE
|
||||
if len(data) < minSize {
|
||||
return nil, errors.New("error parsing lease set: data too short")
|
||||
}
|
||||
|
||||
leaseSet := LeaseSet(data)
|
||||
|
||||
// Verify the LeaseSet is valid by trying to read its components
|
||||
_, err := leaseSet.Destination()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = leaseSet.PublicKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = leaseSet.SigningKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
count, err := leaseSet.LeaseCount()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if count > 16 {
|
||||
return nil, errors.New("invalid lease set: more than 16 leases")
|
||||
}
|
||||
|
||||
_, err = leaseSet.Leases()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = leaseSet.Signature()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debug("Successfully created LeaseSet from bytes")
|
||||
return leaseSet, nil
|
||||
}
|
||||
|
||||
func NewLeaseSetFromLease(
|
||||
destination Destination,
|
||||
encryptionKey crypto.PublicKey,
|
||||
signingKey crypto.SigningPublicKey,
|
||||
lease Lease,
|
||||
signingPrivateKey crypto.SigningPrivateKey,
|
||||
) (LeaseSet, error) {
|
||||
log.Debug("Creating LeaseSet from single Lease")
|
||||
|
||||
// Create slice containing just the one lease
|
||||
leases := []Lease{lease}
|
||||
|
||||
// Create LeaseSet using the main constructor
|
||||
leaseSet, err := NewLeaseSet(
|
||||
destination,
|
||||
encryptionKey,
|
||||
signingKey,
|
||||
leases,
|
||||
signingPrivateKey,
|
||||
)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to create LeaseSet from Lease")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"tunnel_gateway": lease.TunnelGateway(),
|
||||
"tunnel_id": lease.TunnelID(),
|
||||
"expiration": lease.Date().Time(),
|
||||
}).Debug("Successfully created LeaseSet from Lease")
|
||||
|
||||
return leaseSet, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user