tesla

package
v0.2.0-rc.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 25, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package tesla implements a TESLA-inspired hash-chain key schedule for delayed disclosure of packet authentication keys.

Key Schedule Overview

Keys form a backward hash chain: the executor generates a random secret seed k_L (the tail) and hashes it L times to obtain the public anchor k_0:

k_0 = H^L(k_L)          (public anchor, published at setup)
k_i = H(k_{i+1})        (each key is the hash of the next one)

The executor uses key k_i during epoch i and discloses it after a configurable disclosure delay d has elapsed. A verifier who has buffered packets from epoch i can verify them once k_i is published by checking:

H^i(k_i) == k_0

Given a disclosed key k_τ, the key for an earlier epoch t (t ≤ τ) is reconstructed by hashing forward τ-t times:

k_t = H^(τ-t)(k_τ)

Per-Measurement Derivation

Because a single executor may service multiple measurements concurrently, an additional per-measurement key ak is derived from the current chain key:

ak = HKDF-SHA256(secret=k_i, info=measurement_id, length=32)

Authentication Tag

The authentication tag written into the IPv4 IPID field is:

tag = HMAC-SHA256(ak, packet_payload)[0:2]   (16-bit truncation)

Index

Constants

View Source
const DefaultChainHorizon = 7 * 24 * time.Hour

DefaultChainHorizon is the uptime a default-sized chain covers. The default ChainLength is DefaultChainHorizon/Delay, so a longer epoch gives a shorter chain rather than a shorter usable lifetime.

Variables

This section is empty.

Functions

func ComputeBPFTag

func ComputeBPFTag(ak, payload []byte) (uint16, error)

ComputeBPFTag computes the BPF SipHash-2-4 tag for a packet payload. It does not perform packet canonicalization (which should be done by the caller or on raw packet payloads).

func ComputeTag

func ComputeTag(ak, payload []byte) (uint16, error)

ComputeTag computes the 16-bit authentication tag for a packet payload:

tag = HMAC-SHA256(ak, payload)[0:2]

The returned uint16 is in host byte order; the caller is responsible for writing it into the IPID field in network (big-endian) byte order.

func DeriveAK

func DeriveAK(k []byte, measurementID []byte) ([]byte, error)

DeriveAK computes the per-measurement authentication key:

ak = HKDF-SHA256(secret=k, info=measurementID, length=32)

measurementID should be the raw bytes of the UUID (or any stable byte representation of the measurement identifier).

func DeriveFromDisclosed

func DeriveFromDisclosed(disclosedKey []byte, disclosedEpoch, targetEpoch int64) ([]byte, error)

DeriveFromDisclosed reconstructs the key at targetEpoch given a disclosed key at disclosedEpoch. Because the chain runs backward (k_i = H(k_{i+1})), a verifier can only derive keys at epochs ≤ disclosedEpoch by hashing the disclosed key forward (disclosedEpoch → targetEpoch, t ≤ disclosedEpoch):

k_t = H^(disclosedEpoch - t)(k_disclosedEpoch)

To reconstruct a later (newer) key you would need an even newer disclosed key, since the chain cannot be inverted.

func VerifyBPFTag

func VerifyBPFTag(disclosedKey []byte, epoch int64, measurementID, packet []byte, tag uint16) (bool, error)

VerifyBPFTag checks whether tag matches the expected SipHash for the packet

func VerifyChain

func VerifyChain(anchor, key []byte, t int64) bool

VerifyChain checks that H^t(k_t) == k_0 (the public anchor). A verifier calls this after reconstructing k_t to confirm its authenticity.

func VerifyTag

func VerifyTag(disclosedKey []byte, epoch int64, measurementID, packet []byte, tag uint16) (bool, error)

VerifyTag checks whether tag matches the expected HMAC for the packet at a given epoch, given the disclosed key for that epoch and the measurement ID.

If packet begins with a valid IPv4 header (version == 4, length ≥ 20), both the IPID field (bytes 4–5) and the IPv4 checksum field (bytes 10–11) are zeroed before hashing, exactly as TagPacket does. The caller should pass the full received packet bytes (with the IPID field containing the observed tag and the checksum field as received on the wire).

Types

type Config

