1
0
Fork 0
An experimental cryptography library. http://slunkcrypt.osdn.io/
Go to file
LoRd_MuldeR 06f57ca483
Clean up function names.
2021-04-02 16:37:19 +02:00
etc Added simple script to generate the documents. 2021-03-20 21:19:06 +01:00
examples Clean up function names. 2021-04-02 16:37:19 +02:00
frontend Clean up function names. 2021-04-02 16:37:19 +02:00
libslunkcrypt Clean up function names. 2021-04-02 16:37:19 +02:00
.gitignore Added simple script to generate the documents. 2021-03-20 21:19:06 +01:00
LICENSE.txt Initial commit. 2021-03-20 21:17:51 +01:00
Makefile Fixed a bunch of warnings with legacy MinGW version. 2021-03-20 21:18:53 +01:00
README.md Renamed the C++ wrapper classes + updated README file. 2021-03-24 21:34:46 +01:00
Slunk.props Added build script for Windows. 2021-03-20 21:18:48 +01:00
Slunk.sln Implemented Win32 DLL support. 2021-03-20 21:18:38 +01:00
mk-docs.cmd Added simple script to generate the documents. 2021-03-20 21:19:06 +01:00
mk-docs.sh Added simple script to generate the documents. 2021-03-20 21:19:06 +01:00
mk-profiled.cmd Improved command-line syntax for passing the passphrase + Updated README file. 2021-03-22 22:52:00 +01:00
mk-profiled.sh Improved command-line syntax for passing the passphrase + Updated README file. 2021-03-22 22:52:00 +01:00

README.md

title
![SlunkCrypt](etc/img/SlunkCrypt-Logo.png)

Introduction

SlunkCrypt is an experimental cryptography library and command-line tool. See encryption algorithm for details.

Legal Warning

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.

Command-line Usage

This section describes the SlunkCypt command-line application.

Synopsis

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>]

Commands

One of the following commands must be chosen:

  • --encrypt (-e):
    Run application in encrypt mode. Reads the given plaintext and generates ciphertext.
  • --decrypt (-d):
    Run application in decrypt mode. Reads the given ciphertext and restores plaintext.
  • --make-pw (-p):
    Generate a "strong" random passphrase, suitable for use with SlunkCrypt.
  • --self-test (-t):
    Run the application in self-test mode. Program will exit after all test are completed.

Options

The following options are available:

  • pass:<pass>:
    • Specifies the "secret" passphrase directly on the command-line. This is considered insecure.
  • file:<file>:
    • Specifies a file to read the passphrase from. Only the first line of the file will be read!
    • Note: It is also possible to specify - in order to read the passphrase from the stdin.
  • <input>:
    • In encrypt mode specifies the plaintext file (unencrypted information) that is to be encrypted.
    • In decrypt mode specifies the ciphertext file (result of encryption) that is to be decrypted.
  • <output>:
    • In encrypt mode specifies the file where the ciphertext (result of encryption) will be stored.
    • In decrypt mode specifies the file where the plaintext (unencrypted information) will be stored.
  • <length>:
    • Specifies the length of the passphrase to be generated. If not specified, defaults to 24.

Remarks

  • If the passphrase is not specified on the command-line, it will be read from the SLUNK_PASSPHRASE environment variable.

  • 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 command-line may be visible to other users.

Examples

Here are some examples on how to use the SlunkCrypt command-line application:

Example #1

  1. Let's generate a new random (secure) password first:

    slunkcrypt --make-pw
    

    Example output:

    cdG2=fh<C=3[SSCzf[)iDjIV
    
  2. 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
    
  3. 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
    

Example #2

  1. 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
    
  2. Encrypt file by reading the password from the text file:

    slunkcrypt --encrypt file:passwd.txt plaintext.txt ciphertext.enc
    

Example #3

  1. 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}"
    
  2. Encrypt file by reading the password from the stdin:

    slunkcrypt --encrypt - plaintext.txt ciphertext.enc <<< "${MY_PASSWD}"
    

Encryption algorithm

