From 7178231461a4d745fcfa760ba83fddfa451498ff Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Mon, 8 Nov 2021 16:29:04 +0300 Subject: [PATCH] Up to date NNCPE format --- doc/pkt/encrypted.texi | 144 ++++++++++++++++++++++++++++++++++------- 1 file changed, 119 insertions(+), 25 deletions(-) diff --git a/doc/pkt/encrypted.texi b/doc/pkt/encrypted.texi index b036147..7b8ed21 100644 --- a/doc/pkt/encrypted.texi +++ b/doc/pkt/encrypted.texi @@ -7,11 +7,11 @@ storages and that are synchronized between TCP daemons. Each encrypted packet has the following header: @verbatim - +------------ HEADER --------------------+ +------------- ENCRYPTED -------------+ - / \ / \ -+--------------------------------------------+------+---------+----------...---+------+ -| MAGIC | NICE | SENDER | RCPT | EPUB | SIGN | SIZE | BLOCK 0 | BLOCK 1 ... | JUNK | -+-------------------------------------/------\------+---------+----------...---+------+ + +------------ HEADER --------------------+ +------ ENCRYPTED -----+ + / \ / \ ++--------------------------------------------+---------+----------...---+-----...--+ +| MAGIC | NICE | SENDER | RCPT | EPUB | SIGN | BLOCK 0 | BLOCK 1 ... | OPAD | ++-------------------------------------/------\---------+----------...---+-----...--+ / \ +-------------------------------------+ | MAGIC | NICE | SENDER | RCPT | EPUB | @@ -22,7 +22,7 @@ Each encrypted packet has the following header: @headitem @tab XDR type @tab Value @item Magic number @tab 8-byte, fixed length opaque data @tab - @verb{|N N C P E 0x00 0x00 0x05|} + @verb{|N N C P E 0x00 0x00 0x06|} @item Niceness @tab unsigned integer @tab 1-255, packet @ref{Niceness, niceness} level @@ -40,17 +40,96 @@ Each encrypted packet has the following header: ed25519 signature for that packet's header over all previous fields. @end multitable -All following encryption is done in AEAD mode using +Each @code{BLOCK} is AEAD-encrypted 128 KiB data. Last block can have +smaller size. They are encrypted in AEAD mode using @url{https://cr.yp.to/chacha.html, ChaCha20}-@url{https://en.wikipedia.org/wiki/Poly1305, Poly1305} algorithms. Authenticated data is BLAKE3-256 hash of the unsigned -portion of the header (the same data used in the signature). Size is -XDR-encoded unsigned hyper integer, carrying the payload size, encrypted -as a single AEAD-block (with the tag) independently from the following -blocks. It is encoded with the zero nonce. +portion of the header (the same data used in the signature). Nonce is +block's sequence number (64-bit integer starting at 0). -Payload with possible padding is divided on 128 KiB blocks blocks. They -are encrypted with the same authenticated data and increasing big-endian -64-bit nonce, starting at 1. +Concatenated plaintext of those blocks hold the following stream of data: + +@verbatim ++-----------+--------+---------------------+--------+ +| PAYLOAD | SIZE | REST (OF PAYLOAD) | IPAD | ++-----------+--------+---------------------+--------+ + ^ + | + +-- always aligned to the beginning of block +@end verbatim + +Where @code{SIZE} is following XDR structure: + +@multitable @columnfractions 0.2 0.3 0.5 +@headitem @tab XDR type @tab Value +@item Payload @tab + unsigned hyper integer @tab + Full payload size. @code{len(PAYLOAD) + len(REST)} +@item Pad @tab + unsigned hyper integer @tab + Full padding size. @code{len(IPAD) + len(OPAD)} +@end multitable + +@code{SIZE} is always at the beginning of the block. So payload and rest +of it have variable length. Block containing @code{SIZE} is encrypted +with the different key (@code{key=size}), to distinguish it from the +"ordinary" ones (@code{key=full}). + +@code{IPAD} contains zeros and is shorter than single block. Padding is fully +optional and is used only to hide the payload full size. + +It is acceptable to have either @code{PAYLOAD} or @code{REST} of it of +zero length. For example: + +@verbatim ++------+-------------+ +| SIZE | PAYLOAD ... | ++------+-------------+ + \------ BLOCK -----/ + key=size + ++------+-------------+------+ +| SIZE | PAYLOAD ... | IPAD | ++------+-------------+------+ + \--------- BLOCK --------/ + key=size + ++--------------------------+ +------+-------------------+ +| PAYLOAD | .. | SIZE | IPAD ... | ++--------------------------+ +------+-------------------+ + \--------- BLOCK --------/ \--------- BLOCK --------/ + key=full key=size + ++--------------------------+ +------+-------------------+ +| PAYLOAD | .. | SIZE | PAYLOAD ... | ++--------------------------+ +------+-------------------+ + \--------- BLOCK --------/ \--------- BLOCK --------/ + key=full key=size + ++--------------------------+ +------+-------------+------+ +| PAYLOAD | .. | SIZE | PAYLOAD ... | IPAD | ++--------------------------+ +------+-------------+------+ + \--------- BLOCK --------/ \--------- BLOCK --------/ + key=full key=size + ++--------------------------+ +------+-------------------+ +--------------------------+ +| PAYLOAD | .. | SIZE | PAYLOAD ... | .. | PAYLOAD ... | ++--------------------------+ +------+-------------------+ +--------------------------+ + \--------- BLOCK --------/ \--------- BLOCK --------/ \--------- BLOCK --------/ + key=full key=size key=full + ++--------------------------+ +------+-------------------+ +-------------+-------------+ +| PAYLOAD | .. | SIZE | PAYLOAD ... | .. | PAYLOAD ... | IPAD ... | ++--------------------------+ +------+-------------------+ +-------------+------------+ + \--------- BLOCK --------/ \--------- BLOCK --------/ \--------- BLOCK --------/ + key=full key=size key=full +@end verbatim + +@code{OPAD} is appended if @code{IPAD} (inside the block) has not enough +length. @code{OPAD} is just an output of the XOF function. No encryption +and explicit authentication is applied to it. XOF is just faster and can +be computed deterministically on both ends -- you just have to +authenticate its length. Each node has static @strong{exchange} and @strong{signature} keypairs. When node A want to send encrypted packet to node B, it: @@ -63,17 +142,32 @@ When node A want to send encrypted packet to node B, it: @item takes remote node's exchange public key and performs Diffie-Hellman computation on this remote static public key and private ephemeral one -@item derives 32-bytes AEAD encryption key with BLAKE3 derivation - function. Source key is the derived ephemeral key. Context is - @verb{|N N C P E 0x00 0x00 0x05|} magic number +@item derives three keys using BLAKE3 derivation function from the + curve25519-derived ephemeral source key: + @itemize + @item @code{key=full} with the context of: + @verb{|N N C P E 0x00 0x00 0x06 F U L L|} + @item @code{key=size} with the context of: + @verb{|N N C P E 0x00 0x00 0x06 S I Z E|} + @item @code{key=pad} with the context of: + @verb{|N N C P E 0x00 0x00 0x06 P A D|} + @end itemize @item calculates authenticated data: it is BLAKE3-256 hash of the unsigned header (same used for signing) -@item encrypts size, appends its authenticated ciphertext to the header - (with authenticated data, nonce=0) -@item encrypts each payload block, appending its authenticated ciphertext - (with authenticated data, nonce starting at 1, increasing with each block) -@item possibly appends any kind of "junk" noise data to hide real - payload's size from the adversary (generated using BLAKE3 XOF, with - the key derived from the ephemeral one and context string of - @verb{|N N C P E 0x00 0x00 0x05 P A D|}) +@item reads the payload by 128 KiB chunks. If it is enough data to fill + the entire 128 KiB block, then encrypt the chunk with + @code{key=full} key +@item if there is not enough data, then payload is reaching the end. + @itemize + @item prepend @code{SIZE} structure to the finishing chunk of data. + All sizes at that time are known + @item produce block with @code{SIZE} even if there is no payload + data left + @item append remaining payload to the @code{SIZE}, if it is left + @item if there is padding, then fill current block to the end with + zeros (@code{IPAD}) + @item encrypt the block with @code{key=size} key + @end itemize +@item if there is more padding left (@code{OPAD}), then generate it with + BLAKE3 XOF function using the @code{key=pad} key @end enumerate -- 2.44.0