Version bumped to 5.0.0 across include/zupt.h, all packaging recipes, man page, and docs. Audit fixes (pre-5.0.0 review): - src/zupt_format.c: overflow-safe bound in the solid-mode `test` path (off+sz could wrap and drive an OOB read in zupt_xxh64 on a crafted archive; the extract path was already hardened, the test path was not). - gui: run_async now marshals the completion callback onto the GUI thread with QueuedConnection (a bare functor connected DirectConnection and touched widgets off the worker thread); Extract auto-detect note survives the log clear via a new `info` param. - .github/workflows/ci.yml: trigger on `master` (was main/develop, so CI never ran); `make dist` tarball is vaptvupt-*.tar.gz not zupt-*; the ASAN PQ round-trip uses native --pq (was --pq-sdk, which fails on the source-only build and blocked the release job). Documentation: - New AUDIT.md (methodology, FIPS 203 conformance validation, findings, repro). - CHANGELOG 5.0.0 entry covers the FIPS 203 conformance fix + BREAKING note and the GUI/CLI/security/packaging work. - README "What's new in 5.0.0", download tables (incl. Windows/macOS/BSD + portable GUI), version-history row. - SECURITY.md + THREAT_MODEL.md: ML-KEM-768 documented as FIPS 203, validated byte-for-byte against OpenSSL 3.5. - Accuracy fixes: man page (--kdf default is PBKDF2 on source-only; codec 2.60.4), rpm %description, debian control/copyright, homebrew header (no vendored library on source-only builds). make check 16/16 (FIPS 203 conformance 3/3, all distro-safe checks).
730 lines
21 KiB
Groff
730 lines
21 KiB
Groff
.\" Manpage for vaptvupt (formerly zupt; INPI Brasil trademark rename in v3.0.0)
|
|
.\" SPDX-License-Identifier: AGPL-3.0-or-later
|
|
.\" Copyright (c) 2025-2026 Cristian Cezar Moisés
|
|
.TH VAPTVUPT 1 "July 2026" "vaptvupt 5.0.0" "User Commands"
|
|
|
|
.SH NAME
|
|
vaptvupt \- post-quantum backup compression utility (formerly zupt)
|
|
|
|
.SH SYNOPSIS
|
|
.B vaptvupt compress
|
|
.RI [ options ]
|
|
.I out.zupt
|
|
.I files...
|
|
.br
|
|
.B vaptvupt extract
|
|
.RI [ options ]
|
|
.I archive.zupt
|
|
.br
|
|
.B vaptvupt list
|
|
.RI [ options ]
|
|
.I archive.zupt
|
|
.br
|
|
.B vaptvupt test
|
|
.RI [ options ]
|
|
.I archive.zupt
|
|
.br
|
|
.B vaptvupt info
|
|
.I archive.zupt
|
|
.br
|
|
.B vaptvupt bench
|
|
.I files/dirs...
|
|
.br
|
|
.B vaptvupt disk backup
|
|
.RI [ options ]
|
|
.I out.zupt
|
|
.I device
|
|
.br
|
|
.B vaptvupt disk restore
|
|
.RI [ options ]
|
|
.I archive.zupt
|
|
.I device
|
|
.br
|
|
.B vaptvupt keygen
|
|
.RI [ options ]
|
|
.br
|
|
.B vaptvupt version
|
|
.br
|
|
.B vaptvupt help
|
|
|
|
.PP
|
|
The legacy command name
|
|
.B zupt
|
|
is preserved as an alias for backward compatibility; both invocations
|
|
behave identically.
|
|
|
|
.SH DESCRIPTION
|
|
.B vaptvupt
|
|
compresses and encrypts files, directories, and whole block devices
|
|
into self-contained, authenticated archives with the
|
|
.B .zupt
|
|
extension. It targets long-lived backup storage where:
|
|
|
|
.RS
|
|
.IP \(bu 2
|
|
the archive is written once and restored under time pressure many years later;
|
|
.IP \(bu 2
|
|
the encryption envelope must remain secure against a future cryptographically-relevant quantum computer (ML-KEM-768);
|
|
.IP \(bu 2
|
|
every byte of the archive — header, footer, per-block metadata, comments — is authenticated, and a single bit-flip is rejected at restore time.
|
|
.RE
|
|
|
|
.PP
|
|
The compression layer is the
|
|
.B VaptVupt LZ + ANS
|
|
codec (version 2.60.4), which prioritises decode speed and ratio over
|
|
encode speed. Aggregate decode throughput on this build is 1.27\(mu
|
|
zstd\-3; encode throughput is 0.2\(mu\(en0.5\(mu zstd\-3 depending on
|
|
content. See
|
|
.B PERFORMANCE
|
|
below.
|
|
|
|
.PP
|
|
The on-disk format is v1.6 and has been wire-compatible since release
|
|
v2.3.1. The product was renamed from
|
|
.B Zupt
|
|
to
|
|
.B VaptVupt
|
|
in v3.0.0 because of a prior INPI Brasil trademark registration of the
|
|
name "Zupt" for unrelated software. The
|
|
.B .zupt
|
|
file extension and the
|
|
.B ZUPT
|
|
header magic bytes are unchanged: archives produced by any v2.x release
|
|
extract cleanly under v3.0.0 and vice versa.
|
|
|
|
.SH COMMANDS
|
|
|
|
.TP
|
|
.B compress
|
|
Create an archive. Default codec is VaptVupt (level 7). Compression
|
|
is multi-threaded; one worker per detected CPU by default.
|
|
|
|
.TP
|
|
.B extract
|
|
Decompress an archive into the current directory (or
|
|
.BR -o " " \fIdir\fR ).
|
|
Refuses to write outside the destination directory (path-traversal
|
|
defence). Files are written with their original permissions and
|
|
mtime preserved.
|
|
|
|
.TP
|
|
.B list
|
|
Print archive metadata: per-file path, size, mtime, mode, compressed
|
|
size, codec. With
|
|
.B --verbose
|
|
also prints per-block sizes and HMAC tags (first 8 bytes).
|
|
|
|
.TP
|
|
.B test
|
|
Decompress all blocks in memory and verify HMAC tags + archive
|
|
integrity trailer. Does not write any files. Use to validate an
|
|
archive without restoring it. Exit code is non-zero on any failure.
|
|
|
|
.TP
|
|
.B info
|
|
Print archive header metadata without requiring the decryption key.
|
|
Reports: format version, codec, encryption type (none / PBKDF2 /
|
|
Argon2id / ML-KEM-768+X25519 hybrid / ML-KEM-768 pure-PQ), KDF
|
|
iteration count, file count,
|
|
creation timestamp, archive UUID, AIT presence. Safe to run on an
|
|
untrusted archive.
|
|
|
|
.TP
|
|
.B bench
|
|
Compare compression levels 1\(en9 on the supplied files; reports
|
|
ratio and encode/decode throughput per level. Useful when picking
|
|
the right
|
|
.B -l
|
|
for a given workload.
|
|
|
|
.TP
|
|
.B disk backup
|
|
Read a block device and write a sparse-aware archive. Detects
|
|
all-zero regions and records them as runs rather than compressing
|
|
them.
|
|
|
|
.TP
|
|
.B disk restore
|
|
Inverse of
|
|
.BR "disk backup" .
|
|
Writes the archive's contents back to a block device. Verifies
|
|
target device size before writing; refuses if the target is smaller
|
|
than the archived size. With
|
|
.B --sync
|
|
issues
|
|
.BR fsync (2)
|
|
after each block.
|
|
|
|
.TP
|
|
.B keygen
|
|
Generate a key file. With no PQ flag, writes a 32-byte raw key for
|
|
keyfile-mode encryption. With
|
|
.B --pq
|
|
generates a native ML-KEM-768 + X25519 \fBhybrid\fR keypair for
|
|
.B --pq
|
|
encryption (in-tree crypto; no external library). With
|
|
.B --pq-only
|
|
generates a native pure ML-KEM-768 keypair (magic
|
|
.BR ZPQK )
|
|
for
|
|
.B --pq-only
|
|
encryption. With
|
|
.B --sdk
|
|
generates a keypair for the optional
|
|
.B --pq-sdk
|
|
mode, and with
|
|
.B --box
|
|
a libpqvaptvupt sealed-box keypair for
|
|
.B --pq-box
|
|
(both need a
|
|
.B WITH_SDK=1
|
|
build). With
|
|
.B --pub
|
|
extracts the public key from an existing private key (combine with the
|
|
matching PQ flag, e.g.
|
|
.BR "keygen --pub --pq-only" ).
|
|
|
|
.SH GLOBAL OPTIONS
|
|
|
|
.TP
|
|
.BR -v ", " --verbose
|
|
Print per-file and per-block details during compress/extract/list/test.
|
|
|
|
.TP
|
|
.BR -q ", " --quiet
|
|
Suppress non-error output.
|
|
|
|
.TP
|
|
.BR -j " " \fIN\fR ", " --jobs " " \fIN\fR
|
|
Worker thread count for parallel compression. Default: number of
|
|
online CPUs.
|
|
|
|
.SH COMPRESS OPTIONS
|
|
|
|
.TP
|
|
.BR -l " " \fI1..9\fR ", " --level " " \fI1..9\fR
|
|
Compression level. 1\(en2 = ultra-fast (~80 MB/s encode on typical
|
|
hardware, lower ratio). 3\(en7 = balanced (default 7). 8\(en9 =
|
|
extreme (optimal parsing, ~5\(en10\(mu slower encode, best ratio).
|
|
|
|
.TP
|
|
.B --codec \fIid\fR
|
|
Force a specific codec by id. Accepted values:
|
|
.BR store " (0x0000), "
|
|
.BR vaptvupt-lz " (0x0008), "
|
|
.BR vaptvupt-lzh " (0x0009), "
|
|
.BR vaptvupt-lzhp " (0x000A), "
|
|
.BR vaptvupt " (0x0010 — default), "
|
|
.BR auto " (0xFFFF — pick at runtime)."
|
|
|
|
.TP
|
|
.BR -p " " \fIpassword\fR
|
|
Enable password-based encryption (PBKDF2-SHA256 KDF; Argon2id is available
|
|
only in a WITH_SDK=1 build via \fB--kdf argon2id\fR).
|
|
Reading the password from a flag exposes it in
|
|
.BR ps (1)
|
|
output; prefer
|
|
.B --pass-file
|
|
or interactive prompt.
|
|
|
|
.TP
|
|
.B --pass-file \fIpath\fR
|
|
Read password from the first line of the file. The file's permission
|
|
bits should be 0600.
|
|
|
|
.TP
|
|
.B --pass-fd \fIN\fR
|
|
Read password from file descriptor N.
|
|
|
|
.TP
|
|
.B --kdf \fIalgo\fR
|
|
Choose key-derivation function for password mode. In the default source-only
|
|
build the only KDF is
|
|
.BR pbkdf2 " (SHA-256, 600 000 iter), which is the default;"
|
|
.BR argon2id " (memory-hard) is available only in a " WITH_SDK=1 " build."
|
|
|
|
.TP
|
|
.B --keyfile \fIpath\fR
|
|
Use a 32-byte raw key file (generated with
|
|
.BR "vaptvupt keygen" ).
|
|
|
|
.TP
|
|
.B --pq \fIpub\fR
|
|
Enable native post-quantum \fBhybrid\fR encryption (envelope type 0x02,
|
|
recommended). Combines ML-KEM-768 (FIPS 203) with X25519 (RFC 7748) so
|
|
the archive key is secure unless \fBboth\fR the lattice KEM and the
|
|
elliptic-curve exchange are broken. Uses the in-tree crypto only — no
|
|
external library, always available. The
|
|
.I pub
|
|
argument is the recipient's public-key file from
|
|
.BR "vaptvupt keygen" .
|
|
On extraction, pass the secret key:
|
|
.B --pq
|
|
\fIpriv\fR.
|
|
|
|
.TP
|
|
.B --pq-only \fIpub\fR
|
|
Enable native \fBfull\fR (pure) post-quantum encryption (envelope type
|
|
0x06). ML-KEM-768 is the \fIsole\fR key-establishment mechanism — no
|
|
X25519 component. Choose this only when a policy mandates a single
|
|
NIST-standardised PQ primitive with no classical KEM in the envelope
|
|
(e.g. CNSA 2.0-style "PQ-only" postures). The archive key is
|
|
SHA3-512(ml_ss || ml_ct || "ZUPT-PQ-ONLY-v1"). Note the deliberate
|
|
trade-off: unlike
|
|
.BR --pq ,
|
|
a future weakness in ML-KEM-768 alone is sufficient to break the
|
|
envelope, because there is no classical KEM to fall back on. When in
|
|
doubt use
|
|
.B --pq
|
|
(hybrid). Keys are generated with
|
|
.BR "vaptvupt keygen --pq-only" ;
|
|
the private and public key files (magic
|
|
.BR ZPQK )
|
|
are not interchangeable with hybrid
|
|
.B --pq
|
|
keys. On extraction, pass the secret key:
|
|
.B --pq-only
|
|
\fIpriv\fR.
|
|
|
|
.TP
|
|
.B --pq-box \fIpub\fR
|
|
Enable post-quantum sealed-box encryption via libpqvaptvupt (envelope
|
|
type 0x05). \fBRequires an optional\fR \fBWITH_SDK=1\fR \fBbuild\fR: the
|
|
default source-only tree ships no vendored library, so this mode is
|
|
absent unless you build against libpqvaptvupt yourself. Prefer the
|
|
native
|
|
.B --pq
|
|
or
|
|
.B --pq-only
|
|
modes, which need no external library. ML-KEM-768 + X25519 shared secrets are
|
|
combined through HKDF-SHA256 with a domain-separating info string
|
|
("pqvv-seal-v1"); the box carries AES-256-CTR + HMAC-SHA256
|
|
Encrypt-then-MAC. The
|
|
.I pub
|
|
argument is the recipient's public-key file from
|
|
.B keygen --box
|
|
(magic-tagged; public and secret key files are not interchangeable).
|
|
On extraction, pass the secret key:
|
|
.B --pq-box
|
|
\fIpriv\fR.
|
|
.TP
|
|
.B --pq-sdk \fIpub\fR
|
|
Enable post-quantum hybrid encryption via libzuptsdk (envelope type
|
|
0x03). \fBRequires an optional\fR \fBWITH_SDK=1\fR \fBbuild\fR and is
|
|
absent from the default source-only tree; use the native
|
|
.B --pq
|
|
instead, which provides the same ML-KEM-768 + X25519 hybrid with no
|
|
external dependency. Uses ML-KEM-768 + X25519 with HKDF combiner, HPKE
|
|
binding, and key commitment. The
|
|
.I pub
|
|
argument is the recipient's public-key file generated by
|
|
.BR "vaptvupt keygen --sdk" .
|
|
|
|
.TP
|
|
.B -c \fItext\fR ", " --comment " " \fItext\fR
|
|
Embed an encrypted UTF-8 comment in the archive (up to 4096 bytes).
|
|
The comment is bound to the archive's frame-preface AAD; tampering
|
|
is detected at extract time.
|
|
|
|
.TP
|
|
.B --comment-file \fIpath\fR
|
|
Read the comment from a file rather than the command line.
|
|
|
|
.TP
|
|
.B -b \fIsize\fR ", " --block-size " " \fIsize\fR
|
|
Compression block size. Default 4 MiB. Smaller blocks improve
|
|
random-access decode but lose some ratio.
|
|
|
|
.SH EXTRACT, LIST, TEST OPTIONS
|
|
|
|
.TP
|
|
.BR -o " " \fIdir\fR ", " --output " " \fIdir\fR
|
|
Extract into
|
|
.IR dir
|
|
(created if it doesn't exist). Default: current directory.
|
|
|
|
.TP
|
|
.B --no-mtime
|
|
Do not restore archived modification times; use current time instead.
|
|
|
|
.TP
|
|
.B --strip-components \fIN\fR
|
|
Strip
|
|
.I N
|
|
leading path components from each entry, like
|
|
.BR tar 's
|
|
flag of the same name.
|
|
|
|
.SH POST-QUANTUM ENCRYPTION
|
|
|
|
.B vaptvupt
|
|
offers two native post-quantum modes, both built entirely from the
|
|
in-tree crypto (no external library):
|
|
|
|
.RS
|
|
.IP "\fB--pq\fR (hybrid, recommended)" 4
|
|
A hybrid KEM combining ML-KEM-768 (FIPS 203) with X25519 (RFC 7748).
|
|
The archive key is derived as:
|
|
.RS
|
|
.nf
|
|
|
|
ss_pq = ML-KEM-768.decaps(sk_pq, ct_pq)
|
|
ss_ec = X25519(sk_ec, pk_ec_peer)
|
|
session = HKDF-SHA256(ss_pq || ss_ec,
|
|
info = "vaptvupt-pq-sdk-v1",
|
|
salt = archive_uuid)
|
|
.fi
|
|
.RE
|
|
The hybrid combiner means the session key is at least as strong as the
|
|
strongest of {ML-KEM-768, X25519}: an attacker must break \fBboth\fR to
|
|
recover the key. This is the default recommendation and the right choice
|
|
for almost every user, because it stays secure even if one primitive is
|
|
later found weak.
|
|
.IP "\fB--pq-only\fR (full / pure PQ)" 4
|
|
ML-KEM-768 as the \fIsole\fR key-establishment mechanism, with no
|
|
classical component. The archive key is derived as:
|
|
.RS
|
|
.nf
|
|
|
|
(ss_pq, ct_pq) = ML-KEM-768.encaps(pk_pq)
|
|
archive_key = SHA3-512(ss_pq || ct_pq || "ZUPT-PQ-ONLY-v1")
|
|
.fi
|
|
.RE
|
|
Use this only when a compliance posture requires a single
|
|
NIST-standardised PQ primitive with no classical KEM in the envelope
|
|
(for example CNSA 2.0-style "PQ-only" requirements). The deliberate
|
|
trade-off is that the envelope has \fBno hybrid safety net\fR: a future
|
|
cryptanalytic break of ML-KEM-768 alone breaks the archive, whereas
|
|
under
|
|
.B --pq
|
|
the attacker would still have to break X25519 as well. Unless a policy
|
|
forbids the classical component, prefer
|
|
.BR --pq .
|
|
.RE
|
|
|
|
.PP
|
|
Both modes carry the same authenticated envelope as password mode:
|
|
per-block AES-256-CTR with a fresh random 128-bit nonce, HMAC-SHA256
|
|
Encrypt-then-MAC, and ML-KEM Fujisaki-Okamoto implicit rejection, so a
|
|
wrong or tampered ciphertext is rejected rather than yielding garbage.
|
|
|
|
.PP
|
|
.B Key commitment:
|
|
the ciphertext is bound to the exact public key it was encrypted to
|
|
via an HPKE-style derivation. An attacker cannot present a different
|
|
public key that decrypts to the same plaintext (this defeats the
|
|
"partitioning" attack class).
|
|
|
|
.PP
|
|
.B Implementation notes:
|
|
the ML-KEM-768 implementation is vendored from a clean reference and
|
|
verified against the FIPS 203 KAT vectors. The X25519 implementation
|
|
uses 4\(mu64-bit field arithmetic with Jasmin-verified constant-time
|
|
field operations on x86_64. On other architectures the same routines
|
|
run in pure C, also constant-time by construction.
|
|
|
|
.SH SECURITY
|
|
|
|
.SS Threat model
|
|
|
|
What
|
|
.B vaptvupt
|
|
.B protects against:
|
|
|
|
.RS
|
|
.IP \(bu 2
|
|
Confidentiality of archived data at rest (AES-256-CTR with HMAC-SHA256 EtM, or AEAD via libzuptsdk on the
|
|
.B --pq-sdk
|
|
path).
|
|
.IP \(bu 2
|
|
End-to-end byte-level tamper detection on encrypted archives. The F-09 byte-sweep regression (1827 positions on a representative archive, 2000 trials, every run) shows zero silent-accept positions.
|
|
.IP \(bu 2
|
|
Wrong-password and tampered-archive indistinguishability at the user-visible message layer (F-11). The default error wording is identical for both cases; only
|
|
.B --verbose
|
|
prints the distinguishing detail. This closes the "verbal probe-oracle" attack class where the error string leaked which check failed first.
|
|
.IP \(bu 2
|
|
Post-quantum forward secrecy on archives encrypted with
|
|
.B --pq-sdk
|
|
(assuming ML-KEM-768 holds against future quantum attack).
|
|
.IP \(bu 2
|
|
Archive-header and footer authentication via a 32-byte HMAC-SHA256 trailer (F-08). Tampering with the file count, comment offset, or timestamp is detected at archive open time.
|
|
.IP \(bu 2
|
|
Path-traversal at extract time. Entries with absolute paths or
|
|
.B ..
|
|
components are refused or stripped.
|
|
.RE
|
|
|
|
What it does
|
|
.B NOT
|
|
protect against:
|
|
|
|
.RS
|
|
.IP \(bu 2
|
|
Compromise of the endpoint that creates or restores the archive. If the host is compromised, the password, key file, or plaintext is accessible.
|
|
.IP \(bu 2
|
|
Compromise of the key file or password. Key custody is the user's responsibility.
|
|
.IP \(bu 2
|
|
A weak password. Argon2id with default parameters needs ~256 MiB and ~1 s to derive a key on commodity hardware; a 4-character password is still trivially crackable.
|
|
.IP \(bu 2
|
|
Metadata leakage. File names, sizes, and modification times are encrypted, but the archive's total size and the count of compressed blocks are visible to an observer.
|
|
.IP \(bu 2
|
|
Side channels on the compression layer (CRIME/BREACH-style). If the same archive contains both attacker-controlled and secret data and the attacker can observe the compressed size, length-based oracles may be possible.
|
|
.IP \(bu 2
|
|
Denial-of-service via malformed input on the decoder. The decoder rejects malformed input cleanly (no crashes in the fuzz harness), but a very large compressed input can still consume CPU and memory proportional to its size.
|
|
.RE
|
|
|
|
.SS Cryptographic primitives
|
|
|
|
.TS
|
|
tab(|);
|
|
l l.
|
|
SHA-256 | FIPS 180-4
|
|
SHA-3 / SHAKE | FIPS 202
|
|
ML-KEM-768 | FIPS 203
|
|
AES-256-CTR | NIST SP 800-38A
|
|
HMAC-SHA256 | RFC 2104 / FIPS 198-1
|
|
X25519 | RFC 7748
|
|
HKDF-SHA256 | RFC 5869
|
|
PBKDF2-SHA256 | RFC 8018
|
|
Argon2id | RFC 9106
|
|
XXH64 | non-cryptographic; used only inside the AEAD envelope
|
|
.TE
|
|
|
|
.SS Constant-time guarantees
|
|
|
|
All secret-dependent comparisons and table lookups in the cryptographic
|
|
core are constant-time. On x86_64 the hot paths (HMAC equality compare,
|
|
ML-KEM Fujisaki-Okamoto implicit rejection) are implemented in Jasmin
|
|
and assembled with
|
|
.BR jasminc (1).
|
|
On other architectures the same routines run in portable C; the
|
|
constant-time property is preserved by source-level construction.
|
|
|
|
.SH FILES
|
|
|
|
.TP
|
|
.I ~/.config/vaptvupt/
|
|
Per-user configuration directory (reserved; not used in v3.0.0).
|
|
|
|
.TP
|
|
.I /etc/vaptvupt/
|
|
System-wide configuration directory (reserved; not used in v3.0.0).
|
|
|
|
.TP
|
|
.I /usr/share/bash-completion/completions/vaptvupt
|
|
Bash completion (and the symlinked legacy
|
|
.IR /usr/share/bash-completion/completions/zupt ).
|
|
|
|
.TP
|
|
.I /usr/share/zsh/site-functions/_vaptvupt
|
|
zsh completion.
|
|
|
|
.TP
|
|
.I /usr/share/fish/vendor_completions.d/vaptvupt.fish
|
|
fish completion.
|
|
|
|
.SH ENVIRONMENT
|
|
|
|
.TP
|
|
.B VAPTVUPT_BIN
|
|
Override the binary path used by the GUI front-end. Legacy
|
|
.B ZUPT_BIN
|
|
is also honoured.
|
|
|
|
.TP
|
|
.B VAPTVUPT_DEBUG
|
|
If set to any non-empty value, the GUI front-end prints its binary-discovery log to stderr.
|
|
|
|
.SH EXIT STATUS
|
|
|
|
.TP
|
|
.B 0
|
|
Success.
|
|
|
|
.TP
|
|
.B 1
|
|
General error (bad arguments, file not found, etc.).
|
|
|
|
.TP
|
|
.B 2
|
|
Authentication failed. Wrong password, wrong key file, or the archive has been tampered with. Use
|
|
.B --verbose
|
|
to see the distinguishing detail (subject to F-11's threat model: detailed messages may leak which failure cause fired first).
|
|
|
|
.TP
|
|
.B 3
|
|
Archive-format error (wrong magic bytes, unsupported format version, corrupted header).
|
|
|
|
.TP
|
|
.B 4
|
|
I/O error (disk full, permission denied, network failure).
|
|
|
|
.TP
|
|
.B 5
|
|
Compressed-data integrity error (per-block HMAC mismatch detected mid-stream).
|
|
|
|
.SH PERFORMANCE
|
|
|
|
Numbers below are from the v3.0.0 release benchmark (May 2026), run
|
|
on an Intel Xeon @ 2.8 GHz with the codec compiled with the
|
|
distribution's default optimisation level.
|
|
|
|
.TS
|
|
tab(|);
|
|
l l l l l.
|
|
\fBFixture\fR | \fBTool\fR | \fBRatio\fR | \fBEnc MB/s\fR | \fBDec MB/s\fR
|
|
text 8 MB | vv-9 | 34.6% | 5.4 | 219
|
|
text 8 MB | gzip-9 | 30.9% | 6.2 | 137
|
|
text 8 MB | zstd-3 | 31.6% | 137 | 427
|
|
text 8 MB | zstd-19 | 25.5% | 1.6 | 384
|
|
source 670 KB | vv-9 | 25.1% | 11.4 | 128
|
|
source 670 KB | gzip-9 | 23.2% | 10.0 | 107
|
|
source 670 KB | zstd-3 | 24.1% | 91 | 160
|
|
binary 2.4 MB | vv-9 | 44.7% | 7.7 | 153
|
|
binary 2.4 MB | gzip-9 | 52.0% | 12.6 | 109
|
|
binary 2.4 MB | zstd-3 | 77.3% | 164 | 382
|
|
binary 2.4 MB | zstd-19 | 48.0% | 5.8 | 229
|
|
random 5 MB | vv-9 | 100.0% | 11.1 | 477
|
|
random 5 MB | zstd-3 | 100.0% | 397 | 681
|
|
.TE
|
|
|
|
.PP
|
|
Honest reading of these numbers:
|
|
|
|
.RS
|
|
.IP \(bu 2
|
|
On binary-structured data (game saves, mmap'd structures, struct arrays),
|
|
.B vaptvupt
|
|
beats zstd-3 by a wide margin on ratio (44.7% vs 77.3%) at the cost of being ~20\(mu slower to encode. For write-once / restore-often workloads this is the right trade.
|
|
.IP \(bu 2
|
|
On text and source, zstd-19 beats
|
|
.B vaptvupt
|
|
on ratio. The fundamental codec difference is that zstd's reference encoder has had years of compiler-engineering attention that
|
|
.B vaptvupt
|
|
has not.
|
|
.IP \(bu 2
|
|
Encode throughput is
|
|
.BR vaptvupt 's
|
|
weak axis. If encode latency matters more than ratio, use
|
|
.B -l 1
|
|
or
|
|
.BR -l 2 .
|
|
.IP \(bu 2
|
|
On random / already-compressed data, all codecs hit the incompressibility wall; comparing encode/decode throughput in that regime is mostly measuring memcpy speed plus framing overhead.
|
|
.RE
|
|
|
|
.SH EXAMPLES
|
|
|
|
.PP
|
|
Compress with default settings (PBKDF2-SHA256 password, VaptVupt level 7, multi-threaded):
|
|
|
|
.RS
|
|
.nf
|
|
$ vaptvupt compress -p secret backup.zupt ~/Documents
|
|
.fi
|
|
.RE
|
|
|
|
Compress with post-quantum hybrid encryption to a published public key:
|
|
|
|
.RS
|
|
.nf
|
|
$ vaptvupt keygen --sdk -o ~/.config/vaptvupt-mykey
|
|
$ vaptvupt keygen -o ~/.config/vaptvupt-mykey
|
|
$ vaptvupt keygen --pub -o mykey.pub -k ~/.config/vaptvupt-mykey
|
|
$ vaptvupt compress --pq mykey.pub backup.zupt ~/Documents
|
|
.fi
|
|
.RE
|
|
|
|
Compress with full (pure) post-quantum encryption — ML-KEM-768 only,
|
|
no classical component (compliance postures that mandate a single PQ
|
|
primitive):
|
|
|
|
.RS
|
|
.nf
|
|
$ vaptvupt keygen --pq-only -o pqkey
|
|
$ vaptvupt keygen --pub --pq-only -o pqkey.pub -k pqkey
|
|
$ vaptvupt compress --pq-only pqkey.pub backup.zupt ~/Documents
|
|
$ vaptvupt extract --pq-only pqkey -o restored backup.zupt
|
|
.fi
|
|
.RE
|
|
|
|
Backup a block device, sparse-aware:
|
|
|
|
.RS
|
|
.nf
|
|
$ sudo vaptvupt disk backup -p secret system.zupt /dev/nvme0n1p2
|
|
.fi
|
|
.RE
|
|
|
|
Verify an archive without restoring:
|
|
|
|
.RS
|
|
.nf
|
|
$ vaptvupt test -p secret backup.zupt
|
|
.fi
|
|
.RE
|
|
|
|
Print archive metadata without supplying a password:
|
|
|
|
.RS
|
|
.nf
|
|
$ vaptvupt info backup.zupt
|
|
.fi
|
|
.RE
|
|
|
|
Compare compression levels:
|
|
|
|
.RS
|
|
.nf
|
|
$ vaptvupt bench ~/Downloads/big-dataset.bin
|
|
.fi
|
|
.RE
|
|
|
|
Run the GUI from a desktop session where /usr/bin isn't on PATH (the bug fixed in v3.0.0):
|
|
|
|
.RS
|
|
.nf
|
|
$ VAPTVUPT_DEBUG=1 vaptvupt-gui 2> /tmp/discovery.log
|
|
.fi
|
|
.RE
|
|
|
|
.SH STANDARDS
|
|
|
|
ISO C11; POSIX.1-2017 for I/O and threading. The cryptographic
|
|
primitives implement the specifications listed in
|
|
.BR SECURITY
|
|
above. The on-disk archive format is documented in
|
|
.B FORMAT.md
|
|
in the source distribution.
|
|
|
|
.SH AUTHORS
|
|
Cristian Cezar Moisés <zupt@riseup.net> — primary author and maintainer.
|
|
|
|
.SH BUGS
|
|
Report bugs at https://git.securityops.co/cristiancmoises/vaptvupt/issues
|
|
or by email to <zupt@riseup.net>.
|
|
|
|
.SH LICENSE
|
|
AGPL-3.0-or-later for the application; GPL-3.0-or-later for the
|
|
embedded VaptVupt codec. Dual-licensed: a commercial licence is
|
|
available from <sac@securityops.co>.
|
|
|
|
.SH SEE ALSO
|
|
.BR vaptvupt-gui (1),
|
|
.BR zstd (1),
|
|
.BR gzip (1),
|
|
.BR xz (1),
|
|
.BR tar (1),
|
|
.BR cryptsetup (8),
|
|
.BR jasminc (1).
|
|
.PP
|
|
Project home: https://git.securityops.co/cristiancmoises/vaptvupt
|
|
.br
|
|
Threat model: see
|
|
.B THREAT_MODEL.md
|
|
in the source distribution.
|
|
.br
|
|
Archive format spec: see
|
|
.B FORMAT.md
|
|
in the source distribution.
|