Commit 4e9c1298 authored by Johannes Schwab's avatar Johannes Schwab

rewrite protocol documentation

parent 6340764a
......@@ -17,6 +17,7 @@ client/obj/
client/openrecipes
client/qrc_client.cpp
client/target_wrapper.sh
doxygen/
lib/doxygen/
lib/libopenrecipes.a
lib/moc/
......
# Synchronization protocol
The protocol consists of three parts:
* local packing and encryption (client side)
* establish and authenticate a secure connection
* synchronization
## General notes
* All strings must be utf8 encoded and null terminated (size is given including the null byte), except for the keywords, which are in ASCII and NOT null terminated.
* All integers must be unsigned 64 bit big endian.
* All requests of the client are in the form
`[keyword]`
or
`[keyword][size][data]`,
where `[keyword]` is a valid keyword as specified below and `[size]` is the size of `[data]` in byte.
## Prerequisites
Befor the first synchronization happens, server and client both create an public keypair with libsodiums `crypto_sign_keypair()` used for authentication.
The client creates an additional symmetric key with `crypto_secretbox_keygen()` used for encryption.
# Local packing and encryption
The client packs the recipes in the following format:
RECI[dbStruct][id][portions][nameSize][imageSize][instructionSize]
[numberOfIngredients][ingrCount_1]…[ingrCount_n]
[ingrUnitSize_1][ingrArticleSize_1]…[ingrUnitSize_n][ingrArticleSize_n]
[name][image][instructions][ingrUnit_1][ingrArticle_1]…[ingrUnit_n][ingrArticle_n]
where `RECI` is a literal (not null terminated).
The data is afterwards encrypted unsing lobsodiums `crypto_secretbox_easy()`
unsing the encryption key.
# Establish and authenticate a secure connection
A variant of the Station-to-Station protocol is used.
After establishing a tcp connection, client and server both create a key
exchange keypair with `crypto_kx_keypair()`, send there public key to the other
side and generate two symmetric session key with
`crypto_kx_client_session_keys()` (`crypto_kx_server_session_keys()`
respectively), namely a recive and a send key.
Then both sides send the literal `AUTH` or `NOAU` to signal wether they will
authenticated themselfes.
AUTH must be followed by (in order):
* The senders authentication public key
* An unix timestamp
* A detached signature (`crypto_sign_detached()`) of the hash (`crypto_generichash()`) over the data `[receive key][send key][timestamp]`.
The other party then checks the signature and the timestamp and closes the connection if it dosen't
match.
The server must allways authenticatd himself, the client may skip it depending
on the action he wants to performe.
At last both sides send the encryption header generated by
`crypto_secretstream_xchacha20poly1305_init_push()`.
Now data can be exchanged by padding it with `sodium_pad()` to length that is a
multiple of 128 bytes and encrypting the padded data in blocks of
128 bytes with `crypto_secretstream_xchacha20poly1305_push()`, where the
last block is marked with `crypto_secretstream_xchacha20poly1305_TAG_PUSH`.
# Synchronization
The client send requests to the server that are answered.
All requests of the client are in the form
[keyword]
or
[keyword][size][data]
, where `[keyword]` is a valid keyword as specified below and `[size]` is the size of `[data]` in byte.
The possible requests are:
### `GETPV`
(get protocol version) to request the protocol version used by the server.
The server answers with
[protocol version]
### `GETST`
(get startup timestamp) to request the startup timestamp of the server.
The server answers with
[timestamp]
### `GETID`
(get ids) to request the ids of all items in the database.
The server answers with
[number][id_1][id_2]…[id_n]
where
* `[number]` is the number of ids (=n),
* `[id_k]` are the ids (each 16 byte long).
### `GETCH[size][timestamp]`
(get changed) to request all entrys that changed since `[timestamp]`, where timestamp is in seconds since the unix epoche.
The server responses with
[number][data_1][data_2]…[data_n]
where `[number]`=n and `[data_k]` as in `ADDUP`.
### `ADDUP[size][data]`
(add or update) to add a new entry to the database or update an existing one.
`[data]` has the structure
[id][sizeOfCipher][sizeOfNonce][cipher][nonce]
The server replise with `OK` or `ER` (error).
### `DELET[size][number][id_1][id_2]…[id_n]`
to delete an entry from the database, where
* `[number]` is the number of ids (=n),
* `[id_k]` are the ids (each 16 byte long).
The server replise with `OK` or `ER` (error).
### `CLOSE`
to indicate the end of the connection.
The server responses with `[timestamp]` (in seconds since unix epoche).
The client should use this timestamp when requesting `GETCH` on next sync to mitigate missmatching clocks.
\documentclass[a4paper]{article}
\begin{document}
\section{Network Protocol}
\emph{Notes:}
\begin{itemize}
\item All strings must be utf8 encoded and null terminated (size is given including the null byte), except for the keywords, which are in ASCII and \emph{not} null terminated.
\item All integers must be unsigned 64 bit big endian.
\item All requests of the client are in the form
{\center [keyword] or [keyword][size][data],\\}where [keyword] is a valid keyword as specified below and [size] is the size of [data] in byte.
\end{itemize}
The client connects to the server over TCP with SSL.
The client starts by sending one of:
\begin{itemize}
\item {\bf LOGIN}[size][sizeOfUsername][sizeOfPassword][username][password]
\item {\bf NEWUR}[size][sizeOfUsername][sizeOfPassword][username][password] \\
\emph{(new user)}
\end{itemize}
The server replise with {\bf OK}, {\bf SP} \emph{(sync in progress)} or {\bf DE} \emph{(declined)}.
In the latter case, the connection will be closed.
In the case of {\bf SP}, the user is allready logged in with another device and must try again after it has finished.
In the first case, the client is considered to be logged in and the server will accept the following:
\subsubsection* {\bf GETST}
\emph{(get startup timestamp)} to request the startup timestamp of the server.
The server answers with
{\center [timestamp].\\}
\subsubsection* {\bf GETID}
\emph{(get ids)} to request the ids of all items in the database.
The server answers with
{\center [number][id\_1][id\_2]\ldots[id\_n]\\}
where
\begin{itemize}
\item {} [number] is the number of ids (=n),
\item {} [id\_k] are the ids (each 16 byte long).
\end{itemize}
\subsubsection* {{\bf ADDUP}[size][data]}
\emph{(add or update)} to add a new entry to the database or update an existing one.
[data] has the structure
{\center [id][sizeOfCipher][sizeOfNonce][cipher][nonce].\\}
The server replise with {\bf OK} or {\bf ER} \emph{(error)}.
\subsubsection* {{\bf DELET}[size][number][id\_1][id\_2]\ldots[id\_n]}
to delete an entry from the database, where
\begin{itemize}
\item {} [number] is the number of ids (=n),
\item {} [id\_k] are the ids (each 16 byte long).
\end{itemize}
The server replise with {\bf OK} or {\bf ER} \emph{(error)}.
\subsubsection* {{\bf GETCH}[size][timestamp]}
\emph{(get changed)} to request all entrys that changed since [timestamp], where timestamp is in seconds since the unix epoche.
The server responses with
{\center [number][data\_1][data\_2]\ldots[data\_n],\\}
where [number]=n and [data\_k] as in {\bf ADD}.
\subsubsection* {\bf CLOSE}
to indicate the end of the connection.
The server responses with [timestamp] (in seconds since unix epoche).
The client should use this timestamp when requesting {\bf GETCHANGEDSINCE} on next sync to mitigate missmatching clocks.
\section{Data formats}
The data is packed the following way:
\subsubsection*{Recipe}
{\bf RECI}[dbStruct][id][portions][nameSize][imageSize][instructionSize]
[numberOfIngredients][ingrCount\_1]\ldots[ingrCount\_n]
[ingrUnitSize\_1][ingrArticleSize\_1]\ldots[ingrUnitSize\_n][ingrArticleSize\_n]
[name][image][instructions][ingrUnit\_1][ingrArticle\_1]\ldots[ingrUnit\_n][ingrArticle\_n]
\end{document}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment