threadpanic/rustpg
1
0
Fork
You've already forked rustpg
0
2 GUI Reference
Bert van der Weerd edited this page 2026年05月18日 17:37:36 +02:00

GUI Reference (rustpg)

rustpg is the graphical binary. It shares the same keyring, config file, and crypto library (rpglib) as the CLI — keys generated or imported in one are immediately available in the other.

Built with egui / eframe. Window title: Rust PrivacyGuard. Default size: 900 ×ばつ 600 px.


Startup

On launch, rustpg resolves the master password and opens the keyring:

  1. Load master_password and symmetric_password from the OS keyring.
  2. If key_material.rpg exists:
    • If the password was cached and decryption succeeds → open silently.
    • Otherwise → show Open keyring dialog (dark red, password pre-filled from OS keyring).
  3. If no .rpg file exists:
    • Seed two demo identities (Alice, Bob) into memory, or load the legacy key_material.txt if present.
    • Show Protect your keyring dialog to set a master password.
  4. After the dialog resolves → apply_km_to_session() sets the active identity.
  5. If a file was passed as a CLI argument → load it now (deferred until the keyring dialog is gone).

Layout

┌─────────────────────────────────────────────────────┐
│ File Operations Keys Format View Help │ ← Menu bar
├─────────────────────────────────────────────────────┤
│ View: [Plain text] [Hex dump] │ Identity │ Filepath │ ← Toolbar
├─────────────────────────────────────────────────────┤
│ │
│ Central panel (buffer view) │
│ │
├─────────────────────────────────────────────────────┤
│ Status message Type N bytes │ ← Status bar
└─────────────────────────────────────────────────────┘

Toolbar shows: view mode toggle (plain/hex, when applicable) · active identity · open file path.

Status bar shows: last operation result (left) · buffer type and byte count (right).


The buffer

All data lives in a single in-memory buffer managed by CryptoSystem. Every operation reads from and writes back to this buffer — there is no separate input/output concept. Loading a file, pasting from clipboard, or running a crypto operation all replace the buffer contents.

Two write gates exist:

  • load_data(bytes) — used by file open, paste, and edit buffer.
  • run_crypto_op(fn) — used by all crypto and format operations; updates the status bar on success or shows an error.

Both bump buffer_generation, which invalidates the cached hex dump.


Buffer classification and view modes

On every frame the buffer is classified into one of these kinds:

Kind Detection
Plaintext Valid UTF-8, no special prefix
BinarySigned Starts with RUSTPGSIG\x02
ClearSigned Starts with -----BEGIN RUSTPG SIGNED MESSAGE-----
ArmoredCipherSym Starts with -----BEGIN RUSTPG SYMMETRIC MESSAGE-----
ArmoredCipherAsym Starts with -----BEGIN RUSTPG ASYMMETRIC MESSAGE-----
ArmoredCipher Starts with -----BEGIN RUSTPG MESSAGE-----
Armored Starts with -----BEGIN (other)
Binary Non-UTF-8
Empty No data
BigFilePlainText File > 25 MiB, not encrypted — never loaded into buffer
BigFileCipherText File > 25 MiB with RPGS/RPGA/RPGX/RPGV magic — never loaded into buffer

BigFile* kinds are detected by reading only the first 50 bytes of the file. The full content is never loaded into RAM. The central panel shows a centered filename + size placeholder instead of a text view.

The view mode is set automatically when data loads:

Kind Auto view
Armored / cipher Armored text view
Binary Hex dump
Plaintext / signed Masked (if show_plaintext = false) or plain text
BigFile* Placeholder (no content rendered)

The toolbar shows a view toggle (Plain text / Hex dump) for armored and plaintext buffers when show_plaintext is enabled in Settings.

Masked display

When show_plaintext = false (the default), every printable ASCII character in plaintext, binary-signed, and clearsigned buffers is replaced with * in the viewer. Ciphertext and armor always display unmasked regardless of this setting.

Hex dump

Pre-formatted into Vec<String> and cached by buffer_generation. Display is capped at 1 MiB; the hex view renders all pre-formatted lines but is not yet virtualised.


Keyboard shortcuts

