OSDN Git Service

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