SlunkCrypt is an experimental cross-platform cryptography library and command-line tool. A fully-featured GUI is provided for the Windows platform.
Please refer to the section encryption algorithm for more details!
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, which collects information on cryptography laws in many countries.
The SlunkCrypt library and the command-line application currently run on the following platforms:
The SlunkCrypt GUI application currently runs on the following platforms:
This is how the graphical user interface (GUI) for SlunkCrypt looks on Windows 11:
Please be sure to install the .NET Framework 4.5, or
any later .NET Framework 4.x version, before running the
SlunkCrypt GUI application:
https://dotnet.microsoft.com/download/dotnet-framework
Note: If you are running Windows 8 or later, then almost certainly a suitable version of the .NET Framework is already installed đ
The following settings can be adjusted in the
slunkcrypt-gui.exe.config
configuration file:
DisableBusyIndicator
:
If set to true
, the âbusy indicatorâ animation will be
disabled on application startup â default value:
false
.
ThreadCount
:
Specifies the number of worker threads to use â default value:
0
(i.e. detect the number of available processors and
create one thread for each processor).
KeepIncompleteFiles
:
If set to true
, incomplete or corrupted output files will
not be deleted â default value: false
.
This section describes the SlunkCypt command-line application.
The SlunkCypt command-line program is invoked as follows:
slunkcrypt --encrypt [pass:<pass>|file:<file>] <input.txt> <output.enc>
slunkcrypt --decrypt [pass:<pass>|file:<file>] <input.enc> <output.txt>
slunkcrypt --make-pw [<length>]
One of the following commands must be chosen:
--encrypt
(-e
):--decrypt
(-d
):--make-pw
(-p
):--self-test
(-t
):The following command-line options are available:
pass:<pass>
:
file:<file>
:
-
in order to read the passphrase from the
stdin.<input>
:
<output>
:
<length>
:
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.
Passing the passphrase directly on the command-line is insecure, because the full command-line may be visible to other users!
The following environment variables may be used:
SLUNK_PASSPHRASE
:
Specifies the âsecretâ passphrase. This environment variables is only
evaluated, if the passphrase was not specified on the
command-line.
Passing the passphrase via environment variable is considered more
secure, because environment variables are not normally visible to other
(unprivileged) users.
SLUNK_KEEP_INCOMPLETE
:
If set to a non-zero value, incomplete or corrupted output
files will not be deleted automatically. By default,
the files will be deleted.
SLUNK_THREADS
:
Specifies the number of worker threads to use. By default, SlunkCrypt
detects the number of available processors and creates one thread for
each processor.
Here are some examples on how to use the SlunkCrypt command-line application:
Letâs generate a new random (secure) password first:
slunkcrypt --make-pw
Example output:
cdG2=fh<C=3[SSCzf[)iDjIV
Now, encrypt the plaintext message, using the generated password:
slunkcrypt --encrypt pass:"cdG2=fh<C=3[SSCzf[)iDjIV" plaintext.txt ciphertext.enc
Optionally, letâs have a look at the ciphertext:
hexdump -C ciphertext.enc
Finally, decrypt the ciphertext, using the same password as before:
slunkcrypt --decrypt pass:"cdG2=fh<C=3[SSCzf[)iDjIV" ciphertext.enc plaintext.out
Optionally, verify that the decrypted file is identical to the original:
sha256sum -b plaintext.txt plaintext.out
Generate a new password and store it to a text file:
slunkcrypt --make-pw > passwd.txt
Optionally, output the generated password to the terminal:
cat passwd.txt
Encrypt file by reading the password from the text file:
slunkcrypt --encrypt file:passwd.txt plaintext.txt ciphertext.enc
Generate a new password directly to an environment variable:
MY_PASSWD="$(slunkcrypt --make-pw)"
Optionally, output the generated password to the terminal:
echo "${MY_PASSWD}"
Encrypt file by reading the password from the stdin:
slunkcrypt --encrypt - plaintext.txt ciphertext.enc <<< "${MY_PASSWD}"
The SlunkCrypt algorithm is based on core concepts of the well-known Enigma machine but with numerous improvements, largely inspired by R. Andersonâs âA Modern Rotor Machineâ:
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.
In the original Enigma machine, the signal passes through the rotors twice, once in forward direction and then again in backwards direction â 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.
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 â 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.
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.
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.
This section describes the SlunkCypt library interface for software developers.
In order to use the SlunkCypt library in your C++ code, include
<slunkcrypt.hpp>
header and
instantiate the appropriate SlunkCypt classes:
Here is a simple example on how to use the SlunkCrypt Encryptor
class:
#include <slunkcrypt.hpp>
#include <fstream>
#include <iostream>
int main()
{
/* Open input and output files here */
uint8_t buffer[BUFF_SIZE];
slunkcrypt::Encryptor slunk_encrypt(passphrase);
while (input.good())
{
input.read(reinterpret_cast<char*>(buffer), BUFF_SIZE);
if ((!input.bad()) && (input.gcount() > 0))
{
if (!slunk_encrypt.inplace(buffer, (size_t)input.gcount()))
{
/* Implement error handling here */
}
output.write(reinterpret_cast<char*>(buffer), count);
}
}
std::cout << std::hex << slunk_encrypt.get_nonce() << std::endl;
}
Here is a simple example on how to use the SlunkCrypt Decryptor
class:
#include <slunkcrypt.hpp>
#include <fstream>
#include <iostream>
int main()
{
/* Open input and output files here */
uint8_t buffer[BUFF_SIZE];
slunkcrypt::Decryptor slunk_decrypt(passphrase, nonce);
while (input.good())
{
input.read(reinterpret_cast<char*>(buffer), BUFF_SIZE);
if ((!input.bad()) && (input.gcount() > 0))
{
if (!slunk_decrypt.inplace(buffer, (size_t)input.gcount()))
{
/* Implement error handling here */
}
output.write(reinterpret_cast<char*>(buffer), count);
}
}
}
This section describes the âhigh-levelâ C++11 API of the SlunkCrypt
library. All SlunkCrypt classes live in the
slunkcrypt
namespace.
Class for encrypting data using the SlunkCrypt library.
Create and initialize a new Encryptor
instance. Also generated a new, random nonce.
Encryptor::Encryptor(
const std::string &passwd,
const size_t thread_count = 0U
);
Parameters:
passwd
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!
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.
thread_count
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.
Exceptions:
std::runtime_error
, if the nonce could not be
generated, or if the SlunkCrypt context could not be allocated.Encrypt the next message chunk, using separate input/output buffers.
bool process(
const uint8_t *const input,
uint8_t *const output,
size_t length
);
Parameters:
input
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.
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!
output
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.
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!
length
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.
Note: It is recommended to process chunks of at least âź64 KB each, in order to take full advantage of multi-threading.
Return value:
true
is returned; otherwise
false
is returned.Encrypt the next message chunk, using separate input/output
containers (std::vector
).
bool process(
const std::vector<uint8_t> &input,
std::vector<uint8_t> &output
);
Parameters:
input
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.
output
A reference to the std::vector<uint8_t>
instance
where the ciphertext that corresponds to the given plaintext will be
stored.
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!
Return value:
true
is returned; otherwise
false
is returned. The function fails, if the
output std::vector
is too small.Encrypt the next message chunk, using a single buffer.
bool inplace(
uint8_t *const buffer,
size_t length
);
Parameters:
buffer
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.
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.
length
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.
Note: It is recommended to process chunks of at least âź64 KB each, in order to take full advantage of multi-threading.
Return value:
true
is returned; otherwise
false
is returned.Encrypt the next message chunk, using a single container
(std::vector
).
bool inplace(
std::vector<uint8_t> &buffer
);
Parameters:
buffer
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.Return value:
true
is returned; otherwise
false
is returned.Retrieve the random nonce that is used to encrypt the message.
uint64_t get_nonce();
Return value:
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.
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.
Class for decrypting data using the SlunkCrypt library.
Create and initialize a new Decryptor
instance.
Decryptor::Decryptor(
const std::string &passwd,
const uint64_t nonce,
const size_t thread_count = 0U
);
Parameters:
passwd
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!
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.
nonce
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.
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.
thread_count
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.
Exceptions:
std::runtime_error
, if the SlunkCrypt context
could not be allocated.Decrypt the next message chunk, using separate input/output buffers.
bool process(
const uint8_t *const input,
uint8_t *const output,
size_t length
);
Parameters:
input
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
).
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!
output
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.
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!
length
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.
Note: It is recommended to process chunks of at least âź64 KB each, in order to take full advantage of multi-threading.
Return value:
true
is returned; otherwise
false
is returned.Decrypt the next message chunk, using separate input/output
containers (std::vector
).
bool process(
const std::vector<uint8_t> &input,
std::vector<uint8_t> &output
);
Parameters:
input
A reference to the std::vector<uint8_t>
instance
containing the next chunk of the ciphertext to be decrypted.
output
A reference to the std::vector<uint8_t>
instance
where the plaintext that corresponds to the given ciphertext will be
stored.
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!
Return value:
true
is returned; otherwise
false
is returned. The function fails, if the
output std::vector
is too small.Decrypt the next message chunk, using a single buffer.
bool inplace(
uint8_t *const buffer,
size_t length
);
Parameters:
buffer
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.
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.
length
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.
Note: It is recommended to process chunks of at least âź64 KB each, in order to take full advantage of multi-threading.
Return value:
true
is returned; otherwise
false
is returned.Decrypt the next message chunk, using a single container
(std::vector
).
bool inplace(
std::vector<uint8_t> &buffer
);
Parameters:
buffer
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.Return value:
true
is returned; otherwise
false
is returned.This section describes the âlow-levelâ C99 API of the SlunkCypt library.
The SlunkCypt library defines the following functions:
Allocate and initialize a new SlunkCrypt encryption/decryption context.
slunkcrypt_t slunkcrypt_alloc(
const uint64_t nonce,
const uint8_t *const passwd,
const size_t passwd_len,
const int mode
);
Parameters:
nonce
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.
Note: It is recommended to generate a random nonce via the
slunkcrypt_generate_nonce()
function for each message!
passwd
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!
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.
passwd_len
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.
mode
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.
Return value:
If successful, a handle to the new SlunkCrypt context is return;
otherwise SLUNKCRYPT_NULL
is returned.
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()
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!
Allocate and initialize a new SlunkCrypt encryption/decryption context with additional parameters.
slunkcrypt_t slunkcrypt_alloc_ext(
const uint64_t nonce,
const uint8_t *const passwd,
const size_t passwd_len,
const int mode,
const slunkparam_t *const param
);
Parameters:
nonce
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.
Note: It is recommended to generate a random nonce via the
slunkcrypt_generate_nonce()
function for each message!
passwd
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!
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.
passwd_len
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.
mode
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.
param
Additional parameters used to initialize the SlunkCrypt context, given
as a pointer to a slunkparam_t
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.
Return value:
If successful, a handle to the new SlunkCrypt context is return;
otherwise SLUNKCRYPT_NULL
is returned.
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()
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!
Re-initialize an existing SlunkCrypt encryption/decryption context.
int slunkcrypt_reset(
const slunkcrypt_t context,
const uint64_t nonce,
const uint8_t *const passwd,
const size_t passwd_len,
const int mode
);
Parameters:
context
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()
function.
other parameters:
Please refer to the slunkcrypt_alloc()
function
for details!
Return value:
SLUNKCRYPT_SUCCESS
is returned;
otherwise SLUNKCRYPT_FAILURE
or
SLUNKCRYPT_ABORTED
is returned.De-allocate an existing SlunkCrypt encryption/decryption context. This will âclearâ and release any memory occupied by the context.
void slunkcrypt_free(
const slunkcrypt_t context
);
Parameters:
context
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()
function.
Note: Once a handle has been passed to this function, that handle is invalidated and must not be used again!
Generate a new random nonce (number used once), using the systemâs âcryptographically secureâ entropy source.
int slunkcrypt_generate_nonce(
int64_t *const nonce
);
Parameters:
nonce
int64_t
that receives the
new random nonce.Return value:
SLUNKCRYPT_SUCCESS
is returned;
otherwise SLUNKCRYPT_FAILURE
or
SLUNKCRYPT_ABORTED
is returned.Encrypt or decrypt the next message chunk, using separate input/output buffers.
int slunkcrypt_process(
const slunkcrypt_t context,
const uint8_t *const input,
uint8_t *const output,
size_t length
);
Parameters:
context
The existing SlunkCrypt context to be used for processing the message
chunk. This context will be updated.
Note: This function operates either in âencryptionâ mode or in âdecryptionâ mode, depending on how the given SlunkCrypt context has been initialized or re-initialized.
input
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.
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!
output
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.
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!
length
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.
Note: It is recommended to process chunks of at least âź64 KB each, in order to take full advantage of multi-threading.
Return value:
SLUNKCRYPT_SUCCESS
is returned;
otherwise SLUNKCRYPT_FAILURE
or
SLUNKCRYPT_ABORTED
is returned.Encrypt or decrypt the next message chunk, using a single input/output buffer.
int slunkcrypt_inplace(
const slunkcrypt_t context,
uint8_t *const buffer,
size_t length
);
Parameters:
context
The existing SlunkCrypt context to be used for processing the message
chunk. This context will be updated.
Note: This function operates either in âencryptionâ mode or in âdecryptionâ mode, depending on how the given SlunkCrypt context has been initialized or re-initialized.
buffer
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.
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!
length
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.
Note: It is recommended to process chunks of at least âź64 KB each, in order to take full advantage of multi-threading.
Return value:
SLUNKCRYPT_SUCCESS
is returned;
otherwise SLUNKCRYPT_FAILURE
or
SLUNKCRYPT_ABORTED
is returned.Generate a sequence of random bytes, using the systemâs âcryptographically secureâ entropy source.
size_t slunkcrypt_random_bytes(
uint8_t *const buffer,
const size_t length
);
Parameters:
buffer
A pointer to the output buffer where the random bytes will be
stored.
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!
length
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.
Return value:
The number of random bytes that have been generated and that have
been stored to the output
buffer buffer is returned.
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 â in that case, you can try again later. The number of
generated bytes can be as low as 0.
Erase the contents of a byte array, by overwriting it with zero bytes. Compiler optimizations will not remove the erase operation.
void slunkcrypt_bzero(
void *const buffer,
const size_t length
);
Parameters:
buffer
A pointer to the buffer whose content is to be erased.
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!
length
The size of the buffer to be erased, in bytes.
The slunkparam_t
struct is used to pass additional
parameters that will be used for initializing the SlunkCrypt context. It
contains the following fields:
version
â The version of the parameter struct;
must be set to
SLUNKCRYPT_PARAM_VERSION
.thread_count
â 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).The SlunkCypt library defines the following global variables:
These variables can be used to determine the version of the SlunkCrypt library at runtime, using the semantic versioning scheme:
const uint16_t SLUNKCRYPT_VERSION_MAJOR
â The current
major version.const uint16_t SLUNKCRYPT_VERSION_MINOR
â The current
minor version.const uint16_t SLUNKCRYPT_VERSION_PATCH
â The current
patch version.const char *SLUNKCRYPT_BUILD
â The build date and time,
as a C string, in the "mmm dd yyyy, hh:mm:ss"
format.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:
volatile int g_slunkcrypt_abort_flag
â The global
abort flag.
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âing any SlunkCypt contexts that it
allocated successfully!
The SlunkCypt library defines the following constants:
The SlunkCypt library supports the following modes of operation:
SLUNKCRYPT_ENCRYPT
â Run library in encryption
mode, i.e. consume plaintext and produce ciphertext.SLUNKCRYPT_DECRYPT
â Run library in decryption
mode, i.e. consume ciphertext and produce plaintext.The following limits are defined for the SlunkCypt library:
SLUNKCRYPT_PWDLEN_MIN
â The minimum required
length of a password, currently 8 bytes.SLUNKCRYPT_PWDLEN_MAX
â The maximum allowed
length of a password, currently 256 bytes.SlunkCypt library functions that return an error code may return one of the following constants:
SLUNKCRYPT_SUCCESS
â The operation completed
successfully.SLUNKCRYPT_FAILURE
â The operation has failed.SLUNKCRYPT_ABORTED
â The operation was aborted before
completion, as requested by the application.The following functions are fully âthread-safeâ and thus may safely be called by any thread at any time without the need for synchronization:
slunkcrypt_alloc()
slunkcrypt_generate_nonce()
slunkcrypt_random_bytes()
slunkcrypt_bzero()
Encryptor::Encryptor()
Decryptor::Decryptor()
The following functions are âreentrantâ and thus may safely be called
by any thread at any time
without the need for synchronization â
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:
slunkcrypt_reset()
slunkcrypt_free()
slunkcrypt_process()
slunkcrypt_inplace()
Encryptor::process()
Encryptor::inplace()
Encryptor::get_nonce()
Decryptor::process()
Decryptor::inplace()
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.
The latest SlunkCrypt source code is available from the official Git mirrors at:
SlunkCrypt can be built from the sources on Microsoft Windows or any POSIX-compatible platform, using a C-compiler that supports the C99 standard.
Microsoft Windows:
Project/solution files for Visual Studio are
provided. These should work âout of the boxâ with Visual Studio 2017 or
any later version.
Just open the solution, select the âReleaseâ configuration, choose the
âx86â or âx64â platform, and finally press F5
.
Visual Studio also is the only way to build the SlunkCrypt GUI, which is
based on Microsoft.NET and Windows Presentation Foundation (WPF).
Alternatively, SlunkCrypt can built using Mingw-w64 (available via MSYS2) or even Cygwin â see Linux instructions for details!
Linux:
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!
If not already installed, the required build tools can usually be
installed via your distributionâs package manager.
For example, on Debian-based distributions, the command
sudo apt install build-essential
installs
all the required build tools at once.
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:
make -B CC=musl-gcc STATIC=1
BSD and Solaris:
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!
GNU Make can be installed from the package manager. For example, use
pkg install gmake
on FreeBSD or
pkg_add gmake
on OpenBSD.
Mac OS X:
Once you have managed to find a terminal (or even better, connect via
SSH), Mac OS X almost works like a proper operating system.
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!
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.
This work has been released under the CC0 1.0 Universal license.
For details, please refer to:
https://creativecommons.org/publicdomain/zero/1.0/legalcode
SlunkCrypt incorporates code from the following third-party software projects:
The âchecksumâ algorithm used by the SlunkCrypt command-line application was adapted from the BLAKE2 reference C implementation.
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
Windows only: Builds of SlunkCypt that have multi-threading enabled use the POSIX Threads for Windows (pthreads4w) library.
Pthreads4w - POSIX Threads for Windows
Copyright 1998 John E. Bossom
Copyright 1999-2018, Pthreads4w contributors
Homepage: https://sourceforge.net/projects/pthreads4w/
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
âŽ