Suppose we wish to broadcast a stream to a set of users securely.
How can we achieve integrity?
We cannot use MAC’s, otherwise the users could forge packets
to each other.
We cannot sign the entire stream: this solution is vulnerable to
packet loss, and also the whole stream would have to be buffered
for verification.
We cannot sign each packet individually, as this is too inefficient.

Method 1 (Combinatorial)

We describe a simple scheme based on families of coverfree subsets.
It is a too inefficient for practical purposes.

There are $n$ users and a single source.
The source has several MAC keys $K_1, ..., K_m$, where $m$ will be
determined later.

Recipient $i$ accepts a packet $P$ if all the MAC’s corresponding
to their set $S_i$ verify.

At the bare minimum, we want 1-security, that is, any user $j$ should
not be able to forge a packet for any other user $i$, so we must have
$S_i \nsubseteq S_j$. The best way to do this is to use all subsets
of size $m/2$ from the set of keys, so we need
$n = \left( \array { m \\ m/2 } \right) $,
so $m = O(\log n)$.

More generally, for $t$-security (i.e. so that no group of $t$ users can
forge a packet), we require a family of $t$-coverfree subsets, which can
be done with $m = O(t^2 \log n)$. Thus the packet size is quadratic in $t$.
It can be shown that a smaller packet size implies nonrepudiation, that is,
a MAC that short would in fact be a signature.

Method 2 (TESLA)

This solution uses time for security. Assume the total clock skew is $\Delta$,
and that the total routing time is less than or equal to some time $T$.

Sign($M$): find $1 \le i\lt j\le n$ such that $H(M||x_i) = H(M||x_j)$.
The signature is $(x_i, x_j)$ ("Find two balls that hit the same bin.")

We can now remove the buffering problem as follows. Build a hash tree from
the public keys $PK_1,...,PK_n$ of some one-time signature scheme.
Sign the tree and transmit the public keys with signatures (so we commit to
public keys instead of packets), and simply sign each packet.

Method 4: Expanders

Build a directed acyclic graph (DAG) using the packets as nodes.
Then proceed as in the previous scheme, except this time we use
a hash DAG, instead of a hash tree.

To resist up to $t$ packets being lost, we need a graph that remains
connected even if $t$ nodes are removed.

An $\epsilon$-expander graph $(V,E)$ is a graph such that for all
$S \subseteq V$, we have $|neighbour(S)| \ge (1+\epsilon) |S|$ if (?)
$|S| \le |V| / (1+\epsilon)$.

There exist methods of constructing constant degree $d$ expanders
on $n$ nodes such that removing $n^\epsilon$ nodes for some constant
$\epsilon$ does not disconnect the graph.