Various post-quantum anonymous credentials based on the UOV signature scheme and the VOLE-in-the-Head (VOLEitH) proof system from FAEST:
-
PomFRIT, a blind signature. Allows a client to obtain and later present a signature without revealing the message to the issuer.
-
VOLE-IHAT, an issuer-hiding anonymous token (IHAT). Similar to a blind signature, except presentation (aka redemption) also hides the issuer among an anonymity set.
-
VOLE-ACT, an anonymous credit token (ACT). The token carries state across presentations (aka spends) that the issuer updates without learning its value.
Warning
Experimental and not audited. Do not use in production. APIs and wire formats will change as the specifications evolve.
You need Meson 1.4 or later, Ninja, Python 3, and Clang 21 or later or GCC 16 or later.
meson setup build
meson compile -C build
meson test -C build --print-errorlogsOn MacOS you might need to upgrade LLVM:
brew install meson ninja llvm@22
export CC=$(brew --prefix llvm@22)/bin/clang
export CXX=$(brew --prefix llvm@22)/bin/clang++The "Hello, World!" of this library is a blind signature:
#include <vole_mole/pomfrit.hpp>
#include <vole_mole/uov.hpp>
using namespace vole_mole;
const uov::SecretKey sk(uov::generate_secret_key_bytes());
const uov::PublicKey pk(sk.public_key_bytes());
// Client: Generate issue request.
auto [pending, request] = pomfrit::issue_request(pk, msg);
// Issuer: Generate issue response.
const auto response = pomfrit::issue_response(sk, request);
// Client: Finalize the blind signature.
const auto sig = std::move(pending).finalize_issue(pk, response);
if (!sig) {
return EXIT_FAILURE;
}
// Verifier: Verify the blind signature.
const bool ok = pomfrit::verify(pk, msg, *sig);The examples/ folder includes additional examples:
| Example | Shows |
|---|---|
pomfrit.cpp |
PomFRIT signature issuance and verification |
ihat.cpp |
VOLE-IHAT issuance and redemption |
unbound_ihat.cpp |
VOLE-IHAT with late binding of the redemption context |
act.cpp |
VOLE-ACT issuance and spend |
meson setup build-release --buildtype=release
meson test -C build-release --benchmark -vClient messages carrying proofs are 5–17 KB. On an Apple M4 Pro, every step takes under 2 ms, except VOLE-IHAT redemption, which grows with the number of Anchors (about 7 ms for 64). See docs/perf.md for full numbers, the smaller-proof parameter trade-off (4-12KB), and how to run the benchmarks.
Create subprojects/vole-mole.wrap in your project:
[wrap-git]
url = https://github.com/cloudflareresearch/vole-mole.git
revision = <commit>
depth = 1Set revision to a commit hash. The API is unstable, so don't track a branch.
Meson clones the repository and its dependencies during meson setup. Then
add to your meson.build:
vole_mole_dep = subproject('vole-mole',
default_options : ['tests=false', 'benchmarks=false', 'examples=false'],
).get_variable('vole_mole_dep')This code has not been audited.
The library does not prevent double spending. VOLE-IHAT finalize_redeem and
VOLE-ACT spend_response return a nullifier; before accepting the presentation,
the caller needs to ensure that it has not recorded the same nullifier in a
previous presentation. Likewise, typical applications of PomFRIT will include a
nullifier in the message that the verifier is meant to use for double spend
prevention.
BSD 3-Clause, see LICENSE. Meson downloads
faest-arch-opt (MIT) and pqov (CC0 or Apache-2.0) as
subprojects. src/voleith.hpp is adapted from faest-arch-opt and keeps its MIT
notice.
This library is based on a prototype by Tianyu Zhang, written during his Summer 2026 internship at Cloudflare Research. Tianyu also contributed to the circuit and protocol designs.