Crypto library in C, primarily for EC. Still semi-experimental.
Used as the backend for bcrypto.
- Generic, without sacrificing speed or security.
- Use field element backends generated by fiat-crypto (which have proofs of correctness, formal verification, etc).
- Use a generic barrett reduction for scalar arithmetic (we use a reimplementation of GMP's mpn_ functions for this).
- Keep constant-time multiplication algorithms as simple as possible.
- Constant time, stack-based, and so on.
- Expose a simple opaque API which accepts all arguments in wire format (this eases implementation for language bindings, wasm, and other ffis).
-
Curve Support:
- p192
- p224
- p256
- p384
- p521
- secp256k1
- curve25519
- curve448
- edwards25519
- edwards448
- curve1174
-
Schemes:
- ECDSA
- BIP-Schnorr
- BIP340
- ECDH
- EdDSA
- Ristretto
#include <assert.h>
#include <stddef.h>
#include <torsion/ecc.h>
#include <torsion/hash.h>
#include <torsion/rand.h>
int main(void) {
wei_curve_t *ec = wei_curve_create(WEI_CURVE_SECP256K1);
const char str[] = "hello world";
unsigned char priv[32];
unsigned char entropy[32];
unsigned char msg[32];
unsigned char pub[33];
unsigned char sig[64];
sha256_t hash;
/* Hash our message with sha256. */
sha256_init(&hash);
sha256_update(&hash, str, sizeof(str) - 1);
sha256_final(&hash, msg);
/* Grab some entropy from the OS. */
assert(torsion_getentropy(entropy, 32));
/* Generate a key pair using entropy. */
ecdsa_privkey_generate(ec, priv, entropy);
assert(ecdsa_pubkey_create(ec, pub, NULL, priv, 1));
/* Sign in constant time. */
assert(ecdsa_sign(ec, sig, NULL, msg, sizeof(msg), priv));
/* Verify our signature. */
assert(ecdsa_verify(ec, msg, sizeof(msg), sig, pub, sizeof(pub)));
/* Cleanup. */
wei_curve_destroy(ec);
return 0;
}
Compile with:
$ cc -o example -I/path/to/libtorsion/include example.c /path/to/libtorsion.a
libtorsion supports a CMake build (recommended) and an autotools build.
The CMake build is fairly straightforward and offers the following options:
TORSION_ENABLE_ASM=ON
- Use inline assembly if availableTORSION_ENABLE_COVERAGE=OFF
- Enable coverageTORSION_ENABLE_DEBUG=ON
- Enable debug build (forces -g or /Zi)TORSION_ENABLE_INT128=ON
- Use__int128
if availableTORSION_ENABLE_MPI=OFF
Export MPI functionsTORSION_ENABLE_PIC=ON
- Enable PICTORSION_ENABLE_PTHREAD=ON
- Use pthread if present in libcTORSION_ENABLE_RNG=ON
- Enable RNGTORSION_ENABLE_SHARED=ON
- Build shared libraryTORSION_ENABLE_TESTS=ON
- Build testsTORSION_ENABLE_TLS=ON
- Use thread-local storage if availableTORSION_ENABLE_VERIFY=OFF
- Enable scalar bounds checks
To view the autoconf options, see ./configure --help
.
CMake:
$ cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=Release .
$ make
Autotools:
./autogen.sh
./configure CFLAGS=-O3
make
Builds on windows will produce both a static and shared library. To deal with
the naming collision, the static library is called libtorsion.lib
whereas the
shared import library is named torsion.lib
(this follows Microsoft's new
naming convention).
MSVC:
$ cmake .
$ cmake --build . --config Release
Clang (better performance):
$ cmake -G 'NMake Makefiles' -DCMAKE_C_COMPILER=clang-cl \
-DCMAKE_BUILD_TYPE=Release .
$ nmake
For systems without CMake installed, a simple NMake build is also included. It assumes MSVC (cl), but also works with Windows Clang (clang-cl).
$ nmake /F Makefile.msvc
$ nmake /F Makefile.msvc CC=clang-cl
Another way to build for Windows is by cross-compiling with MinGW (useful for those averse to Windows or who do not have a Windows machine to build on).
CMake:
$ ./scripts/mingw-cmake cmake -DCMAKE_BUILD_TYPE=Release .
$ make
Autotools:
./autogen.sh
./scripts/mingw-configure ./configure CFLAGS=-O3
make
CMake:
$ ./scripts/wasi-cmake cmake -DCMAKE_BUILD_TYPE=Release .
$ make
Autotools:
./autogen.sh
./scripts/wasi-configure ./configure CFLAGS=-O3
make
CMake:
$ emcmake cmake -DCMAKE_BUILD_TYPE=Release .
$ make
Autotools:
./autogen.sh
emconfigure ./configure CFLAGS=-O3
make
When CMakeLists.txt is invoked as a CMake subproject, it will expose a single
static library target named torsion
, skipping all other targets (tests,
benchmarks, etc). The static library is built with -fPIC
and all symbols
hidden, thus allowing other libraries to be built on top of a vendored
libtorsion.
Example:
add_subdirectory(deps/libtorsion)
target_link_libraries(my_project PRIVATE torsion)
libtorsion was written generically enough to support any build system you might want to use, with only a few key configuration options necessary.
To incorporate libtorsion into a different build system you must be aware of various configuration options that torsion uses internally.
Any of the following may be passed as defines to the preprocessor:
TORSION_EXPORT
- Export symbols (necessary for shared if-fvisibility=hidden
is passed).TORSION_HAVE_CONFIG
- Disables preprocessor-based autoconfiguration¹.TORSION_HAVE_ASM
- GNU-flavored inline assembly is available².TORSION_HAVE_INT128
- The__int128
type is available².TORSION_HAVE_PTHREAD
- The pthread API is available².TORSION_TLS=[tls-keyword]
- Thread-local storage is available².TORSION_COVERAGE
- Coverage is enabled viagcov
. Disable assertions.TORSION_DEBUG
- Enable assertions.TORSION_VERIFY
- Enable extra debugging checks.TORSION_HAVE_CLOCK_GETTIME
-clock_gettime(3)
is available²³.TORSION_HAVE_FORK
-fork(2)
andwaitpid(2)
are available²³.TORSION_HAVE_GETTIMEOFDAY
-gettimeofday(3)
is available²³.TORSION_HAVE_MPI
- Export MPI functions.TORSION_HAVE_RNG
- libtorsion was compiled with RNG support³.TORSION_HAVE_TIME
-time(2)
is available²³.TORSION_HAVE_ZLIB
-<zlib.h>
is available and we are linked with-lz
³.
Footnotes:
- By default torsion will attempt to autoconfigure some options by using the C preprocessor to detect features.
TORSION_HAVE_CONFIG
must be defined for this option to have any effect.- This option affects tests and benchmarks only.
If you are using a build system where detecting features is difficult, you can
have libtorsion attempt to auto-detect features using the C preprocessor:
simply do not pass -DTORSION_HAVE_CONFIG
.
libtorsion is written to be compatible with C89/C90 (with one caveat: the
system must provide an stdint.h header). This means that passing -std=c89
should be fine unless you are building with RNG support. Various C standard
libraries base their default features on the language standard and will not
expose certain POSIX APIs (or system-specific APIs) if a strict C version is
passed.
This also means you should not pass any feature test macros that may downgrade
the features apart from what is necessary for the RNG to function. For example,
passing _POSIX_SOURCE
or _POSIX_C_SOURCE
will probably break the RNG on
Linux (assuming glibc is used).
Furthermore, the RNG accesses errno
, which means a thread-local errno
is
desirable. By defalt, certain OSes do not expose a thread-safe errno
. This
includes Solaris and AIX. Please ensure that your build produces thread-safe
code (the flags required for this differ from system to system).
The libtorsion codebase is also valid C++ and can be compiled inside your C++ project without any modifications.
If you contribute code to this project, you are implicitly allowing your code
to be distributed under the MIT license. You are also implicitly verifying that
all code is your original work. </legalese>
- Copyright (c) 2020, Christopher Jeffrey (MIT License).
See LICENSE for more info.