Skip to content

ffi: entropy encoding + backup archive building blocks - #2435

Open
ronaldtse wants to merge 3 commits into
mainfrom
key-backup-building-blocks
Open

ffi: entropy encoding + backup archive building blocks#2435
ronaldtse wants to merge 3 commits into
mainfrom
key-backup-building-blocks

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

Summary

Adds two general-purpose building-block APIs that clients can compose into backup, sync, and escrow workflows. Each is self-contained and parameterised; rnp deliberately does not bake in any specific application's workflow.

What's in this PR

Entropy encoding utility (rnp_entropy_encode_human_readable, _decode, _validate):

  • Generates cryptographically random entropy via the FFI RNG.
  • Encodes it in a caller-specified alphabet, split into groups with optional identifiers and optional SHA-256-based checksum.
  • Useful whenever random bytes need to be transcribed by humans (paper backup, manual entry).
  • Default alphabet is hex; callers supply their own alphabet via the params struct (e.g. handwriting-friendly variants).
  • disable_* bool fields follow C convention: false (zero-init default) = include feature, true = omit. This lets callers pass an all-zero params struct for the common default case.

Backup archive format (rnp_backup_archive_create, _load):

  • Wraps a sequence of secret-key exports in a standard OpenPGP signed-and-encrypted message.
  • Wire format is a literal-data packet containing concatenated transferable secret keys, signed by a caller-specified key, encrypted to a caller-specified public key.
  • Format is RFC 9580-compliant; any OpenPGP library can produce or consume it.
  • Documented in docs/develop/backup-format.adoc.

Tests:

  • test_ffi_entropy_encoding_roundtrip covers default-alphabet round-trip, custom-alphabet round-trip, order-independent group entry, tampered-checksum rejection, invalid-params rejection.
  • test_ffi_backup_archive_roundtrip covers generate-keys → create archive → fresh FFI → load archive → verify recovered key present and secret.

Why

These two building blocks come up in many real-world workflows:

  • Enterprise key escrow
  • Personal offline backups
  • Multi-device key synchronisation
  • Application-specific recovery flows

Previously each client would re-implement the entropy encoding and the signed+encrypted container pattern from scratch, with attendant correctness risk (checksum bugs, signature-then-encrypt ordering bugs, etc.). This PR gives them a tested, canonical implementation in the rnp library itself.

Architectural decision

rnp is intentionally a crypto library, not a workflow framework. The APIs in this PR expose building blocks that clients compose on their own; they do NOT prescribe a specific workflow. Naming (encryption_key, decryption_key, signing_key) is intentionally generic so multiple applications can adopt the same primitives without coupling.

What's NOT in this PR

  • No mention of any specific application or external proposal.
  • No CLI surface for these APIs (callers use the FFI directly).
  • No "recovery keypair" or "data-signkey" pattern baked in; callers compose their own key structure as they see fit.

Test plan

  • Build clean on default config (no warnings)
  • test_ffi_entropy_encoding_roundtrip passes locally (5 cases covered)
  • test_ffi_backup_archive_roundtrip passes locally (full round-trip with separate FFIs)
  • No regression in test_ffi_encrypt_pass, test_ffi_argon2_locked_seckey, test_ffi_encrypt_pk_with_v6_key
  • CI green on all platforms

Comment thread src/tests/ffi-enc.cpp
assert_true(archive_len > 0);

/* Save to a file for re-input. */
FILE *f = fopen("backup.archive", "wb");
@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.76471% with 120 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.11%. Comparing base (b6112ce) to head (5ea3f4f).

Files with missing lines Patch % Lines
src/lib/rnp.cpp 66.96% 75 Missing ⚠️
src/lib/entropy_encoding.cpp 77.27% 45 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2435      +/-   ##
==========================================
- Coverage   85.37%   85.11%   -0.26%     
==========================================
  Files         126      127       +1     
  Lines       22866    23291     +425     
==========================================
+ Hits        19521    19825     +304     
- Misses       3345     3466     +121     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ronaldtse
ronaldtse requested review from antonsviridenko and ni4 July 31, 2026 16:19
@ronaldtse
ronaldtse force-pushed the key-backup-building-blocks branch from 2018478 to 458f4c8 Compare August 2, 2026 09:43

@ni4 ni4 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM as soon as CI passes!

Adds two generic building-block APIs that clients can compose into
backup, sync, and escrow workflows. Each is self-contained and
parameterised so callers can adapt them to their own formats and
storage models; rnp deliberately does not bake in any one workflow.

Entropy encoding (rnp_entropy_encode_human_readable and friends):
  Generates cryptographically random entropy and encodes it in a
  caller-specified alphabet, split into groups with optional
  identifiers and optional SHA-256-based checksum. Useful whenever
  random bytes need to be transcribed by humans (paper backup,
  manual entry, etc.). The default alphabet is hex; callers can
  supply their own alphabet (e.g., handwriting-friendly variants)
  via the params struct.

  The 'disable_*' fields are bool but follow C convention: false
  (zero-init default) means "include the feature", true means
  "omit". This lets callers pass an all-zero params struct for the
  common default case.

Backup archive (rnp_backup_archive_create / _load):
  Wraps a sequence of secret-key exports in a standard OpenPGP
  signed-and-encrypted message. The wire format is documented in
  docs/develop/backup-format.adoc and is just a literal-data
  packet containing concatenated transferable secret keys, signed
  by a caller-specified key, then encrypted to a caller-specified
  public key. The format is RFC 9580-compliant and any
  OpenPGP library can produce or consume it.

Tests:
  test_ffi_entropy_encoding_roundtrip covers default-alphabet
  round-trip, custom-alphabet round-trip, order-independent group
  entry, tampered-checksum rejection, and invalid-params rejection.
  test_ffi_backup_archive_roundtrip covers generate-keys → create
  archive → fresh FFI → load archive → verify recovered key
  present and secret.

Wire format docs: docs/develop/backup-format.adoc.

This PR does NOT mention any specific application or external
proposal. Both building blocks are general-purpose: useful for
enterprise key escrow, personal offline backups, multi-device
sync, or any other workflow that needs human-transcribable
entropy or signed/encrypted key containers.
@ronaldtse
ronaldtse force-pushed the key-backup-building-blocks branch from 458f4c8 to 5ea3f4f Compare August 4, 2026 16:26
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.

3 participants