# Stateless Time Scrambling Protocol
## Motivation
After designing some APIs, I found out that you must have at some point a *token* system where the token is a fixed-length string. An easy MITM attack could be to repeat a previously sent request while the token is still valid. Or in worse conditions, catch the client *token* and build a malicious request with its authenticated session.
In the rest of this document we will admit that what travels through the network is public, so any MITM can store it. Obviously I highly recommend using TLS for communicating, but we look here for a consistent token system, it only can be better through TLS.
A good solution could be to use a one-time token so the server sends back a new token for each response. This behavior means that the token travels through the network - which we consider public - before being used. In addition we would like the server to create only a secret key once to fasten the authentication system, because it could manage millions of clients.
A better solution would be to keep a private key and wrap it in a one-time system that generates a public token for each request. It would avoid attackers to repeat our requests or guess the private key from the token. Also short-lived one-time passwords have a mechanism that we could use to build a time-dependent system.
**What we need**
1. Generate a *public token* for each request from a fixed *private key*
2. The *public token* never to be the same
3. Each *public token* to be only valid a few seconds after sending it
4. Each *public token* to give no clue that could help guessing the next token.
5. A system where the *server* does not have to share a private key with each *client* and does not need to.
**Technology requirements**
1. Mixing 2 hashes in a way that without one of them, the other is *cryptographically impossible* to guess (*i.e. [one-time pad](https://en.wikipedia.org/wiki/One-time_pad)*).
2. Having a time-dependent unique hash, that could be found only a few seconds after sending it (as for *[TOTP](https://tools.ietf.org/html/rfc6238)*).
3. A cryptographic hash function that, from an input of any length, outputs a fixed-length digest in a way that is *impossible* to guess the input back from it.
**Protocols to define**
This document will define and bundle 2 distinct protocols to implement a token system that implements the previous statements.
1. a Stateless Time Scrambling Protocol to take care of the request's expiration over time
2. a Stateless Cyclic Hash Algorithm to generate several public keys from a single secret key in a way that no clue is given over published keys.
## General knowledge & Notations
##### Notation
| Symbols | Description |
|:-----:|:----------|
| $\parallel a\parallel $ | The absolute value of $a$ ; *e.g.* $\parallel a \parallel = \parallel -a \parallel$ |
| $\mid a \mid$ | The integer value of $a$ ; *e.g.* $\mid 12.34 \mid = 12$ |
| $a \oplus b$ | The bitwise operation XOR between binary words $a$ and $b$ |
| $h(m)$ | The digest of the message $m$ by a consistent cryptographic hashing function $h()$ ; *e.g. sha512* |
| $h^n(m)$ | The digest of the $n$-recursive hashing function $h()$ with the input data $m$ ; *e.g. $h^2(m) \equiv h(h(m))$ , $h^1(m) \equiv h(m)$ and $h^0(m) \equiv m$*. |
| $a \mod b$ | The result of $a$ modulo $b$ ; *i.e.* the remainder of the Euclidean division of $a$ by $b$ |
| $T_{now}$ | The current *Unix Timestamp* in seconds |
##### Entities
- A machine $C$ (*typically a client*)
- A machine $S$ (*typically a server*)
##### Common variables
These variables are both on the server and clients. They are specific to the server so each client must match these.
| Notation | Name | Description |
|:--------:|:----:|:------------|
| $W$ | time window divider | A fixed number of seconds that is typically the maximum transmission time from end to end. |
##### Client variables
These variables defines the state of each client, each having different values.
| Notation | Name | Description |
|:--------:|:----:|:------------|
| $K$ | shifting key | The client private key. It is only known by the client, it must be large enough not to be brute forced. |
| $ n_0 $ | shifting nonce | A private number that is decremented for each request. It is unique to each private key $K$. Before $n_0$ reaches 0, a new key $K$ must be generated and $n_0$ is set to its higher value. |
| $s$ | next request order | The next request order is a number that, according on its value, will change the client's behavior :
- $0$ : normal request
- $1$ : new key generated
- $2$ : rescue mode (resynchronize with the server) |
##### Server variables
| Notation | Name | Description |
|:--------:|:----:|:------------|
| $H$ | last valid hash | The server stores the last valid hash from the client to check the next one. |
If a client sends its token $h^{n_0}(K)$, if the token is valid the server stores it inside $H$.
> Note that for the first synchronization, the server has to "blindly" consider the token as valid.
When the client sends its next token $h^{n_0-1}(K)$, the server has to hash it and compare it with the last token $H$.
> $h(h^{n_0-1}) = h^{n_0}(K)$
## Description of the problem
$C$ wants to send a token that will only be valid one time and within a fixed time window.
> *Note: This document only gives a solution for the time-dependent feature, the one-time aspect is wrapped into the implementation of the $f()$ function. If you only need the time-dependent feature, you can set $f(x, n^1)$ to always return $x$ so the key $K$ will be only protected by the time protection algorithm.*
##### Constraints
- $S$ must be able to recover the token if the data is received within the time window.
- If the window expired, the token must be invalidated by the server.
##### Limitations
- If an arbitrary catches, then blocks a request from $C$ to $S$ and sends it afterwards, it will be authenticated. This case is equivalent to being $C$ (with all secret variables), which can *never* occur if you use TLS. Notice that you won't be able to extract anything from the token anyway.
- With requests meta data (*e.g. HTTP headers containing the date*), an attacker knowing $W$ can forge the time hash $h_n$ and be able to recover the private key $K$ by processing a simple *XOR* on the public token. Because the cyclic-hash algorithm generates a unique pseudo-random token from $K$ for each request, this case does not give the attacker any clue about the next token to be sent.
## Protocol
Each request and response will hold a pair of tokens.
### 1. Client request
This case is the default one where $n_0$ is far from $1$ so there is no key generation to do.
| Step | Description | Formula |
|:----:|-------------|:--------|
| `c1` | Decrement the shifting nonce | $n_0 = n_0 - 1$ |
| `c2` | Calculate the one-time token $T_C$ | $T_C = h^{n_0}(K)$ |
| `c3` | Get the current window id $n_C$ | $n_C =\ \mid \frac{T_{now}}{W} \mid$ |
| `c4` | Calculate $m_C$, the parity of $n_C$ | $m_C = n_C \mod 2$ |
| `c5` | Calculate the time hash $h_{n_C}$ | $h_{n_C} = h(n_C)$ |
| `c6` | Calculate $T_{req}$, the scrambled *request token* | $T_{req} = T_C \oplus h_{n_C}$ |
**Steps explanation**
- `c2` - The window id corresponds to the index of the time slice where slices are $W$ seconds wide. By dividing the time in slices of $W$ seconds, if we process the same calculation at an interval of $W$ or less seconds, we will have either the same result or a result greater by 1.
- `c3` - The window id parity $m_C$ allows us to adjust the value of $n_S$ made on $S$ when it receives the request. This difference of 1 second is caused by the division of time in slices, the precision is also divided by $W$.
- $T_{now}\mod W = 0 \implies \mid \frac{T_{now}}{W} \mid = \mid \frac{T_{now}+(W-1)}{W} \mid$; no need for adjustment
- $T_{now}\mod W = 1 \implies \mid \frac{T_{now}}{W} \mid = \mid \frac{T_{now}+(W-1)}{W} \mid + 1$; need to subtract $1$
- $T_{now}\mod W = 2 \implies \mid \frac{T_{now}}{W} \mid = \mid \frac{T_{now}+(W-1)}{W} \mid + 1$; need to subtract $1$
- $...$
- $T_{now}\mod W = (W-1) \implies \mid \frac{T_{now}}{W} \mid = \mid \frac{T_{now}+(W-1)}{W} \mid + 1$; need to subtract $1$
- `c4` - $h(n_C)$ allows $h_{n_C}$ to be $L$ bits long and protects $n_C$ to be predictable from $h_{n_C}$.
- `c5` - we process a one-time pad between $T_C$ and $h_{n_C}$ it is crucial that both values have the same size of $L$ bits. It makes $T_C$ impossible to extract without having the value $h_{n_C}$, this property applies in both ways.
**Short formulas**
| Field to send | Short formula |
| :-----------: | ------------------------------------------------ |
| $T_{req}$ | $h^{n_0}(K) \oplus h(\mid\frac{T_{now}}{W}\mid)$ |
| $m_C$ | $\mid\frac{T_{now}}{W}\mid \mod 2$ |
> Note
>
> - In order to send all the data in one request, for instance you can simply concatenate the 2 variables.
### 2. Server check
Received data
- $T_{req}$ the received request token
- $m_C$ the received time id parity
| Step | Description | Formula |
|:----:|-------------|---------|
| `s1` | Store the reception time window id $n'$ | $n' = \mid \frac{T_{now}}{W}\mid$ |
| `s2` | Calculate $m_S$, the parity of $n'$ | $m_S = n' \mod 2$ |
| `s3` | Use $m_C$ to try to correct the reception window id and guess the request time id | $n_S = n' - \parallel m_C - m_S \parallel$ |
| `s4` | Calculate the time hash $h_{n_S}$ | $h_{n_S} = h(n_S)$ |
| `s5` | Cancel $h_{n_S}$ to extract $T_{C'}$ | $T_{C'} = T_{req} \oplus h_{n_S}$ |
| `s6` | Check if $T_{C'}$ matches $T_S$ | $T_{C'} = T_S ?$ |
> If $T_{C'} = T_S$, $S$ can consider that $C$ sent the request $0$ to $(W + \frac{W}{2})$ seconds ago.
**Steps explanation**
- `s1` - If $C$ and $S$ have the same values for $K$ and $n^1$, $f(K,n^1)$ must result in the same output; in other words $T_C=T_S$.
- `s3`/`s4` - $\| m_C - m_s\|$ is the difference between $m_C$ and $m_S$.
- If the receiver time window id ($n'$) is the same as the sender ($n_C$)
$n'=n_C \implies m_S=m_C$
$m_C=m_S \implies \| m_C - m_S\| = 0$
$n_S = n_C - 0$
$n_S=n_C$, the time ids are the same, $S$ can now unscramble the request to check the token
- If the receiver time window if further the sender by $1$
$n'=n_C+1 \implies \| m_C - m_S \| = 1$
$n_S = n_C + 1 - 1$
$n_S = n_C$, the time ids are the same, $S$ can now unscramble the request to check the token
- If the receiver time window if further the sender by $2$ or more, let $k \in \N$
$n'= n_C+2+k \implies \parallel m_C - m_S\parallel \in \{0,1\}$
$- \parallel m_C - m_S\parallel \in \{-1,0\}$
$n_S \in \{n_C + 2 + k - 1, n_C + 2 + k + 0\}$
$n_S \in \{n_C + k + 1, n_C + k + 2\}$
$\rarr n_S = n_C + k + 1 \implies \forall (k\in \N), n_S \gt n_C$, the time ids differ, $S$ cannot extract $T_S$
$\rarr n_S = n_C + k + 2 \implies \forall (k \in \N), n_S \gt n_C+1$, the time ids differ, $S$ cannot extract $T_S$
- `s6` - By the *non-idempotency* (*i.e. $a\oplus b \oplus a = b$*) and *associativity* properties of the *XOR* operator, considering $h_{n_S}=h_{n_C}$:
$T_{C'} = T_{req} \oplus h_{n_S} = (T_C \oplus h_{n_C}) \oplus h_{n_S}$
$h_{n_S} = h_{n_C} \implies T_{C'} = T_C \oplus h_{n_C} \oplus h_{n_C}$
$T_{C'} = T_C$, the one-time token of $C$ have successfully been extracted
- `s7` - If $K$ and $n^1$ are the same on both machines, $T_S=T_C$. Furthermore, if the time ids are the same (*c.f. step `s6`*) the 2 tokens should match.
**Short formulas**
The whole unscrambling process can be shortened into the following formula resulting in $0$ if the client is authenticated.
$T_{req} \oplus h(\mid \frac{T_{now}}{W}\mid - \parallel m_C - (\mid \frac{T_{now}}{W}\mid \mod 2) \parallel) \oplus f(K, n^1)$