A portable and efficient C library for developing Zero-Knowledge applications for embedded systems.
DISCLAIMER: this library is currently unstable. Furthermore, it has not gone through an exhaustive security analysis, so it is not intended to be used in a production environment, only for academic purposes.
An academic paper about ZPiE has been published in the special issue Recent Advances in Security, Privacy, and Applied Cryptography of the journal Mathematics (2021) and can be found here.
ZPiE supports the following Zero-Knowledge schemes, defined over the elliptic curves BN128 and BLS12-381:
- zk-SNARKs for arithmetic circuits. We support the Groth'16 scheme. ZPiE includes the following gadgets:
- Twisted Edwards curve operations.
- EdDSA signature algorithm over Baby JubJub elliptic curve and BN128.
- MiMC-7 hashing function (BN128 order).
- Bulletproofs. We support range proofs (and aggregated range proofs).
In order to compute the circuit inputs for the above described gadgets, you can use this repository.
ZPiE needs criterion. To install it, simply run:
sudo apt install libcriterion-dev
MCL is also required, but will be compiled automatically when compiling ZPiE.
ZPiE can be built as follows (build/libzpie.a):
git clone https://github.com/xevisalle/zpie
cd zpie
make
You can execute the tests by running:
make test
You can compile a benchmarking application by running the following command, which will also prompt you with a set of available options to benchmark all the features of ZPiE:
make bench
We can specify the elliptic curve to be used:
make bench CURVE=[OPTION]
Where [OPTION] can be:
BN128 (default)
BLS12_381
We can specify to compile the code to run in multi-thread mode:
make bench MULTI=on
Here there is an example on how to use zk-SNARKs. Copy the following snippet into a file (e.g. called /src/main.c):
#include <zpie.h>
void circuit()
{
// set a public element
zpie_element out;
zpie_init_public(&out);
// set private elements
zpie_element a, b;
zpie_init(&a);
zpie_init(&b);
// input a value for the elements
zpie_input(&a, "1234");
zpie_input(&b, "5678");
// apply a constraint multiplying such elements
zpie_mul(&out, &a, &b);
}
int main()
{
// we perform the setup
zpie_setup_keys keys;
zpie_perform_setup(&keys, &circuit);
// we generate a proof
zpie_proof p;
zpie_generate_proof(&p, &circuit, &keys.pk);
// we verify the proof
if (zpie_verify_proof(&circuit, &p, &keys.vk))
printf("Proof verified.\n");
else
printf("Proof cannot be verified.\n");
}And compile and execute using:
gcc main.c -o main build/libzpie.a lib/mcl/lib/lishe384_256.a lib/mcl/lib/libmcl.a -I ./include -I lib/mcl/include -lcriterion -lm -lstdc++ -DBN128 && ./main
More circuit examples can be found in the /src/tests.c file.
TBC.
First, we have to build MCL for i386 64-bits:
git submodule update --init
cd lib/mcl
make -j16 ARCH=x86_64
We finally build ZPiE:
make bench ARCH=x86_64
First, we have to build MCL for i386 32-bits:
git submodule update --init
cd lib/mcl
make -j12 ARCH=x86
We finally build ZPiE:
make bench ARCH=x86
First, we have to build MCL for ARM 64-bits:
git submodule update --init
cd lib/mcl
make -j12 CXX=aarch64-linux-gnu-g++ ARCH=aarch64 MCL_USE_GMP=0
We finally build ZPiE:
make bench ARCH=aarch64
First, we have to build MCL for ARM 32-bits:
git submodule update --init
cd lib/mcl
make -j12 CXX=arm-linux-gnueabihf-g++ ARCH=armv6l CFLAGS_USER="-I /usr/local/include" LDFLAGS="/usr/local/lib/libgmp.a /usr/local/lib/libgmpxx.a"
We finally build ZPiE:
make bench ARCH=arm