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:
- Load
master_passwordandsymmetric_passwordfrom the OS keyring. - If
key_material.rpgexists:- If the password was cached and decryption succeeds → open silently.
- Otherwise → show Open keyring dialog (dark red, password pre-filled from OS keyring).
- If no
.rpgfile exists:- Seed two demo identities (Alice, Bob) into memory, or load the legacy
key_material.txtif present. - Show Protect your keyring dialog to set a master password.
- Seed two demo identities (Alice, Bob) into memory, or load the legacy
- After the dialog resolves →
apply_km_to_session()sets the active identity. - 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.RPGSor 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.