Introduction

Geralt is a modern cryptographic library for .NET 6+ based on libsodium and inspired by Monocypher.

  • Simple: an easy-to-learn API with descriptive naming. Only one algorithm for each task is provided when possible.

  • Modern: the latest and greatest cryptographic algorithms, such as AEGIS-128L/AEGIS-256, (X)ChaCha20-Poly1305, BLAKE2b, Argon2id, X25519, and Ed25519.

  • Secure: libsodium was audited in 2017 and is the library of choice for lots of projects and even large companies.

  • Fast: libsodium is faster than many other cryptographic libraries. Furthermore, Geralt uses Span<T> buffers to avoid memory allocations.

Installation

Geralt is available as a NuGet package. It's supported on the following platforms:

Note that libsodium requires the Visual C++ Redistributable for Visual Studio 2015-2022 on Windows. Instructions on how to deal with this can be found here.

To get Geralt working on Android, you need to build the libsodium binaries yourself because they aren't included in the libsodium NuGet package. You then need to modify the project slightly to target that platform.

win-arm64 support was added to the 1.0.19.1+ libsodium NuGet package, but it reportedly doesn't work, which is an upstream issue.

Source code

You can find the source code on GitHub.

License

Geralt is licensed under the MIT license.

Goals

  • Span<T> all the things: enables the secure erasure of bytes and boosts performance.

  • Descriptive naming: BLAKE2b, not GenericHash.

  • Same vocabulary for everything: key, nonce, salt, input keying material, output keying material, etc.

  • Minimal parameters: no key parameter for an unkeyed hash.

  • Consistent parameter ordering: buffers come first.

  • Public constants: easy to create buffers.

  • One algorithm for each task: (X)ChaCha20-Poly1305, BLAKE2b, Argon2id, X25519, and Ed25519.

  • Some low-level functions: useful for custom constructions.

Out of scope

  • Full misuse resistance (e.g. no nonces or optional nonces). This can limit the user, doesn't work well with spans, and overcomplicates code.

  • Solving the key reuse problem (e.g. a mandatory context for everything or wrappers instead of raw bytes). I'm not convinced either tactic works, and it again adds complexity.

  • Old NaCl APIs, such as crypto_box. These shouldn't be used.

  • Other primitives unless they solve a problem. AES-GCM causes problems (e.g. it requires hardware support). AEGIS solves problems (e.g. it's key committing and supports random nonces whilst being faster/stronger than AES-GCM).

  • Experimental ideas/custom constructions (e.g. anything without an RFC or Internet-Draft), which can go in a separate project.

  • Duplicate methods that return byte arrays.

  • Unnecessary 'convenience' functions, like GenerateKey() in almost every class.

  • Guarded heap allocations, which would add complexity and reduce performance.

  • Support for old/no longer supported versions of .NET.

Acknowledgements

I'd like to say a big thanks to:

Last updated