# ObsidianDart

A minimal command-line C++ utility for Linux that encrypts and decrypts a local text file of passwords or credentials with AES-256-GCM via OpenSSL.

## Overview

ObsidianDart is a minimal, command-line cryptography utility for the secure local storage of sensitive, text-based information such as passwords or credentials. It encrypts or decrypts a single file in the working directory using AES-256, relying on the system's OpenSSL libraries rather than custom cryptographic code. The project is intentionally lightweight and narrowly scoped. It is not a full password manager. It is a simple local encryption tool that minimizes attack surface by avoiding cloud services, background daemons and large software stacks.

## How it works

- **Language and platform:** a single C++ source file (`obsidian.cpp`) targeting Linux systems.
- **Cryptography:** provided by the system-installed OpenSSL library (`libcrypto`). Using pre-packaged, well-audited tooling keeps the program simple while retaining strong cryptographic primitives.
  - The passphrase is read with terminal echo turned off and is never used as the key directly. The key is derived with PBKDF2-HMAC-SHA256 (600,000 iterations) from the passphrase and a random 16-byte salt.
  - The file is encrypted with AES-256-GCM using a random 12-byte nonce. GCM is authenticated encryption: a 16-byte tag detects a wrong passphrase or any modified byte, and in either case nothing is written.
  - Key material and plaintext buffers are wiped from memory when no longer needed.
- **File format:** `passwords.wf.enc` is a small versioned header (magic `OBSDART`, format version, salt, nonce), then the ciphertext, then the tag. The header is covered by the tag too.
- **Interface:** a small terminal menu. It shows which of the two files are in the current folder, suggests the matching action (Enter accepts it), checks the file exists before asking for a passphrase, and uses color only on a real terminal (`NO_COLOR` turns it off). Ctrl+C during passphrase entry restores terminal echo.
- **Data file:** encrypts or decrypts a file located in the working directory (`passwords.wf`). The file format is user-defined and may use tab- or comma-separated values, so the decrypted output can be easily parsed or opened in external applications.
- **Plaintext handling:** after a successful encryption the plaintext file is overwritten with zeros and deleted. After a successful decryption the encrypted file is deleted, the same as before. Files are written with owner-only permissions (0600).
- **Design choices:** no cloud storage, no background services and no large dependency stack, which keeps the attack surface small.

## Status

Current revision: **o1.2A**. A terminal interface pass on top of the o1.1A security rewrite, plus a Makefile with install targets. Cryptography and file format are unchanged, so o1.1A files decrypt as before.

## Build and use

**Requirements:** a Linux system with a C++ compiler and the OpenSSL development libraries installed.

**Build and install:**

```bash
make                             # builds ./obsidiandart
make install                     # installs to ~/.local/bin, no root needed
sudo make install PREFIX=/usr/local   # or system wide
```

Without make: `g++ -std=c++17 -O2 obsidian.cpp -o obsidiandart -lcrypto`.

**Use:** run `obsidiandart` from the terminal in the directory containing `passwords.wf` (to encrypt) or `passwords.wf.enc` (to decrypt).

1. Check the file status at the top, then choose `1` to encrypt, `2` to decrypt or `q` to quit. Enter alone takes the suggested action.
2. Enter your passphrase (it is not echoed).
3. When encrypting, enter the passphrase a second time to confirm it.

`obsidiandart --help` and `obsidiandart --version` print usage and the revision.

Keep the plaintext file in a simple tab- or comma-separated format so the decrypted output can be read by other tools. There is no passphrase recovery: if you forget it, the file cannot be decrypted.

## Known limits

- Not independently audited. The design uses standard primitives, but the code has not had an outside security review.
- Files encrypted by o1.0A cannot be decrypted by o1.1A or later. Decrypt them with the o1.0A build first, then encrypt again.
- Overwriting the plaintext before deleting it is best-effort. On SSDs and on copy-on-write or journaling filesystems (btrfs, ZFS and similar) old copies of the data may remain on disk.
- While decrypted, `passwords.wf` sits on disk as plaintext until you encrypt it again.
- The whole file is held in memory while it is processed, and the passphrase strength is up to you.
- Not a full password manager: it only encrypts and decrypts a single local file with a fixed name.
- Targets Linux only.

## Revisions

- **o1.2A** (current): terminal interface pass: file status header, suggested action, re-prompt on bad input, quit option, file check before the passphrase prompt, color with `NO_COLOR` support, echo restored on Ctrl+C, `--help` and `--version`, Makefile with install and uninstall. Same crypto and file format as o1.1A.
- **c1.1A** (closed): security rewrite: PBKDF2-HMAC-SHA256 key derivation with random salt, AES-256-GCM with random nonce and tag check, versioned file header, echo-free passphrase input, plaintext overwritten and removed after encryption. Not compatible with o1.0A files. Superseded by o1.2A.
- **c1.0A** (closed): initial prototype: single-file C++ command-line tool performing AES-256-CBC encryption and decryption of a local credentials file using OpenSSL. Superseded by o1.1A.

Revision codes read o (open) or c (closed), then major.minor, then the branch letter; A is the main line.

## License

Copyright (C) 2026 Sanchez Performance LLC.

GNU GPL v3 or later (`GPL-3.0-or-later`). See [LICENSE](Legal/LICENSE).
