OSDN Git Service

Added language bindings for Java.
[slunkcrypt/SlunkCrypt.git] / README.md
1 % ![SlunkCrypt](etc/img/SlunkCrypt-Logo.png)
2
3 Introduction
4 ============
5
6 SlunkCrypt is an experimental cross-platform cryptography library and command-line tool. A fully-featured GUI is provided for the Windows platform.
7
8 Please refer to the section [*encryption algorithm*](#encryption-algorithm) for more details!
9
10 For news and updates, please check out the official SlunkCrypt project web-site at: <https://lord_mulder.gitlab.io/slunkcrypt/>
11
12
13 Legal Warning
14 =============
15
16 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.
17
18
19 System Requirements
20 ===================
21
22 The SlunkCrypt library and the command-line application currently run on the following platforms:
23
24 * **Microsoft Windows** (Windows XP SP-3, or later) &mdash; i686, x86-64 and ARM64
25 * **Linux** (kernel version 3.17, or later) &mdash; i686, x86-64, ARM64 and MIPS
26 * **Various BSD flavors** (tested on NetBSD 9.2, FreeBSD 13.0 and OpenBSD 7.0) &mdash; i686 and x86-64
27 * **Solaris** (tested on Solaris 11.4 and OmniOS/illumos) &mdash; i686 and x86-64
28 * **GNU/Hurd** (tested on Debian GNU/Hurd 0.9) &mdash; i686
29 * **Haiku** (tested on Haiku R1/b3) &mdash; i686 and x86-64
30 * **Mac OS X** (tested on “Big Sur”) &mdash; x86-64 and ARM64
31
32 The SlunkCrypt GUI application currently runs on the following platforms:
33
34 * **Microsoft Windows** with .NET Framework 4.7.2 &mdash; can be installed on Windows 7 SP1, 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.7.2**, or any later *.NET Framework 4.x* version, before running the SlunkCrypt **Windows GUI** application:  
48 <https://dotnet.microsoft.com/download/dotnet-framework>
49
50 ***Note:*** If you are running Windows 8.1 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 - **`LegacyCompat`:**  
67   If set to `1`, show options to enable “legacy” compatibility-mode in the GUI; if set to `2`, select “legacy” compatibility-mode by default &mdash; default value: `0`.
68
69 Command-line Usage
70 ==================
71
72 This section describes the SlunkCypt command-line application.
73
74 Synopsis
75 --------
76
77 The SlunkCypt command-line program is invoked as follows:
78
79     slunkcrypt --encrypt [pass:<pass>|file:<file>] <input.txt> <output.enc>
80     slunkcrypt --decrypt [pass:<pass>|file:<file>] <input.enc> <output.txt>
81     slunkcrypt --make-pw [<length>]
82
83 Commands
84 --------
85
86 One of the following commands **must** be chosen:
87
88 - **`--encrypt` (`-e`):**  
89   Run application in ***encrypt*** mode. Reads the given *plaintext* and generates *ciphertext*.
90 - **`--decrypt` (`-d`):**  
91   Run application in ***decrypt*** mode. Reads the given *ciphertext* and restores *plaintext*.
92 - **`--make-pw` (`-p`):**  
93   Generate a "strong" random passphrase, suitable for use with SlunkCrypt.
94 - **`--self-test` (`-t`):**  
95   Run the application in ***self-test*** mode. Program will exit after all test are completed.
96
97 Options
98 -------
99
100 The following command-line options are available:
101
102 - **`pass:<pass>`**:  
103   * Specifies the "secret" passphrase directly on the command-line. This is considered *insecure*.
104 - **`file:<file>`**:  
105   * Specifies a file to read the passphrase from. Only the *first* line of the file will be read!
106   * *Note:* It is also possible to specify **`-`** in order to read the passphrase from the *stdin*.
107 - **`<input>`**:  
108   * In ***encrypt*** mode &ndash; specifies the *plaintext* file (unencrypted information) that is to be encrypted.
109   * In ***decrypt*** mode &ndash; specifies the *ciphertext* file (result of encryption) that is to be decrypted.
110 - **`<output>`**:  
111   * In ***encrypt*** mode &ndash; specifies the file where the *ciphertext* (result of encryption) will be stored.
112   * In ***decrypt*** mode &ndash; specifies the file where the *plaintext* (unencrypted information) will be stored.
113 - **`<length>`**:  
114   * Specifies the length of the passphrase to be generated. If *not* specified, defaults to 24.
115
116 ### Remarks {.unlisted}
117
118 - 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.
119
120 - Passing the passphrase directly on the command-line is insecure, because the full command-line may be visible to other users!
121
122 Environment
123 -----------
124
125 The following environment variables may be used:
126
127 - **`SLUNK_PASSPHRASE`**:  
128   Specifies the "secret" passphrase. This environment variables is only evaluated, if the passphrase was **not** specified on the command-line.  
129   Passing the passphrase via environment variable is considered more secure, because environment variables are not normally visible to other (unprivileged) users.
130
131 - **`SLUNK_KEEP_INCOMPLETE`**:  
132   If set to a *non-zero* value, incomplete or corrupted output files will **not** be deleted automatically. By default, the files will be deleted.
133
134 - **`SLUNK_THREADS`**:  
135   Specifies the number of worker threads to use. By default, SlunkCrypt detects the number of available processors and creates one thread for each processor.
136
137 - **`SLUNK_LEGACY_COMPAT`**:  
138   If set to a *non-zero* value, enables “legacy” compatibility-mode, required to decrypt files encrypted with SlunkCrypt version 1.2.x or older.
139
140 - **`SLUNK_DEBUG_LOGGING`**:  
141   If set to a *non-zero* value, enables additional logging output to the syslog (Unix-like) or to the debugger (Windows). This is intended for debugging purposes only!
142
143 Examples
144 --------
145
146 Here are some examples on how to use the SlunkCrypt command-line application:
147
148 ### Example #1 {.unlisted}
149
150 1. Let's generate a new random (secure) password first:
151
152        slunkcrypt --make-pw
153
154    *Example output:*
155
156        cdG2=fh<C=3[SSCzf[)iDjIV
157
158 2. Now, encrypt the plaintext message, using the generated password:
159
160        slunkcrypt --encrypt pass:"cdG2=fh<C=3[SSCzf[)iDjIV" plaintext.txt ciphertext.enc
161
162    Optionally, let's have a look at the ciphertext:
163
164        hexdump -C ciphertext.enc
165
166 3. Finally, decrypt the ciphertext, using the same password as before:
167
168        slunkcrypt --decrypt pass:"cdG2=fh<C=3[SSCzf[)iDjIV" ciphertext.enc plaintext.out
169
170    Optionally, verify that the decrypted file is identical to the original:
171
172        sha256sum -b plaintext.txt plaintext.out
173
174 ### Example #2 {.unlisted}
175
176 1. Generate a new password and store it to a text file:
177
178        slunkcrypt --make-pw > passwd.txt
179
180    Optionally, output the generated password to the terminal:
181
182        cat passwd.txt
183
184 2. Encrypt file by reading the password from the text file:
185
186        slunkcrypt --encrypt file:passwd.txt plaintext.txt ciphertext.enc
187
188 ### Example #3 {.unlisted}
189
190 1. Generate a new password directly to an environment variable:
191
192        MY_PASSWD="$(slunkcrypt --make-pw)"
193
194    Optionally, output the generated password to the terminal:
195
196        echo "${MY_PASSWD}"
197
198 2. Encrypt file by reading the password from the *stdin*:
199
200        slunkcrypt --encrypt - plaintext.txt ciphertext.enc <<< "${MY_PASSWD}"
201
202
203 Encryption algorithm
204 ====================
205
206 SlunkCrypt is based on concepts of the well-known [**Enigma**](https://en.wikipedia.org/wiki/Enigma_machine) machine, but with significant improvements, largely inspired by [***Ross Anderson &ndash; “A Modern Rotor Machine”***](https://rdcu.be/cBo8y).
207
208 A great explanation and visualization of how the *original* Enigma machine works can be found in [***this***](https://www.youtube.com/watch?v=ybkkiGtJmkM) video.
209
210 Overview
211 --------
212
213 This section summarizes the improvements that have been implemented in SlunkCrypt:
214
215 - 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.
216
217 - 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.
218
219 - 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.
220
221 - 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 passphrase for each of the 256 simulated rotors. The initial rotor positions are *randomized* as well.
222
223 - SlunkCrypt does **not** currently implement the *plugboard* (“Steckerbrett”). Even though the plugboard significantly contributed to the key space of the original Engima machine, it was simply a *fixed* substitution cipher. SlunkCrypt already has a ***much*** bigger key space than that of the original Engine machine, because the number of rotors is substantially larger and because the internal wiring of these rotors is completely key-dependant. Therefore, adding a plugboard would *not* contribute notably to SlunkCrypt's cryptographic strength.
224
225 Details
226 -------
227
228 This section explains some crucial implementation details of the SlunkCrypt library:
229
230 * **DRBG:** The *deterministic random bit generator* (DRBG) employed by SlunkCrypt is called [*Xorwow*](https://en.wikipedia.org/wiki/Xorshift#xorwow), an enhanced variant of *Xorshift* , i.e. a form of *linear-feedback shift registers (LSFR)*.
231
232 * **Initialization (key schedule):** In the initialization phase, the *pseudo-random* internal wiring (i.e. permutation) is generated &ndash; separately for each of the 256 rotors. For this purpose, the initial state of the DRBG is set up in a way that depends on the given *passphrase*, a message-specific *nonce* as well as the current *rotor index*. More specifically, the initial state of the DRBG is derived from a combination of all input parameters, by applying a <u>large</u> number of iterations of the *FNV&#8209;1a 128-Bit* hash function. The permutation for the current rotor is then created by the ***Fisher&#8209;Yates*** shuffle algorithm, using the DRBG as its randomness source. This produces a distinct "randomized" internal rotor wiring for each message to be encrypted. 
233
234 * **Message processing:** During the encryption or decryption process, the individual offsets (positions) of the first 8 rotors are controlled by a 64-Bit counter, whereas the offsets of the remaining 248 rotors are continuously "randomized" by the DRBG. The initial counter value as well as the initial state of the DRBG are set up in a way that depends on the given *passphrase* and a message-specific *nonce*. Also, after each symbol that was processed, the counter is incremented by one and new *pseudo-random* offsets (rotor positions) are drawn.
235
236 * **Checksum:** The message-length is padded to a multiple of 8 bytes and a 64-Bit [BLAKE2s](https://www.blake2.net/) hash is appended, *before* encryption. This "checksum" can be used to detect decryption errors.
237
238
239 Programming Interface (API)
240 ===========================
241
242 This section describes the SlunkCypt library interface for software developers.
243
244 Getting started
245 ---------------
246
247 In order to use the SlunkCypt library in your C++ code, include **`<slunkcrypt.hpp>`** header and instantiate the appropriate SlunkCypt classes:
248
249 ### Example #1 {.unlisted}
250
251 Here is a simple example on how to use the SlunkCrypt [**`Encryptor`**](#encryptor) 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::Encryptor slunk_encrypt(passphrase);
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_encrypt.inplace(buffer, (size_t)input.gcount()))
268                 {
269                     /* Implement error handling here */
270                 }
271                 output.write(reinterpret_cast<char*>(buffer), count);
272             }
273         }
274         std::cout << std::hex << slunk_encrypt.get_nonce() << std::endl;
275     }
276
277 ### Example #2 {.unlisted}
278
279 Here is a simple example on how to use the SlunkCrypt [**`Decryptor`**](#decryptor) class:
280
281     #include <slunkcrypt.hpp>
282     #include <fstream>
283     #include <iostream>
284
285     int main()
286     {
287         /* Open input and output files here */
288         uint8_t buffer[BUFF_SIZE];
289         slunkcrypt::Decryptor slunk_decrypt(passphrase, nonce);
290         while (input.good())
291         {
292             input.read(reinterpret_cast<char*>(buffer), BUFF_SIZE);
293             if ((!input.bad()) && (input.gcount() > 0))
294             {
295                 if (!slunk_decrypt.inplace(buffer, (size_t)input.gcount()))
296                 {
297                     /* Implement error handling here */
298                 }
299                 output.write(reinterpret_cast<char*>(buffer), count);
300             }
301         }
302     }
303
304 C++11 API
305 ---------
306
307 This section describes the "high-level" C++11 API of the SlunkCrypt library. All SlunkCrypt classes live in the **`slunkcrypt`** namespace.
308
309 ### Encryptor
310
311 Class for *encrypting* data using the SlunkCrypt library.
312
313 #### Constructor
314
315 Create and initialize a new **``Encryptor``** instance. Also generated a new, random nonce.
316
317     Encryptor::Encryptor(
318       const std::string &passwd,
319       const size_t thread_count = 0U,
320       const bool legacy_compat = false,
321       const bool debug_logging = false
322     );
323
324 ***Parameters:***
325
326   * `passwd`  
327     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!
328      
329     *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.
330
331   * `thread_count`  
332     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.
333
334   * `legacy_compat`  
335     Enables "legacy" compatibility-mode; required to encrypt messages in a way that allows decryption with SlunkCrypt version 1.2.x or earlier. Option is disabled by default.
336
337   * `debug_logging`  
338     Enables additional debug logging. Messages are written to the syslog (Unix-like) or to the debugger (Windows). Option is disabled by default.
339
340 ***Exceptions:***
341
342   * Throws `std::runtime_error`, if the nonce could not be generated, or if the SlunkCrypt context could not be allocated.
343
344 #### Encryptor::process() [1]
345
346 Encrypt the next message chunk, using separate input/output buffers.
347
348     bool process(
349       const uint8_t *const input,
350       uint8_t *const output,
351       size_t length
352     );
353
354 ***Parameters:***
355
356  * `input`  
357     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.
358     
359     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!
360
361  * `output`  
362     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.
363     
364     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!
365
366  * `length`  
367    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.
368
369    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
370
371 ***Return value:***
372
373   * If successful, `true` is returned; otherwise `false` is returned.
374
375 #### Encryptor::process() [2]
376
377 Encrypt the next message chunk, using separate input/output containers (`std::vector`).
378
379     bool process(
380       const std::vector<uint8_t> &input,
381       std::vector<uint8_t> &output
382     );
383
384 ***Parameters:***
385
386  * `input`  
387     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.
388
389  * `output`  
390     A reference to the `std::vector<uint8_t>` instance where the ciphertext that corresponds to the given plaintext will be stored.
391     
392     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!
393
394 ***Return value:***
395
396   * If successful, `true` is returned; otherwise `false` is returned. The function fails, if the *output* `std::vector` is too small.
397
398 #### Encryptor::inplace() [1]
399
400 Encrypt the next message chunk, using a single buffer.
401
402     bool inplace(
403       uint8_t *const buffer,
404       size_t length
405     );
406
407 ***Parameters:***
408
409  * `buffer`  
410     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.
411     
412     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.
413
414  * `length`  
415    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.
416
417    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
418
419 ***Return value:***
420
421   * If successful, `true` is returned; otherwise `false` is returned.
422
423 #### Encryptor::inplace() [2]
424
425 Encrypt the next message chunk, using a single container (`std::vector`).
426
427     bool inplace(
428       std::vector<uint8_t> &buffer
429     );
430
431 ***Parameters:***
432
433  * `buffer`  
434     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.
435
436 ***Return value:***
437
438   * If successful, `true` is returned; otherwise `false` is returned.
439
440 #### Encryptor::get_nonce()
441
442 Retrieve the random nonce that is used to encrypt the message.
443
444     uint64_t get_nonce();
445
446 ***Return value:***
447
448   * 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.
449     
450     *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.
451
452 ### Decryptor
453
454 Class for *decrypting* data using the SlunkCrypt library.
455
456 #### Constructor
457
458 Create and initialize a new **``Decryptor``** instance.
459
460     Decryptor::Decryptor(
461       const std::string &passwd,
462       const uint64_t nonce,
463       const size_t thread_count = 0U,
464       const bool legacy_compat = false,
465       const bool debug_logging = false
466     );
467
468 ***Parameters:***
469
470   * `passwd`  
471     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!
472     
473     *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.
474
475   * `nonce`  
476     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.
477     
478     *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.
479
480   * `thread_count`  
481     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.
482
483   * `legacy_compat`  
484     Enables "legacy" compatibility-mode; required to decrypt messages that were encrypted with SlunkCrypt version 1.2.x or earlier. Option is disabled by default.
485
486   * `debug_logging`  
487     Enables additional debug logging. Messages are written to the syslog (Unix-like) or to the debugger (Windows). Option is disabled by default.
488
489 ***Exceptions:***
490
491   * Throws `std::runtime_error`, if the SlunkCrypt context could not be allocated.
492
493 #### Decryptor::process() [1]
494
495 Decrypt the next message chunk, using separate input/output buffers.
496
497     bool process(
498       const uint8_t *const input,
499       uint8_t *const output,
500       size_t length
501     );
502
503 ***Parameters:***
504
505  * `input`  
506     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`).
507     
508     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!
509
510  * `output`  
511     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.
512     
513     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!
514
515  * `length`  
516    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.
517
518    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
519
520 ***Return value:***
521
522   * If successful, `true` is returned; otherwise `false` is returned.
523
524 #### Decryptor::process() [2]
525
526 Decrypt the next message chunk, using separate input/output containers (`std::vector`).
527
528     bool process(
529       const std::vector<uint8_t> &input,
530       std::vector<uint8_t> &output
531     );
532
533 ***Parameters:***
534
535  * `input`  
536     A reference to the `std::vector<uint8_t>` instance containing the next chunk of the ciphertext to be decrypted.
537
538  * `output`  
539     A reference to the `std::vector<uint8_t>` instance where the plaintext that corresponds to the given ciphertext will be stored.
540     
541     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!
542
543 ***Return value:***
544
545   * If successful, `true` is returned; otherwise `false` is returned. The function fails, if the *output* `std::vector` is too small.
546
547 #### Decryptor::inplace() [1]
548
549 Decrypt the next message chunk, using a single buffer.
550
551     bool inplace(
552       uint8_t *const buffer,
553       size_t length
554     );
555
556 ***Parameters:***
557
558  * `buffer`  
559     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.
560     
561     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.
562
563  * `length`  
564    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.
565
566    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
567
568 ***Return value:***
569
570   * If successful, `true` is returned; otherwise `false` is returned.
571
572 #### Decryptor::inplace() [2]
573
574 Decrypt the next message chunk, using a single container (`std::vector`).
575
576     bool inplace(
577       std::vector<uint8_t> &buffer
578     );
579
580 ***Parameters:***
581
582  * `buffer`  
583     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.
584
585 ***Return value:***
586
587   * If successful, `true` is returned; otherwise `false` is returned.
588
589 C99 API
590 -------
591
592 This section describes the "low-level" C99 API of the SlunkCypt library.
593
594 ### Functions
595
596 The SlunkCypt library defines the following functions:
597
598 #### slunkcrypt_alloc()
599
600 Allocate and initialize a new SlunkCrypt encryption/decryption context.
601
602     slunkcrypt_t slunkcrypt_alloc(
603         const uint64_t nonce,
604         const uint8_t *const passwd,
605         const size_t passwd_len,
606         const int mode
607     );
608
609 ***Parameters:***
610
611   * `nonce`  
612     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.
613     
614     *Note:* It is recommended to generate a random nonce via the [`slunkcrypt_generate_nonce()`](#slunkcrypt_generate_nonce) function for each message!
615   
616   * `passwd`  
617     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!
618     
619     *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.
620   
621   * `passwd_len`  
622     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.
623
624   * `mode`  
625     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*.
626
627 ***Return value:***
628
629   * If successful, a handle to the new SlunkCrypt context is return; otherwise `SLUNKCRYPT_NULL` is returned.
630     
631     *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!
632
633 #### slunkcrypt_alloc_ext()
634
635 Allocate and initialize a new SlunkCrypt encryption/decryption context with additional parameters.
636
637     slunkcrypt_t slunkcrypt_alloc_ext(
638         const uint64_t nonce,
639         const uint8_t *const passwd,
640         const size_t passwd_len,
641         const int mode,
642         const slunkparam_t *const param
643     );
644
645 ***Parameters:***
646
647   * `nonce`  
648     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.
649     
650     *Note:* It is recommended to generate a random nonce via the [`slunkcrypt_generate_nonce()`](#slunkcrypt_generate_nonce) function for each message!
651   
652   * `passwd`  
653     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!
654     
655     *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.
656   
657   * `passwd_len`  
658     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.
659
660   * `mode`  
661     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*.
662
663   * `param`  
664     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.
665
666 ***Return value:***
667
668   * If successful, a handle to the new SlunkCrypt context is return; otherwise `SLUNKCRYPT_NULL` is returned.
669     
670     *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!
671
672 #### slunkcrypt_reset()
673   
674 Re-initialize an existing SlunkCrypt encryption/decryption context.
675
676     int slunkcrypt_reset(
677         const slunkcrypt_t context,
678         const uint64_t nonce,
679         const uint8_t *const passwd,
680         const size_t passwd_len,
681         const int mode
682     );
683
684 ***Parameters:***
685
686   * `context`  
687     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.
688
689   * *other parameters*:  
690     Please refer to the [`slunkcrypt_alloc()`](#slunkcrypt_alloc) function for details!
691
692 ***Return value:***
693
694   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
695
696 #### slunkcrypt_free()
697
698 De-allocate an existing SlunkCrypt encryption/decryption context. This will "clear" and release any memory occupied by the context.
699
700     void slunkcrypt_free(
701         const slunkcrypt_t context
702     );
703
704 ***Parameters:***
705
706  * `context`  
707     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.
708     
709     *Note:* Once a handle has been passed to this function, that handle is *invalidated* and **must not** be used again!
710
711 #### slunkcrypt_generate_nonce()
712
713 Generate a new random *nonce* (number used once), using the system's "cryptographically secure" entropy source.
714
715     int slunkcrypt_generate_nonce(
716       int64_t *const nonce
717     );
718
719 ***Parameters:***
720
721  * `nonce`  
722    A pointer to a variable of type `int64_t` that receives the new random nonce.
723
724 ***Return value:***
725
726   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
727
728 #### slunkcrypt_process()
729
730 Encrypt or decrypt the next message chunk, using separate input/output buffers.
731
732     int slunkcrypt_process(
733         const slunkcrypt_t context,
734         const uint8_t *const input,
735         uint8_t *const output,
736         size_t length
737     );
738
739 ***Parameters:***
740
741  * `context`  
742     The existing SlunkCrypt context to be used for processing the message chunk. This context will be updated.
743
744     *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).
745
746  * `input`  
747     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.
748     
749     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!
750
751  * `output`  
752     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.
753     
754     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!
755
756  * `length`  
757    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.
758
759    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
760
761 ***Return value:***
762
763   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
764
765 #### slunkcrypt_inplace()
766
767 Encrypt or decrypt the next message chunk, using a *single* input/output buffer.
768
769     int slunkcrypt_inplace(
770         const slunkcrypt_t context,
771         uint8_t *const buffer,
772         size_t length
773     );
774
775 ***Parameters:***
776
777  * `context`  
778     The existing SlunkCrypt context to be used for processing the message chunk. This context will be updated.
779
780     *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).
781
782  * `buffer`  
783     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.
784     
785     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!
786
787  * `length`  
788    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.
789
790    *Note:* It is recommended to process chunks of at least &sim;64 KB each, in order to take full advantage of multi-threading.
791
792 ***Return value:***
793
794   * If successful, `SLUNKCRYPT_SUCCESS` is returned; otherwise `SLUNKCRYPT_FAILURE` or `SLUNKCRYPT_ABORTED` is returned.
795
796 #### slunkcrypt_random_bytes()
797
798 Generate a sequence of random bytes, using the system's "cryptographically secure" entropy source.
799
800     size_t slunkcrypt_random_bytes(
801       uint8_t *const buffer,
802       const size_t length
803     );
804
805 ***Parameters:***
806
807  * `buffer`  
808    A pointer to the *output* buffer where the random bytes will be stored.
809
810    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!
811
812  * `length`  
813    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.
814
815 ***Return value:***
816
817   * The number of random bytes that have been generated and that have been stored to the `output` buffer buffer is returned.
818     
819     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**.
820
821
822 #### slunkcrypt_bzero()
823
824 Erase the contents of a byte array, by overwriting it with *zero* bytes. Compiler optimizations will **not** remove the erase operation.
825
826     void slunkcrypt_bzero(
827       void *const buffer,
828       const size_t length
829     );
830
831 ***Parameters:***
832
833  * `buffer`  
834    A pointer to the buffer whose content is to be erased.
835
836    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!
837
838  * `length`  
839    The size of the buffer to be erased, in bytes.
840
841 ### Types
842
843 #### SlunkCrypt parameters
844
845 The `slunkparam_t` struct is used to pass additional parameters that will be used for initializing the SlunkCrypt context. It contains the following fields:
846
847 * `version` &ndash; The version of the parameter struct; **must** be set to *`SLUNKCRYPT_PARAM_VERSION`*.
848 * `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 **32**).
849 * `legacy_compat` &ndash; If set to *`SLUNKCRYPT_TRUE`*, enables "legacy" compatibility-mode; required to decrypt messages that were encrypted with SlunkCrypt version 1.2.x or earlier.
850 * `debug_logging` &ndash; If set to *`SLUNKCRYPT_TRUE`*, enables additional debug logging; messages are written to the syslog (Unix-like) or to the debugger (Windows).
851
852 ### Global variables
853
854 The SlunkCypt library defines the following global variables:
855
856 #### Version information
857
858 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:
859
860 * `const uint16_t SLUNKCRYPT_VERSION_MAJOR` &ndash; The current *major* version.
861 * `const uint16_t SLUNKCRYPT_VERSION_MINOR` &ndash; The current *minor* version.
862 * `const uint16_t SLUNKCRYPT_VERSION_PATCH` &ndash; The current *patch* version.
863 * `const char *SLUNKCRYPT_BUILD` &ndash; The build date and time, as a C string, in the *`"mmm dd yyyy, hh:mm:ss"`* format.
864
865 #### Abort request
866
867 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:
868
869 * `volatile int g_slunkcrypt_abort_flag` &ndash; The global abort flag.
870
871   *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!
872
873 ### Constants
874
875 The SlunkCypt library defines the following constants:
876
877 #### Mode of operation
878
879 The SlunkCypt library supports the following modes of operation:
880
881 * `SLUNKCRYPT_ENCRYPT` &ndash; Run library in *encryption* mode, i.e. consume plaintext and produce ciphertext.
882 * `SLUNKCRYPT_DECRYPT` &ndash; Run library in *decryption* mode, i.e. consume ciphertext and produce plaintext.
883
884 #### Limits
885
886 The following limits are defined for the SlunkCypt library:
887
888 * `SLUNKCRYPT_PWDLEN_MIN` &ndash; The *minimum* required length of a password, currently **8** bytes.
889 * `SLUNKCRYPT_PWDLEN_MAX` &ndash; The *maximum* allowed length of a password, currently **256** bytes.
890
891 #### Error codes
892
893 SlunkCypt library functions that return an error code may return one of the following constants:
894
895 * `SLUNKCRYPT_SUCCESS` &ndash; The operation completed successfully.
896 * `SLUNKCRYPT_FAILURE` &ndash; The operation has failed.
897 * `SLUNKCRYPT_ABORTED` &ndash; The operation was aborted before completion, as requested by the application.
898
899 Thread safety
900 -------------
901
902 The following functions are fully "thread-safe" and thus may safely be called by *any* thread at *any* time ***without*** the need for synchronization:
903
904 * `slunkcrypt_alloc()`
905 * `slunkcrypt_generate_nonce()`
906 * `slunkcrypt_random_bytes()`
907 * `slunkcrypt_bzero()`
908 * `Encryptor::Encryptor()`
909 * `Decryptor::Decryptor()`
910
911 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:
912
913 * `slunkcrypt_reset()`
914 * `slunkcrypt_free()`
915 * `slunkcrypt_process()`
916 * `slunkcrypt_inplace()`
917 * `Encryptor::process()`
918 * `Encryptor::inplace()`
919 * `Encryptor::get_nonce()`
920 * `Decryptor::process()`
921 * `Decryptor::inplace()`
922
923 ***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).
924
925
926 Source Code
927 ===========
928
929 The latest SlunkCrypt source code is available from the official Git mirrors at:
930
931 * <https://gitlab.com/lord_mulder/slunkcrypt/>
932 * <https://bitbucket.org/muldersoft/slunkcrypt/>
933 * <https://repo.or.cz/slunkcrypt.git>
934 * <https://punkindrublic.mooo.com:3000/Muldersoft/SlunkCrypt>
935
936 Deprecated mirror sites:
937
938 * <https://osdn.net/projects/slunkcrypt/scm/git/SlunkCrypt/>
939
940
941 Build Instructions
942 ==================
943
944 SlunkCrypt can be built from the sources on Microsoft Windows or any POSIX-compatible platform, using a C-compiler that supports the C99 standard.
945
946 * **Microsoft Windows:**  
947   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.  
948   Just open the solution, select the “Release” configuration, choose the “x86” or “x64” platform, and finally press `F5`.  
949   Visual Studio also is the only way to build the SlunkCrypt GUI, which is based on Microsoft.NET and Windows Presentation Foundation (WPF).
950
951   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!
952
953 * **Linux:**  
954   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!
955
956   If not already installed, the required build tools can usually be installed via your distribution's package manager.  
957   For example, on Debian-based distributions, the command **`sudo apt install build-essential`** installs all the required build tools at once.
958
959   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/):  
960   `make -B CC=musl-gcc STATIC=1`
961
962 * **BSD and Solaris:**  
963   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!  
964   GNU Make can be installed from the package manager. For example, use **`pkg install gmake`** on FreeBSD or **`pkg_add gmake`** on OpenBSD.
965
966 * **Mac OS X:**  
967   Once you have managed to find a terminal (or even better, connect via SSH), Mac OS X almost works like a proper operating system.  
968   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!
969
970   *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).
971
972
973 Frequently Asked Questions
974 ==========================
975
976 * **Why does the decryption of my file fail with a checksum error?**
977
978   If SlunkCrypt fails to decrypt a file and reports a “checksum mismatch” error, then this means that either the given file was *not* actually encrypted with SlunkCrypt, the file was corrupted in some kind of way (e.g. incomplete download), or you did *not* provide the correct passphrase for the file. There is, unfortuantely, *no* way to distinguish these three cases, as files encrypted with SlunkCrypt are indistingushable from random noise &ndash; only with the correct passphrase, some meaningful data can be restored from the encrypted file. Trying to decrypt the file with a *wrong* passphrase results in just "random" gibberish! However, the same also happens if the file was corrupted, or if the file was *not* encrypted with SlunkCrypt.
979
980   *Note:* If you are using SlunkCrypt 1.3.0 or later, then files that have been encrypted with SlunkCrypt 1.2.x or older can only be decrypted by enabling the “legacy” compatibility-mode!
981
982 * **How can I recover the lost passphrase for my file?**
983
984   SlunkCrypt uses a combination of the given passphrase and the individual nonce to encrypt each file in a *unique* (pseudo-random) way. This means that *no* two files are encrypted in the same way. Consequently, the decryption of the file is *only* possible using the correct passphrase, i.e. the one which was used to encrypt the file. Trying to decrypt the file with a *wrong* passphrase results in just "random" gibberish. And, for good reasons, there is *no* way to recover the passphrase from an encrypted file, so take good care of your passphrase!
985
986   In theory, it is possible to “crack” the passphrase using the *brute-force* method, i.e. try out every possible passphrase (up to a certain length) until the correct one is found. However, provided that a sufficiently long and random passphrase was chosen &ndash; which is highly recommended &ndash; there are *way* too many combinations to try them all, in a reasonable time. For example, with a length of 12 characters (ASCII), there are 95<sup>12</sup> = 540,360,087,662,636,962,890,625 possible combinations! This renders *brute-force* attacks practically impossible.
987
988
989 License
990 =======
991
992 This work has been released under the **CC0 1.0 Universal** license.
993
994 For details, please refer to:  
995 <https://creativecommons.org/publicdomain/zero/1.0/legalcode>
996
997 Acknowledgement
998 ---------------
999
1000 SlunkCrypt incorporates code from the following *third-party* software projects:
1001
1002 * The "checksum" algorithm used by the SlunkCrypt command-line application was adapted from the **BLAKE2** reference C implementation.  
1003   ```
1004    BLAKE2 reference source code package - reference C implementations
1005    Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
1006    terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
1007    your option.  The terms of these licenses can be found at:
1008    - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
1009    - OpenSSL license   : https://www.openssl.org/source/license.html
1010    - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
1011
1012    More information about the BLAKE2 hash function can be found at
1013    https://blake2.net.
1014    ```
1015
1016 * ***Windows only:*** Builds of SlunkCypt that have multi-threading enabled use the **POSIX Threads for Windows (pthreads4w)** library.  
1017   ```
1018   Pthreads4w - POSIX Threads for Windows
1019   Copyright 1998 John E. Bossom
1020   Copyright 1999-2018, Pthreads4w contributors
1021
1022   Homepage: https://sourceforge.net/projects/pthreads4w/
1023  
1024   Licensed under the Apache License, Version 2.0 (the "License");
1025   you may not use this file except in compliance with the License.
1026   You may obtain a copy of the License at
1027
1028       http://www.apache.org/licenses/LICENSE-2.0
1029
1030   Unless required by applicable law or agreed to in writing, software
1031   distributed under the License is distributed on an "AS IS" BASIS,
1032   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1033   See the License for the specific language governing permissions and
1034   limitations under the License.
1035   ```
1036
1037
1038 &marker;