Shortcut Action
Ctrl+O Open file
Ctrl+Q Quit
Ctrl+V Paste from clipboard
Ctrl+C Copy to clipboard
Ctrl+D Decrypt (auto-detect)
Ctrl+E Asymmetric encrypt
Ctrl+A ASCII armor
Ctrl+B Detached sign
Ctrl++ Zoom in
Ctrl+- Zoom out

Ctrl+C and Ctrl+V are intercepted as egui::Event::Copy / egui::Event::Paste — they do not go through the standard key-press path.


File menu

Item Action
Paste from clipboard Ctrl+V Load clipboard text into the buffer
Copy to clipboard Ctrl+C Copy buffer to clipboard; shows a red confirmation if it contains plaintext
Clear clipboard Overwrites the clipboard with an empty string
Clear buffer Empties the buffer
Edit buffer... Opens a full-window text editor over the buffer; "Commit to buffer" replaces contents
Recent Submenu of recently opened files; hover for full path
Open... Ctrl+O Native file picker; prompts for confirmation if file > 25 MiB
Save As... Save buffer to disk; warns before writing plaintext; confirms if > 25 MiB
Quit Ctrl+Q Close the window

Large file threshold: 25 MiB. Files above this size are opened in big-file mode: only the first 50 bytes are read for format detection, no content is loaded into the buffer, and the central panel shows a filename/size placeholder. Crypto operations that require buffer data (sign, armor, verify, asymmetric encrypt) show a hint to use LFM instead. Decrypt and symmetric encrypt route to LFM automatically when Large File Mode is enabled in Settings.


Operations menu

Encrypt

Item Notes
Symmetric (passwords)... AES-256-GCM + Argon2id. Opens a red passphrase dialog (two fields, 👁 toggle). Pre-fills from the last-saved symmetric passphrase. Optionally saves the passphrase to the OS keyring. When Large File Mode is enabled and a file is open, routes to LFM stream encrypt instead.
Asymmetric (keys)... Ctrl+E X25519 ECIES. Opens the identity picker; Enter selects the last-used recipient. Requires buffer data — not available for big files.
Asymmetric + Sign... Sign-then-encrypt: Ed25519-signs the buffer first, then ECIES-encrypts. Requires an own identity with a signing key loaded.
Stream Encrypt File (LFM)... Opens a file picker, then a green passphrase dialog. Writes a .rpgx file alongside the source using ChaCha20-Poly1305 + Argon2id. Progress shown in a green modal.

Decrypt Ctrl+D

Auto-detects from the 4-byte magic:

  • RPGA → asymmetric decrypt with the current identity's X25519 private key. If the decrypted payload is a binary-signed blob, the signature wrapper is stripped and a signer picker opens.
  • RPGS or unknown → opens the symmetric passphrase dialog (pre-filled from OS keyring).
  • BigFileCipherText (file > 25 MiB) → opens the Stream Decrypt File (LFM) dialog directly.
Item Notes
Decrypt Ctrl+D Auto-detect as above.
Stream Decrypt File (LFM)... Opens a file picker for an .rpgx file, then a passphrase dialog. Writes the decrypted output alongside the source (stripping .rpgx). Progress shown in a green modal.

Sign (your key)

Item Notes
Binary Sign RUSTPGSIG\x02 + 64-byte Ed25519 sig prepended to buffer
Plain Text Sign Clearsign: UTF-8 text wrapped in -----BEGIN RUSTPG SIGNED MESSAGE----- block
Detached Signature Ctrl+B Saves a raw 64-byte .sig file via native save dialog; buffer unchanged
Remove Signature Strips a binary or clearsign wrapper, leaving the original payload

Verify

Auto-detects binary or clearsign format from the buffer. If neither, opens a file picker for a detached signature file. Opens the identity picker (signer key). After a good verification, the signature wrapper is stripped and the status bar shows Good signature from <name>..


Keys menu