The SlunkCrypt algorithm is based on concepts of the well-known Enigma machine, but with various improvements:

  • The original Enigma machine had only three (or somtimes four) rotors, plus a static "reflector" wheel. In SlunkCrypt, we uses 256 simulated rotors for an improved security.

  • 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, because encryption and decryption no longer are the same.

  • In the original Enigma machine, only the rightmost rotor was stepped after every symbol. The other rotors were stepped infrequently. Specifically, if one rotor had completed a full turn, it caused the next rotor to move by one step much like the odometer in a car. The fact that most of the rotors remained in the same "static" position for a long time was another important weakness of the Enigma machine that ultimately lead to its demise. Furthermore, the positions of the Enigma's rotors would start to repeat after "only" 16,900 characters. In SlunkCrypt, an improved stepping algorithm is used, which ensures that all rotors are stepped often. At the same time, the rotor positions in SlunkCrypt never repeat (practically).

  • 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 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 too much to the cryptographic strength of the Enigma machine. In fact, the plugboard could be "erased" by Welchman's diagonal board.

Programming Interface (API)

This section describes the SlunkCypt library interface for software developers.

Getting started

In order to use the SlunkCypt library in your C++ code, include <slunkcrypt.hpp> header and instantiate the appropriate SlunkCypt classes:

Example #1

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.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;
}

Example #2

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(nonce, passphrase);
    while (input.good())
    {
        input.read(reinterpret_cast<char*>(buffer), BUFF_SIZE);
        if ((!input.bad()) && (input.gcount() > 0))
        {
            if (!slunk_decrypt.decrypt_inplace(buffer, (size_t)input.gcount()))
            {
                /* Implement error handling here */
            }
            output.write(reinterpret_cast<char*>(buffer), count);
        }
    }
}

C++11 API

This section describes the "high-level" C++11 API of the SlunkCrypt library. All SlunkCrypt classes live in the slunkcrypt namespace.

Encryptor

Class for encrypting data using the SlunkCrypt library.

Constructor

Create and initialize a new Encryptor instance. Also generated a new, random nonce.

Encryptor::Encryptor(
  const std::string &passwd
);

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.

Exceptions:

  • Throws std::runtime_error, if the nonce could not be generated, or if the SlunkCrypt context could not be allocated.

Encryptor::encrypt() [1]

Encrypt the next message chunk, using separate input/output buffers.

