v4.0.0: codec 2.60.4 security release, --pq-box sealed-box mode, F-16 fix
Some checks failed
CI / build-and-test (clang) (push) Has been cancelled
CI / build-and-test (gcc) (push) Has been cancelled
CI / strict-warnings (clang, -Wall -Wextra -Wpedantic -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnull-dereference -O2 -std=c11 -Werror) (push) Has been cancelled
CI / strict-warnings (gcc, -Wall -Wextra -Wpedantic -Wshadow -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnull-dereference -Wformat-security -Wlogical-op -Wjump-misses-init -Wdouble-promotion -O2 -std=c11 -Werror) (push) Has been cancelled
CI / sanitizers (push) Has been cancelled
CI / pie-hardening (push) Has been cancelled
CI / cross-aarch64 (push) Has been cancelled
CI / dist-reproducibility (push) Has been cancelled
CI / packaging-syntax (push) Has been cancelled
CI / release (push) Has been cancelled

Major release. Highlights:

- Codec: vendored VaptVupt codec moves to canonical 2.60.4 security
  release. Fixes a high-severity OOB heap write in the AVX2 decode fast
  path (reachable on a valid stream sized to exactly content_size, both
  tail variants). Brings CBMC-formally-verified BCJ filters with
  automatic ELF/PE/Mach-O detection. Compressed output stays
  byte-identical (ratio gate Δ 0.00%); wire format unchanged at v1.6.
- New --pq-box sealed-box recipient mode (vendored libpqvaptvupt 0.6.0):
  ML-KEM-768 + X25519 combined via HKDF-SHA256 with domain separation,
  AES-256-CTR + HMAC-SHA256 EtM. Legacy --pq and --pq-sdk stay readable.
- F-16: discloses and fixes a pre-existing data-loss defect in the
  <= 3.8.0 in-tree BCJ encoder. Full back-compat matrix decodes
  byte-exact under 4.0.0; every readable pre-4.0 archive remains readable.

Repository hygiene:
- Sync full 4.0.0 source tree (codec, crypto, SDK, GUI, packaging, tests).
- Remove internal scratch files (PROMPT.md, FORMAL_AUDIT_PROMPT.md)
  and superseded version-specific docs (INTEGRATION_PROTOCOL_2.60.4.md,
  docs/FINDINGS-2.x.md) and a stray test binary.
- Refresh README download/install section to real 4.0.0 release assets;
  bump version badge to 4.0.0.
- Add .gitignore for build outputs (keeps vendored prebuilt libraries).
This commit is contained in:
Cristian Cezar Moisés 2026-06-10 18:48:58 -03:00
commit 544a2cd647
98 changed files with 15615 additions and 1397 deletions

616
doc/vaptvupt.1 Normal file
View file

@ -0,0 +1,616 @@
.\" 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 "May 2026" "vaptvupt 4.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.53.3), 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), 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 for keyfile-mode encryption. With
.B --sdk
generates an ML-KEM-768 + X25519 hybrid keypair suitable for
.B --pq-sdk
mode. With
.B --box
generates a libpqvaptvupt sealed-box keypair (writes \fIfile\fR and
\fIfile\fR.pub) for
.B --pq-box
mode. With
.B --pub
extracts the public key from an existing private key.
.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 zupt-lz " (0x0008), "
.BR zupt-lzh " (0x0009), "
.BR zupt-lzhp " (0x000A), "
.BR vaptvupt " (0x0010 — default), "
.BR auto " (0xFFFF — pick at runtime)."
.TP
.BR -p " " \fIpassword\fR
Enable password-based encryption (Argon2id KDF by default since v2.4.1).
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:
.BR argon2id " (default since v2.4.1; memory-hard) or "
.BR pbkdf2 " (SHA-256, 600 000 iter; needed for compatibility with v2.4.0 and earlier readers)."
.TP
.B --keyfile \fIpath\fR
Use a 32-byte raw key file (generated with
.BR "vaptvupt keygen" ).
.TP
.B --pq-box \fIpub\fR
Enable post-quantum sealed-box encryption via the vendored libpqvaptvupt
(v4.0.0+, envelope type 0x05). 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. 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
implements a hybrid KEM as specified in FIPS 203 (ML-KEM) combined
with X25519 (RFC 7748). The session 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 both
to recover the key.
.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 (Argon2id 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 --sdk --pub -o mykey.pub -k ~/.config/vaptvupt-mykey
$ vaptvupt compress --pq-sdk mykey.pub backup.zupt ~/Documents
.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/zupt/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/zupt
.br
Threat model: see
.B THREAT_MODEL.md
in the source distribution.
.br
Archive format spec: see
.B FORMAT.md
in the source distribution.

View file

@ -1,368 +0,0 @@
.TH ZUPT 1 "2026-05-01" "Zupt 2.2.3" "User Commands"
.SH NAME
zupt \- backup-oriented compression utility with hybrid post-quantum encryption
.SH SYNOPSIS
.B zupt compress
.RI [ OPTIONS ]
.I output.zupt files/dirs...
.br
.B zupt extract
.RI [ OPTIONS ]
.I archive.zupt
.br
.B zupt list
.RI [ OPTIONS ]
.I archive.zupt
.br
.B zupt test
.RI [ OPTIONS ]
.I archive.zupt
.br
.B zupt info
.I archive.zupt
.br
.B zupt bench
.RI [ --compare ]
.I files/dirs...
.br
.B zupt disk
.B backup\fR | \fBrestore
.RI [ OPTIONS ]
.br
.B zupt keygen
.RI [ -o
.IR file ]
.RI [ --pub ]
.RI [ --sdk ]
.RI [ -k
.IR privkey ]
.br
.B zupt version
.br
.B zupt help
.SH DESCRIPTION
.B zupt
is a backup-oriented compression utility with multi-threaded compression,
integrity verification, password-based encryption, and hybrid post-quantum
public-key encryption (ML-KEM-768 + X25519). Two PQ encryption modes are
supported: a legacy combiner kept for backward compatibility, and a
state-of-the-art mode backed by libzuptsdk (HKDF-SHA3 hybrid combiner with
domain separation, key commitment, HPKE binding RFC 9180, anti-fault
decapsulation, and Argon2id RFC 9106 password derivation).
.SH COMMANDS
.TP
.B compress, c
Create a compressed archive from one or more files or directories.
.TP
.B extract, x
Extract files from an archive.
.TP
.B list, l
List archive contents without extracting.
.TP
.B test, t
Verify archive integrity (decompresses without writing files).
.TP
.B info
Show archive metadata; works without password and without keys.
.TP
.B bench
Compare compression levels 1\(en9 on the given input.
.TP
.B disk backup\fR / \fBrestore
Full-disk backup/restore with sparse-region detection, progress
reporting, and proper sync discipline (\fBO_SYNC\fR + \fBfsync\fR + \fBsync\fR).
.TP
.B keygen
Generate or export hybrid PQ keypair. With
.B --sdk
flag, generates a libzuptsdk v2 keypair (private key file plus
.IR file .pub
public key file). Without
.BR --sdk ,
generates a legacy keypair compatible with
.BR --pq .
.SH GLOBAL OPTIONS
.TP
.BR -v ", " --verbose
Verbose per-file output.
.TP
.BR -q ", " --quiet
Suppress non-error output.
.TP
.BR -t ", " --threads " " \fIN\fR
Thread count: 0 = auto, 1 = single, 2\(en64 = explicit.
.SH COMPRESS OPTIONS
.TP
.BR -l ", " --level " " \fI1-9\fR
Compression level. Default 7. 1\(en2 fast/small window;
3\(en5 balanced; 6\(en7 high; 8\(en9 maximum (1MB window, deep search).
.TP
.BR -b ", " --block " " \fISIZE\fR
Block size in bytes. Default 128KB.
.TP
.BR -s ", " --store
Store without compression.
.TP
.BR -f ", " --fast
Use the fast LZ codec (less compression, higher throughput).
.TP
.BR --vv ", " --vaptvupt
Use the VaptVupt codec (LZ77 + tANS entropy, SIMD decode).
.TP
.B --lzhp
Use Zupt-LZHP (LZ77 + Huffman, no SIMD required).
.TP
.BR -p ", " --password " " \fIPW\fR
Encrypt with AES-256. If
.I PW
is empty, prompt the user.
.TP
.BR --pq " " \fIPUBKEY\fR
Encrypt using legacy PQ combiner (XOR + SHA3-512). Kept for
compatibility. New archives should prefer
.BR --pq-sdk .
.TP
.BR --pq-sdk " " \fIPUBKEY\fR
Encrypt using libzuptsdk v2 (recommended): HKDF-SHA3 hybrid combiner
with domain separation, 32-byte key commitment, HPKE binding (RFC 9180),
anti-fault decapsulation, AEAD via XChaCha20-Poly1305, password mode
via Argon2id (RFC 9106). The
.I PUBKEY
file is the
.IR file .pub
produced by
.BR "zupt keygen --sdk" .
.TP
.BR -D ", " --dedup
Block-level deduplication. Identical blocks across files are stored once.
.TP
.B --solid
Solid mode: concatenate files into a single stream before compression.
.SH EXTRACT / LIST / TEST OPTIONS
.TP
.BR -o ", " --output " " \fIDIR\fR
Output directory (extract only). Default: current directory.
.TP
.BR -p ", " --password " " \fIPW\fR
Decryption password.
.TP
.BR --pq " " \fIPRIVKEY\fR
Decrypt a legacy PQ archive.
.TP
.BR --pq-sdk " " \fIPRIVKEY\fR
Decrypt an SDK v2 PQ archive.
.SH KEYGEN OPTIONS
.TP
.BR -o " " \fIFILE\fR
Output keyfile path (required).
.TP
.B --pub
Export public key from an existing private key (used with
.BR -k ).
.TP
.BR -k " " \fIPRIVKEY\fR
Source private keyfile when exporting public key.
.TP
.BR --sdk ", " --pq-sdk
Generate an SDK v2 keypair. Writes
.I FILE
(private key) and
.IR FILE .pub
(public key) in one step. Use these keys with
.BR --pq-sdk .
.SH EXAMPLES
.TP
Compress without encryption:
.B
zupt c backup.zupt ~/Documents/
.TP
Compress with password:
.B
zupt c -l 9 -p 'my-pass' secure.zupt data/
.TP
Generate legacy keypair, encrypt, decrypt:
.nf
zupt keygen -o mykey.key
zupt keygen --pub -o pub.key -k mykey.key
zupt c --pq pub.key backup.zupt ~/Documents/
zupt x --pq mykey.key backup.zupt -o ~/restored/
.fi
.TP
Generate SDK v2 keypair, encrypt, decrypt (recommended):
.nf
zupt keygen --sdk -o mykey.priv
# creates mykey.priv (private) and mykey.priv.pub (public)
zupt c --pq-sdk mykey.priv.pub backup.zupt ~/Documents/
zupt x --pq-sdk mykey.priv backup.zupt
.fi
.TP
Full-disk backup with PQ encryption:
.nf
zupt keygen --sdk -o disk.priv
zupt disk backup --pq-sdk disk.priv.pub /dev/sda backup.img.zupt
.fi
.SH FILES
.TP
.I /usr/bin/zupt
The zupt binary.
.TP
.I /usr/lib/x86_64-linux-gnu/libzuptsdk.so.2
The libzuptsdk shared library (Linux x86_64).
.TP
.I /usr/include/zuptsdk.h
libzuptsdk public C API.
.TP
.I /usr/share/doc/zupt/
Documentation, changelog, audit reports.
.SH ENVIRONMENT
.TP
.B ZUPT_THREADS
Default thread count when
.B -t
is not specified.
.TP
.B ZUPT_TMPDIR
Temporary directory for intermediate files (default:
.IR /tmp ).
.SH EXIT STATUS
.TP
.B 0
Success.
.TP
.B 1
General error (invalid arguments, file not found, etc.).
.TP
.B 2
Authentication failure (wrong password, wrong key, tampered ciphertext).
.TP
.B 3
I/O error.
.TP
.B 4
Archive format error (corrupt, unsupported version, malformed header).
.SH SECURITY
.B zupt 2.2+
recommends
.B --pq-sdk
for new archives. The legacy
.B --pq
mode uses an XOR+SHA3-512 hybrid combiner that has been superseded
by HKDF-SHA3 with domain separation in the SDK path. Both modes
remain supported for archive interoperability.
For password-encrypted archives, prefer the SDK path: it uses
Argon2id (RFC 9106) with OWASP-compliant minimum parameters
(64 MiB memory, 3 iterations, 1 thread), versus PBKDF2-SHA256 in
the legacy path.
.B Path traversal protection.
zupt 2.2.3+ rejects archive entries containing
.IR ".." ,
absolute paths
.RI ( /foo
or
.IR C:\\foo ),
or embedded NUL bytes. On POSIX systems, output files are opened with
.B O_NOFOLLOW
so that pre-existing symlinks at the extraction target are not followed
(defense against TOCTOU attacks where an attacker plants a symlink in the
output directory before extraction). On Windows, this defense relies on
directory ACLs.
.B Operational guidance for untrusted archives.
Always extract into an empty dedicated directory, audit symlinks before
extraction, and never run extraction as root.
.SH BUGS
Report at
.UR https://git.securityops.co/cristiancmoises/zupt/issues
.UE
or by email to
.MT zupt@riseup.net
.ME .
.SH AUTHOR
Cristian Cezar Moisés
.MT zupt@riseup.net
.ME
.SH SEE ALSO
.BR zupt-gui (1),
.BR tar (1),
.BR gzip (1).
.SH STANDARDS
Zupt implements algorithms from FIPS 197 (AES), FIPS 202 (Keccak/SHA-3),
FIPS 203 (ML-KEM), and follows RFC 5297 (AES-SIV), RFC 5869 (HKDF),
RFC 7748 (X25519), RFC 8439 (ChaCha20-Poly1305), RFC 9106 (Argon2),
and RFC 9180 (HPKE). Cryptographic primitive selection is aligned
with Brazilian Instrução Normativa ITI nº 35/2026, which incorporated
ML-KEM-768/1024 into the ICP-Brasil framework.
.SH LICENSE
.PP
Zupt itself (CLI, GUI, libzuptsdk, Jasmin source) is licensed under the
.B GNU Affero General Public License version 3 or later
(AGPL-3.0-or-later). The bundled VaptVupt LZ codec
.RB ( src/vv_*.c ", " src/vaptvupt_api.c )
is licensed under the
.B GNU General Public License version 3 or later
(GPL-3.0-or-later). VaptVupt is GPL not AGPL so that, with sufficient
maturity, it can be considered for upstreaming into the Linux or BSD
kernels.
.PP
Commercial licenses (relief from copyleft terms) are available for both
components. Contact
.MT sac@securityops.co
.ME .
.PP
See
.B /usr/share/doc/zupt/LICENSE
and
.B /usr/share/doc/zupt/THIRD-PARTY-NOTICES.md
for the full text and complete attribution.
.SH PROJECT
.PP
Home page:
.UR https://git.securityops.co/cristiancmoises/zupt
.UE
.PP
Related projects (all by Cristian Cezar Moisés, hosted on
git.securityops.co):
.IP \(bu 2
.B zupt-android
\(em
.UR https://git.securityops.co/cristiancmoises/zupt-android
.UE
.IP \(bu 2
.B zupt-web
\(em
.UR https://git.securityops.co/cristiancmoises/zupt-web
.UE
.IP \(bu 2
.B libzuptsdk
\(em
.UR https://git.securityops.co/cristiancmoises/libzuptsdk
.UE
.IP \(bu 2
.B vaptvupt
(standalone GPL codec) \(em
.UR https://git.securityops.co/cristiancmoises/vaptvupt
.UE

1
doc/zupt.1 Symbolic link
View file

@ -0,0 +1 @@
vaptvupt.1