_images/LibSWIFFT-logo.png

LibSWIFFT v1.2.0 josspaper

LibSWIFFT: Fast Secure Homomorphic Hashing

LibSWIFFT is a production-ready C/C++ library providing SWIFFT, one of the fastest available secure hash functions, which is also collision-resistant as well as facilitates zero-knowledge proofs of knowledge of a preimage (ZKPoKP) and post-quantum digital signatures.

Secure Homomorphic Hashing

LibSWIFFT provides a function to hash an input vector of 2048 values in [0..1], given in a buffer of 256 bytes (packed 8-bits), to an output vector of 64 values in [0..256], given in a buffer of 64 words (padded 16-bits). It also provides a function to hash a vector of 2048 values in [-1..1], given in an input and a sign vector, each of 2048 bits. These are implementations of the SWIFFT secure hash function homomorphic (i.e., the hash of the sum of vectors is the sum of their hashes) in modulu-257 arithmetic.

Fast

LibSWIFFT is fast. Here is the output from a test-case of LibSwifft v1.0.0 that demonstrates hashing (for an input of 256 bytes) running at a rate of less than 5 cycles-per-byte single-threaded using AVX2 on an Intel Skylake microarchitecture (Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz):

$ ./test/swifft_catch "swifft takes at most 2000 cycles per call"
Filters: swifft takes at most 2000 cycles per call
running 1*10000000 rounds: cycles/rounds=1097.94 cycles/byte=4.28882 Giga-cycles/sec=2.30399 MB/sec=512.322 cycles/rdtsc=16

This is faster than the rate of the recent K2SN-MSS’s binary 16-bit SWIFFT function implementation (for an input of 128 bytes) on the same execution settings, i.e. single-threaded using AVX2 on an Intel Skylake microarchitecture (Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz):

$ ./tester
 1000000 SWIFFT16 rounds: cycles/round=737.363098 cycles/byte=5.760649

LibSWIFFT supports microarchitectures with AVX, AVX2, and AVX512 instruction sets to take advantage of available hardware acceleration.

Production-Ready

LibSWIFFT v1.2.0 ships with over 30 test-cases including millions of checks that provide excellent coverage of the library’s code and the mathematical properties of the SWIFFT function it implements:

$ ./test/swifft_catch

===============================================================================
All tests passed (6648384 assertions in 32 test cases)

LibSWIFFT also ships with detailed documentation, including references for its C API and C++ API. It has a robust and portable build system based on cmake. All include files are conveniently organized under a dedicated libswifft directory. Finally, it requires few dependencies at build-time and run-time.

Easy to use C and C++ APIs

LibSWIFFT is also easy to use. Minimal code using the C API looks like this:

#include "libswifft/swifft.h"
/* later, inside a function: */
SWIFFT_ALIGN BitSequence input[SWIFFT_INPUT_BLOCK_SIZE];
SWIFFT_ALIGN BitSequence output[SWIFFT_OUTPUT_BLOCK_SIZE];
/* after input is populated (not shown here), it is time to compute the hash: */
SWIFFT_Compute(input, output); /* compute the hash of the input into the output */

The SWIFFT_ALIGN macro is needed for the required memory-alignment of buffers passed to LibSWIFFT functions. The equivalent code using the C++ API looks like this:

#include "libswifft/swifft.hpp"
using namespace LibSwifft;
/* later, inside a function: */
SwifftInput input;
SwifftOutput output;
/* after input is populated (not shown here), it is time to compute the hash: */
SWIFFT_Compute(input.data, output.data); /* compute the hash of the input into the output */

SwifftInput and SwifftOutput are auto-memory-aligned.

The code using the C API for signed hashing in compact-form looks like this:

#include "libswifft/swifft.h"
/* later, inside a function: */
SWIFFT_ALIGN BitSequence input[SWIFFT_INPUT_BLOCK_SIZE];
SWIFFT_ALIGN BitSequence output[SWIFFT_OUTPUT_BLOCK_SIZE];
SWIFFT_ALIGN BitSequence compact[SWIFFT_COMPACT_BLOCK_SIZE];
SWIFFT_ALIGN BitSequence sign[SWIFFT_INPUT_BLOCK_SIZE];
/* after input and sign are populated (not shown here), it is time to compute the hash: */
SWIFFT_Compute(input, sign, output); /* compute the hash of the signed input into the output */
SWIFFT_Compact(output, compact); /* compact the hash */

And the equivalent code using the C++ API looks like this:

#include "libswifft/swifft.hpp"
using namespace LibSwifft;
/* later, inside a function: */
SwifftInput input;
SwifftOutput output;
SwifftCompact compact;
SwifftInput sign;
/* after input and sign are populated (not shown here), it is time to compute the hash: */
SWIFFT_Compute(input.data, sign.data, output.data); /* compute the hash of the signed input into the output */
SWIFFT_Compact(output.data, compact.data);

For future flexibility in implementation, it is recommended to invoke SWIFFT functions via the SWIFFT object APIs (since v1.2.0):

#include "libswifft/swifft_object.h"
using namespace LibSwifft;
/* initialize object APIs once, possibly inside a function: */
swifft_object_t swifft;
SWIFFT_InitObject(&swifft);
/* later, inside a function: */
SwifftInput input; /* auto-memory-aligned */
SwifftOutput output; /* auto-memory-aligned */
SwifftCompact compact; /* optional, auto-memory-aligned */
/* arithmetic operations are available via swifft.arith, for example: */
swifft.arith.SWIFFT_ConstSet(input.data, 1);
/* hash operations are available via swifft.hash, for example: */
swifft.hash.SWIFFT_Compute(input.data, output.data); /* compute the hash of the input into the output */
swifft.hash.SWIFFT_Compact(output.data, compact.data); /* optionally, compact the hash */

Rationale

Here the rationale for making LibSWIFFT is explained.

About SWIFFT and LibSWIFFT

This part describes SWIFFT and LibSWIFFT.

User Guide

The User Guide explains how to get started with LibSWIFFT and how to make the most of it.

API Guide

The API Guide leads to the LibSWIFFT API reference.