OSDN Git Service

Small code clean-up + improved the Makefile + detect GNU/Hurd operating system.
[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 * **GNU/Hurd** (tested on Debian GNU/Hurd 0.9) — 32-Bit (i686)
30 * **Mac OS X** (tested on macOS 11 “Big Sur”) — Intel x86-64 (AMD64) and Apple Silicon (AArch64)
31
32 The SlunkCrypt GUI application currently runs on the following platforms:
33
34 * **Microsoft Windows** with .NET Framework 4.5 — can be installed on Windows Vista, or later
35
36
37 GUI Usage
38 =========
39
40 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):
41
42 ![](etc/img/SlunkCrypt-GUI.jpg)
43
44 Prerequisites
45 -------------
46
47 Please be sure to install the **.NET Framework 4.5**, or any later *.NET Framework 4.x* version, before running the SlunkCrypt GUI application:  
48 <https://dotnet.microsoft.com/download/dotnet-framework>
49
50 ***Note:*** If you are running Windows 8 or later, then almost certainly a suitable version of the .NET Framework is already installed &#128526;
51
52 Settings
53 --------
54
55 The following settings can be adjusted in the `slunkcrypt-gui.exe.config` configuration file:
56
57 - **`DisableBusyIndicator`:**  
58   If set to `true`, the “busy indicator” animation will be *disabled* on application startup &mdash; default value: `false`.
59
60 - **`ThreadCount`:**  
61   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).
62
63 - **`KeepIncompleteFiles`:**  
64   If set to `true`, incomplete or corrupted output files will *not* be deleted &mdash; default value: `false`.
65
66 Command-line Usage
67 ==================
68
69 This section describes the SlunkCypt command-line application.
70
71 Synopsis
72 --------
73
74 The SlunkCypt command-line program is invoked as follows:
75
76     slunkcrypt --encrypt [pass:<pass>|file:<file>] <input.txt> <output.enc>
77     slunkcrypt --decrypt [pass:<pass>|file:<file>] <input.enc> <output.txt>
78     slunkcrypt --make-pw [<length>]
79
80 Commands
81 --------
82
83 One of the following commands **must** be chosen:
84
85 - **`--encrypt` (`-e`):**  
86   Run application in ***encrypt*** mode. Reads the given *plaintext* and generates *ciphertext*.
87 - **`--decrypt` (`-d`):**  
88   Run application in ***decrypt*** mode. Reads the given *ciphertext* and restores *plaintext*.
89 - **`--make-pw` (`-p`):**  
90   Generate a "strong" random passphrase, suitable for use with SlunkCrypt.
91 - **`--self-test` (`-t`):**  
92   Run the application in ***self-test*** mode. Program will exit after all test are completed.
93
94 Options
95 -------
96
97 The following command-line options are available:
98
99 - **`pass:<pass>`**:  
100   * Specifies the "secret" passphrase directly on the command-line. This is considered *insecure*.
101 - **`file:<file>`**:  
102   * Specifies a file to read the passphrase from. Only the *first* line of the file will be read!
103   * *Note:* It is also possible to specify **`-`** in order to read the passphrase from the *stdin*.
104 - **`<input>`**:  
105   * In ***encrypt*** mode &ndash; specifies the *plaintext* file (unencrypted information) that is to be encrypted.
106   * In ***decrypt*** mode &ndash; specifies the *ciphertext* file (result of encryption) that is to be decrypted.
107 - **`<output>`**:  
108   * In ***encrypt*** mode &ndash; specifies the file where the *ciphertext* (result of encryption) will be stored.
109   * In ***decrypt*** mode &ndash; specifies the file where the *plaintext* (unencrypted information) will be stored.
110 - **`<length>`**:  
111   * Specifies the length of the passphrase to be generated. If *not* specified, defaults to 24.
112
113 ### Remarks {.unlisted}
114
115 - 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.
116
117 - Passing the passphrase directly on the command-line is insecure, because the full command-line may be visible to other users!
118
119 Environment
120 -----------
121
122 The following environment variables may be used:
123
124 - **`SLUNK_PASSPHRASE`**:  
125   Specifies the "secret" passphrase. This environment variables is only evaluated, if the passphrase was **not** specified on the command-line.  
126   Passing the passphrase via environment variable is considered more secure, because environment variables are not normally visible to other (unprivileged) users.
127
128 - **`SLUNK_KEEP_INCOMPLETE`**:  
129   If set to a *non-zero* value, incomplete or corrupted output files will **not** be deleted automatically. By default, the files will be deleted.
130
131 - **`SLUNK_THREADS`**:  
132   Specifies the number of worker threads to use. By default, SlunkCrypt detects the number of available processors and creates one thread for each processor.
133
134 Examples
135 --------
136
137 Here are some examples on how to use the SlunkCrypt command-line application:
138
139 ### Example #1 {.unlisted}
140
141 1. Let's generate a new random (secure) password first:
142
143        slunkcrypt --make-pw
144
145    *Example output:*
146
147        cdG2=fh<C=3[SSCzf[)iDjIV
148
149 2. Now, encrypt the plaintext message, using the generated password:
150
151        slunkcrypt --encrypt pass:"cdG2=fh<C=3[SSCzf[)iDjIV" plaintext.txt ciphertext.enc
152
153    Optionally, let's have a look at the ciphertext:
154
155        hexdump -C ciphertext.enc
156
157 3. Finally, decrypt the ciphertext, using the same password as before:
158
159        slunkcrypt --decrypt pass:"cdG2=fh<C=3[SSCzf[)iDjIV" ciphertext.enc plaintext.out
160
161    Optionally, verify that the decrypted file is identical to the original:
162
163        sha256sum -b plaintext.txt plaintext.out
164
165 ### Example #2 {.unlisted}
166
167 1. Generate a new password and store it to a text file:
168
169        slunkcrypt --make-pw > passwd.txt
170
171    Optionally, output the generated password to the terminal:
172
173        cat passwd.txt
174
175 2. Encrypt file by reading the password from the text file:
176
177        slunkcrypt --encrypt file:passwd.txt plaintext.txt ciphertext.enc
178
179 ### Example #3 {.unlisted}
180
181 1. Generate a new password directly to an environment variable:
182
183        MY_PASSWD="$(slunkcrypt --make-pw)"
184
185    Optionally, output the generated password to the terminal:
186
187        echo "${MY_PASSWD}"
188
189 2. Encrypt file by reading the password from the *stdin*:
190
191        slunkcrypt --encrypt - plaintext.txt ciphertext.enc <<< "${MY_PASSWD}"
192
193
194 Encryption algorithm
195 ====================
196
197 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):
198
199 - 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.
200
201 - 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.
202
203 - 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.
204
205 - 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.
206
207 - 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).
208
209
210 Programming Interface (API)
211 ===========================
212
213 This section describes the SlunkCypt library interface for software developers.
214
215 Getting started
216 ---------------
217
218 In order to use the SlunkCypt library in your C++ code, include **`<slunkcrypt.hpp>`** header and instantiate the appropriate SlunkCypt classes:
219
220 ### Example #1 {.unlisted}
221
222 Here is a simple example on how to use the SlunkCrypt [**`Encryptor`**](#encryptor) class:
223
224     #include <slunkcrypt.hpp>
225     #include <fstream>
226     #include <iostream>
227
228     int main()
229     {
230         /* Open input and output files here */
231         uint8_t buffer[BUFF_SIZE];
232         slunkcrypt::Encryptor slunk_encrypt(passphrase);
233         while (input.good())
234         {
235             input.read(reinterpret_cast<char*>(buffer), BUFF_SIZE);
236             if ((!input.bad()) && (input.gcount() > 0))
237             {
238                 if (!slunk_encrypt.inplace(buffer, (size_t)input.gcount()))
239                 {
240                     /* Implement error handling here */
241                 }
242                 output.write(reinterpret_cast<char*>(buffer), count);
243             }
244         }
245         std::cout << std::hex << slunk_encrypt.get_nonce() << std::endl;
246     }
247
248 ### Example #2 {.unlisted}
249
250 Here is a simple example on how to use the SlunkCrypt [**`Decryptor`**](#decryptor) class:
251
252     #include <slunkcrypt.hpp>
253     #include <fstream>
254     #include <iostream>
255
256     int main()
257     {
258         /* Open input and output files here */
259         uint8_t buffer[BUFF_SIZE];
260         slunkcrypt::Decryptor slunk_decrypt(passphrase, nonce);
261         while (input.good())
262         {
263             input.read(reinterpret_cast<char*>(buffer), BUFF_SIZE);
264             if ((!input.bad()) && (input.gcount() > 0))
265             {
266                 if (!slunk_decrypt.inplace(buffer, (size_t)input.gcount()))
267                 {
268                     /* Implement error handling here */
269                 }
270                 output.write(reinterpret_cast<char*>(buffer), count);
271             }
272         }
273     }
274
275 C++11 API
276 ---------
277
278 This section describes the "high-level" C++11 API of the SlunkCrypt library. All SlunkCrypt classes live in the **`slunkcrypt`** namespace.
279
280 ### Encryptor
281
282 Class for *encrypting* data using the SlunkCrypt library.
283
284 #### Constructor
285
286 Create and initialize a new **``Encryptor``** instance. Also generated a new, random nonce.
287
288     Encryptor::Encryptor(
289       const std::string &passwd,
290       const size_t thread_count = 0U
291     );
292
293 ***Parameters:***
294
295   * `passwd`  
296     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!
297      
298     *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.
299
300   * `thread_count`  
301     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.
302
303 ***Exceptions:***
304
305   * Throws `std::runtime_error`, if the nonce could not be generated, or if the SlunkCrypt context could not be allocated.
306
307 #### Encryptor::process() [1]
308
309 Encrypt the next message chunk, using separate input/output buffers.
310
311     bool process(
312       const uint8_t *const input,
313       uint8_t *const output,
314       size_t length
315     );
316
317 ***Parameters:***
318
319  * `input`  
320     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.
321     
322     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!
323
324  * `output`  
325     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.
326     
327     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!
328
329  * `length`  
330    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.
331
332    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
333
334 ***Return value:***
335
336   * If successful, `true` is returned; otherwise `false` is returned.
337
338 #### Encryptor::process() [2]
339
340 Encrypt the next message chunk, using separate input/output containers (`std::vector`).
341
342     bool process(
343       const std::vector<uint8_t> &input,
344       std::vector<uint8_t> &output
345     );
346
347 ***Parameters:***
348
349  * `input`  
350     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.
351
352  * `output`  
353     A reference to the `std::vector<uint8_t>` instance where the ciphertext that corresponds to the given plaintext will be stored.
354     
355     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!
356
357 ***Return value:***
358
359   * If successful, `true` is returned; otherwise `false` is returned. The function fails, if the *output* `std::vector` is too small.
360
361 #### Encryptor::inplace() [1]
362
363 Encrypt the next message chunk, using a single buffer.
364
365     bool inplace(
366       uint8_t *const buffer,
367       size_t length
368     );
369
370 ***Parameters:***
371
372  * `buffer`  
373     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.
374     
375     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.
376
377  * `length`  
378    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.
379
380    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
381
382 ***Return value:***
383
384   * If successful, `true` is returned; otherwise `false` is returned.
385
386 #### Encryptor::inplace() [2]
387
388 Encrypt the next message chunk, using a single container (`std::vector`).
389
390     bool inplace(
391       std::vector<uint8_t> &buffer
392     );
393
394 ***Parameters:***
395
396  * `buffer`  
397     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.
398
399 ***Return value:***
400
401   * If successful, `true` is returned; otherwise `false` is returned.
402
403 #### Encryptor::get_nonce()
404
405 Retrieve the random nonce that is used to encrypt the message.
406
407     uint64_t get_nonce();
408
409 ***Return value:***
410
411   * 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.
412     
413     *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.
414
415 ### Decryptor
416
417 Class for *decrypting* data using the SlunkCrypt library.
418
419 #### Constructor
420
421 Create and initialize a new **``Decryptor``** instance.
422
423     Decryptor::Decryptor(
424       const std::string &passwd,
425       const uint64_t nonce,
426       const size_t thread_count = 0U
427     );
428
429 ***Parameters:***
430
431   * `passwd`  
432     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!
433     
434     *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.
435
436   * `nonce`  
437     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.
438     
439     *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.
440
441   * `thread_count`  
442     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.
443
444 ***Exceptions:***
445
446   * Throws `std::runtime_error`, if the SlunkCrypt context could not be allocated.
447
448 #### Decryptor::process() [1]
449
450 Decrypt the next message chunk, using separate input/output buffers.
451
452     bool process(
453       const uint8_t *const input,
454       uint8_t *const output,
455       size_t length
456     );
457
458 ***Parameters:***
459
460  * `input`  
461     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`).
462     
463     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!
464
465  * `output`  
466     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.
467     
468     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!
469
470  * `length`  
471    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.
472
473    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
474
475 ***Return value:***
476
477   * If successful, `true` is returned; otherwise `false` is returned.
478
479 #### Decryptor::process() [2]
480
481 Decrypt the next message chunk, using separate input/output containers (`std::vector`).
482
483     bool process(
484       const std::vector<uint8_t> &input,
485       std::vector<uint8_t> &output
486     );
487
488 ***Parameters:***
489
490  * `input`  
491     A reference to the `std::vector<uint8_t>` instance containing the next chunk of the ciphertext to be decrypted.
492
493  * `output`  
494     A reference to the `std::vector<uint8_t>` instance where the plaintext that corresponds to the given ciphertext will be stored.
495     
496     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!
497
498 ***Return value:***
499
500   * If successful, `true` is returned; otherwise `false` is returned. The function fails, if the *output* `std::vector` is too small.
501
502 #### Decryptor::inplace() [1]
503
504 Decrypt the next message chunk, using a single buffer.
505
506     bool inplace(
507       uint8_t *const buffer,
508       size_t length
509     );
510
511 ***Parameters:***
512
513  * `buffer`  
514     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.
515     
516     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.
517
518  * `length`  
519    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.
520
521    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
522
523 ***Return value:***
524
525   * If successful, `true` is returned; otherwise `false` is returned.
526
527 #### Decryptor::inplace() [2]
528
529 Decrypt the next message chunk, using a single container (`std::vector`).
530
531     bool inplace(
532       std::vector<uint8_t> &buffer
533     );
534
535 ***Parameters:***
536
537  * `buffer`  
538     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.
539
540 ***Return value:***
541
542   * If successful, `true` is returned; otherwise `false` is returned.
543
544 C99 API
545 -------
546
547 This section describes the "low-level" C99 API of the SlunkCypt library.
548
549 ### Functions
550
551 The SlunkCypt library defines the following functions:
552
553 #### slunkcrypt_alloc()
554
555 Allocate and initialize a new SlunkCrypt encryption/decryption context.
556
557     slunkcrypt_t slunkcrypt_alloc(
558         const uint64_t nonce,
559         const uint8_t *const passwd,
560         const size_t passwd_len,
561         const int mode
562     );
563
564 ***Parameters:***
565
566   * `nonce`  
567     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.
568     
569     *Note:* It is recommended to generate a random nonce via the [`slunkcrypt_generate_nonce()`](#slunkcrypt_generate_nonce) function for each message!
570   
571   * `passwd`  
572     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!
573     
574     *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.
575   
576   * `passwd_len`  
577     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.
578
579   * `mode`  
580     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*.
581
582 ***Return value:***
583
584   * If successful, a handle to the new SlunkCrypt context is return; otherwise `SLUNKCRYPT_NULL` is returned.
585     
586     *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!
587
588 #### slunkcrypt_alloc_ext()
589
590 Allocate and initialize a new SlunkCrypt encryption/decryption context with additional parameters.
591
592     slunkcrypt_t slunkcrypt_alloc_ext(
593         const uint64_t nonce,
594         const uint8_t *const passwd,
595         const size_t passwd_len,
596         const int mode,
597         const slunkparam_t *const param
598     );
599
600 ***Parameters:***
601
602   * `nonce`  
603     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.
604     
605     *Note:* It is recommended to generate a random nonce via the [`slunkcrypt_generate_nonce()`](#slunkcrypt_generate_nonce) function for each message!
606   
607   * `passwd`  
608     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!
609     
610     *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.
611   
612   * `passwd_len`  
613     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.
614
615   * `mode`  
616     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*.
617
618   * `param`  
619     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.
620
621 ***Return value:***
622
623   * If successful, a handle to the new SlunkCrypt context is return; otherwise `SLUNKCRYPT_NULL` is returned.
624     
625     *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!
626
627 #### slunkcrypt_reset()
628   
629 Re-initialize an existing SlunkCrypt encryption/decryption context.
630
631     int slunkcrypt_reset(
632         const slunkcrypt_t context,
633         const uint64_t nonce,
634         const uint8_t *const passwd,
635         const size_t passwd_len,
636         const int mode
637     );
638
639 ***Parameters:***
640
641   * `context`  
642     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.
643
644   * *other parameters*:  
645     Please refer to the [`slunkcrypt_alloc()`](#slunkcrypt_alloc) function for details!
646
647 ***Return value:***
648
649   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
650
651 #### slunkcrypt_free()
652
653 De-allocate an existing SlunkCrypt encryption/decryption context. This will "clear" and release any memory occupied by the context.
654
655     void slunkcrypt_free(
656         const slunkcrypt_t context
657     );
658
659 ***Parameters:***
660
661  * `context`  
662     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.
663     
664     *Note:* Once a handle has been passed to this function, that handle is *invalidated* and **must not** be used again!
665
666 #### slunkcrypt_generate_nonce()
667
668 Generate a new random *nonce* (number used once), using the system's "cryptographically secure" entropy source.
669
670     int slunkcrypt_generate_nonce(
671       int64_t *const nonce
672     );
673
674 ***Parameters:***
675
676  * `nonce`  
677    A pointer to a variable of type `int64_t` that receives the new random nonce.
678
679 ***Return value:***
680
681   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
682
683 #### slunkcrypt_process()
684
685 Encrypt or decrypt the next message chunk, using separate input/output buffers.
686
687     int slunkcrypt_process(
688         const slunkcrypt_t context,
689         const uint8_t *const input,
690         uint8_t *const output,
691         size_t length
692     );
693
694 ***Parameters:***
695
696  * `context`  
697     The existing SlunkCrypt context to be used for processing the message chunk. This context will be updated.
698
699     *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).
700
701  * `input`  
702     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.
703     
704     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!
705
706  * `output`  
707     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.
708     
709     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!
710
711  * `length`  
712    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.
713
714    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
715
716 ***Return value:***
717
718   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
719
720 #### slunkcrypt_inplace()
721
722 Encrypt or decrypt the next message chunk, using a *single* input/output buffer.
723
724     int slunkcrypt_inplace(
725         const slunkcrypt_t context,
726         uint8_t *const buffer,
727         size_t length
728     );
729
730 ***Parameters:***
731
732  * `context`  
733     The existing SlunkCrypt context to be used for processing the message chunk. This context will be updated.
734
735     *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).
736
737  * `buffer`  
738     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.
739     
740     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!
741
742  * `length`  
743    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.
744
745    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
746
747 ***Return value:***
748
749   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
750
751 #### slunkcrypt_random_bytes()
752
753 Generate a sequence of random bytes, using the system's "cryptographically secure" entropy source.
754
755     size_t slunkcrypt_random_bytes(
756       uint8_t *const buffer,
757       const size_t length
758     );
759
760 ***Parameters:***
761
762  * `buffer`  
763    A pointer to the *output* buffer where the random bytes will be stored.
764
765    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!
766
767  * `length`  
768    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.
769
770 ***Return value:***
771
772   * The number of random bytes that have been generated and that have been stored to the `output` buffer buffer is returned.
773     
774     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**.
775
776
777 #### slunkcrypt_bzero()
778
779 Erase the contents of a byte array, by overwriting it with *zero* bytes. Compiler optimizations will **not** remove the erase operation.
780
781     void slunkcrypt_bzero(
782       void *const buffer,
783       const size_t length
784     );
785
786 ***Parameters:***
787
788  * `buffer`  
789    A pointer to the buffer whose content is to be erased.
790
791    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!
792
793  * `length`  
794    The size of the buffer to be erased, in bytes.
795
796 ### Types
797
798 #### SlunkCrypt parameters
799
800 The `slunkparam_t` struct is used to pass additional parameters that will be used for initializing the SlunkCrypt context. It contains the following fields:
801
802 * `version` &ndash; The version of the parameter struct; **must** be set to *`SLUNKCRYPT_PARAM_VERSION`*.
803 * `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**).
804
805 ### Global variables
806
807 The SlunkCypt library defines the following global variables:
808
809 #### Version information
810
811 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:
812
813 * `const uint16_t SLUNKCRYPT_VERSION_MAJOR` &ndash; The current *major* version.
814 * `const uint16_t SLUNKCRYPT_VERSION_MINOR` &ndash; The current *minor* version.
815 * `const uint16_t SLUNKCRYPT_VERSION_PATCH` &ndash; The current *patch* version.
816 * `const char *SLUNKCRYPT_BUILD` &ndash; The build date and time, as a C string, in the *`"mmm dd yyyy, hh:mm:ss"`* format.
817
818 #### Abort request
819
820 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:
821
822 * `volatile int g_slunkcrypt_abort_flag` &ndash; The global abort flag.
823
824   *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!
825
826 ### Constants
827
828 The SlunkCypt library defines the following constants:
829
830 #### Mode of operation
831
832 The SlunkCypt library supports the following modes of operation:
833
834 * `SLUNKCRYPT_ENCRYPT` &ndash; Run library in *encryption* mode, i.e. consume plaintext and produce ciphertext.
835 * `SLUNKCRYPT_DECRYPT` &ndash; Run library in *decryption* mode, i.e. consume ciphertext and produce plaintext.
836
837 #### Limits
838
839 The following limits are defined for the SlunkCypt library:
840
841 * `SLUNKCRYPT_PWDLEN_MIN` &ndash; The *minimum* required length of a password, currently **8** bytes.
842 * `SLUNKCRYPT_PWDLEN_MAX` &ndash; The *maximum* allowed length of a password, currently **256** bytes.
843
844 #### Error codes
845
846 SlunkCypt library functions that return an error code may return one of the following constants:
847
848 * `SLUNKCRYPT_SUCCESS` &ndash; The operation completed successfully.
849 * `SLUNKCRYPT_FAILURE` &ndash; The operation has failed.
850 * `SLUNKCRYPT_ABORTED` &ndash; The operation was aborted before completion, as requested by the application.
851
852 Thread safety
853 -------------
854
855 The following functions are fully "thread-safe" and thus may safely be called by *any* thread at *any* time ***without*** the need for synchronization:
856
857 * `slunkcrypt_alloc()`
858 * `slunkcrypt_generate_nonce()`
859 * `slunkcrypt_random_bytes()`
860 * `slunkcrypt_bzero()`
861 * `Encryptor::Encryptor()`
862 * `Decryptor::Decryptor()`
863
864 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:
865
866 * `slunkcrypt_reset()`
867 * `slunkcrypt_free()`
868 * `slunkcrypt_process()`
869 * `slunkcrypt_inplace()`
870 * `Encryptor::process()`
871 * `Encryptor::inplace()`
872 * `Encryptor::get_nonce()`
873 * `Decryptor::process()`
874 * `Decryptor::inplace()`
875
876 ***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).
877
878
879 License
880 =======
881
882 This work has been released under the **CC0 1.0 Universal** license.
883
884 For details, please refer to:  
885 <https://creativecommons.org/publicdomain/zero/1.0/legalcode>
886
887 Acknowledgement
888 ---------------
889
890 SlunkCrypt incorporates code from the following *third-party* software projects:
891
892 * The "checksum" algorithm used by the SlunkCrypt command-line application was adapted from the **BLAKE2** reference C implementation.  
893   ```
894    BLAKE2 reference source code package - reference C implementations
895    Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
896    terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
897    your option.  The terms of these licenses can be found at:
898    - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
899    - OpenSSL license   : https://www.openssl.org/source/license.html
900    - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
901
902    More information about the BLAKE2 hash function can be found at
903    https://blake2.net.
904    ```
905
906 * ***Windows only:*** Builds of SlunkCypt that have multi-threading enabled use the **POSIX Threads for Windows (pthreads4w)** library.  
907   ```
908   Pthreads4w - POSIX Threads for Windows
909   Copyright 1998 John E. Bossom
910   Copyright 1999-2018, Pthreads4w contributors
911
912   Homepage: https://sourceforge.net/projects/pthreads4w/
913  
914   Licensed under the Apache License, Version 2.0 (the "License");
915   you may not use this file except in compliance with the License.
916   You may obtain a copy of the License at
917
918       http://www.apache.org/licenses/LICENSE-2.0
919
920   Unless required by applicable law or agreed to in writing, software
921   distributed under the License is distributed on an "AS IS" BASIS,
922   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
923   See the License for the specific language governing permissions and
924   limitations under the License.
925   ```
926
927
928 &marker;