]> Cypherpunks.ru repositories - nncp.git/blob - doc/pkt/encrypted.texi
Add various documentation indices
[nncp.git] / doc / pkt / encrypted.texi
1 @node Encrypted
2 @cindex encrypted packet
3 @cindex AEAD
4 @cindex ChaCha20-Poly1305
5 @section Encrypted packet
6
7 Encrypted packets are the only files found in spools, in exchangeable
8 storages and that are synchronized between TCP daemons.
9
10 Each encrypted packet has the following header:
11
12 @verbatim
13   +------------ HEADER --------------------+   +------ ENCRYPTED -----+
14  /                                          \ /                        \
15 +--------------------------------------------+---------+----------...---+-----...--+
16 | MAGIC | NICE | SENDER | RCPT | EPUB | SIGN | BLOCK 0 | BLOCK 1  ...   |   OPAD   |
17 +-------------------------------------/------\---------+----------...---+-----...--+
18                                      /        \
19                       +-------------------------------------+
20                       | MAGIC | NICE | SENDER | RCPT | EPUB |
21                       +-------------------------------------+
22 @end verbatim
23
24 @multitable @columnfractions 0.2 0.3 0.5
25 @headitem @tab XDR type @tab Value
26 @item Magic number @tab
27     8-byte, fixed length opaque data @tab
28     @verb{|N N C P E 0x00 0x00 0x06|}
29 @item Niceness @tab
30     unsigned integer @tab
31     1-255, packet @ref{Niceness, niceness} level
32 @item Sender @tab
33     32-byte, fixed length opaque data @tab
34     Sender node's id
35 @item Recipient @tab
36     32-byte, fixed length opaque data @tab
37     Recipient node's id
38 @item Exchange public key @tab
39     32-byte, fixed length opaque data @tab
40     Ephemeral curve25519 public key
41 @item Signature @tab
42     64-byte, fixed length opaque data @tab
43     ed25519 signature for that packet's header over all previous fields.
44 @end multitable
45
46 Each @code{BLOCK} is AEAD-encrypted 128 KiB data. Last block can have
47 smaller size. They are encrypted in AEAD mode using
48 @url{https://cr.yp.to/chacha.html, ChaCha20}-@url{https://en.wikipedia.org/wiki/Poly1305, Poly1305}
49 algorithms. Authenticated data is BLAKE3-256 hash of the unsigned
50 portion of the header (the same data used in the signature). Nonce is
51 block's sequence number (64-bit integer starting at 0).
52
53 Concatenated plaintext of those blocks hold the following stream of data:
54
55 @verbatim
56 +-----------+--------+---------------------+--------+
57 |  PAYLOAD  |  SIZE  |  REST (OF PAYLOAD)  |  IPAD  |
58 +-----------+--------+---------------------+--------+
59             ^
60             |
61             +-- always aligned to the beginning of block
62 @end verbatim
63
64 Where @code{SIZE} is following XDR structure:
65
66 @multitable @columnfractions 0.2 0.3 0.5
67 @headitem @tab XDR type @tab Value
68 @item Payload @tab
69     unsigned hyper integer @tab
70     Full payload size. @code{len(PAYLOAD) + len(REST)}
71 @item Pad @tab
72     unsigned hyper integer @tab
73     Full padding size. @code{len(IPAD) + len(OPAD)}
74 @end multitable
75
76 @code{SIZE} is always at the beginning of the block. So payload and rest
77 of it have variable length. Block containing @code{SIZE} is encrypted
78 with the different key (@code{key=size}), to distinguish it from the
79 "ordinary" ones (@code{key=full}).
80
81 @code{IPAD} contains zeros and is shorter than single block. Padding is fully
82 optional and is used only to hide the payload full size.
83
84 It is acceptable to have either @code{PAYLOAD} or @code{REST} of it of
85 zero length. For example:
86
87 @verbatim
88 +------+-------------+
89 | SIZE | PAYLOAD ... |
90 +------+-------------+
91  \------ BLOCK -----/
92          key=size
93
94 +------+-------------+------+
95 | SIZE | PAYLOAD ... | IPAD |
96 +------+-------------+------+
97  \--------- BLOCK --------/
98             key=size
99
100 +--------------------------+    +------+-------------------+
101 |          PAYLOAD         | .. | SIZE | IPAD ...           |
102 +--------------------------+    +------+-------------------+
103  \--------- BLOCK --------/      \--------- BLOCK --------/
104             key=full                        key=size
105
106 +--------------------------+    +------+-------------------+
107 |          PAYLOAD         | .. | SIZE | PAYLOAD ...       |
108 +--------------------------+    +------+-------------------+
109  \--------- BLOCK --------/      \--------- BLOCK --------/
110             key=full                        key=size
111
112 +--------------------------+    +------+-------------+------+
113 |          PAYLOAD         | .. | SIZE | PAYLOAD ... | IPAD |
114 +--------------------------+    +------+-------------+------+
115  \--------- BLOCK --------/      \--------- BLOCK --------/
116             key=full                        key=size
117
118 +--------------------------+    +------+-------------------+    +--------------------------+
119 |          PAYLOAD         | .. | SIZE | PAYLOAD ...       | .. | PAYLOAD ...              |
120 +--------------------------+    +------+-------------------+    +--------------------------+
121  \--------- BLOCK --------/      \--------- BLOCK --------/      \--------- BLOCK --------/
122             key=full                        key=size                        key=full
123
124 +--------------------------+    +------+-------------------+    +-------------+-------------+
125 |          PAYLOAD         | .. | SIZE | PAYLOAD ...       | .. | PAYLOAD ... | IPAD ...    |
126 +--------------------------+    +------+-------------------+    +-------------+------------+
127  \--------- BLOCK --------/      \--------- BLOCK --------/      \--------- BLOCK --------/
128             key=full                        key=size                        key=full
129 @end verbatim
130
131 @code{OPAD} is appended if @code{IPAD} (inside the block) has not enough
132 length. @code{OPAD} is just an output of the XOF function. No encryption
133 and explicit authentication is applied to it. XOF is just faster and can
134 be computed deterministically on both ends -- you just have to
135 authenticate its length.
136
137 Each node has static @strong{exchange} and @strong{signature} keypairs.
138 When node A want to send encrypted packet to node B, it:
139
140 @enumerate
141 @item generates ephemeral @url{http://cr.yp.to/ecdh.html, curve25519} keypair
142 @item prepares structure for signing
143 @item signs that structure using private
144     @url{http://ed25519.cr.yp.to/, ed25519} signature key
145 @item takes remote node's exchange public key and performs
146     Diffie-Hellman computation on this remote static public key and
147     private ephemeral one
148 @item derives three keys using BLAKE3 derivation function from the
149     curve25519-derived ephemeral source key:
150     @itemize
151     @item @code{key=full} with the context of:
152         @verb{|N N C P E 0x00 0x00 0x06 <SP> F U L L|}
153     @item @code{key=size} with the context of:
154         @verb{|N N C P E 0x00 0x00 0x06 <SP> S I Z E|}
155     @item @code{key=pad} with the context of:
156         @verb{|N N C P E 0x00 0x00 0x06 <SP> P A D|}
157     @end itemize
158 @item calculates authenticated data: it is BLAKE3-256 hash of the
159     unsigned header (same used for signing)
160 @item reads the payload by 128 KiB chunks. If it is enough data to fill
161     the entire 128 KiB block, then encrypt the chunk with
162     @code{key=full} key
163 @item if there is not enough data, then payload is reaching the end.
164     @itemize
165     @item prepend @code{SIZE} structure to the finishing chunk of data.
166         All sizes at that time are known
167     @item produce block with @code{SIZE} even if there is no payload
168         data left
169     @item append remaining payload to the @code{SIZE}, if it is left
170     @item if there is padding, then fill current block to the end with
171         zeros (@code{IPAD})
172     @item encrypt the block with @code{key=size} key
173     @end itemize
174 @item if there is more padding left (@code{OPAD}), then generate it with
175     BLAKE3 XOF function using the @code{key=pad} key
176 @end enumerate