LibAscon is an ISO C99/C11 cryptographic library wrapping the reference C implementation of the Ascon family of lightweight authenticated encryption schemes with associated data (AEAD) and hashing functions, but it also includes Init-Update-Final processing and variable tag length. Heavily tested and ready for embedded systems!
Security disclaimer
This is not a security-hardened implementation, just a simple one, focused mostly on usability, portability, and high(er) set of features compared to the reference implementation. There is no explicit protection against side-channel attacks other than what the Ascon algorithm itself provides by design.
Nevertheless, this implementation:
- uses constant-time operations (should help against timing attacks),
- tries to force the compiler to actually clear sensitive data instead of optimising the operations away (this is hard to achieve properly),
- has 100% line and 100% branch test coverage.
Features
LibAscon provides:
- 3 AEAD ciphers:
- Ascon128 v1.2 (128 bit key, 64 bit rate)
- Ascon128a v1.2 (128 bit key, 128 bit rate)
- Ascon80pq v1.2 (160 bit key, 64 bit rate)
- 4 hashing functions
- Ascon-Hash v1.2 (fixed-length output, 12-rounds absorption/squeeze)
- Ascon-XOF v1.2 (variable-length output, 12-rounds absorption/squeeze)
- Ascon-Hasha v1.2 (fixed-length output, 8-rounds absorption/squeeze)
- Ascon-XOFa v1.2 (variable-length output, 8-rounds absorption/squeeze)
- Online processing (Init-Update-Final paradigm) for hashing and encryption/decryption. This means that the data can be processed one chunk at the time. Useful when operating on large amounts of data that are not available contiguously in memory, e.g. a too-large file or data in transmission.
- Offline processing (whole data contiguous in memory) is also available with a simple wrapper.
Variable tag length for authenticated encryption: can generate any tag length. Of course at least 16 bytes (128 bits) is recommended.
Note: the tag bytes above 16 bytes are an extension of the original Ascon algorithm using the same sponge squeezing technique as for the XOF;
- Encryption/decryption can be performed in-place, without the need of a second output buffer.
- AEAD tag may be provided to a separate location, i.e. not concatenated to the ciphertext.
- Same performance as the original reference (unoptimised) C implementation in Release mode, about 2x slower in MinSizeRel mode.
- Hashing functions that can also automatically validate the digest against a known one when the hashing process is completed.
- A heavily documented developer-friendly API, making it easier to compile and add to your project, both through static and dynamic inclusion.
- Tested with 100% line and branch* coverage, with CI running on Linux, macOS and Windows with GCC, Clang and CL (MSVC) (*: branch coverage excludes the debugging-asserts).
Usage example
En/decrypting using Ascon128's Init-Update-Final API
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6
};
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6
};
const char associated_data_pt1[] = "2 messages will foll";
const char associated_data_pt2[] = "ow, but they are both secret.";
(associated_data_pt1));
(associated_data_pt2));
const char plaintext_pt1[] = "Hello, I'm a secret mes";
const char plaintext_pt2[] = "sage and I should be encrypted!";
uint8_t buffer[100];
size_t ciphertext_len = 0;
&ctx, buffer + ciphertext_len,
(uint8_t*) plaintext_pt1, strlen(plaintext_pt1));
&ctx, buffer + ciphertext_len,
(uint8_t*) plaintext_pt2, strlen(plaintext_pt2));
&ctx, buffer + ciphertext_len,
tag, sizeof(tag));
strlen(associated_data_pt1));
strlen(associated_data_pt2));
size_t plaintext_len = 0;
&ctx, buffer,
buffer, ciphertext_len);
bool is_tag_valid = false;
&ctx, buffer + plaintext_len,
&is_tag_valid, tag, sizeof(tag));
buffer[plaintext_len] = '\0';
printf("Decrypted msg: %s, tag is valid: %d\n", buffer, is_tag_valid);
Ascon cipher - Lightweight Authenticated Encryption & Hashing, also with Init-Update-Final paradigm.
#define ASCON_AEAD_TAG_MIN_SECURE_LEN
Minimum recommended length in bytes of the authentication tag generated by the authenticated encrypti...
Definition: ascon.h:131
ASCON_API void ascon_aead128_init(ascon_aead_ctx_t *ctx, const uint8_t key[ASCON_AEAD128_KEY_LEN], const uint8_t nonce[ASCON_AEAD_NONCE_LEN])
Online symmetric encryption/decryption using Ascon128, initialisation.
ASCON_API void ascon_aead128_assoc_data_update(ascon_aead_ctx_t *ctx, const uint8_t *assoc_data, size_t assoc_data_len)
Online symmetric encryption/decryption using Ascon128, feeding associated data.
#define ASCON_AEAD128_KEY_LEN
Length in bytes of the secret symmetric key used for the Ascon128 cipher.
Definition: ascon.h:109
ASCON_API size_t ascon_aead128_decrypt_update(ascon_aead_ctx_t *ctx, uint8_t *plaintext, const uint8_t *ciphertext, size_t ciphertext_len)
Online symmetric decryption using Ascon128, feeding ciphertext and getting plaintext.
ASCON_API size_t ascon_aead128_encrypt_final(ascon_aead_ctx_t *ctx, uint8_t *ciphertext, uint8_t *tag, size_t tag_len)
Online symmetric encryption using Ascon128, finalisation and tag generation.
ASCON_API size_t ascon_aead128_encrypt_update(ascon_aead_ctx_t *ctx, uint8_t *ciphertext, const uint8_t *plaintext, size_t plaintext_len)
Online symmetric encryption using Ascon128, feeding plaintext and getting ciphertext.
ASCON_API size_t ascon_aead128_decrypt_final(ascon_aead_ctx_t *ctx, uint8_t *plaintext, bool *is_tag_valid, const uint8_t *expected_tag, size_t expected_tag_len)
Online symmetric decryption using Ascon128, finalisation and tag validation.
#define ASCON_AEAD_NONCE_LEN
Length in bytes of the public nonce used for authenticated encryption and decryption.
Definition: ascon.h:125
Cipher context for authenticated encryption and validated decryption.
Definition: ascon.h:230
Encrypting using Ascon128's offline API for contiguous data
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6
};
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6
};
const char associated_data[] = "1 contiguous message will follow.";
const char plaintext[] = "Hello, I'm a secret message and I should be encrypted!";
uint8_t buffer[100];
uint8_t tag[42];
tag,
secret_key,
unique_nonce,
(uint8_t*) associated_data,
(uint8_t*) plaintext,
strlen(associated_data),
strlen(plaintext),
sizeof(tag));
secret_key,
unique_nonce,
(uint8_t*) associated_data,
(uint8_t*) buffer,
tag,
strlen(associated_data),
strlen(plaintext),
sizeof(tag));
puts("Correct decryption!");
} else {
puts("Something went wrong!");
}
ASCON_API bool ascon_aead128_decrypt(uint8_t *plaintext, const uint8_t key[ASCON_AEAD128_KEY_LEN], const uint8_t nonce[ASCON_AEAD_NONCE_LEN], const uint8_t *assoc_data, const uint8_t *ciphertext, const uint8_t *expected_tag, size_t assoc_data_len, size_t ciphertext_len, size_t expected_tag_len)
Offline symmetric decryption using Ascon128.
ASCON_API void ascon_aead128_encrypt(uint8_t *ciphertext, uint8_t *tag, const uint8_t key[ASCON_AEAD128_KEY_LEN], const uint8_t nonce[ASCON_AEAD_NONCE_LEN], const uint8_t *assoc_data, const uint8_t *plaintext, size_t assoc_data_len, size_t plaintext_len, size_t tag_len)
Offline symmetric encryption using Ascon128.
#define ASCON_TAG_OK
The tag is valid thus the associated data and ciphertext were intact.
Definition: ascon.h:161
Keyed hashing using Ascon-XOF's Init-Update-Final API
const uint8_t secret_key[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6
};
const char message_pt1[] = "Hello, I'm some data we need the digest of";
const char message_pt2[] = " but I'm very long and I was not transmit";
const char message_pt3[] = "ted in one contiguous block.";
uint8_t digest[21];
puts("Correct decryption!");
} else {
puts("Something went wrong!");
}
ASCON_API void ascon_hash_xof_init(ascon_hash_ctx_t *ctx)
Online Ascon-Hash with custom digest length (eXtendable Output Function, XOF), initialisation.
ASCON_API void ascon_hash_xof_update(ascon_hash_ctx_t *ctx, const uint8_t *data, size_t data_len)
Online Ascon-Hash with custom digest length (eXtendable Output Function, XOF), feeding data to hash.
ASCON_API bool ascon_hash_xof_final_matches(ascon_hash_ctx_t *ctx, const uint8_t *expected_digest, size_t expected_digest_len)
Online Ascon-Hash with custom digest length (eXtendable Output Function, XOF), finalisation and diges...
ASCON_API void ascon_hash_xof_final(ascon_hash_ctx_t *ctx, uint8_t *digest, size_t digest_len)
Online Ascon-Hash with custom digest length (eXtendable Output Function, XOF), finalisation and diges...
Internal cipher sponge state associated with a buffer holding for less-than-rate updates.
Definition: ascon.h:190
For more examples, check the test suite and how the Ascon API is used in there.
Dependencies of the library
Only the C standard library, mostly C99 features:
stdint.h
: uint8_t
, uint_fast8_t
, uint64_t
stddef.h
: size_t
, NULL
stdbool.h
: bool
, true
, false
Optional dependency: assert.h
, for assert()
. Used to add runtime checks of the Ascon API input for debugging (NULL pointers and incorrect order of function calling). The CMake script uses it only if assert.h
is found and only in the debug build type (CMAKE_BUILD_TYPE=Debug
). If compiled without the included CMakeLists.txt
, it's not used unless ASCON_INPUT_ASSERTS
is defined at compile time. The assertion function ASCON_ASSERT
can also be changed, if assert()
is not available.
FAQ
Q: May I use this library for-
A: YES! :D The library (and also the Ascon reference implementation) is released under the Creative Commons Zero (CC0) license which basically(*) means you can do whatever you want with it. Commercial purposes, personal projects, modifications of it, anything goes.
(*) for the legally-binding text check the license file.
Q: Where is the documentation?
A: The library header file inc/ascon.h
is documented with Doxygen and you can find it compiled here.
Q: Why should I use Ascon-AEAD instead of, say, AES?
A: Ascon is designed to be lightweight (great for embedded systems) and natively supports authenticated encryption of data of any length, while AES must be wrapped in an AEAD mode such as AES-GCM, which is well-proven but heavier.
Q: Why should I use Ascon-Hash instead of, say, SHA-256?
A: Ascon is designed to be lightweight (great for embedded systems) and does not suffer from length-extension attacks as SHA-256, given its sponge construction (similarly to what SHA-3 does). Additionally Ascon offers also the XOF hashing producing digests of variable length.
Q: Who designed Ascon? Who wrote this library?
A: Check the Authors file for details.
Q: I don't trust Ascon.
A: Good. You should not keep your guard up for everything, but Ascon has been selected as the primary choice for lightweight authenticated encryption in the final portfolio of the CAESAR competition (2014–2019) and is currently competing in the NIST Lightweight Cryptography competition (2019–) . Cryptographers like it and that's a good sign, right?
Q: I don't trust this implementation.
A: Good, again. You can read the source code to see what it does to be sure ;) If you find any bugs or possible improvements, open a pull request or an issue. I would like to make as clear and as good as possible.
Known limitations
- There is no architecture-specific optimisation, only a generic portable implementation using mostly
uint64_t
data types.
Compiling
The project's compilation has been tested with GCC, Clang and CL (MSVC). Most compiler warnings have already been mitigated, so they hopefully don't occur on your platform.
Static source inclusion
The project is relatively small, so you can simply include it into yours as a Git Subtree, Git Submodule or by simply copy-pasting the inc
and src
folders. Be sure to:
- Add
inc
and src
to the include folders list (the internal header is in src
).
- Add
src
to the sources folders list.
- Compile.
Compiling Ascon into all possible targets with CMake
A note if you are compiling on Windows from the command line:
- you will need the environment variables to use the MSVC toolchain from the command line
- be sure to select the generator
NMake Makefiles
when configuring CMake
Compile an out of source build:
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release # On Windows add: -G "NMake Makefiles"
cmake --build . --parallel 8
This will build all useful targets:
- static libraries:
asconfull
with full feature set
ascon128
with only Ascon128
ascon128a
with only Ascon128a
ascon80pq
with only Ascon80pq
asconhash
with only Ascon-hash and Ascon-XOF
ascon128hash
with only Ascon128, Ascon-hash and Ascon-XOF
ascon128ahash
with only Ascon128a, Ascon-hash and Ascon-XOF
ascon80pqhash
with only Ascon80pq, Ascon-hash and Ascon-XOF for a smaller build result when not all features are needed
ascon
a shared library (.dll
or .dylib
or .so
) with full feature set (like asconfull
, but shared)
testascon
a test runner executable , which test all features of the static library
testasconshared
a test runner executable , which test all features of the shared library
Doxygen (if installed) is built separately to avoid recompiling it for any library change:
cmake --build . --target ascon_doxygen
To compile only a single target, for example ascon80pq
, run
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --target ascon80pq
To compile with the optimisation for size, use the -DCMAKE_BUILD_TYPE=MinSizeRel
flag instead.
To run the test executables, call ctest
in the build directory.