bool encrypt(
  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.

Return value:

  • If successful, true is returned; otherwise false is returned.

Encryptor::encrypt() [2]

Encrypt the next message chunk, using separate input/output containers (std::vector).

bool encrypt(
  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:

  • If successful, true is returned; otherwise false is returned. The function fails, if the output std::vector is too small.

Encryptor::encrypt_inplace() [1]

Encrypt the next message chunk, using a single buffer.

bool encrypt_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.

Return value:

  • If successful, true is returned; otherwise false is returned.

Encryptor::encrypt_inplace() [2]

Encrypt the next message chunk, using a single container (std::vector).

bool encrypt_inplace(
  std::vector<uint8_t> &buffer
);

Parameters:

  • buffer
    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.

Return value:

  • If successful, true is returned; otherwise false is returned.

Encryptor::get_nonce()

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.

Decryptor

Class for decrypting data using the SlunkCrypt library.

Constructor

Create and initialize a new Decryptor instance.

Decryptor::Decryptor(
  const uint64_t nonce,
  const std::string& passwd
);

Parameters:

  • 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.

  • 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.

Exceptions:

  • Throws std::runtime_error, if the SlunkCrypt context could not be allocated.

Decryptor::decrypt() [1]

Decrypt the next message chunk, using separate input/output buffers.

bool decrypt(
  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.

Return value:

  • If successful, true is returned; otherwise false is returned.

Decryptor::decrypt() [2]

Decrypt the next message chunk, using separate input/output containers (std::vector).

bool decrypt(
  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:

  • If successful, true is returned; otherwise false is returned. The function fails, if the output std::vector is too small.

Decryptor::decrypt_inplace() [1]

Decrypt the next message chunk, using a single buffer.

bool decrypt_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.

Return value:

  • If successful, true is returned; otherwise false is returned.

Decryptor::decrypt_inplace() [2]

Decrypt the next message chunk, using a single container (std::vector).

bool decrypt_inplace(
  std::vector<uint8_t> &buffer
);

Parameters:

  • buffer
    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.

Return value:

  • If successful, true is returned; otherwise false is returned.

C99 API

This section describes the "low-level" C99 API of the SlunkCypt library.

slunkcrypt_alloc()

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
);

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.

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 "clear" and de-allocate that context.

slunkcrypt_reset()

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
);

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.

  • nonce
    Please refer to the slunkcrypt_alloc() function for details!

  • passwd
    Please refer to the slunkcrypt_alloc() function for details!

  • passwd_len
    Please refer to the slunkcrypt_alloc() function for details!

Return value:

  • If successful, SLUNKCRYPT_SUCCESS is returned; otherwise SLUNKCRYPT_FAILURE or SLUNKCRYPT_ABORTED is returned.

slunkcrypt_free()

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!

slunkcrypt_generate_nonce()

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
    A pointer to a variable of type int64_t that receives the new random nonce.

Return value:

  • If successful, SLUNKCRYPT_SUCCESS is returned; otherwise SLUNKCRYPT_FAILURE or SLUNKCRYPT_ABORTED is returned.

slunkcrypt_encrypt()

Encrypt the next message chunk, using separate input/output buffers.

int slunkcrypt_encrypt(
    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 encrypting the message chunk. This context will be updated.

  • 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.

Return value:

  • If successful, SLUNKCRYPT_SUCCESS is returned; otherwise SLUNKCRYPT_FAILURE or SLUNKCRYPT_ABORTED is returned.

slunkcrypt_encrypt_inplace()

Encrypt the next message chunk, using a single buffer.

int slunkcrypt_encrypt_inplace(
    const slunkcrypt_t context,
    uint8_t* const buffer,
    size_t length
);

Parameters:

  • context
    The existing SlunkCrypt context to be used for encrypting the message chunk. This context will be updated.

  • 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.

Return value:

  • If successful, SLUNKCRYPT_SUCCESS is returned; otherwise SLUNKCRYPT_FAILURE or SLUNKCRYPT_ABORTED is returned.

slunkcrypt_decrypt()

Decrypt the next ciphertext chunk, using separate input/output buffers.

int slunkcrypt_decrypt(
    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 decrypting the ciphertext chunk. This context will be updated.

  • 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 plaintext 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.

Return value:

  • If successful, SLUNKCRYPT_SUCCESS is returned; otherwise SLUNKCRYPT_FAILURE or SLUNKCRYPT_ABORTED is returned.

slunkcrypt_decrypt_inplace()

Decrypt the next ciphertext chunk, using a single buffer.

int slunkcrypt_decrypt_inplace(
    const slunkcrypt_t context,
    uint8_t* const buffer,
    size_t length
);

Parameters:

  • context
    The existing SlunkCrypt context to be used for decrypting the ciphertext chunk. This context will be updated.

  • 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, 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 decrypted 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.

Return value:

  • If successful, SLUNKCRYPT_SUCCESS is returned; otherwise SLUNKCRYPT_FAILURE or SLUNKCRYPT_ABORTED is returned.

slunkcrypt_random_bytes()

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. If the buffer is longer than length bytes, then 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 determines the minimum required size of the output buffer given by the output parameters, in bytes.

Return value:

  • If successful, the number of random bytes that have been generated and stored to the output buffer is returned; otherwise 0 is returned.

    The number of generated bytes can be at most length. Less than length bytes may be generated, if the entropy source could not provide the requested number of bytes at this time. In that case, you can try again.

slunkcrypt_bzero()

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; the remainder of the buffer will not be modified!

  • length
    The size of the buffer to be erased, in bytes.

Thread safety

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_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 each instance will exclusively be access by its respective "owner" thread:

  • slunkcrypt_reset()
  • slunkcrypt_free()
  • slunkcrypt_encrypt()
  • slunkcrypt_encrypt_inplace()
  • slunkcrypt_decrypt()
  • slunkcrypt_decrypt_inplace()
  • Encryptor::encrypt()
  • Encryptor::encrypt_inplace()
  • Encryptor::get_nonce()
  • Decryptor::decrypt()
  • Decryptor::decrypt_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.

License

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