Item Notes
Select identity... Pick which own identity to use for sign/decrypt operations
Generate New Identity... Name + optional email → X25519 + Ed25519 keypair generated into the keyring. Slug derived from email local-part (or name). Prompts for confirmation if slug exists.
List Identities Modal showing name, email, fingerprint, revocation status for all identities. Current identity highlighted in turquoise.
Remove Identities... Checkbox list; permanent deletion after confirmation
Change master password... Re-encrypts key_material.rpg with a new password
Revoke My Key... Generates and stores a revocation certificate in the keyring (red confirmation dialog). Irreversible without deleting the cert.
Import Identity → From file... File picker → parse → checkbox picker for which identities to import
Import Identity → From window Parse the current buffer as a keyring file → checkbox picker
Import Revocation Cert → From file... Reads a .pem cert, finds the matching identity by verifying against all Ed25519 keys, confirms before applying
Import Revocation Cert → From window Same but reads the cert from the buffer
Export Public Identity... Checkbox picker → save to file or load into window. Roles downgraded to contact.
Export Full Identity... Same but includes private keys. File permissions set to 0600.
Backup keyring → To file... Saves an encrypted copy of key_material.rpg to an arbitrary path
Backup keyring → To window Encrypts the keyring into the buffer (RPGS format, using the master password)
Restore keyring → From file... Decrypts a backup .rpg file and replaces the live keyring after confirmation
Restore keyring → From window Decrypts the buffer as an RPGS keyring backup and replaces the live keyring

Identity picker (ChooseKey dialog)

The red identity picker opens for encrypt, sign+encrypt, verify, and select-own-identity operations. Identities are sorted by name. The last-used identity for the purpose (stored in rustpg.conf as last_recipient_id or last_verification_id) is highlighted white. Pressing Enter selects the highlighted identity immediately — repeat operations on the same key require no mouse click.

Revoked identities appear in light red with [REVOKED] appended.


Format menu

Item Notes
Armor Ctrl+A Wraps binary buffer in OpenPGP-style ASCII armor with CRC24. Refused if already armored.
Dearmor Strips -----BEGIN ... ----- armor, verifies CRC24, returns binary.

View menu

Item Notes
Settings... See below
Zoom In Ctrl++ Increases pixels_per_point by 0.1, max 3.0
Zoom Out Ctrl+- Decreases by 0.1, min 0.5
Reset Zoom Returns to 1.0

Settings dialog

Setting Description
Startup zoom pixels_per_point saved to rustpg.conf; applied on next launch
Default view Plain text or hex dump on open
Plaintext Masked (***) or visible
Theme Dark · Light · Htop · GreenTerminal · Pink · Robust
Large File Mode When enabled, symmetric encrypt/decrypt on an open file routes to streaming LFM (RPGX) instead of block AES-256-GCM. Saved as use_lfm in rustpg.conf.
Forget keyring password Removes passwd_keyring from OS keyring
Forget symmetric passphrase Removes passwd_symmetric from OS keyring

Settings are written to ~/.config/rustpg/rustpg.conf immediately on OK.


Security dialogs

Dialogs that handle sensitive material use a dark red background (rgb(150, 0, 0)) with pale text to make them visually distinct from normal UI:

  • Open keyring / Protect your keyring — master password entry
  • Symmetric Encrypt / Decrypt — passphrase entry
  • LFM Encrypt / LFM Decrypt — passphrase entry for stream operations
  • ChooseKey (encrypt, sign+encrypt) — recipient selection
  • Revoke My Key — irreversible revocation confirmation
  • Copy to clipboard — warns before copying plaintext
  • Save keyring unencrypted — warns before writing private keys in plaintext

Progress modal — while a streaming LFM operation is running, a centered dark green window (rgb(0, 100, 40)) overlays the app showing a progress bar (percentage + MB processed). The rest of the UI remains live during the operation.

All password/passphrase fields have a 👁 visibility toggle. Passwords are stored in Zeroizing<String> and zeroed on drop.


Themes

Six themes selectable in Settings:

Name Description
Dark Default dark grey egui theme
Light Light grey
Htop Black background, cyan accents
GreenTerminal Phosphor green on black
Pink Pink tones
Robust High-contrast

File association

On Linux, rustpg.desktop registers rustpg as a handler for .rpg files (Thunar, Nautilus, etc.). When a file is opened this way, the path arrives as the first CLI argument — pending_file — and is loaded after the keyring dialog is dismissed.