Skip to content

Commit 48d3104

Browse files
committed
Dev guide for authentication
1 parent 600d93b commit 48d3104

2 files changed

Lines changed: 96 additions & 0 deletions

File tree

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"setaf",
5858
"Shamir",
5959
"Shor's",
60+
"Starlette",
6061
"urandom",
6162
"Uvicorn",
6263
"venv"

docs/developer-guide.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,98 @@ Sharing a secret means sending the some information about the `Allocation` objec
252252
which bytes in which blocks have been allocated, but not the byte values themselves.
253253
The peer then uses this information to create a corresponding `Allocation` object with
254254
identical byte values.
255+
256+
## Message authentication
257+
258+
The DSKE protocol runs over HTTP and not over HTTPS;
259+
it uses its own authentication and encryption mechanisms instead of relying on TLS.
260+
261+
In-band DSKE protocol messages are signed using PSRD data for authentication.
262+
263+
The client signs outgoing HTTP request messages and the hub verifies the signature on incoming
264+
HTTP request messages.
265+
The hub signs outgoing HTTP response message and the client verifies the signature on incoming
266+
HTTP response messages.
267+
268+
The sender of an HTTP message signs outgoing HTTP messages as follows:
269+
270+
* Allocate a 32 (SIGNING_KEY_SIZE) byte signing key from the local pool associated with the
271+
received of the message.
272+
273+
* Compute a SHA256 hash over the concatenation of the allocated signing key and the content of
274+
the signed HTTP message and the parameters of the request. This hash is used as the signature.
275+
276+
* Convey the base64 encoded signature in the HTTP header `DSKE-Signature`.
277+
278+
* Convey the meta-data of the signing key in the HTTP header `DSKE-Signing-Key`.
279+
This allows the receiver to allocate the same signing key from the Pre-Shared Random Data
280+
to verify the signature.
281+
The encoding of the signing key meta data into an HTTP header is described below.
282+
283+
The received of an HTTP message verifies the signature on incoming HTTP messages as follows:
284+
285+
* Extract the meta-data of the signing key from received HTTP header `DSKE-Signing-Key`.
286+
287+
* Use this meta data to take the signing key value from the pool of Pre-Shared Random Data.
288+
289+
* Compute a SHA256 hash over the concatenation of the allocated signing key and the content of
290+
the signed HTTP message and the parameters of the request.
291+
This hash is the locally computed signature.
292+
293+
* Compare the locally computed signature with the signature received in the HTTP header
294+
`DSKE-Signature`. If they match, the signature is correct.
295+
296+
* If the signatures do not match, the locally allocated signing key is given back to the pool.
297+
This is to prevent Denial-of-Service attacks from an attacker guessing singing keys.
298+
299+
The meta-data of the signing key is encoded into the `DSKE-Signing-Key` header as follows:
300+
301+
* One or more encoded fragment meta-data strings, separated by commas.
302+
303+
* Each fragment meta-data string is encoded as the block UUID, the start byte within the block,
304+
and the size of the fragment, separated by colons.
305+
306+
* Note that the key data (fragment data) is not encoded into the meta-data.
307+
308+
Example of an encoded signing key meta-data (consisting of two fragments, one fragment
309+
of 20 bytes, and another fragment of a different block of 12 bytes):
310+
311+
```
312+
9ad7f620-5a0c-4979-8a2d-66142e06fd79:0:20,cda527e9-5ca7-40d6-a842-0b606597611c:0:12
313+
```
314+
315+
The signatures have to be computed over the body of the HTTP message, exactly as it is encoded
316+
in the HTTP message.
317+
This was non-trivial to implement in the code.
318+
319+
On the client side, we use the Python
320+
[httpx](https://www.python-httpx.org/)
321+
module.
322+
On the server (hub) side, we use the Python
323+
[FastAPI](https://fastapi.tiangolo.com/)
324+
module.
325+
Both modules try to make life easier for the developer by allowing the code to use Python objects
326+
(instead of raw bytes or strings) to represent the body of a message.
327+
However, to compute the signature we needed the exact encoded bytes in the HTTP message, not
328+
its representation as a Python object.
329+
We could have tried to work with canonical encoders/decoders, but that would be complex and
330+
error-prone.
331+
Instead, we used a different mechanism to get access to the encoded message body and
332+
compute/verify the signature over it.
333+
334+
On the client (httpx) side, we use the
335+
[per-request authentication mechanism](https://www.python-httpx.org/advanced/authentication/)
336+
to register a `async_auth_flow` callback.
337+
This callback is called after the message is encoded but before it is sent.
338+
This allows us to compute the signature and add the `DSKE-Signature` header on the outgoing
339+
HTTP request.
340+
341+
On the hub (server, FastAPI) side, we use the
342+
[Starlette middleware mechanism](https://www.starlette.dev/middleware/).
343+
We register the `dske_authentication` function as a middleware for HTTP.
344+
This gives us access to the body in a request before decoding and the body in a response
345+
before encoding.
346+
347+
## Share encryption
348+
349+
TODO

0 commit comments

Comments
 (0)