% #1: fig:label % #2: Handler title % #3: caption \newenvironment{handler}[3]{% \def\handlerlabel{fig:#1}% \def\handlertitle{#2}% \def\handlercaption{#3}% \begin{figure}% \center\vspace{1em}% \noindent\begin{tabular}{|p{\myboxlen}|}% \hline% \footnotesize% {\tt\bf \handlertitle}% } {% \\ \hline% \end{tabular}% \caption{\handlercaption}% \label{\handlerlabel}% \end{figure}% } \begin{handler}{server-init}{Server at round $i$}{} \begin{lstlisting}{} let phase$^i$ = Seeding; let seed$^i$ = random_seed(); let S$^i_{seed}$ = sign( <$i$,seed$^i$>, KS$_{priv}$); let M$^i_{seed}$ = Seed($i$,seed$^i$,S$^i_{seed}$); let map$^i$ = $\emptyset$ $\forall q \in$ NS$_{server}$, send($q$, M$^i_{seed}$); wait $T$; phase$^i$ = Idle; H$^i$ = Hash(map$^i$); let S$^i_{pulse}$ = sign( <$i$,seed$^i$,H$^i$>, KS$_{priv}$ ); let M$^i_{pulse}$ = Pulse($i$, seed$^i$, H$^i$, 0, $\{$ 0 $\rightarrow$ map$^i$ $\}$, S$^i_{pulse}$); $\forall q \in$ NS$_{server}$, send($q$, M$^i_{pulse}$); \end{lstlisting} \end{handler} \begin{handler}{xn}{Server or peer receiving SeedReply ($i$, X$_q$) from peer $q$:}{} \begin{lstlisting}{} if phase$^i$ = Seeding then map$^i$ = $\{ q \rightarrow $X$_q \} \oplus$ map$^i$; end if \end{lstlisting} \end{handler} \begin{handler}{xn}{Every $\Delta << T$ seconds, on peer $p$:}{} \begin{lstlisting}{} if phase$^i$ = Seeding then let H$^i$ = H(map$^i$); let M$^i_{seedreply}$ = SeedReply($i$, H$^i$ ); nreplies$^i$ = nreplies$^i$ + 1; replies$^i$[ nreplies$^i$ ] = (H$^i$, map$^i$); $\forall q \in$ NS$_p$, send($q$, M$^i_{seedreply}$); end if \end{lstlisting} \end{handler} \begin{handler}{x1}{Peer $p$ receiving M$^i_{seed}$ = Seed ($i$,seed$^i$,S$^i_{seed}$):}{} \begin{lstlisting}{} if verify_sig( S$^i_{seed}$, <$i$,seed$^i$>, KS$_{priv}$) then $\forall q \in$ NS$_p$, send($q$, M$^i_{seed}$); let S$^i_p$ = sign( <$i$,seed$^i$>, K$^p_{priv}$); let map$^i$ = $\{ p \rightarrow H(S^i_p) \}$ nreplies$^i$ = 0; phase$^i$ = Seeding; end if \end{lstlisting} \end{handler} \begin{handler}{x3}{Peer $p$ receiving Pulse($i$, seed$^i$, H$^i$, level, tree$^i$, S$^i_{pulse}$):}{} \begin{lstlisting}{} if verify_sig(S$^i_{pulse}$, <$i$, seed$^i$, H$^i$ >, KS$_{pub}$ ) then phase$^i$ = Idle; included$^i$ = $\bot$; if $\exists$ $\{$ $p$ $\rightarrow$ H$^i$ $\}$ $\in$ tree$^i$[level] and $\exists$ $n$ $|$ replies[$n$] = (H$^i$, oldmap$^i$) and included$^i$ $<$ $n$ and verify_tree(H$^i$, level, tree$^i$) then let tree'$^i$ = tree$^i$ $\oplus$ $\{$ level+1 $\rightarrow$ oldmap$^i$ $\}$; M$^i_{pulse}$ = ($i$, seed$^i$, H$^i$, level+1, tree'$^i$, S$^i_{pulse}$) History[$i$] = M$^i_{pulse}$; included$^i$ = $n$; $\forall q \in$ children$^p$, send($q$, Pulse M$^i_{pulse}$); end if end if \end{lstlisting} \end{handler} \begin{handler}{x4}{Peer $p$ sending to $q$ its availability at round $i$:}{} \begin{lstlisting}{} let bits$^i$ = new bitfield[$N_t$]; for $x$ in [1..$N_t$] if History[$i-N_t+x$] = $\emptyset$ then bits$^i$[$x$] := 0 else bits$^i$[$x$] := 1 end if end for let S$^i_{avail}$ = sign( < $i$, bits$^i$ >, K$^p_{priv}$ ) let M$^i_{avail}$ = ($i$,bits,S$^i_{avail}$); send( $q$, Availability M$^i_{avail}$ ) \end{lstlisting} \end{handler} \begin{handler}{x5}{Peer $p$ receiving Challenge($i$, nonce) from peer $q$:}{} \begin{lstlisting}{} let M$^i_{pulse}$ = History[$i$] send( $q$, Proof M$^i_{pulse}$) \end{lstlisting} \end{handler} \begin{handler}{x6}{Peer $q$ receiving from peer $p$ Proof ($i$, nonce, K$^i_{pub}$, trees$^i$, S$^i_p$, S$^i_{pulse}$, S$_{proof}$):}{} \begin{lstlisting}{} Peer $q$ receiving from peer $p$ Proof ($i$, nonce, K$^i_{pub}$, trees$^i$, S$^i_p$, S$^i_{pulse}$, S$_{proof}$): if ($i$, nonce, $p$) $\in$ challenges $\land$ verify_sig(S$^i_{pulse}$,<$i$, seed$^i$,$K^i_{pub}$,trees$^i$[0]>,KS$_{pub}$) $\land$ verify_sig(S$^i_p$, <$i$, seed$^i$ >, K$^p_{pub}$) $\land$ S$^i_p$ $\in$ trees$^i$ $\land$ $\forall n>0$, H(trees$^i$[n]) $\in$ trees$^i$[n-1] $\land$ verify_sig(S$_{proof}$, < nonce, H$^p$, H$^q$ >, K$^i_{pub}$ ) then good_reply($p$) else bad_reply($p$) end if \end{lstlisting} \end{handler} \endinput A major problem in peer-to-peer networks is that peers might work together ({\em collude}) to break security properties of a protocol. In our case, some peers might work together to increase their measured availability. In this section, we describe an extension of our protocol to fight against collusion. The easiest way to collude to break our original protocol is for a peer to give the pulse to another peer, that was not available when the pulse was distributed. This can be done as part of an exchange (for other pulses) so that both peers will increase their measured availability, or as part of an attack, if the peer wants to increase measured availability of all peers to break the system. Our solution is a three phases protocol: \begin{itemize} \item {\bf Phase 1} The server diffuses a {\em seed} for the round on the network using a {\tt Seed} message. \item {\bf Phase 2} Every client generates a signature of the seed with its private key. It then computes a short hash of the signature. It then joins its hash to the hashes received from its children and computes a new hash, that it sends to its parents, using a {\tt Tree} message. The server itself computes a hash from the hashes received from its children. \item {\bf Phase 3} The server computes the new pulse for the round, and diffuses it in a {\tt Pulse} message, together with the seed for the round and the hash computed in phase 2, both signed by its private key. Every parent propagates the pulse to its children, adding also the list of hashes it used to compute the hash sent to its parents. \end{itemize} The goal of this extension of the original protocol is that the pulse now contains a piece of information recording the presence of all the peers in the network through a merkle-tree\cite{1979-merkle}. Colluding peers will only be able to use the pulse if they can provide the signature of the hash and the merkle tree showing it has been taken into account in the computation of the pulse. Now, let's assume peers $p$ and $q$ are colluding: peer $p$ is online during the diffusion of the pulse, while $q$ is offline. To be able to give a useful pulse to $q$, $p$ must have included $q$ into the merkle-tree. To do that, it must have issued a signature of the seed using $q$ private key, and then put the hash of the signature in its own tree. This means that peer $p$ must know the private key of peer $q$ to collude. It is thus an important requirement on applications using our system that they discourage peers from sharing their private keys. This can easily been done by giving extra-power to key owners, i.e. for instance the owner of a private key should be allowed to delete data associated with the key, or to book storage using the key. As a consequence, colluding peers would have to trust each other, to such a high degree that collusion would only be possible among a very small part of the network. We assume to know the depth of the network. Is it bad ? Probably... ;-)