{"id":36967557,"url":"https://github.com/markrai/obsidenc","last_synced_at":"2026-01-13T20:06:48.748Z","repository":{"id":329060871,"uuid":"1117942663","full_name":"markrai/obsidenc","owner":"markrai","description":"paranoid-grade rust-based encryption utility + cross-platform GUI","archived":false,"fork":false,"pushed_at":"2025-12-29T20:50:46.000Z","size":4261,"stargazers_count":66,"open_issues_count":5,"forks_count":3,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-02T03:30:39.692Z","etag":null,"topics":["cross-platform","encryption","infosec","rust","security","tauri"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/markrai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-17T03:27:02.000Z","updated_at":"2025-12-29T20:50:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/markrai/obsidenc","commit_stats":null,"previous_names":["markrai/obsidenc"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/markrai/obsidenc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markrai%2Fobsidenc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markrai%2Fobsidenc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markrai%2Fobsidenc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markrai%2Fobsidenc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/markrai","download_url":"https://codeload.github.com/markrai/obsidenc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markrai%2Fobsidenc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28399658,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cross-platform","encryption","infosec","rust","security","tauri"],"created_at":"2026-01-13T20:06:48.015Z","updated_at":"2026-01-13T20:06:48.742Z","avatar_url":"https://github.com/markrai.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg width=\"1250\" height=\"273\" alt=\"image\" src=\"https://github.com/user-attachments/assets/adf5102d-b34a-447c-a826-88938be67ff3\" /\u003e\n\n\n# obsidenc v1.0.2\n\nParanoid-grade encryption utility. It tars a directory (no compression) and encrypts/decrypts it with Argon2id (RFC 9106 guidance) + XChaCha20-Poly1305. See [ANALYSIS.md](./ANALYSIS.md) for full details.\n\n## Building\n\n### Prerequisites\n\n- [Rust](https://www.rust-lang.org/tools/install) (latest stable version)\n\n### Build Commands\n\n**Debug build:**\n```sh\ncargo build\n```\nBinary will be at: `target/debug/obsidenc` (or `target/debug/obsidenc.exe` on Windows)\n\n**Release build (optimized):**\n```sh\ncargo build --release\n```\nBinary will be at: `target/release/obsidenc` (or `target/release/obsidenc.exe` on Windows)\n\n**Run directly (without installing):**\n```sh\ncargo run -- encrypt \u003cvault_dir\u003e \u003coutput_file\u003e\ncargo run --release -- encrypt \u003cvault_dir\u003e \u003coutput_file\u003e\n```\n\n**Windows (Command Prompt):**\n```batch\nrun.bat encrypt \u003cvault_dir\u003e \u003coutput_file\u003e\n```\n\n**Linux/Unix:**\n```sh\nchmod +x run.sh\n./run.sh encrypt \u003cvault_dir\u003e \u003coutput_file\u003e\n```\n\n## Security model\n\n- Attacker has full access to the encrypted file.\n- Attacker has unlimited offline time.\n- Attacker does *not* have runtime access to the machine during encryption/decryption.\n\n## Usage\n\n```sh\nobsidenc encrypt \u003cvault_dir\u003e \u003coutput_file\u003e [--keyfile \u003cpath\u003e] [--force]\nobsidenc decrypt \u003cinput_file\u003e \u003coutput_dir\u003e [--keyfile \u003cpath\u003e] [--force]\n```\n\nNotes:\n- Encryption prompts for the password twice (confirmation).\n- Minimum password length is 20 characters.\n- If `--keyfile` is used, both password and keyfile are required.\n- Decryption refuses to overwrite an existing output directory unless `--force` is supplied.\n\n### Non-interactive password input\n\nFor automation (and the bundled GUI), passwords can be provided via stdin:\n\n```sh\n# Encrypt: 2 lines on stdin (password + confirmation)\nprintf '%s\\n%s\\n' \"$PW\" \"$PW\" | obsidenc --password-stdin encrypt \u003cvault_dir\u003e \u003coutput_file\u003e\n\n# Decrypt: 1 line on stdin (password)\nprintf '%s\\n' \"$PW\" | obsidenc --password-stdin decrypt \u003cinput_file\u003e \u003coutput_dir\u003e\n```\n\n## GUI (Tauri)\n\nThe repository includes a minimal Tauri desktop UI that drives `obsidenc` as a bundled sidecar binary. The GUI does **not** implement crypto; it spawns `obsidenc` and passes the password via stdin (`--password-stdin`).\n\nFrom `gui/`:\n\n```sh\n# Dev (builds sidecar + starts a local UI server)\ncargo tauri dev\n\n# Release bundle (builds sidecar from source and embeds it)\ncargo tauri build\n```\n\n## Supply-chain security (release blockers)\n\nInstall and run:\n\n```sh\ncargo install cargo-audit\ncargo audit\n```\n\n## Smoke test (CLI round-trip)\n\nThere is an automated smoke test that:\n- Encrypts the files in `tests/mock` into `tests/test.oen`\n- Decrypts `tests/test.oen` into `tests/decrypt`\n- Verifies that all decrypted files exactly match the originals in `tests/mock`\n\nTo run it:\n\n```sh\n# From the project root\ncargo test --test roundtrip\n```\n\nThe test never modifies the original `tests/mock` data; it only creates and deletes `tests/test.oen` and `tests/decrypt/`.\n\n## Fuzzing\n\nThe project includes fuzzing infrastructure to verify robustness against malformed input. Fuzzing helps ensure that the decryption parser never panics on invalid data.\n\n**Platform Support:** Fuzzing is only available on Linux/Unix. The fuzzing targets are automatically disabled on Windows (libfuzzer-sys doesn't support Windows). The main obsidenc binary works perfectly on Windows - only the fuzzing infrastructure is platform-limited.\n\n### Running Fuzzing on Linux\n\n**Prerequisites:**\n- Linux system (or WSL on Windows)\n- Rust nightly toolchain (fuzzing requires nightly features)\n- LLVM/Clang (required for libfuzzer)\n\n**Step 1: Install Rust nightly toolchain**\n```sh\n# Install nightly (if not already installed)\nrustup toolchain install nightly\n\n# Use nightly for fuzzing (you can switch back to stable after)\nrustup default nightly\n# OR use nightly just for this project:\nrustup override set nightly\n```\n\n**Step 2: Install cargo-fuzz**\n```sh\ncargo install cargo-fuzz\n```\n\n**Step 3: Run the fuzzing target**\n```sh\n# From the project root directory\ncargo fuzz run fuzz_decrypt\n```\n\n**Note:** If you want to keep stable as your default toolchain, you can use `rustup override set nightly` in the project directory instead of `rustup default nightly`. This sets nightly only for this project.\n\n**Step 3: Let it run**\n- The fuzzer will run indefinitely, generating random inputs\n- Press Ctrl+C to stop\n- If a panic is found, the fuzzer will save the input that caused it to `fuzz/artifacts/fuzz_decrypt/`\n- Check the output for any crashes or panics\n\n**Advanced options:**\n```sh\n# Run with a timeout (e.g., 60 seconds)\ncargo fuzz run fuzz_decrypt -- -max_total_time=60\n\n# Run for a specific number of iterations\ncargo fuzz run fuzz_decrypt -- -runs=10000\n\n# Run with corpus (saved interesting inputs)\ncargo fuzz run fuzz_decrypt -- -merge=1\n```\n\n**What the fuzzing target tests:**\n- Header parsing with malformed input (wrong magic bytes, invalid version, etc.)\n- Chunk parsing with invalid lengths and data\n- Buffer handling edge cases (empty chunks, oversized chunks, etc.)\n- Ensures all errors are returned as `Result::Err`, never panics\n\n**Improving Fuzzing Coverage:**\n\nThe fuzzer automatically constructs valid headers to test chunk parsing logic, but you can improve coverage by adding seed corpus files. Seed corpus files are real encrypted files that help the fuzzer discover valid input patterns.\n\n**Creating a Seed Corpus:**\n\n1. Create some test encrypted files:\n   ```sh\n   # Create a test directory\n   mkdir -p /tmp/test_vault\n   echo \"test content\" \u003e /tmp/test_vault/test.txt\n   \n   # Encrypt it\n   ./target/release/obsidenc encrypt /tmp/test_vault /tmp/test.oen\n   \n   # Copy to seed corpus\n   cp /tmp/test.oen fuzz/corpus/fuzz_decrypt/seed_001.oen\n   ```\n\n2. The fuzzer will automatically use files in `fuzz/corpus/fuzz_decrypt/` as starting points.\n\n3. You can add multiple seed files with different characteristics:\n   - Small files (empty or single byte)\n   - Large files (multi-chunk)\n   - Files with various directory structures\n   - Files encrypted with different Argon2 parameters\n\n**Fuzzing Strategy:**\n\nThe improved fuzzer uses a dual-mode approach:\n- **Mode 1**: Tests raw header parsing to find edge cases in error handling\n- **Mode 2**: Constructs valid headers with random data to test chunk parsing logic\n\nThis ensures coverage of both error paths and the actual decryption code paths.\n\n**Windows Users:** If you need to run fuzzing, use WSL (Windows Subsystem for Linux) or a Linux VM. The main encryption/decryption functionality works natively on Windows.\n\n\u003cimg width=\"595.5\" height=\"451.5\" alt=\"image\" src=\"https://github.com/user-attachments/assets/259ec585-0e6e-4200-a469-4dbb1c89a39b\" /\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkrai%2Fobsidenc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarkrai%2Fobsidenc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkrai%2Fobsidenc/lists"}