X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=doc%2Fpkt.texi;h=567d3f77226d7e2d192de79b3ea5fd14ddf8d744;hb=0fad171c0d79ad583c0faf5427e22d1d62a0a52d;hp=4549505961533aed1290bffe37d79f85824abb60;hpb=093f249044a62ce4d988542c7267caf1da5d0968;p=nncp.git diff --git a/doc/pkt.texi b/doc/pkt.texi index 4549505..567d3f7 100644 --- a/doc/pkt.texi +++ b/doc/pkt.texi @@ -13,25 +13,28 @@ All packets are @section Plain packet Plain packet contains either the whole file, or file request (freq), or -transition packet or email message. It is called "plain", because it +transition packet or exec message. It is called "plain", because it contains plaintext, but plain packets would never be stored on your hard drive. @verbatim HEADER -+-------------------------------+--...---+ -| MAGIC | TYPE | PATHLEN | PATH | PAYLOAD| -+-------------------------------+--...---+ ++--------------------------------------+--...---+ +| MAGIC | TYPE | NICE | PATHLEN | PATH | PAYLOAD| ++--------------------------------------+--...---+ @end verbatim @multitable @columnfractions 0.2 0.3 0.5 @headitem @tab XDR type @tab Value @item Magic number @tab 8-byte, fixed length opaque data @tab - @verb{|N N C P P 0x00 0x00 0x01|} + @verb{|N N C P P 0x00 0x00 0x03|} @item Payload type @tab unsigned integer @tab - 0 (file), 1 (freq), 2 (mail), 3 (transition) + 0 (file), 1 (freq), 2 (exec), 3 (transition), 4 (exec-fat) +@item Niceness @tab + unsigned integer @tab + 1-255, preferred packet @ref{Niceness, niceness} level @item Path length @tab unsigned integer @tab actual length of @emph{path} field's payload @@ -40,23 +43,32 @@ drive. @itemize @item UTF-8 encoded destination path for file transfer @item UTF-8 encoded source path for file request - @item UTF-8 encoded, space separated, email recipients list + @item UTF-8 encoded, zero byte separated, exec's arguments @item Node's id the transition packet must be relayed on @end itemize @end multitable Path has fixed size because of hiding its actual length -- it is valuable metadata. Payload is appended to the header -- it is not stored -as XDR field, because most XDR libraries will store all that data in the -memory. +as XDR field, because XDR has no ability to pass more than 4 GiB of +opaque data. Moreover most XDR libraries store fields in the memory in +practice. Depending on the packet's type, payload could store: @itemize @item File contents @item Destination path for freq -@item @url{http://zlib.net/, zlib} compressed email +@item @url{https://facebook.github.io/zstd/, Zstandard} compressed exec body @item Whole encrypted packet we need to relay on +@item Uncompressed exec body +@end itemize + +Also depending on packet's type, niceness level means: + +@itemize +@item Preferable niceness level for files sent by freq +@item @env{NNCP_NICE} variable's value passed during @ref{CfgExec} invocation. @end itemize @node Encrypted @@ -68,28 +80,31 @@ storages and that are synchronized between TCP daemons. Each encrypted packet has the following header: @verbatim - +------------ HEADER -------------+ +-------- ENCRYPTED --------+ - / \ / \ -+-------------------------------------+------------+----...-----------+------+ -| MAGIC | NICE | SENDER | EPUB | SIGN | SIZE | MAC | CIPHERTEXT | MAC | JUNK | -+------------------------------/------\------------+----...-----------+------+ - / \ - +-------------------------------------+ - | MAGIC | NICE | RCPT | SENDER | EPUB | - +-------------------------------------+ + +------------ HEADER --------------------+ +------------- ENCRYPTED -------------+ + / \ / \ ++--------------------------------------------+------+---------+----------...---+------+ +| MAGIC | NICE | SENDER | RCPT | EPUB | SIGN | SIZE | BLOCK 0 | BLOCK 1 ... | JUNK | ++-------------------------------------/------\------+---------+----------...---+------+ + / \ + +-------------------------------------+ + | MAGIC | NICE | SENDER | RCPT | EPUB | + +-------------------------------------+ @end verbatim @multitable @columnfractions 0.2 0.3 0.5 @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 0x01|} + @verb{|N N C P E 0x00 0x00 0x05|} @item Niceness @tab unsigned integer @tab 1-255, packet @ref{Niceness, niceness} level @item Sender @tab 32-byte, fixed length opaque data @tab Sender node's id +@item Recipient @tab + 32-byte, fixed length opaque data @tab + Recipient node's id @item Exchange public key @tab 32-byte, fixed length opaque data @tab Ephemeral curve25519 public key @@ -98,25 +113,14 @@ Each encrypted packet has the following header: ed25519 signature for that packet's header @end multitable -Signature is calculated over the following structure: - -@itemize -@item Magic number -@item Niceness -@item Recipient (32-byte recipient node's id) -@item Sender -@item Exchange public key -@end itemize +Signature is calculated over all previous fields. -All following encryption is done using -@url{https://www.schneier.com/academic/twofish/, Twofish} algorithm with -256-bit key in -@url{https://en.wikipedia.org/wiki/Counter_mode#Counter_.28CTR.29, CTR} -mode of operation with zero initialization vector (because each -encrypted packet has ephemeral exchange key). @url{https://blake2.net/, -BLAKE2b-256} MAC is appended to the ciphertext. +All following encryption is done in AEAD mode using +@url{https://cr.yp.to/chacha.html, ChaCha20}-@url{https://en.wikipedia.org/wiki/Poly1305, Poly1305} +algorithms. Data is divided on 128 KiB blocks. Each block is encrypted with +increasing nonce counter. -After the headers comes an encrypted payload size and MAC of that size. +Authenticated and encrypted size come after the header: @multitable @columnfractions 0.2 0.3 0.5 @headitem @tab XDR type @tab Value @@ -125,7 +129,7 @@ After the headers comes an encrypted payload size and MAC of that size. Payload size. @end multitable -Next comes the actual encrypted payload with corresponding MAC. +Then comes the actual payload. Each node has static @strong{exchange} and @strong{signature} keypairs. When node A want to send encrypted packet to node B, it: @@ -138,20 +142,13 @@ 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 derived ephemeral key is used as an input to - @url{https://en.wikipedia.org/wiki/HKDF, HKDF}-BLAKE2b-256 KDF -@item derives four session keys using - @url{https://en.wikipedia.org/wiki/HKDF, HKDF}-BLAKE2b-256 KDF: - @enumerate - @item "Size" encryption (for Twofish) key - @item "Size" authentication (for BLAKE2b-MAC) key - @item Payload encryption key - @item Payload authentication key - @end enumerate -@item encrypts size, appends its ciphertext to the header -@item appends MAC tag over that ciphertext -@item encrypts and appends payload ciphertext -@item appends MAC tag over that payload ciphertext +@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 encrypts size, appends its authenticated ciphertext to the header +@item encrypts each payload block, appending its authenticated ciphertext @item possibly appends any kind of "junk" noise data to hide real - payload's size from the adversary + 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|}) @end enumerate