Build from source with no vendored binaries: - Remove prebuilt libzuptsdk.so / libpqvaptvupt.so (and a stray .pyc). The default build needs only a C compiler + make; it links no external library and installs no .so. The libzuptsdk-backed modes (Argon2id KDF, --pq-sdk, --pq-box) are gated behind an opt-in `make WITH_SDK=1`. The default password KDF is PBKDF2-SHA256 and --pq (native ML-KEM-768 + X25519) is the built-in PQ mode. openSUSE/RPM/deb/AUR/Homebrew/Nix recipes bumped to 4.1.0; the openSUSE spec now builds source-only (%files ships no .so, %build/%install WITH_SDK=0). Fix: multithreaded encrypted archives were unextractable on the native AEAD path. The parallel compress/decompress workers skipped the F-09 frame-preface AAD that the serial path and the archive's AAD_PREFACE flag bind into every block MAC, so each multithreaded block failed authentication. The workers now bind the preface via a shared serializer; output is byte-identical across thread counts and interoperates with single-threaded archives (also fixes `--kdf pbkdf2 -t N` in any build). Security hardening (crafted-archive memory safety + crypto): - LZH raw code-length stack overflow + huff_lut OOB write - overflow-safe bounds in parse_index and solid-mode extract (heap OOB read) - SEQ decoder safe-zone heap overflow (litlen+matchlen reserve) - require the per-block ENCRYPTED flag on encrypted archives (plaintext forgery) - cap archive-supplied PBKDF2 iteration count (KDF-amplification DoS) - non-elidable secret wipe in the SDK path; restored disk images created 0600 Docs: remove AUDIT.md / BENCHMARKS.md / ROADMAP.md; trim marketing/AI-styled text and correct KDF/PQ facts across README, SECURITY, INSTALL, DISTRIBUTION, THREAT_MODEL, THIRD-PARTY-NOTICES, the man page, and packaging READMEs. Wire format v1.6 unchanged.
6.2 KiB
libzuptsdk
Public C ABI for the VaptVupt backup compression library.
Provides post-quantum encrypted compression as a stable, embeddable shared library, independent of the vaptvupt CLI and of any external compression library — everything is built from VaptVupt's own implementations.
- Version: 1.0.0
- License: AGPL-3.0-or-later
- ABI: Stable across 1.x via versioned symbols (
ZUPTSDK_1.0) - C standard: Public header is C99; C11 implementation; works in C++17
Features
- Hybrid post-quantum encryption — ML-KEM-768 + X25519 KEM
- Authenticated encryption — AES-256-CTR + HMAC-SHA256, PBKDF2-SHA256 KDF
- Hardware-adaptive compression — VaptVupt on AVX2/NEON, LZHP elsewhere
- Streaming I/O — read/write callbacks for sockets, pipes, encrypted volumes
- Secure memory — mlock-backed buffers for passwords and keys, zeroed on destroy
- Constant-time crypto — Jasmin-verified assembly on x86_64
- Per-context state — no globals; safe to use from any thread on distinct contexts
- Custom allocator hooks — supply your own malloc/free
Quick start (C)
#include <zuptsdk.h>
zuptsdk_ctx_t *ctx;
zuptsdk_ctx_create(&ctx);
zuptsdk_secure_buf_t *pw;
zuptsdk_secure_buf_from_data((const uint8_t *)"mypassword", 10, &pw);
uint8_t *archive;
size_t archive_sz;
zuptsdk_compress_buffer(ctx, NULL, "data.bin",
my_data, my_data_size,
pw, NULL,
&archive, &archive_sz);
/* ... store archive somewhere ... */
uint8_t *out;
size_t out_sz;
zuptsdk_extract_buffer(ctx, archive, archive_sz, pw, NULL, &out, &out_sz);
zuptsdk_free(archive);
zuptsdk_free(out);
zuptsdk_secure_buf_destroy(pw);
zuptsdk_ctx_destroy(ctx);
Build with pkg-config:
gcc myapp.c $(pkg-config --cflags --libs zuptsdk) -o myapp
Quick start (Python)
import zuptsdk
with zuptsdk.Context() as ctx:
archive = ctx.compress_buffer(b"hello world",
name="hello.txt",
password=b"secret")
data = ctx.extract_buffer(archive, password=b"secret")
assert data == b"hello world"
Post-quantum mode:
with zuptsdk.Context() as ctx:
kp = ctx.generate_keypair()
kp.save("/tmp/mykey") # writes mykey.key (priv, 0600) + mykey.pub (pub, 0644)
archive = ctx.compress_buffer(b"secret data",
name="s.txt",
public_key=kp.public)
data = ctx.extract_buffer(archive, private_key=kp.private)
Build & install
git clone https://git.securityops.co/cristiancmoises/vaptvupt
cd vaptvupt
make # builds CLI (required: produces jasmin/*.o assembly objects)
make sdk # builds libzuptsdk.so.1.0.0 + libzuptsdk.a + zuptsdk.pc
make sdk-test # runs C roundtrip suite (15 tests)
sudo make sdk-install PREFIX=/usr/local
This SDK is built from source via make sdk; the previously vendored prebuilt vendor/zuptsdk/libzuptsdk.so has been removed from the tree.
This installs:
/usr/local/include/zuptsdk.h/usr/local/lib/libzuptsdk.so.1.0.0(with versioned.so.1and.sosymlinks)/usr/local/lib/libzuptsdk.a/usr/local/lib/pkgconfig/zuptsdk.pc
Symbol visibility
The shared library exports only the 55 documented public symbols, all prefixed with zuptsdk_. Internal zupt_* and vv_* symbols are hidden via a linker version script.
Verify yourself:
make sdk-verify-symbols
# [sdk-verify] checking exported symbols in sdk/build/libzuptsdk.so.1.0.0
# 55 exported / 55 declared in version script
# PASS: no symbol leakage, all declared symbols exported
ABI stability policy
Every symbol declared in zuptsdk.h is part of the stable v1.0 ABI and is gated under the linker tag ZUPTSDK_1.0.
- New symbols in v1.x get added under new tags (
ZUPTSDK_1.1, ...) - Existing symbols never change signature within v1.x
- Breaking changes require a major bump (
libzuptsdk.so.2)
Do not link against internal zupt_* symbols even if you find them in the static archive — they will disappear without notice.
Thread safety
- Concurrent calls on distinct contexts are safe (MT-Safe).
- Concurrent calls on the same context are not safe.
For parallel work, create one context per worker thread.
Memory ownership
Every output pointer documents its destroyer. Always use the documented function (zuptsdk_free, zuptsdk_*_destroy) to release memory — never bare free() — because the library may have been built with a custom allocator.
Function parameter conventions:
[in]— caller owns, library reads only[out]— caller owns, library writes[in,out]— caller owns, library reads and writes[transfers]— ownership moves caller ↔ library[borrowed]— pointer valid only for the duration of the call
Error handling
Functions return int where 0 = success, negative = zuptsdk_error_t code.
int rc = zuptsdk_compress_buffer(...);
if (rc != ZUPTSDK_OK) {
fprintf(stderr, "%s\n", zuptsdk_strerror(rc));
fprintf(stderr, " detail: %s\n", zuptsdk_last_error_detail());
return rc;
}
zuptsdk_last_error_detail() returns a thread-local string with file:line context.
Components
sdk/
├── include/zuptsdk.h # Public C99 header (55 functions, 7 opaque types)
├── src/zuptsdk.c # Implementation (wraps zupt internals)
├── zuptsdk.map # Linker version script (gates exports)
├── Makefile.sdk # Build integration
├── bindings/python/zuptsdk.py # Python cffi reference bindings
├── tests/test_sdk_roundtrip.c # C roundtrip suite
└── tests/test_python.py # Python test suite
License
libzuptsdk is licensed under AGPL-3.0-or-later (see sdk/LICENSE).
The AGPL allows everyone to use the library freely, but anyone running it as a network service must publish their source code modifications.
Contact
- Repository: https://git.securityops.co/cristiancmoises/vaptvupt
- Website: https://zupt.securityops.co
- Email: zupt@riseup.net