type Config struct {
	// Seed is the secret tail k_L of the hash chain. If nil, a random
	// 32-byte seed is generated on the first call to NewKeySchedule.
	// The seed is NEVER disclosed; it is only used internally to derive
	// keys by hashing backwards toward k_0.
	Seed []byte

	// ChainLength L is the total number of epochs supported by this
	// schedule. The keys k_0 … k_L are generated; k_0 is the public
	// anchor and k_L is derived from the seed.
	//
	// If zero, it is derived from Delay so that the chain covers
	// DefaultChainHorizon of uptime. Sizing this from a wall-clock horizon
	// matters: once epoch L is reached the schedule stops advancing, keeps
	// tagging with the never-disclosed k_L, and every packet from then on
	// becomes unverifiable.
	ChainLength int64

	// Delay is the interval duration I (one epoch). A key disclosed after
	// the disclosure delay d (expressed as a number of epochs) has elapsed.
	// Defaults to 10 seconds.
	Delay time.Duration

	// Epoch is the reference wall-clock time that anchors epoch 0.
	// Defaults to the time NewKeySchedule is called.
	Epoch time.Time
}

Config carries the tuneable parameters of the TESLA key schedule.

type KeySchedule

type KeySchedule struct {
	// contains filtered or unexported fields
}

KeySchedule is a thread-safe TESLA hash-chain key schedule.

Keys are indexed by epoch number t where t ∈ [0, L]:

epoch t covers the time interval [Epoch + t*Delay, Epoch + (t+1)*Delay).

The chain direction is backward: k_0 is the public anchor and k_L is the private seed tail. Key k_t is used during epoch t and disclosed after the disclosure delay d has elapsed (i.e., once epoch t+d has started).

func NewKeySchedule

func NewKeySchedule(cfg Config) (*KeySchedule, error)

NewKeySchedule creates a KeySchedule from cfg.

The chain direction is backward (k_i = H(k_{i+1})). The private seed k_L is stored internally and the public anchor k_0 = H^L(seed) is computed once.

If cfg.Seed is empty a cryptographically random 32-byte seed is generated. A seed that is not exactly 32 bytes long is folded through SHA-256 so that k_L is always one key wide. If cfg.Delay is zero it defaults to 10 seconds. If cfg.ChainLength is zero it is derived from Delay (see DefaultChainHorizon).

func (*KeySchedule) Anchor

func (ks *KeySchedule) Anchor() []byte

Anchor returns k_0, the public anchor that should be published at setup. Verifiers use it to check consistency: H^t(k_t) == k_0.

func (*KeySchedule) ChainLength

func (ks *KeySchedule) ChainLength() int64

ChainLength returns L, the highest epoch this schedule can serve.

func (*KeySchedule) ComputeBPFTagForPacket

func (ks *KeySchedule) ComputeBPFTagForPacket(t time.Time, measurementID, payload []byte) (uint16, error)

ComputeBPFTagForPacket derives ak from the chain key at time t and then computes the BPF SipHash-2-4 tag over payload.

func (*KeySchedule) ComputeTagForPacket

func (ks *KeySchedule) ComputeTagForPacket(t time.Time, measurementID, payload []byte) (uint16, error)

ComputeTagForPacket is a convenience wrapper that derives ak from the chain key at time t and then computes the tag over payload.

func (*KeySchedule) Config

func (ks *KeySchedule) Config() Config

Config returns a copy of the schedule's configuration.

func (*KeySchedule) CurrentKey

func (ks *KeySchedule) CurrentKey(t time.Time) []byte

CurrentKey returns the chain key k_t for the epoch that contains time t.

func (*KeySchedule) DisclosedKey

func (ks *KeySchedule) DisclosedKey(t time.Time) (index int64, key []byte, ok bool)

DisclosedKey returns the epoch index and key that should be disclosed at time t. A key for epoch τ is disclosed once d disclosure-delay epochs have elapsed after τ. With d=1, the key for epoch (current−1) is disclosed when epoch current starts.

If t is still within epoch 0 (no key is disclosable yet), ok is false.

func (*KeySchedule) Exhausted

func (ks *KeySchedule) Exhausted(t time.Time) bool

Exhausted reports whether time t falls at or past the end of the chain. Once exhausted the schedule keeps returning k_L, which is never disclosed, so packets tagged from then on can no longer be verified.

func (*KeySchedule) Expiry

func (ks *KeySchedule) Expiry() time.Time

Expiry returns the wall-clock time at which the chain runs out.

func (*KeySchedule) KeyAtEpoch

func (ks *KeySchedule) KeyAtEpoch(epoch int64) ([]byte, error)

KeyAtEpoch returns the chain key for the given epoch index.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL