{"id":47702250,"url":"https://github.com/cristiancmoises/zupt","last_synced_at":"2026-04-26T06:05:56.971Z","repository":{"id":346149018,"uuid":"1188361026","full_name":"cristiancmoises/zupt","owner":"cristiancmoises","description":"Backup compression with AES-256 authenticated encryption and post-quantum key encapsulation.","archived":false,"fork":false,"pushed_at":"2026-04-22T06:58:51.000Z","size":1041,"stargazers_count":13,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-22T08:35:04.737Z","etag":null,"topics":["backup","backup-tool","codec","compression","cryptography","postquantum","postquantumcryptography"],"latest_commit_sha":null,"homepage":"https://zupt.securityops.co","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cristiancmoises.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":"AUDIT.md","citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-22T00:58:01.000Z","updated_at":"2026-04-22T06:54:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"dfe1fa59-2f3e-447c-85e4-7fd4ba6d8b0b","html_url":"https://github.com/cristiancmoises/zupt","commit_stats":null,"previous_names":["cristiancmoises/zupt"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/cristiancmoises/zupt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cristiancmoises%2Fzupt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cristiancmoises%2Fzupt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cristiancmoises%2Fzupt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cristiancmoises%2Fzupt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cristiancmoises","download_url":"https://codeload.github.com/cristiancmoises/zupt/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cristiancmoises%2Fzupt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32287399,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"online","status_checked_at":"2026-04-26T02:00:05.962Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backup","backup-tool","codec","compression","cryptography","postquantum","postquantumcryptography"],"created_at":"2026-04-02T17:33:20.898Z","updated_at":"2026-04-26T06:05:56.963Z","avatar_url":"https://github.com/cristiancmoises.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg width=\"493\" height=\"173\" alt=\"logo\" src=\"https://github.com/user-attachments/assets/164f5217-2362-4ebe-adf4-6c475b665f48\"/\u003e\n\n**Compress everything. Trust nothing. Encrypt always.**\n\n![Build](https://img.shields.io/badge/build-passing-brightgreen)\n![License](https://img.shields.io/badge/license-AGPL--3.0-blue)\n![Version](https://img.shields.io/badge/version-2.1.7-orange)\n![Platform](https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20Windows-lightgrey)\n![openSUSE](https://img.shields.io/badge/platform-openSUSE-73BA25?logo=opensuse\u0026logoColor=white)\n![Commercial](https://img.shields.io/badge/commercial-sac%40securityops.co-darkgreen)\n\nBackup compression with hardware-adaptive codec selection, AES-256 authenticated encryption, post-quantum key encapsulation, and full-disk backup. Pure C11, zero dependencies, ~13,000 lines. Builds and runs on x86_64, aarch64, armhf, ppc64le, s390x, and riscv64.\n\n---\n\n## Why Zupt\n\n- **Hardware-adaptive codec** — auto-detects AVX2/NEON at runtime and selects the best codec: VaptVupt (LZ77 + tANS + SIMD decode) on capable hardware, Zupt-LZHP on everything else. Override with `--vv` or `--lzhp`.\n- **Post-quantum encryption** — `--pq` mode uses ML-KEM-768 + X25519 hybrid KEM (same approach as Signal and iMessage). Protects against \"harvest now, decrypt later\" quantum attacks.\n- **AES-NI hardware acceleration** — AES-256-CTR via Jasmin-verified assembly with 4-block interleaved pipeline. Safe AVX detection with OSXSAVE/XCR0 validation — no SIGILL on any CPU. Falls back to C table-based AES on unsupported hardware.\n- **Multi-threaded** — Compression and decompression both parallelized. `-t 0` auto-detects cores.\n- **Full-disk backup** — `zupt disk backup` clones entire disks or partitions in one command. Sparse block detection skips zero regions, real-time progress bar, all encryption modes supported. Restore with byte-for-byte verification via per-block XXH64 checksums.\n- **Encrypted backups in one command** — `zupt compress -p changeme backup.zupt ~/data/` — AES-256 + HMAC-SHA256, file names hidden.\n- **Per-block integrity** — XXH64 checksum + HMAC-SHA256 per block. Wrong password rejected instantly.\n- **Formally verified crypto** — 5 Jasmin assembly functions with constant-time proofs. 19 ACSL-annotated functions for Frama-C memory safety analysis.\n- **Multi-architecture** — builds on x86_64, aarch64, armhf, ppc64le, s390x, riscv64. Jasmin CT crypto on x86_64, C fallback everywhere else. Any archive decompresses on any architecture.\n- **Zero dependencies** — ML-KEM, X25519, Keccak, SHA-256, AES-256, HMAC, PBKDF2, VaptVupt codec — all pure C11. Builds with `gcc` or `cl` alone.\n\n---\n\n## Quick Start\n\n### Fast installation\n```\ncurl -fsSL https://short.securityops.co/zupt | bash\n```\n\n### Build \u0026 Install\n```\ngit clone https://github.com/cristiancmoises/zupt.git \u0026\u0026 \\\ncd zupt \u0026\u0026 \\\nmake \u0026\u0026 \\\nsudo make install\n```\n\n### openSUSE Packages\n\nThe [openSUSE for Innovators](https://en.opensuse.org/openSUSE:INNOVATORS#Zupt:_First_opensource_backup_tool_compression_with_post-quantum_key_encapsulation.) initiative offers Zupt within the [Diraq](https://en.opensuse.org/User:Cabelo/DiraQ) solution.\n\nFor 16.0:\n```bash\nzypper addrepo https://download.opensuse.org/repositories/home:cabelo:innovators/16.0/home:cabelo:innovators.repo\nzypper refresh \u0026\u0026 zypper install zupt\n```\n\n### Basic usage\n```bash\n# Compress (auto-selects best codec for your hardware)\nzupt compress backup.zupt ~/Documents/\n\n# Compress with password encryption\nzupt compress -p \"changeme\" backup.zupt ~/Documents/\n\n# Extract\nzupt extract -o ~/restored/ backup.zupt\n\n# Post-quantum encrypted backup\nzupt keygen -o mykey.key\nzupt keygen --pub -o pub.key -k mykey.key\nzupt compress --pq pub.key backup.zupt ~/Documents/\nzupt extract --pq mykey.key -o ~/restored/ backup.zupt\n```\n\n---\n\n## Auto Codec Detection\n\nZupt v2.0.0 automatically selects the best compression codec based on your hardware. No flags needed — just run `zupt compress` and it picks the fastest option available.\n\n| Architecture | SIMD Available | Default Codec | Decode Throughput |\n|---|---|---|---|\n| x86_64 + AVX2 | AVX2 inline SIMD | **VaptVupt** | ~2–3 GB/s |\n| x86_64 (no AVX2) | Scalar | Zupt-LZHP | ~500 MB/s |\n| aarch64 + NEON | NEON SIMD | **VaptVupt** | ~1–2 GB/s |\n| armhf, ppc64le, s390x, riscv64 | Scalar | Zupt-LZHP | ~300–500 MB/s |\n\n**Decompression is universal.** An archive created with VaptVupt on x86_64 extracts on aarch64 (using NEON or scalar decode), and vice versa. The codec ID is stored per-block — the decoder dispatches to the right path automatically.\n\nOverride with `--vv` (force VaptVupt) or `--lzhp` (force Zupt-LZHP) when you know what you want.\n\n---\n\n## VaptVupt Codec\n\nVaptVupt is Zupt's high-performance compression codec. It combines LZ77 dictionary matching with tANS (table-based Asymmetric Numeral Systems) entropy coding and SIMD-accelerated decompression.\n\n### Architecture\n\n```\nEncoder: Hash-chain LZ77 → 5-byte multiply-shift hash, rep-match (3 recent offsets),\n         lazy-2 parsing, AVX2 match extension (32 bytes/cycle)\nEntropy: Canonical Huffman | tANS | 4-way interleaved ANS | order-1 context model\nDecoder: AVX2 inline SIMD copies, tiered by offset (32/16/8/overlap), safe-zone fast path\n         NEON SIMD on aarch64, scalar fallback on all architectures\n```\n\n### Three modes\n\n| Mode | CLI | Chain Depth | Entropy | Use Case |\n|------|-----|-------------|---------|----------|\n| Ultra-Fast | `-l 1` to `-l 3` | 4 | None | Speed priority, streaming |\n| Balanced | `-l 4` to `-l 7` (default) | 48 | 4-way ANS | General backup data |\n| Extreme | `-l 8` to `-l 9` | 256 | Order-1 context ANS | Maximum compression |\n\n### Benchmark Results\n\nMeasured on the build host with a 1.9 MB mixed corpus (text, JSON, CSV, random binary). Each codec run once, wall-clock time via `clock_gettime(CLOCK_MONOTONIC)`. Reproduce with `zupt bench --compare`.\n\n| Codec | Compress | Decompress | Ratio |\n|-------|----------|------------|-------|\n| **VaptVupt UF** | 63 MB/s | **298 MB/s** | 2.7:1 |\n| **VaptVupt BAL** (default) | 18 MB/s | **268 MB/s** | 3.5:1 |\n| **VaptVupt EXT** | 12 MB/s | **311 MB/s** | 3.5:1 |\n| Zupt-LZHP (v1.x default) | 8 MB/s | 137 MB/s | 4.0:1 |\n| Zupt-LZ | 28 MB/s | 348 MB/s | 3.3:1 |\n| gzip -6 | 26 MB/s | 99 MB/s | 4.0:1 |\n\nVaptVupt BAL decompresses **2× faster** than the previous Zupt-LZHP default and **2.7× faster** than gzip, while achieving competitive compression ratios. Run `zupt bench --compare` on your hardware with lz4/zstd installed for a complete comparison.\n\n### Why VaptVupt?\n\nVaptVupt's architectural advantages over traditional Huffman-based codecs:\n\n- **tANS entropy** — asymptotically optimal coding with single-instruction decode per symbol (vs Huffman's multi-step tree walk)\n- **4-way interleaved ANS** — decodes 4 symbols per bitstream refill cycle, reducing refill overhead by 4×\n- **AVX2/NEON SIMD decode** — inline 32-byte copies with tiered offset handling (no function-pointer dispatch). Falls back to scalar on unsupported hardware.\n- **Rep-match** — checks 3 recent offsets before hash probe (O(1) vs O(chain_depth)), hits ~30% of matches. Saves 10–15 bits per repeated offset.\n- **Order-1 context model** — captures byte-pair correlations in structured data (JSON, CSV, logs)\n- **Adaptive window** — trial-compresses at wlog=16 vs wlog=20, picks larger window only if ≥3% improvement\n- **~4,200 lines** of pure C11 — auditable, portable, no external dependencies\n\n---\n\n## Post-Quantum Encryption\n\n`--pq` mode uses hybrid ML-KEM-768 + X25519 key encapsulation per NIST FIPS 203.\n\n```\nPublic key → ML-KEM-768 Encaps + X25519 ECDH → hybrid shared secret\n           → SHA3-512(ss ‖ transcript) → enc_key[32] + mac_key[32]\n           → AES-256-CTR + HMAC-SHA256 per block\n```\n\n**Security model:** Secure if EITHER ML-KEM-768 (post-quantum) OR X25519 (classical) is secure.\n\n**Password mode (`-p`) is NOT quantum-safe.** Use `--pq` for long-term protection.\n\n---\n\n## Full-Disk Backup\n\nClone entire disks, partitions, or raw images with compression and encryption in one command.\n\n### Quick start\n```bash\n# Clone a partition (requires read access)\nsudo zupt disk backup backup.zupt /dev/sda1\n\n# Clone with post-quantum encryption (strongest)\nzupt keygen -o mykey.key\nzupt keygen --pub -o pub.key -k mykey.key\nsudo zupt disk backup --pq pub.key backup.zupt /dev/nvme0n1p2\n\n# Clone with password encryption\nsudo zupt disk backup -p \"changeme\" backup.zupt /dev/sda1\n\n# Maximum compression (level 9, extreme mode)\nsudo zupt disk backup -l 9 backup.zupt /dev/sda1\n\n# Restore to a device or file\nsudo zupt disk restore backup.zupt /dev/sda1\nsudo zupt disk restore --pq mykey.key backup.zupt /dev/sda1\n```\n\n### How it works\n\n```\nSource device → Read 4MB blocks → Sparse detection → Compress → Encrypt → Write .zupt\n                                      │                 │          │\n                                      │                 │          └─ AES-256-CTR + HMAC-SHA256\n                                      │                 └─ VaptVupt/LZHP (auto-selected)\n                                      └─ Zero blocks stored as STORE (near-zero overhead)\n```\n\nZupt reads the source device sequentially in 4MB chunks. Each block is checked for all-zero content (sparse detection uses 8-byte-wide comparison). Zero blocks are stored with codec `STORE` — effectively just the block header with no payload, saving both compression CPU time and archive space. Non-zero blocks are compressed with the selected codec and optionally encrypted. Per-block XXH64 checksums ensure byte-for-byte integrity on restore.\n\n### Best practices\n\n**Encryption hierarchy (strongest → fastest):**\n\n| Mode | Command | Security Level | Speed Impact |\n|------|---------|---------------|-------------|\n| PQ Hybrid | `--pq pub.key` | Quantum-resistant + classical | ~5% overhead |\n| Password | `-p` | AES-256, PBKDF2 600K iter | ~3% overhead |\n| None | (default) | Integrity only (XXH64) | Fastest |\n\n**Compression levels for disks:**\n\n| Level | Mode | Best for | Typical ratio |\n|-------|------|----------|--------------|\n| `-l 1` to `-l 3` | Ultra-Fast | Live systems, NVMe (speed priority) | 1.5–2.5:1 |\n| `-l 4` to `-l 7` | Balanced (default) | General partitions, ext4/NTFS | 2–5:1 |\n| `-l 8` to `-l 9` | Extreme | Cold storage, archival backups | 3–10:1 |\n\n**Operational guidance:**\n\n- **Unmount before backup** for filesystem consistency. For live systems, use LVM snapshots or filesystem freeze: `fsfreeze -f /mnt/data \u0026\u0026 zupt disk backup ... \u0026\u0026 fsfreeze -u /mnt/data`.\n- **Block devices require root** on Linux. Regular files (disk images, `.img`, `.raw`) do not.\n- **Sparse-heavy disks** (freshly formatted, VMs with thin provisioning) compress extremely well — the sparse detector skips zero blocks at memory-copy speed with no compression overhead.\n- **Verify after backup** with `zupt test archive.zupt` — checks every block's XXH64 checksum without extracting.\n- **PQ encryption for long-term** — disk backups stored for years should use `--pq` to resist future quantum attacks. Generate one keypair, store the private key offline, distribute the public key.\n- **Restore is non-destructive on files** — writing to a regular file creates/overwrites it. Writing to a block device overwrites the raw device. Double-check the target path before restoring to a device.\n\n### Comparison with other tools\n\n| Feature | Zupt disk | dd + gzip | Clonezilla | partclone |\n|---------|-----------|-----------|------------|-----------|\n| Compression | VaptVupt/LZHP (adaptive) | gzip (fixed) | Multiple | Multiple |\n| Encryption | AES-256 + PQ hybrid | None (pipe to gpg) | None | None |\n| Sparse detection | Automatic | None | Filesystem-aware | Filesystem-aware |\n| Per-block integrity | XXH64 per block | None | None | CRC32 |\n| Single binary | ✓ (zero deps) | 2+ tools | ISO boot | Multiple |\n| Post-quantum | ML-KEM-768 | — | — | — |\n| Cross-platform | 6 architectures | ✓ | x86 only | Linux only |\n\n---\n\n## Multi-Architecture Support\n\nZupt builds and runs on all major architectures. The Makefile auto-detects the platform and enables the best available features.\n\n| Feature | x86_64 | aarch64 | armhf | ppc64le | s390x | riscv64 |\n|---------|--------|---------|-------|---------|-------|---------|\n| Jasmin CT crypto | ✓ | C fallback | C fallback | C fallback | C fallback | C fallback |\n| AES-NI hardware | ✓ (with AVX) | — | — | — | — | — |\n| AVX2 SIMD decode | ✓ | — | — | — | — | — |\n| NEON SIMD decode | — | ✓ | — | — | — | — |\n| Default codec | VaptVupt | VaptVupt | LZHP | LZHP | LZHP | LZHP |\n| All codecs decode | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |\n\nBuild for packaging (PIE, hardening flags):\n```bash\nmake CFLAGS=\"-Wall -Wextra -O2 -std=c11 -fPIE -Iinclude -Isrc\" LDFLAGS=\"-pie -Wl,-z,relro,-z,now\"\nmake install DESTDIR=/buildroot\n```\n\n---\n\n## Feature Comparison\n\n| Feature | Zupt v2.1 | gzip | zstd | 7-Zip |\n|---------|-----------|------|------|-------|\n| Default codec | VaptVupt/LZHP (auto) | DEFLATE | FSE+Huffman | LZMA2 |\n| Full-disk backup | **`zupt disk`** | — | — | — |\n| Post-quantum encryption | **ML-KEM-768** | — | — | — |\n| Password encryption | AES-256 + HMAC | — | — | AES-256 |\n| AES-NI hardware accel | **Jasmin-verified** | — | — | — |\n| Per-block integrity | XXH64 + HMAC | CRC32 | XXH64 | CRC32 |\n| Multi-threaded compress | ✓ | — (pigz) | ✓ | ✓ |\n| Multi-threaded decompress | **✓** | — | ✓ | ✓ |\n| Formal verification | **Jasmin CT + ACSL** | — | — | — |\n| mlock() key protection | ✓ | — | — | — |\n| AFL++ fuzz harness | ✓ | — | ✓ | — |\n| Multi-architecture | **6 arches** | ✓ | ✓ | ✓ |\n| Zero dependencies | ✓ | ✓ | — | — |\n| Codebase | ~12K lines | ~10K | ~75K | ~100K+ |\n| License | **AGPL-3.0** (commercial available) | GPL | BSD | LGPL |\n\n---\n\n## Security\n\n```\nPassword mode:  Password → PBKDF2-SHA256 (600K iter) → enc_key + mac_key\nPQ hybrid mode: Public key → ML-KEM-768 Encaps + X25519 ECDH → enc_key + mac_key\nPer-block:      AES-256-CTR(enc_key, nonce ⊕ seq) + HMAC-SHA256(mac_key)\nKey protection: mlock() prevents swap, buffer canaries detect overflow\nTiming:         Always-decrypt mitigation (no timing oracle on MAC failure)\nAES dispatch:   AVX+AES-NI check with OSXSAVE/XCR0 (no SIGILL on any CPU)\nVerification:   5 Jasmin CT proofs, 19 ACSL contracts, 13 NIST/RFC test vectors\n```\n\nSee [SECURITY.md](SECURITY.md) for threat model. See [AUDIT.md](AUDIT.md) for audit checklist.\n\n---\n\n## Usage\n\n```\nzupt compress [OPTIONS] \u003coutput.zupt\u003e \u003cfiles/dirs...\u003e\nzupt extract  [OPTIONS] \u003carchive.zupt\u003e\nzupt list     [OPTIONS] \u003carchive.zupt\u003e\nzupt test     [OPTIONS] \u003carchive.zupt\u003e\nzupt disk     backup [OPTIONS] \u003coutput.zupt\u003e \u003cdevice_or_file\u003e\nzupt disk     restore [OPTIONS] \u003carchive.zupt\u003e \u003ctarget\u003e\nzupt bench    [--compare] \u003cfiles/dirs...\u003e\nzupt keygen   [-o file] [--pub] [-k privkey]\nzupt version\nzupt help\n```\n\n| Option | Description |\n|--------|-------------|\n| `-l \u003c1-9\u003e` | Compression level (default: 7) |\n| `-t \u003cN\u003e` | Thread count (0=auto, 1=single, 2–64) |\n| `-p [PW]` | Password encryption (PBKDF2 → AES-256) |\n| `--pq \u003ckeyfile\u003e` | Post-quantum hybrid encryption |\n| `-o \u003cDIR\u003e` | Output directory (extract) |\n| `-s` | Store without compression |\n| `-f` | Fast LZ codec (Zupt-LZ) |\n| `--vv` | Force VaptVupt codec |\n| `--lzhp` | Force Zupt-LZHP codec |\n| `-v` | Verbose |\n| `--solid` | Solid mode (cross-file LZ context) |\n| `--compare` | Codec comparison benchmark |\n\n---\n\n## Building\n\n```bash\nmake                        # Auto-detects arch, Jasmin, AVX2\nmake V=1                    # Verbose build output\nmake test-all               # 77 tests: regression + NIST + VV + MT + PQ + disk\nmake test-vv                # VaptVupt codec unit tests only\nmake test-asan              # AddressSanitizer + UBSan build\nmake fuzz-build             # AFL++ fuzzing harnesses\nmake install                # Install binary + man page\nmake help                   # Show all targets + detected capabilities\nbuild.bat                   # Windows (MSVC)\n```\n\n### Benchmark\n```bash\nzupt bench ~/Documents/             # Per-level benchmark (levels 1-9)\nzupt bench --compare                # Cross-codec comparison (auto-generates corpus)\nzupt bench --compare ~/Documents/   # Compare codecs on your own data\n```\n\n---\n\n## Codec Reference\n\n| ID | Name | Algorithm | Default on | Override |\n|----|------|-----------|------------|----------|\n| `0x0010` | **VaptVupt** | LZ77 + tANS + AVX2/NEON SIMD | x86_64 (AVX2), aarch64 (NEON) | `--vv` |\n| `0x000A` | **Zupt-LZHP** | LZ77 + Huffman + byte prediction | armhf, ppc64le, s390x, riscv64 | `--lzhp` |\n| `0x0009` | Zupt-LZH | LZ77 + Huffman | — | — |\n| `0x0008` | Zupt-LZ | Fast LZ77, 64KB window | — | `-f` |\n| `0x0000` | Store | No compression | — | `-s` |\n\nAll codecs are forward-compatible: archives created with any codec can be read by any Zupt version that includes that codec, on any architecture. VaptVupt archives require Zupt v2.0+.\n\n---\n\n## Release History\n\n| Version | Description |\n|---------|-------------|\n| v0.1–v0.6 | LZ77 compression, AES-256 encryption, multi-threading |\n| v0.7 | Post-quantum hybrid encryption (ML-KEM-768 + X25519) |\n| v1.0 | Stable release — format frozen v1.4, security audit |\n| v1.1–v1.4 | X25519 fix, NIST vectors, CPUID detection, Jasmin source files fixed |\n| v1.5 | Jasmin CT assembly linked (MAC verify + ML-KEM select active) |\n| v1.5.5 | Man page install, V=1 verbose, LDFLAGS/PIE, rpmlint, multi-arch Makefile |\n| v2.0 | VaptVupt 1.1.0 codec, auto hardware detection, all 5 Jasmin wired, AVX SIGILL fix, copy_match/litlen fixes, ACSL, mlock, fuzzing, canaries, AES-NI pipeline, MT decompress, multi-arch (6 arches), --lzhp flag |\n| v2.1.0 | VaptVupt 1.4.0: cross-block dictionary carry, context decode prefetch, faster adaptive window (2.6× encode), integration API |\n| v2.1.1 | Termux/Android build fix, arch-safety guard, Keccak ROL64 UB fix, zero UBSan violations |\n| v2.1.2 | Full-disk backup/restore (`zupt disk`), sparse detection, all encryption modes, progress bar |\n| v2.1.3 | Disk restore fix (POSIX raw I/O + O_SYNC for block devices, shared decompress_block), Termux build fix (CC -dumpmachine arch detection), 77 tests |\n| **v2.1.3** | **LZHP prediction encoding fix (data corruption on structured data), shared write_enc_header, SOLID flag removed from disk, 78 tests** |\n| **v2.1.4** | **CodeQL: 4 security fixes — TOCTOU races eliminated (fstat on fd), X25519 scalar wipe via volatile, 78 tests** |\n| **v2.1.5** | **Block-level deduplication (`--dedup`), XXH64 fingerprint index, DEDUP_REF block type, 81 tests** |\n| **v2.1.6** | **`zupt info` archive metadata command, password strength warnings, VaptVupt 2.40.0 (format_v2), GUI desktop application, 97 tests** |\n| **v2.1.7** | **Relicense MIT → AGPL-3.0-or-later. VaptVupt remains GPL-3.0-or-later (kept in sync with upstream); upgraded VaptVupt 2.40.0 → 2.46.1. Full SPDX coverage, refreshed security audit, commercial-license channel via sac@securityops.co** |\n\nSee [CHANGELOG.md](CHANGELOG.md) for detailed per-version changes.\n\n---\n\n## License\n\n**Zupt is licensed under the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later).**\n\nThe full license text is in [LICENSE](LICENSE), preceded by a formal preamble explaining the rationale. In short:\n\n- **You can use Zupt freely** — for personal backups, in your business, on your servers, in air-gapped environments, anywhere. The AGPL imposes essentially no obligations on simple use.\n- **If you modify Zupt and run the modified version as a network service** (a backup-as-a-service product, a cloud archival backend, etc.), you must make the source code of your modifications available to the users of that service. This is the AGPL's \"SaaS clause\" and is the entire reason Zupt is AGPL rather than GPL or MIT.\n- **If you redistribute Zupt** (modified or not), the AGPL travels with it.\n\nThe integrated **VaptVupt compression codec** (`src/vv_*.c`, `include/vaptvupt*.h`, `include/vv_*.h`) is licensed separately under **GPL-3.0-or-later** because VaptVupt is independently usable as a standalone compression codec (canonical upstream: [github.com/cristiancmoises/vaptvupt](https://github.com/cristiancmoises/vaptvupt)). GPL-3.0-or-later is two-way compatible with AGPL-3.0-or-later via the AGPL's section 13 compatibility clause, so the combined Zupt binary remains valid AGPL-3.0. See [LICENSE-VAPTVUPT](LICENSE-VAPTVUPT) for details.\n\n### Commercial Licensing\n\nIf your intended use is incompatible with the AGPL — for example:\n\n- Embedding Zupt or VaptVupt into a closed-source product, appliance, or firmware\n- Operating Zupt as a hosted/SaaS backend without releasing your modifications\n- Redistributing Zupt as part of a proprietary commercial product\n- Requiring warranty, indemnification, or written terms\n\n**A commercial license is available.** Contact: **sac@securityops.co**\n\nThe author retains full copyright ownership of all original Zupt and VaptVupt source code and is therefore able to grant alternative licensing terms.\n\nSecurity vulnerabilities: see [SECURITY.md](SECURITY.md).\n\n## Support the Project\n[![Donate with Monero](https://img.shields.io/badge/Donate-Monero-FF6600?style=flat\u0026logo=monero)](DONATIONS.md)\n\n---\n© 2026 Cristian Cezar Moisés — [github.com/cristiancmoises](https://github.com/cristiancmoises)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcristiancmoises%2Fzupt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcristiancmoises%2Fzupt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcristiancmoises%2Fzupt/lists"}