Skip to content

repo-create: split --encryption into --encryption + --id-hash (#9168)#9779

Merged
ThomasWaldmann merged 6 commits into
borgbackup:masterfrom
ThomasWaldmann:split-encryption-id-hash-9168
Jun 15, 2026
Merged

repo-create: split --encryption into --encryption + --id-hash (#9168)#9779
ThomasWaldmann merged 6 commits into
borgbackup:masterfrom
ThomasWaldmann:split-encryption-id-hash-9168

Conversation

@ThomasWaldmann

Copy link
Copy Markdown
Member

Resolves #9168.

What

borg repo-create --encryption packed two orthogonal dimensions — the cipher / AE algorithm and the id hash function — into a single combined string (e.g. blake3-chacha20-poly1305), which grows combinatorially as ciphers/hashes are added. Key location was already split out into --key-location. This finishes the decomposition:

  • --encryption / -e (required): cipher / AE algorithm — none, authenticated, aes256-ocb, chacha20-poly1305
  • --id-hash / -i (default sha256): id hash function — sha256 or blake3
  • --key-location (unchanged): repokey (default) or keyfile

Example:

borg repo-create --encryption aes256-ocb --id-hash blake3 --key-location keyfile

Notes / decisions

  • Clean break: the old combined --encryption names are removed. Select a BLAKE3 suite via --encryption ... --id-hash blake3 instead of blake3-*. Borg 2 is unreleased, so no deprecation shim.
  • aes-ocb renamed to aes256-ocb for clarity. The key NAME shown by borg repo-info (AES256-OCB) and the ARG_NAME reported in --json (encryption.mode) were updated to match.
  • none (plaintext) has no key, so it only supports the sha256 id hash; --encryption none --id-hash blake3 is rejected with a clear error.

Implementation

No on-disk format, key-type byte, or crypto behavior changes — the 7 existing key classes already form a clean cross-product of {cipher} × {id-hash}. Selection is now driven by two new class attributes, ENC_NAME and IDHASH_NAME (the latter set once on the id-hash mix-ins), and key_creator() matches on the pair.

Tests / docs

  • Added cross-product resolution tests plus rejection tests (none+blake3, legacy combined name) in repo_create_cmd_test.py; updated test constants and the few blake3-aes-ocb literals.
  • Regenerated docs/usage/repo-create.rst.inc, rewrote the epilog (table → three-axis explanation), updated transfer.rst, and added a changes.rst entry.

Full archiver + crypto + benchmark suites pass locally.

🤖 Generated with Claude Code

…ckup#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>
@ThomasWaldmann ThomasWaldmann force-pushed the split-encryption-id-hash-9168 branch from e6f8686 to 29a760e Compare June 15, 2026 15:45
@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.88%. Comparing base (9ba7241) to head (2eef6c8).
⚠️ Report is 12 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #9779   +/-   ##
=======================================
  Coverage   84.87%   84.88%           
=======================================
  Files          92       92           
  Lines       15165    15172    +7     
  Branches     2271     2275    +4     
=======================================
+ Hits        12872    12879    +7     
  Misses       1589     1589           
  Partials      704      704           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

ThomasWaldmann and others added 5 commits June 15, 2026 18:31
…ckup#9168

Stop using key.ARG_NAME (the combined crypto-suite name) for the JSON output.
The "encryption" object now mirrors the split CLI options: the "mode" field is
replaced by "encryption" (cipher / AE algorithm, key.ENC_NAME) and "id_hash"
(id hash function, key.IDHASH_NAME).

This is a breaking change to the documented JSON API.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ARG_NAME had no readers left after the JSON output switched to ENC_NAME/IDHASH_NAME,
so remove it from all (current and legacy) key classes.

Give the legacy (borg 1.x, read-only) key classes the two dimensions so that
repo-info/list --json reports a meaningful crypto suite for legacy repos instead
of null/null:
- AESCTRKey:            encryption=aes256-ctr, id_hash=sha256
- Blake2AESCTRKey:      encryption=aes256-ctr, id_hash=blake2
- Blake2AuthenticatedKey: encryption=authenticated, id_hash=blake2

IDHASH_NAME="blake2" is set on the ID_BLAKE2b_256 mix-in (parallel to the
ID_HMAC_SHA_256 / ID_BLAKE3_256 mix-ins). These legacy values never become CLI
choices: encryption_argument_names()/id_hash_argument_names() only iterate
AVAILABLE_KEY_TYPES, not LEGACY_KEY_TYPES.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…not NAME

The keyfile detection used `key.NAME.startswith("key file")`, but since the
keyfile/repokey unification no key class has such a NAME, so encryption.keyfile
was never emitted (even for keyfile repos). Decide it from the key storage
(KeyBlobStorage.KEYFILE), matching the text repo-info output. Add a test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…splay string

The "you need KEY AND PASSPHRASE" warning was gated on key.NAME != "plaintext",
a brittle dependency on a human-readable display string. Use the cipher dimension
instead: only plaintext has ENC_NAME == "none"; every key-bearing suite (including
the authenticated ones, which should warn) differs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…om ENC_NAME/IDHASH_NAME

NAME was only read by "borg repo-info" to show the crypto suite. Remove it from
all (current and legacy) key classes and let repo-info assemble the display from
the two real dimensions instead: "<mode>, <ENC_NAME>, <IDHASH_NAME>", e.g.
"Encrypted: Yes (repokey, aes256-ocb, sha256)" or
"Encrypted: No (repokey, authenticated, blake3)".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ThomasWaldmann ThomasWaldmann marked this pull request as ready for review June 15, 2026 17:52
@ThomasWaldmann ThomasWaldmann merged commit b483c9e into borgbackup:master Jun 15, 2026
18 of 20 checks passed
@ThomasWaldmann ThomasWaldmann deleted the split-encryption-id-hash-9168 branch June 15, 2026 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split repo-create --encryption into --mode, --encryption, and --hash (Borg 2 only)

1 participant