OSDN Git Service

Updated pthreads libraries for the Windows platform (pthread4w) to version 3.0.0.
[slunkcrypt/SlunkCrypt.git] / README.md
1 ---
2 title: "![SlunkCrypt](etc/img/SlunkCrypt-Logo.png)"
3 ---
4
5
6 Introduction
7 ============
8
9 SlunkCrypt is an experimental cross-platform cryptography library and command-line tool. A fully-featured GUI is provided for the Windows platform.
10
11 Please refer to the section [*encryption algorithm*](#encryption-algorithm) for more details!
12
13
14 Legal Warning
15 =============
16
17 Use of SlunkCrypt may be illegal in countries where encryption is outlawed. We believe it is legal to use SlunkCrypt in many countries all around the world, but we are not lawyers, and so if in doubt you should seek legal advice before downloading it. You may find useful information at [cryptolaw.org](http://www.cryptolaw.org/), which collects information on cryptography laws in many countries.
18
19
20 System Requirements
21 ===================
22
23 The SlunkCrypt library and the command-line application currently run on the following platforms:
24
25 * **Microsoft Windows** (Windows XP SP-3, or later) — 32-Bit (i686) and 64-Bit (AMD64)
26 * **Linux** (kernel version 3.17, or later) — 32-Bit (i686) and 64-Bit (AMD64)
27 * **Various BSD flavors** (tested on NetBSD 9.2, FreeBSD 13.0 and OpenBSD 7.0) — 32-Bit (i686) and 64-Bit (AMD64)
28 * **Solaris** (tested on Solaris 11.4 and OmniOS/illumos) — 32-Bit (i686) and 64-Bit (AMD64)
29 * **Mac OS X** (tested on macOS 11 “Big Sur”) — Intel x86-64 (AMD64) and Apple Silicon (AArch64)
30
31 The SlunkCrypt GUI application currently runs on the following platforms:
32
33 * **Microsoft Windows** with .NET Framework 4.5 — can be installed on Windows Vista, or later
34
35
36 GUI Usage
37 =========
38
39 This is how the graphical user interface (GUI) for SlunkCrypt looks on [Windows 11](https://i.pinimg.com/736x/0f/57/4c/0f574c445b497cc4748a9e1ab7491582--taps-funny-stuff.jpg):
40
41 ![](etc/img/SlunkCrypt-GUI.jpg)
42
43 Prerequisites
44 -------------
45
46 Please be sure to install the **.NET Framework 4.5**, or any later *.NET Framework 4.x* version, before running the SlunkCrypt GUI application:  
47 <https://dotnet.microsoft.com/download/dotnet-framework>
48
49 ***Note:*** If you are running Windows 8 or later, then almost certainly a suitable version of the .NET Framework is already installed &#128526;
50
51 Settings
52 --------
53
54 The following settings can be adjusted in the `slunkcrypt-gui.exe.config` configuration file:
55
56 - **`DisableBusyIndicator`:**  
57   If set to `true`, the “busy indicator” animation will be *disabled* on application startup &mdash; default value: `false`.
58
59 - **`ThreadCount`:**  
60   Specifies the number of worker threads to use &mdash; default value: `0` (i.e. detect the number of available processors and create one thread for each processor).
61
62 - **`KeepIncompleteFiles`:**  
63   If set to `true`, incomplete or corrupted output files will *not* be deleted &mdash; default value: `false`.
64
65 Command-line Usage
66 ==================
67
68 This section describes the SlunkCypt command-line application.
69
70 Synopsis
71 --------
72
73 The SlunkCypt command-line program is invoked as follows:
74
75     slunkcrypt --encrypt [pass:<pass>|file:<file>] <input.txt> <output.enc>
76     slunkcrypt --decrypt [pass:<pass>|file:<file>] <input.enc> <output.txt>
77     slunkcrypt --make-pw [<length>]
78
79 Commands
80 --------
81
82 One of the following commands **must** be chosen:
83
84 - **`--encrypt` (`-e`):**  
85   Run application in ***encrypt*** mode. Reads the given *plaintext* and generates *ciphertext*.
86 - **`--decrypt` (`-d`):**  
87   Run application in ***decrypt*** mode. Reads the given *ciphertext* and restores *plaintext*.
88 - **`--make-pw` (`-p`):**  
89   Generate a "strong" random passphrase, suitable for use with SlunkCrypt.
90 - **`--self-test` (`-t`):**  
91   Run the application in ***self-test*** mode. Program will exit after all test are completed.
92
93 Options
94 -------
95
96 The following command-line options are available:
97
98 - **`pass:<pass>`**:  
99   * Specifies the "secret" passphrase directly on the command-line. This is considered *insecure*.
100 - **`file:<file>`**:  
101   * Specifies a file to read the passphrase from. Only the *first* line of the file will be read!
102   * *Note:* It is also possible to specify **`-`** in order to read the passphrase from the *stdin*.
103 - **`<input>`**:  
104   * In ***encrypt*** mode &ndash; specifies the *plaintext* file (unencrypted information) that is to be encrypted.
105   * In ***decrypt*** mode &ndash; specifies the *ciphertext* file (result of encryption) that is to be decrypted.
106 - **`<output>`**:  
107   * In ***encrypt*** mode &ndash; specifies the file where the *ciphertext* (result of encryption) will be stored.
108   * In ***decrypt*** mode &ndash; specifies the file where the *plaintext* (unencrypted information) will be stored.
109 - **`<length>`**:  
110   * Specifies the length of the passphrase to be generated. If *not* specified, defaults to 24.
111
112 ### Remarks {.unlisted}
113
114 - The same passphrase must be used for both, ***encrypt*** and ***decrypt*** mode. The decryption of the ciphertext will only be possible, if the "correct" passphrase is known. It is recommended to choose a "random" password that is at least 12 characters in length and consists of a mix of upper-case characters, lower-case characters, digits as well as special characters.
115
116 - Passing the passphrase directly on the command-line is insecure, because the full command-line may be visible to other users!
117
118 Environment
119 -----------
120
121 The following environment variables may be used:
122
123 - **`SLUNK_PASSPHRASE`**:  
124   Specifies the "secret" passphrase. This environment variables is only evaluated, if the passphrase was **not** specified on the command-line.  
125   Passing the passphrase via environment variable is considered more secure, because environment variables are not normally visible to other (unprivileged) users.
126
127 - **`SLUNK_KEEP_INCOMPLETE`**:  
128   If set to a *non-zero* value, incomplete or corrupted output files will **not** be deleted automatically. By default, the files will be deleted.
129
130 - **`SLUNK_THREADS`**:  
131   Specifies the number of worker threads to use. By default, SlunkCrypt detects the number of available processors and creates one thread for each processor.
132
133 Examples
134 --------
135
136 Here are some examples on how to use the SlunkCrypt command-line application:
137
138 ### Example #1 {.unlisted}
139
140 1. Let's generate a new random (secure) password first:
141
142        slunkcrypt --make-pw
143
144    *Example output:*
145
146        cdG2=fh<C=3[SSCzf[)iDjIV
147
148 2. Now, encrypt the plaintext message, using the generated password:
149
150        slunkcrypt --encrypt pass:"cdG2=fh<C=3[SSCzf[)iDjIV" plaintext.txt ciphertext.enc
151
152    Optionally, let's have a look at the ciphertext:
153
154        hexdump -C ciphertext.enc
155
156 3. Finally, decrypt the ciphertext, using the same password as before:
157
158        slunkcrypt --decrypt pass:"cdG2=fh<C=3[SSCzf[)iDjIV" ciphertext.enc plaintext.out
159
160    Optionally, verify that the decrypted file is identical to the original:
161
162        sha256sum -b plaintext.txt plaintext.out
163
164 ### Example #2 {.unlisted}
165
166 1. Generate a new password and store it to a text file:
167
168        slunkcrypt --make-pw > passwd.txt
169
170    Optionally, output the generated password to the terminal:
171
172        cat passwd.txt
173
174 2. Encrypt file by reading the password from the text file:
175
176        slunkcrypt --encrypt file:passwd.txt plaintext.txt ciphertext.enc
177
178 ### Example #3 {.unlisted}
179
180 1. Generate a new password directly to an environment variable:
181
182        MY_PASSWD="$(slunkcrypt --make-pw)"
183
184    Optionally, output the generated password to the terminal:
185
186        echo "${MY_PASSWD}"
187
188 2. Encrypt file by reading the password from the *stdin*:
189
190        slunkcrypt --encrypt - plaintext.txt ciphertext.enc <<< "${MY_PASSWD}"
191
192
193 Encryption algorithm
194 ====================
195
196 The SlunkCrypt algorithm is based on core concepts of the well-known [**Enigma**](https://en.wikipedia.org/wiki/Enigma_machine) machine but with numerous improvements, largely inspired by R. Anderson's [***“A Modern Rotor Machine”***](https://rdcu.be/cBo8y):
197
198 - The original Enigma machine had only *three* (or, in some models, *four*) rotors, plus a static "reflector" wheel. In SlunkCrypt, we uses **256** simulated rotors for an improved security. Furthermore, the original Enigma machine supported only 26 distinct symbols, i.e. the letters `A` to `Z`. In SlunkCrypt, we use **256** distinct symbols, i.e. the byte values `0x00` to `0xFF`, which allows the encryption (and decryption) of arbitrary streams of bytes, rather than just plain text. Of course, SlunkCrypt can encrypt (and decrypt) text files as well.
199
200 - In the original Enigma machine, the signal passes through the rotors *twice*, once in forward direction and then again in backwards direction &ndash; thus the "reflector" wheel. This way, the Enigma's encryption was made *involutory*, i.e. encryption and decryption were the same operation. While this was highly convenient, it also severely weakened the cryptographic strength of the Enigma machine, because the number of possible permutations was reduced drastically! This is one of the main reasons why the Enigma machine eventually was defeated. In SlunkCrypt, the signal passes through the simulated rotors just *once*, in order to maximize the number of possible permutations. This eliminates the most important known weakness of the Enigma machine. Obviously, in SlunkCrypt, separate "modes" for encryption and decryption need to be provided, since encryption and decryption *no* longer are the same operation.
201
202 - In the original Enigma machine, the rightmost rotor was moved, by one step, after every symbol. Meanwhile, all other rotors were moved, by one step, *only* when their right-hand neighbor had completed a full turn &ndash; much like the odometer in a car. The fact that most of the rotors remained in the same "static" position most of the time was an important weakness of the Enigma machine. Also, the sequence of the Enigma's rotor positions started to repeat after only 16,900 characters. SlunkCrypt employs an improved stepping algorithm, based on a ***linear-feedback shift register* (LSFR)**, ensuring that *all* rotors move frequently and in a "randomized" unpredictable pattern. The rotor positions of SlunkCrypt practically *never* repeat.
203
204 - The internal wiring of each of the original Enigma machine's rotors was *fixed*. Each rotor "type" came with a different internal wiring (i.e. permutation). Some models had up to eight rotor "types" to choose from, but only three or four rotors were used at a time. Nonetheless, the internal wiring (i.e. permutation) of each of the supplied rotors was **not** modifiable. This severely restricted the key space of the Enigma machine, as far as the rotors are concerned, because *only* the order of the rotors and the initial position of each rotor could be varied. In SlunkCrypt, a fully *randomized* wiring (i.e. permutation) is generated from the password for each of the 256 simulated rotors. The initial rotor positions are *randomized* as well.
205
206 - SlunkCrypt does **not** currently implement the *plugboard* (“Steckerbrett”) of the original Enigma machine. That is because, even though the plugboard has a large key space, it is just a *fixed* substitution cipher that does *not* contribute much to the cryptographic strength of the Enigma machine. In fact, the plugboard could be "erased" by Welchman's [diagonal board](https://en.wikipedia.org/wiki/Bombe#Stecker_values).
207
208
209 Programming Interface (API)
210 ===========================
211
212 This section describes the SlunkCypt library interface for software developers.
213
214 Getting started
215 ---------------
216
217 In order to use the SlunkCypt library in your C++ code, include **`<slunkcrypt.hpp>`** header and instantiate the appropriate SlunkCypt classes:
218
219 ### Example #1 {.unlisted}
220
221 Here is a simple example on how to use the SlunkCrypt [**`Encryptor`**](#encryptor) class:
222
223     #include <slunkcrypt.hpp>
224     #include <fstream>
225     #include <iostream>
226
227     int main()
228     {
229         /* Open input and output files here */
230         uint8_t buffer[BUFF_SIZE];
231         slunkcrypt::Encryptor slunk_encrypt(passphrase);
232         while (input.good())
233         {
234             input.read(reinterpret_cast<char*>(buffer), BUFF_SIZE);
235             if ((!input.bad()) && (input.gcount() > 0))
236             {
237                 if (!slunk_encrypt.inplace(buffer, (size_t)input.gcount()))
238                 {
239                     /* Implement error handling here */
240                 }
241                 output.write(reinterpret_cast<char*>(buffer), count);
242             }
243         }
244         std::cout << std::hex << slunk_encrypt.get_nonce() << std::endl;
245     }
246
247 ### Example #2 {.unlisted}
248
249 Here is a simple example on how to use the SlunkCrypt [**`Decryptor`**](#decryptor) class:
250
251     #include <slunkcrypt.hpp>
252     #include <fstream>
253     #include <iostream>
254
255     int main()
256     {
257         /* Open input and output files here */
258         uint8_t buffer[BUFF_SIZE];
259         slunkcrypt::Decryptor slunk_decrypt(passphrase, nonce);
260         while (input.good())
261         {
262             input.read(reinterpret_cast<char*>(buffer), BUFF_SIZE);
263             if ((!input.bad()) && (input.gcount() > 0))
264             {
265                 if (!slunk_decrypt.inplace(buffer, (size_t)input.gcount()))
266                 {
267                     /* Implement error handling here */
268                 }
269                 output.write(reinterpret_cast<char*>(buffer), count);
270             }
271         }
272     }
273
274 C++11 API
275 ---------
276
277 This section describes the "high-level" C++11 API of the SlunkCrypt library. All SlunkCrypt classes live in the **`slunkcrypt`** namespace.
278
279 ### Encryptor
280
281 Class for *encrypting* data using the SlunkCrypt library.
282
283 #### Constructor
284
285 Create and initialize a new **``Encryptor``** instance. Also generated a new, random nonce.
286
287     Encryptor::Encryptor(
288       const std::string &passwd,
289       const size_t thread_count = 0U
290     );
291
292 ***Parameters:***
293
294   * `passwd`  
295     The password to "protect" the message. The password is given as an `std::string`, e.g. UTF-8 encoded characters. The same password **may** be used to encrypt *multiple* messages. Also, the same password **must** be used for both, encryption *and* decryption; it will *only* be possible decrypt the ciphertext, if the "correct" password is known. The password must be kept confidential under all circumstances!
296      
297     *Note:* In order to thwart *brute force* attacks, it is recommended to choose a "random" password that is at least 12 characters in length and that consists of upper-case characters, lower-case characters, digits as well as other "special" characters.
298
299   * `thread_count`  
300     Specifies the number of worker threads to use (optional). By default, SlunkCrypt detects the number of available processors and creates one thread for each processor.
301
302 ***Exceptions:***
303
304   * Throws `std::runtime_error`, if the nonce could not be generated, or if the SlunkCrypt context could not be allocated.
305
306 #### Encryptor::process() [1]
307
308 Encrypt the next message chunk, using separate input/output buffers.
309
310     bool process(
311       const uint8_t *const input,
312       uint8_t *const output,
313       size_t length
314     );
315
316 ***Parameters:***
317
318  * `input`  
319     A pointer to the *input* buffer containing the next chunk of the plaintext to be encrypted. The plaintext is given as a byte array (`uint8_t`). This can be arbitrary binary data, e.g. UTF-8 encoded text. NULL bytes are **not** treated specially.
320     
321     The *input* buffer must contain *at least* `length` bytes of data. If the buffer is longer than `length` bytes, then only the first `length` bytes will be processed and the remainder is ignored!
322
323  * `output`  
324     A pointer to the *output* buffer where the ciphertext chunk that corresponds to the given plaintext chunk will be stored. The ciphertext is stored as a byte array (`uint8_t`); it has the same length as the plaintext data.
325     
326     The *output* buffer must provide sufficient space for storing *at least* `length` bytes of encrypted data. If the buffer is longer than `length` bytes, then only the first `length` bytes of the buffer will be filled with encrypted data!
327
328  * `length`  
329    The length of the plaintext chunk contained in the *input* buffer given by the `input` parameter, in bytes. At the same time, this determines the minimum required size of the *output* buffer given by the `output` parameters, in bytes.
330
331    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
332
333 ***Return value:***
334
335   * If successful, `true` is returned; otherwise `false` is returned.
336
337 #### Encryptor::process() [2]
338
339 Encrypt the next message chunk, using separate input/output containers (`std::vector`).
340
341     bool process(
342       const std::vector<uint8_t> &input,
343       std::vector<uint8_t> &output
344     );
345
346 ***Parameters:***
347
348  * `input`  
349     A reference to the `std::vector<uint8_t>` instance containing the next chunk of the plaintext to be encrypted. This can be arbitrary binary data, e.g. UTF-8 encoded text. NULL bytes are **not** treated specially.
350
351  * `output`  
352     A reference to the `std::vector<uint8_t>` instance where the ciphertext that corresponds to the given plaintext will be stored.
353     
354     The `output.size()` must be *greater than or equal* to `input.size()`. If the `output.size()` is larger than the `input.size()`, then only the first `input.size()` elements of `output` will be filled with encrypted data!
355
356 ***Return value:***
357
358   * If successful, `true` is returned; otherwise `false` is returned. The function fails, if the *output* `std::vector` is too small.
359
360 #### Encryptor::inplace() [1]
361
362 Encrypt the next message chunk, using a single buffer.
363
364     bool inplace(
365       uint8_t *const buffer,
366       size_t length
367     );
368
369 ***Parameters:***
370
371  * `buffer`  
372     A pointer to the buffer initially containing the next chunk of the plaintext to be encrypted. The plaintext is given as a byte array (`uint8_t`). This can be arbitrary binary data, e.g. UTF-8 encoded text. NULL bytes are **not** treated specially. The ciphertext chunk that corresponds to the given plaintext chunk will be stored to the *same* buffer, thus replacing the plaintext data.
373     
374     The buffer must initially contain *at least* `length` bytes of input data; the first `length` bytes of the buffer will be overwritten with the encrypted data. If the buffer is longer than `length` bytes, then only the first `length` bytes will be processed and overwritten.
375
376  * `length`  
377    The length of the plaintext chunk initially contained in the input/output buffer given by the `buffer` parameter, in bytes. At the same time, this determines the portion of the input/output buffer that will be overwritten with encrypted data, in bytes.
378
379    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
380
381 ***Return value:***
382
383   * If successful, `true` is returned; otherwise `false` is returned.
384
385 #### Encryptor::inplace() [2]
386
387 Encrypt the next message chunk, using a single container (`std::vector`).
388
389     bool inplace(
390       std::vector<uint8_t> &buffer
391     );
392
393 ***Parameters:***
394
395  * `buffer`  
396     A reference to the `std::vector<uint8_t>` initially containing the next chunk of the plaintext to be encrypted. This can be arbitrary binary data, e.g. UTF-8 encoded text. NULL bytes are **not** treated specially. The ciphertext chunk that corresponds to the given plaintext chunk will be stored to the *same* `std::vector<uint8_t>`, thus replacing all the plaintext data.
397
398 ***Return value:***
399
400   * If successful, `true` is returned; otherwise `false` is returned.
401
402 #### Encryptor::get_nonce()
403
404 Retrieve the random nonce that is used to encrypt the message.
405
406     uint64_t get_nonce();
407
408 ***Return value:***
409
410   * Returns the nonce that is used to encrypt the message. The purpose of the nonce is to ensure that each message will be encrypted differently, even when the same password is used to encrypt multiple (possibly identical) messages. Therefore, a new random nonce must be chosen for each message! It is not necessary to keep the nonce confidential, but the same nonce must be used for both, encryption and decryption. Typically, the nonce is stored/transmitted alongside the ciphertext.
411     
412     *Note:* The `Encryptor` class automatically generates a new, random nonce for each message to be encrypted. Use *this* function to retrieve that nonce, so that it can be passed to `Decryptor` for decryption later.
413
414 ### Decryptor
415
416 Class for *decrypting* data using the SlunkCrypt library.
417
418 #### Constructor
419
420 Create and initialize a new **``Decryptor``** instance.
421
422     Decryptor::Decryptor(
423       const std::string &passwd,
424       const uint64_t nonce,
425       const size_t thread_count = 0U
426     );
427
428 ***Parameters:***
429
430   * `passwd`  
431     The password to "protect" the message. The password is given as an `std::string`, e.g. UTF-8 encoded characters. The same password **may** be used to encrypt *multiple* messages. Also, the same password **must** be used for both, encryption *and* decryption; it will *only* be possible decrypt the ciphertext, if the "correct" password is known. The password must be kept confidential under all circumstances!
432     
433     *Note:* In order to thwart *brute force* attacks, it is recommended to choose a "random" password that is at least 12 characters in length and that consists of upper-case characters, lower-case characters, digits as well as other "special" characters.
434
435   * `nonce`  
436     The *nonce* (number used once) to be used for the decryption process. The purpose of the nonce is to ensure that each message will be encrypted differently, even when the same password is used to encrypt *multiple* (possibly identical) messages. Therefore, a new *random* nonce **must** be chosen for each message! It is *not* necessary to keep the nonce confidential, but the same nonce **must** be used for both, encryption *and* decryption. Typically, the nonce is stored/transmitted alongside the ciphertext.
437     
438     *Note:* The `Encryptor` class automatically generates a new, random nonce for each message to be encrypted. Use `Encryptor::get_nonce()` to retrieve that nonce, so that it can be passed to `Decryptor` for decryption later.
439
440   * `thread_count`  
441     Specifies the number of worker threads to use (optional). By default, SlunkCrypt detects the number of available processors and creates one thread for each processor.
442
443 ***Exceptions:***
444
445   * Throws `std::runtime_error`, if the SlunkCrypt context could not be allocated.
446
447 #### Decryptor::process() [1]
448
449 Decrypt the next message chunk, using separate input/output buffers.
450
451     bool process(
452       const uint8_t *const input,
453       uint8_t *const output,
454       size_t length
455     );
456
457 ***Parameters:***
458
459  * `input`  
460     A pointer to the *input* buffer containing the next chunk of the ciphertext to be decrypted. The ciphertext is given as a byte array (`uint8_t`).
461     
462     The *input* buffer must contain *at least* `length` bytes of data. If the buffer is longer than `length` bytes, then only the first `length` bytes will be processed and the remainder is ignored!
463
464  * `output`  
465     A pointer to the *output* buffer where the plaintext chunk that corresponds to the given ciphertext chunk will be stored. The plaintext is stored as a byte array (`uint8_t`); it has the same length as the ciphertext data.
466     
467     The *output* buffer must provide sufficient space for storing *at least* `length` bytes of decrypted data. If the buffer is longer than `length` bytes, then only the first `length` bytes of the buffer will be filled with decrypted data!
468
469  * `length`  
470    The length of the ciphertext chunk contained in the *input* buffer given by the `input` parameter, in bytes. At the same time, this determines the minimum required size of the *output* buffer given by the `output` parameters, in bytes.
471
472    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
473
474 ***Return value:***
475
476   * If successful, `true` is returned; otherwise `false` is returned.
477
478 #### Decryptor::process() [2]
479
480 Decrypt the next message chunk, using separate input/output containers (`std::vector`).
481
482     bool process(
483       const std::vector<uint8_t> &input,
484       std::vector<uint8_t> &output
485     );
486
487 ***Parameters:***
488
489  * `input`  
490     A reference to the `std::vector<uint8_t>` instance containing the next chunk of the ciphertext to be decrypted.
491
492  * `output`  
493     A reference to the `std::vector<uint8_t>` instance where the plaintext that corresponds to the given ciphertext will be stored.
494     
495     The `output.size()` must be *greater than or equal* to `input.size()`. If the `output.size()` is greater than the `input.size()`, then only the first `input.size()` elements of `output` will be filled with decrypted data!
496
497 ***Return value:***
498
499   * If successful, `true` is returned; otherwise `false` is returned. The function fails, if the *output* `std::vector` is too small.
500
501 #### Decryptor::inplace() [1]
502
503 Decrypt the next message chunk, using a single buffer.
504
505     bool inplace(
506       uint8_t *const buffer,
507       size_t length
508     );
509
510 ***Parameters:***
511
512  * `buffer`  
513     A pointer to the buffer initially containing the next chunk of the ciphertext to be decrypted. The ciphertext is given as a byte array (`uint8_t`). The plaintext that corresponds to the given ciphertext will be stored to the *same* buffer, replacing the plaintext data.
514     
515     The buffer must initially contain *at least* `length` bytes of input data; the first `length` bytes of the buffer will be overwritten with the encrypted data. If the buffer is longer than `length` bytes, then only the first `length` bytes will be processed and overwritten.
516
517  * `length`  
518    The length of the ciphertext chunk initially contained in the input/output buffer given by the `buffer` parameter, in bytes. At the same time, this determines the portion of the input/output buffer that will be overwritten with decrypted data, in bytes.
519
520    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
521
522 ***Return value:***
523
524   * If successful, `true` is returned; otherwise `false` is returned.
525
526 #### Decryptor::inplace() [2]
527
528 Decrypt the next message chunk, using a single container (`std::vector`).
529
530     bool inplace(
531       std::vector<uint8_t> &buffer
532     );
533
534 ***Parameters:***
535
536  * `buffer`  
537     A reference to the `std::vector<uint8_t>` initially containing the next chunk of the ciphertext to be decrypted. The plaintext that corresponds to the given ciphertext will be stored to the *same* `std::vector<uint8_t>`, replacing all the ciphertext data.
538
539 ***Return value:***
540
541   * If successful, `true` is returned; otherwise `false` is returned.
542
543 C99 API
544 -------
545
546 This section describes the "low-level" C99 API of the SlunkCypt library.
547
548 ### Functions
549
550 The SlunkCypt library defines the following functions:
551
552 #### slunkcrypt_alloc()
553
554 Allocate and initialize a new SlunkCrypt encryption/decryption context.
555
556     slunkcrypt_t slunkcrypt_alloc(
557         const uint64_t nonce,
558         const uint8_t *const passwd,
559         const size_t passwd_len,
560         const int mode
561     );
562
563 ***Parameters:***
564
565   * `nonce`  
566     The *nonce* (number used once) to be used for the encryption/decryption process. The purpose of the nonce is to ensure that each message will be encrypted differently, even when the same password is used to encrypt *multiple* (possibly identical) messages. Therefore, a new *random* nonce **must** be chosen for each message to be encrypted! It is *not* necessary to keep the nonce confidential, but the same nonce **must** be used for both, encryption *and* decryption. Typically, the nonce is stored/transmitted alongside the ciphertext.
567     
568     *Note:* It is recommended to generate a random nonce via the [`slunkcrypt_generate_nonce()`](#slunkcrypt_generate_nonce) function for each message!
569   
570   * `passwd`  
571     The password to "protect" the message. The password is given as a byte array (`uint8_t`), e.g. UTF-8 encoded characters; a terminating NULL character is *not* required, as the length of the password is specified explicitly. The same password **may** be used to encrypt *multiple* messages. Also, the same password **must** be used for both, encryption *and* decryption; it will *only* be possible decrypt the ciphertext, if the "correct" password is known. The password must be kept confidential under all circumstances!
572     
573     *Note:* In order to thwart *brute force* attacks, it is recommended to choose a "random" password that is at least 12 characters in length and that consists of upper-case characters, lower-case characters, digits as well as other "special" characters.
574   
575   * `passwd_len`  
576     The length of password given by the `passwd` parameter, in bytes, **not** counting a terminating NULL character. The minimum/maximum length of the password are given by the `SLUNKCRYPT_PWDLEN_MIN` and `SLUNKCRYPT_PWDLEN_MAX` constants, respectively.
577
578   * `mode`  
579     The mode of operation. Use `SLUNKCRYPT_ENCRYPT` in order to set up this context for *encryption*, or use `SLUNKCRYPT_DECRYPT` in order to set up this context for *decryption*.
580
581 ***Return value:***
582
583   * If successful, a handle to the new SlunkCrypt context is return; otherwise `SLUNKCRYPT_NULL` is returned.
584     
585     *Note:* Applications **should** treat `slunkcrypt_t` as an *opaque* handle type. Also, as soon as the SlunkCrypt context is *not* needed anymore, the application **shall** call [`slunkcrypt_free()`](#slunkcrypt_free) in order to "erase" and de-allocate that context. If a SlunkCrypt context is *not* de-allocated properly, it will result in a memory leak!
586
587 #### slunkcrypt_alloc_ext()
588
589 Allocate and initialize a new SlunkCrypt encryption/decryption context with additional parameters.
590
591     slunkcrypt_t slunkcrypt_alloc_ext(
592         const uint64_t nonce,
593         const uint8_t *const passwd,
594         const size_t passwd_len,
595         const int mode,
596         const slunkparam_t *const param
597     );
598
599 ***Parameters:***
600
601   * `nonce`  
602     The *nonce* (number used once) to be used for the encryption/decryption process. The purpose of the nonce is to ensure that each message will be encrypted differently, even when the same password is used to encrypt *multiple* (possibly identical) messages. Therefore, a new *random* nonce **must** be chosen for each message to be encrypted! It is *not* necessary to keep the nonce confidential, but the same nonce **must** be used for both, encryption *and* decryption. Typically, the nonce is stored/transmitted alongside the ciphertext.
603     
604     *Note:* It is recommended to generate a random nonce via the [`slunkcrypt_generate_nonce()`](#slunkcrypt_generate_nonce) function for each message!
605   
606   * `passwd`  
607     The password to "protect" the message. The password is given as a byte array (`uint8_t`), e.g. UTF-8 encoded characters; a terminating NULL character is *not* required, as the length of the password is specified explicitly. The same password **may** be used to encrypt *multiple* messages. Also, the same password **must** be used for both, encryption *and* decryption; it will *only* be possible decrypt the ciphertext, if the "correct" password is known. The password must be kept confidential under all circumstances!
608     
609     *Note:* In order to thwart *brute force* attacks, it is recommended to choose a "random" password that is at least 12 characters in length and that consists of upper-case characters, lower-case characters, digits as well as other "special" characters.
610   
611   * `passwd_len`  
612     The length of password given by the `passwd` parameter, in bytes, **not** counting a terminating NULL character. The minimum/maximum length of the password are given by the `SLUNKCRYPT_PWDLEN_MIN` and `SLUNKCRYPT_PWDLEN_MAX` constants, respectively.
613
614   * `mode`  
615     The mode of operation. Use `SLUNKCRYPT_ENCRYPT` in order to set up this context for *encryption*, or use `SLUNKCRYPT_DECRYPT` in order to set up this context for *decryption*.
616
617   * `param`  
618     Additional parameters used to initialize the SlunkCrypt context, given as a pointer to a [`slunkparam_t`](#slunkcrypt-parameters) struct. The memory for the struct must be allocated by the caller and SlunkCrypt does **not** take owner ship of this memory; it will *copy* the relevant fields. The caller is responsible to free the struct; it can be allocated with automatic storage duration.
619
620 ***Return value:***
621
622   * If successful, a handle to the new SlunkCrypt context is return; otherwise `SLUNKCRYPT_NULL` is returned.
623     
624     *Note:* Applications **should** treat `slunkcrypt_t` as an *opaque* handle type. Also, as soon as the SlunkCrypt context is *not* needed anymore, the application **shall** call [`slunkcrypt_free()`](#slunkcrypt_free) in order to "erase" and de-allocate that context. If a SlunkCrypt context is *not* de-allocated properly, it will result in a memory leak!
625
626 #### slunkcrypt_reset()
627   
628 Re-initialize an existing SlunkCrypt encryption/decryption context.
629
630     int slunkcrypt_reset(
631         const slunkcrypt_t context,
632         const uint64_t nonce,
633         const uint8_t *const passwd,
634         const size_t passwd_len,
635         const int mode
636     );
637
638 ***Parameters:***
639
640   * `context`  
641     The existing SlunkCrypt context to be re-initialized. This must be a valid handle that was returned by a previous invocation of the [`slunkcrypt_alloc()`](#slunkcrypt_alloc) function.
642
643   * *other parameters*:  
644     Please refer to the [`slunkcrypt_alloc()`](#slunkcrypt_alloc) function for details!
645
646 ***Return value:***
647
648   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
649
650 #### slunkcrypt_free()
651
652 De-allocate an existing SlunkCrypt encryption/decryption context. This will "clear" and release any memory occupied by the context.
653
654     void slunkcrypt_free(
655         const slunkcrypt_t context
656     );
657
658 ***Parameters:***
659
660  * `context`  
661     The existing SlunkCrypt context to be de-allocated. This must be a valid handle that was returned by a previous invocation of the [`slunkcrypt_alloc()`](#slunkcrypt_alloc) function.
662     
663     *Note:* Once a handle has been passed to this function, that handle is *invalidated* and **must not** be used again!
664
665 #### slunkcrypt_generate_nonce()
666
667 Generate a new random *nonce* (number used once), using the system's "cryptographically secure" entropy source.
668
669     int slunkcrypt_generate_nonce(
670       int64_t *const nonce
671     );
672
673 ***Parameters:***
674
675  * `nonce`  
676    A pointer to a variable of type `int64_t` that receives the new random nonce.
677
678 ***Return value:***
679
680   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
681
682 #### slunkcrypt_process()
683
684 Encrypt or decrypt the next message chunk, using separate input/output buffers.
685
686     int slunkcrypt_process(
687         const slunkcrypt_t context,
688         const uint8_t *const input,
689         uint8_t *const output,
690         size_t length
691     );
692
693 ***Parameters:***
694
695  * `context`  
696     The existing SlunkCrypt context to be used for processing the message chunk. This context will be updated.
697
698     *Note:* This function operates either in "encryption" mode or in "decryption" mode, depending on how the given SlunkCrypt context has been [initialized](#slunkcrypt_alloc) or [re-initialized](#slunkcrypt_reset).
699
700  * `input`  
701     A pointer to the *input* buffer containing the next chunk of the plaintext to be encrypted (*encryption* mode), or the next chunk of the ciphertext to be decrypted (*decryption* mode). The input data is given as a byte array (`uint8_t`). This can be arbitrary binary data, e.g. UTF-8 encoded text. NULL bytes are **not** treated specially by this function.
702     
703     The *input* buffer must contain *at least* `length` bytes of data. If the buffer is longer than `length` bytes, then only the first `length` bytes will be processed; the remainder is ignored!
704
705  * `output`  
706     A pointer to the *output* buffer where the ciphertext that corresponds to the given plaintext chunk (*encryption* mode), or the plaintext that corresponds to the given ciphertext chunk (*decryption* mode) will be stored. The output data is stored as a byte array (`uint8_t`) and it always has the same length as the input data.
707     
708     The *output* buffer **must** provide sufficient space for storing *at least* `length` bytes. If the buffer is longer than `length` bytes, then only the first `length` bytes will be filled!
709
710  * `length`  
711    The length of the given plaintext chunk (*encryption* mode), or the length of the given ciphertext chunk (*decryption* mode) in the `input` buffer, in bytes. At the same time, this parameter determines the minimum required size of the `output` buffer, in bytes. If this parameter is set to *zero*, the function does nothing; this is *not* considered an error.
712
713    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
714
715 ***Return value:***
716
717   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
718
719 #### slunkcrypt_inplace()
720
721 Encrypt or decrypt the next message chunk, using a *single* input/output buffer.
722
723     int slunkcrypt_inplace(
724         const slunkcrypt_t context,
725         uint8_t *const buffer,
726         size_t length
727     );
728
729 ***Parameters:***
730
731  * `context`  
732     The existing SlunkCrypt context to be used for processing the message chunk. This context will be updated.
733
734     *Note:* This function operates either in "encryption" mode or in "decryption" mode, depending on how the given SlunkCrypt context has been [initialized](#slunkcrypt_alloc) or [re-initialized](#slunkcrypt_reset).
735
736  * `buffer`  
737     A pointer to the buffer containing the next chunk of the plaintext to be encrypted (*encryption* mode), or the next chunk of the ciphertext to be decrypted (*decryption* mode). The input data is given as a byte array (`uint8_t`). This can be arbitrary binary data, e.g. UTF-8 encoded text. NULL bytes are **not** treated specially by this function. The ciphertext that corresponds to the given plaintext chunk (*encryption* mode), or the plaintext that corresponds to the given ciphertext chunk (*decryption* mode) will be stored to the ***same*** buffer.
738     
739     The given buffer **must** initially contain *at least* `length` bytes of input data. The first `length` bytes in the buffer will be processed and will be *overwritten* with the corresponding output data. If the buffer is longer than `length` bytes, then only the first `length` bytes in the buffer will be processed; the remainder is ignored!
740
741  * `length`  
742    The length of the plaintext chunk (*encryption* mode), or the length of the ciphertext chunk (*decryption* mode) initially contained in the input/output buffer, in bytes.
743
744    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
745
746 ***Return value:***
747
748   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
749
750 #### slunkcrypt_random_bytes()
751
752 Generate a sequence of random bytes, using the system's "cryptographically secure" entropy source.
753
754     size_t slunkcrypt_random_bytes(
755       uint8_t *const buffer,
756       const size_t length
757     );
758
759 ***Parameters:***
760
761  * `buffer`  
762    A pointer to the *output* buffer where the random bytes will be stored.
763
764    The *output* buffer **must** provide sufficient space for storing *at least* `length` bytes of random data. *At most* the first `length` bytes of the buffer will be filled with random data!
765
766  * `length`  
767    The number of random bytes to be generated. At the same time, this parameter determines the minimum required size of the `output` buffer, in bytes.
768
769 ***Return value:***
770
771   * The number of random bytes that have been generated and that have been stored to the `output` buffer buffer is returned.
772     
773     The number of generated random bytes can be *at most* `length`. Less than `length` random bytes will be generated, if and only if the the system's "cryptographically secure" entropy source could *not* provide the requested number of bytes at this time &ndash; in that case, you can try again later. The number of generated bytes can be as low as **0**.
774
775
776 #### slunkcrypt_bzero()
777
778 Erase the contents of a byte array, by overwriting it with *zero* bytes. Compiler optimizations will **not** remove the erase operation.
779
780     void slunkcrypt_bzero(
781       void *const buffer,
782       const size_t length
783     );
784
785 ***Parameters:***
786
787  * `buffer`  
788    A pointer to the buffer whose content is to be erased.
789
790    The buffer **must** be *at least* `length` bytes in size. If the buffer is longer than `length` bytes, then *only* the first `length` bytes of the buffer will be erased!
791
792  * `length`  
793    The size of the buffer to be erased, in bytes.
794
795 ### Types
796
797 #### SlunkCrypt parameters
798
799 The `slunkparam_t` struct is used to pass additional parameters that will be used for initializing the SlunkCrypt context. It contains the following fields:
800
801 * `version` &ndash; The version of the parameter struct; **must** be set to *`SLUNKCRYPT_PARAM_VERSION`*.
802 * `thread_count` &ndash; The number of worker threads to use. If this parameter is set to **0**, which is the *default* value, then SlunkCrypt automatically detects the number of available (logical) processors and creates one thread for each processor. Also, the number of threads is capped to a maximum of `MAX_THREADS` (currently defined as **16**).
803
804 ### Global variables
805
806 The SlunkCypt library defines the following global variables:
807
808 #### Version information
809
810 These variables can be used to determine the version of the SlunkCrypt library at runtime, using the [semantic versioning](https://semver.org/spec/v2.0.0.html) scheme:
811
812 * `const uint16_t SLUNKCRYPT_VERSION_MAJOR` &ndash; The current *major* version.
813 * `const uint16_t SLUNKCRYPT_VERSION_MINOR` &ndash; The current *minor* version.
814 * `const uint16_t SLUNKCRYPT_VERSION_PATCH` &ndash; The current *patch* version.
815 * `const char *SLUNKCRYPT_BUILD` &ndash; The build date and time, as a C string, in the *`"mmm dd yyyy, hh:mm:ss"`* format.
816
817 #### Abort request
818
819 If this flag is set to a non-zero value by the application, any ongoing SlunkCypt library invocation will be aborted as quickly as possible:
820
821 * `volatile int g_slunkcrypt_abort_flag` &ndash; The global abort flag.
822
823   *Note:* Applications may set this flag in their signal handler, e.g. when a `SIGINT` is received, in order to "gracefully" shut down the SlunkCypt library. All long-running library functions will return `SLUNKCRYPT_ABORTED`, if the invocation was interrupted. The application still is responsible for [free](#slunkcrypt_free)'ing any SlunkCypt contexts that it allocated successfully!
824
825 ### Constants
826
827 The SlunkCypt library defines the following constants:
828
829 #### Mode of operation
830
831 The SlunkCypt library supports the following modes of operation:
832
833 * `SLUNKCRYPT_ENCRYPT` &ndash; Run library in *encryption* mode, i.e. consume plaintext and produce ciphertext.
834 * `SLUNKCRYPT_DECRYPT` &ndash; Run library in *decryption* mode, i.e. consume ciphertext and produce plaintext.
835
836 #### Limits
837
838 The following limits are defined for the SlunkCypt library:
839
840 * `SLUNKCRYPT_PWDLEN_MIN` &ndash; The *minimum* required length of a password, currently **8** bytes.
841 * `SLUNKCRYPT_PWDLEN_MAX` &ndash; The *maximum* allowed length of a password, currently **256** bytes.
842
843 #### Error codes
844
845 SlunkCypt library functions that return an error code may return one of the following constants:
846
847 * `SLUNKCRYPT_SUCCESS` &ndash; The operation completed successfully.
848 * `SLUNKCRYPT_FAILURE` &ndash; The operation has failed.
849 * `SLUNKCRYPT_ABORTED` &ndash; The operation was aborted before completion, as requested by the application.
850
851 Thread safety
852 -------------
853
854 The following functions are fully "thread-safe" and thus may safely be called by *any* thread at *any* time ***without*** the need for synchronization:
855
856 * `slunkcrypt_alloc()`
857 * `slunkcrypt_generate_nonce()`
858 * `slunkcrypt_random_bytes()`
859 * `slunkcrypt_bzero()`
860 * `Encryptor::Encryptor()`
861 * `Decryptor::Decryptor()`
862
863 The following functions are "reentrant" and thus may safely be called by *any* thread at *any* time ***without*** the need for synchronization &ndash; provided that each instance of `slunkcrypt_t`, `Encryptor` or `Decryptor` is "owned" by a *single* thread **and** that each instance will *exclusively* be access by its respective "owner" thread:
864
865 * `slunkcrypt_reset()`
866 * `slunkcrypt_free()`
867 * `slunkcrypt_process()`
868 * `slunkcrypt_inplace()`
869 * `Encryptor::process()`
870 * `Encryptor::inplace()`
871 * `Encryptor::get_nonce()`
872 * `Decryptor::process()`
873 * `Decryptor::inplace()`
874
875 ***Note:*** If the same `slunkcrypt_t`, `Encryptor` or `Decryptor` instance needs to be shared across *multiple* threads (i.e. the same instance is accessed by *concurrent* threads), then the application **must** *serialize* any invocation of the above functions on that shared instance, by using a suitable synchronization mechanism! This can be achieved by using a [*mutex*](https://linux.die.net/man/3/pthread_mutex_lock).
876
877
878 License
879 =======
880
881 This work has been released under the **CC0 1.0 Universal** license.
882
883 For details, please refer to:  
884 <https://creativecommons.org/publicdomain/zero/1.0/legalcode>
885
886 Acknowledgement
887 ---------------
888
889 SlunkCrypt incorporates code from the following *third-party* software projects:
890
891 * The "checksum" algorithm used by the SlunkCrypt command-line application was adapted from the **BLAKE2** reference C implementation.  
892   ```
893    BLAKE2 reference source code package - reference C implementations
894    Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
895    terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
896    your option.  The terms of these licenses can be found at:
897    - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
898    - OpenSSL license   : https://www.openssl.org/source/license.html
899    - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
900
901    More information about the BLAKE2 hash function can be found at
902    https://blake2.net.
903    ```
904
905 * ***Windows only:*** Builds of SlunkCypt that have multi-threading enabled use the **POSIX Threads for Windows (pthreads4w)** library.  
906   ```
907   Pthreads4w - POSIX Threads for Windows
908   Copyright 1998 John E. Bossom
909   Copyright 1999-2018, Pthreads4w contributors
910
911   Homepage: https://sourceforge.net/projects/pthreads4w/
912  
913   Licensed under the Apache License, Version 2.0 (the "License");
914   you may not use this file except in compliance with the License.
915   You may obtain a copy of the License at
916
917       http://www.apache.org/licenses/LICENSE-2.0
918
919   Unless required by applicable law or agreed to in writing, software
920   distributed under the License is distributed on an "AS IS" BASIS,
921   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
922   See the License for the specific language governing permissions and
923   limitations under the License.
924   ```
925
926
927 &marker;