From 9800530d2e3f18d3ba355b556f4fe4a76665e77e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristian=20Cezar=20Mois=C3=A9s?= Date: Fri, 10 Jul 2026 00:20:49 -0300 Subject: [PATCH] v4.2.1: info correctly reports --pq-only vs hybrid post-quantum mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `vaptvupt info` mislabelled full post-quantum (--pq-only, enc_type 0x06) archives as "PQ Hybrid: YES (ML-KEM-768 + X25519)". Full-PQ archives set the generic ZUPT_FLAG_PQ_HYBRID header flag (the enc_type byte is what distinguishes hybrid 0x02 from pure 0x06), but info only checked the flag. info now seeks to hdr.encryption_header_off, reads the real enc_type from the encryption-header block, and reports the actual mode: "ML-KEM-768 only, no classical layer" for --pq-only, and hybrid / SDK-v2 / sealed-box for the others. Reader-side only — no wire-format change; existing 4.2.0 archives are relabelled correctly with no re-encryption. --- CHANGELOG.md | 16 ++++++++++++++++ doc/vaptvupt.1 | 2 +- include/zupt.h | 2 +- src/zupt_format.c | 36 ++++++++++++++++++++++++++++++++++-- 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc2f7f9..15899d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,22 @@ # VaptVupt Changelog +## [4.2.1] — 2026-07-10 — `info` correctly reports the post-quantum mode + +### Fixed + +- **`vaptvupt info` mislabelled `--pq-only` archives as hybrid.** Full + post-quantum archives set the generic `ZUPT_FLAG_PQ_HYBRID` header flag (the + `enc_type` byte is what distinguishes hybrid `0x02` from pure `0x06`), but + `info` only checked the flag and always printed "PQ Hybrid: YES (ML-KEM-768 + + X25519)". It now reads the real `enc_type` from the encryption-header block + and reports the actual mode: "ML-KEM-768 only, no classical layer" for + `--pq-only`, and hybrid / SDK-v2 / sealed-box for the others. Reader-side only + — no wire-format change; existing 4.2.0 archives are relabelled correctly with + no re-encryption. The crypto was always correct; only the `info` label was + wrong. + + ## [4.2.0] — 2026-07-09 — Full (pure) post-quantum mode; dedup keystream-reuse fix ### Added — full post-quantum encryption (`--pq-only`) diff --git a/doc/vaptvupt.1 b/doc/vaptvupt.1 index 3578b64..db97dc3 100644 --- a/doc/vaptvupt.1 +++ b/doc/vaptvupt.1 @@ -1,7 +1,7 @@ .\" 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 4.2.0" "User Commands" +.TH VAPTVUPT 1 "July 2026" "vaptvupt 4.2.1" "User Commands" .SH NAME vaptvupt \- post-quantum backup compression utility (formerly zupt) diff --git a/include/zupt.h b/include/zupt.h index 4ed6e21..96d8ff9 100644 --- a/include/zupt.h +++ b/include/zupt.h @@ -50,7 +50,7 @@ #define ZUPT_PRODUCT_EXTENSION ".zupt" /* on-disk archive extension (kept stable) */ #define ZUPT_PRODUCT_TAGLINE "Post-quantum backup compression" -#define ZUPT_VERSION_STRING "4.2.0" +#define ZUPT_VERSION_STRING "4.2.1" /* Vendored codec release (upstream tag) — single source for display strings. * The codec's own VV_VERSION_* is its internal API version, not the release. */ #define ZUPT_CODEC_RELEASE "2.60.4" diff --git a/src/zupt_format.c b/src/zupt_format.c index 7828bbc..5139d42 100644 --- a/src/zupt_format.c +++ b/src/zupt_format.c @@ -2903,6 +2903,23 @@ zupt_error_t zupt_archive_info(const char *path) { has_footer = 1; } } + + /* Read the real enc_type from the encryption-header block so `info` can + * distinguish hybrid --pq (0x02) from full --pq-only (0x06), the SDK-v2 + * (0x03) and sealed-box (0x05) modes — the ZUPT_FLAG_PQ_HYBRID header flag + * is a generic PQ indicator set by all of them. Block layout from + * write_enc_header: 7-byte prefix (magic0,magic1,block_type,codec u16, + * flags u16) + varint(len) + varint(len) + u64 xxh64 + enc_hdr[0]=enc_type. */ + uint8_t enc_type = 0; + if ((hdr.global_flags & ZUPT_FLAG_ENCRYPTED) && hdr.encryption_header_off != 0 && + fseeko(f, (off_t)hdr.encryption_header_off + 7, SEEK_SET) == 0) { + uint64_t l1 = 0, l2 = 0; + if (zupt_read_varint(f, &l1) > 0 && zupt_read_varint(f, &l2) > 0 && + fseeko(f, 8, SEEK_CUR) == 0) { + uint8_t b; + if (fread(&b, 1, 1, f) == 1) enc_type = b; + } + } fclose(f); /* UUID */ @@ -2938,8 +2955,23 @@ zupt_error_t zupt_archive_info(const char *path) { if (has_footer) printf(" Blocks: %llu\n", (unsigned long long)total_blocks); printf(" Encrypted: %s\n", (fl & ZUPT_FLAG_ENCRYPTED) ? "YES" : "no"); - if (fl & ZUPT_FLAG_PQ_HYBRID) - printf(" PQ Hybrid: YES (ML-KEM-768 + X25519)\n"); + if (fl & ZUPT_FLAG_PQ_HYBRID) { + switch (enc_type) { + case ZUPT_ENC_PQ_ONLY: + printf(" Post-quantum: YES (ML-KEM-768 only, no classical layer)\n"); + break; + case ZUPT_ENC_PQ_SDK_V2: + printf(" Post-quantum: YES (ML-KEM-768 + X25519, SDK v2 + HPKE)\n"); + break; + case ZUPT_ENC_PQ_BOX_V1: + printf(" Post-quantum: YES (ML-KEM-768 + X25519, sealed box)\n"); + break; + case ZUPT_ENC_PQ_HYBRID: + default: + printf(" Post-quantum: YES (ML-KEM-768 + X25519, hybrid)\n"); + break; + } + } if (fl & ZUPT_FLAG_SOLID) printf(" Solid: YES\n"); if (fl & ZUPT_FLAG_MULTITHREADED)