Commit graph

13 commits

Author SHA1 Message Date
Thomas Waldmann
0e3876d5e4
buzhash64: add FastCDC-style normalized chunking
Normalized chunking switches between a stricter and a looser cut mask
around the target chunk size. This greatly tightens the chunk-size
distribution (coefficient of variation ~0.9 -> ~0.3 in tests) and removes
the dedup-hostile max-size-clamped chunks, with unchanged deduplication.

chunker-params for buzhash64 gains a required 6th field, nc_level:

  buzhash64,chunk_min,chunk_max,chunk_mask,window_size,nc_level

Use nc_level=2 for the new default, nc_level=0 to disable (then behavior
is byte-identical to the previous single-mask chunker).

buzhash (32bit) is untouched and stays bit-compatible with borg 1.x.

The mask transition point (normal_size) defaults to a principled formula
(target minus the expected loose-phase tail) so the mean stays near the
target; it can be tuned via the normal_size constructor arg.

scripts/chunker_bench.py: evidence harness used to measure chunk-size
distribution, dedup ratio, throughput and shift-resilience.

Measurements (before = nc_level 0, after = nc_level 2; both at the default
params buzhash64,19,23,21,4095; measured with scripts/chunker_bench.py):

5 GiB of incompressible data (~2000-2700 chunks, statistically stable):

  before:  CV 0.739,  49 max-size-clamped (8 MiB) chunks,   953 MB/s
  after:   CV 0.311,   0 max-size-clamped chunks,          1024 MB/s

Re-backup of a 2.5 GiB file after a few scattered single-byte edits
(deduplication ratio; 0.5 = v2 fully deduplicated against v1, lower is
better):

   64 edits:  before 0.5424  ->  after 0.5235
  320 edits:  before 0.6791  ->  after 0.6142

Normalized chunking deduplicates better after edits: removing the
max-size-clamped chunks means a single-byte change invalidates much less
data (about 36% less dedup overhead at 320 edits). Throughput was also
consistently higher with nc_level=2 at this scale.

Also: fix bug when computing the mask, one needs to use 1ULL instead of
1, so the shifting computation is done in a uint64, not in a 32bit int.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 12:00:09 +02:00
Thomas Waldmann
29a760e2b3
repo-create: split --encryption into --encryption + --id-hash, #9168
The combined --encryption value packed two orthogonal dimensions (cipher / AE
algorithm and id hash function) into a single string, causing a combinatorial
explosion of mode names. Key location was already split out into --key-location.

Now:
- --encryption selects only the cipher / AE algorithm:
  none, authenticated, aes256-ocb, chacha20-poly1305
- --id-hash selects the id hash function: sha256 (default) or blake3
- --key-location (unchanged) selects key storage: repokey (default) or keyfile

The old combined names were removed (clean break): select a BLAKE3 suite via
--encryption ... --id-hash blake3 instead of blake3-*. aes-ocb was renamed to
aes256-ocb (key NAME shown by repo-info and ARG_NAME in JSON updated to match).
"none" has no key, so it only supports the sha256 id hash.

No on-disk format, key-type byte, or crypto behavior changes: the existing key
classes form a clean cross-product of {cipher} x {id-hash}, selected via the new
ENC_NAME / IDHASH_NAME class attributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:44:38 +02:00
Thomas Waldmann
d2bc45f56d
key: unify keyfile/repokey classes, locate key independent of type byte (#9743)
Borg used to read the manifest's key-type byte and then look for the key in
exactly one place (keyfile or repokey) depending on the key class that byte
selected. As a result every crypto suite was duplicated into a keyfile class
and a repokey class that differed only in TYPE, NAME, ARG_NAME and STORAGE.

Now key *location* is independent of the type byte: detection tries keyfiles
first and repokeys afterwards until a passphrase unlocks a key. The type byte
still selects the crypto suite (id hash, MAC, cipher) to instantiate. Where a
key is stored (keyfile vs repokey) is therefore a per-key property
(self.storage), not a separate class, so a repository may even hold a mix of
keyfile- and repo-stored borg keys.

With storage decoupled from class identity, the keyfile/repokey class pairs
collapse into one class per crypto suite:
- modern AEAD: AESOCBKey, CHPOKey, Blake3AESOCBKey, Blake3CHPOKey
- legacy borg 1.x (read-only): AESCTRKey, Blake2AESCTRKey
There is now exactly one type byte per modern crypto suite (the old separate
repokey type bytes 0x11/0x21/0x31/0x41 were removed; borg2 is beta and only
needs to read repos it created). identify_key() matches on TYPES_ACCEPTABLE.

CLI: --encryption selects only the crypto suite (aes-ocb, chacha20-poly1305,
blake3-aes-ocb, blake3-chacha20-poly1305, authenticated*, none); the storage
location is chosen with the new --key-location=repokey|keyfile (default
repokey). The old combined modes (repokey-aes-ocb etc.) were removed.
borg key import also gained --key-location. borg key change-location no longer
swaps key classes or rewrites the manifest; it just re-saves the unlocked key
at the new location.

Keyfile removal (key remove, change-location) now overwrites the keyfile with
random data via secure_erase() before unlinking, consistent with save().

borg 1.x legacy read compatibility is preserved (the legacy class merge is a
behavior-preserving rename; the legacy type bytes incl. PASSPHRASE stay in
TYPES_ACCEPTABLE).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 23:48:45 +02:00
Thomas Waldmann
ff6d0e8775
fix typos / grammar in transfer docs 2026-06-06 19:34:46 +02:00
Thomas Waldmann
5d8b761a6c
crypto: integrate blake3, blake2b is legacy, fixes #8867
BLAKE3 is generally faster and provides a more modern construction for
keyed hashing (using its internal keyed mode instead of the construction
used for BLAKE2b).

Key types changed:
- authenticated-blake2 -> authenticated-blake3
- {keyfile,repokey}-blake2-aes-ocb -> {keyfile,repokey}-blake3-aes-ocb
- {keyfile,repokey}-blake2-chacha20-poly1305 -> {keyfile,repokey}-blake3-chacha20-poly1305

This also fixes the slightly unusual way how we used blake2b,
it is only supported for importing borg 1.x repos.

New repos either use HMAC-SHA256 or BLAKE3.
2026-06-06 19:34:45 +02:00
Mrityunjay Raj
02f447536c docs: document platformdirs change and platform-specific directory paths, fixes #7332 2026-02-27 11:50:35 +05:30
Thomas Waldmann
3120f9cd1c
fixed typos and grammar (AI)
this was done by Junie AI.
2025-09-23 14:56:23 +02:00
Thomas Waldmann
04dfadbbd6
cli: rename r* commands to repo-*
also:
- adapt tests
- adapt BuildMan manpage generation
- adapt help strings / doc strings
- docs
2024-09-08 18:06:24 +02:00
Thomas Waldmann
89e4a52c56 docs: misc. updates
- remove outdated stuff
- fix infos for borg 2.0
2022-08-03 11:35:25 +02:00
Thomas Waldmann
dbb63f874b docs: fix rst literal blocks 2022-07-05 00:38:37 +02:00
Thomas Waldmann
0a7baa53c4 docs: fix borg transfer formatting / rendering, fixes #6800 2022-06-26 20:29:10 +02:00
Thomas Waldmann
3232cb4a7e transfer: add a specific transfer example 2022-06-26 01:22:28 +02:00
Thomas Waldmann
51cf85e627 build_usage / build_man / doc updates 2022-06-25 21:58:19 +02:00