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