# Keyper
A basic password manager with a TUI interface.
## Storage
The [sled] database is used for on-disk storage. However, [sled] does not natively support encryption.
Instead, we use an encryption scheme composed from well-tested primitives implemented in the [RustCrypto] cryptographic libraries.
### Salt Encryption
A salt is a cryptographic value used to add randomness to inputs, and is commonly used in key-derivation algorithms.
We use the following scheme for password-based key derivation (in pseudo-code):
```text
SALT = {random 32-bytes}
PASSWORD = {user-input password}
ENCRYPTION_KEY = sha3::TurboShake256::hash(SALT | PASSWORD);
```
However, we also want to keep the salt value secret when storing to disk (maybe a bit of paranoia is a good thing? :3)
The following scheme is used to encrypt the salt for storage (in pseudo-code):
```text
SALT = {zeroes 32-bytes}
PASSWORD = {user-input password}
SALT_KEY = sha3::TurboShake256::hash(SALT | PASSWORD);
SALT_NONCE = {random 12-bytes}
ENCRYPTED_SALT = chacha20poly1305::encrypt(SALT_KEY, SALT_NONCE, SALT)
```
The entry is then stored in the database as:
```text
SALT_DB_KEY = sha3::TurboShake256::hash("salt");
sled::Db::insert(SALT_DB_KEY, SALT_NONCE | ENCRYPTED_SALT);
```
### Entry Encryption
Entries are encrypted in much the same way, with the slight change that the fields need to be length-prefix encoded.
We currently use 32-bit, little-endian length fields.
```text
TITLE = Entry.title;
CONTENT = Entry.content;
TITLE_LEN = (TITLE.len() as u32).to_le_bytes();
CONTENT_LEN = (CONTENT.len() as u32).to_le_bytes();
ENTRY_NONCE = {random 12-bytes}
ENTRY_INDEX = EntryList.len()
ENTRY_DB_KEY = sha3::TurboShake256::hash(ENTRY_INDEX)
ENCRYPTED_ENTRY = chacha20poly1305::encrypt(ENCRYPTION_KEY, ENTRY_NONCE, ENTRY_PLAINTEXT)
sled::Db::insert(ENTRY_DB_KEY, ENTRY_NONCE | ENCRYPTED_ENTRY)
```
Using the length-prefixed value encoding is very common, and allows for extending the `Entry` fields almost indefinitely.
By using the AEAD ChaCha20Poly1305 algorithm, we also get the benefit of database corruption protection.
If someone messes with your database entries, they won't decrypt properly.
## Credits
- TUI powered by [ratatui] + [crossterm]
- Crypto provided by [RustCrypto]
- Storage provided by [sled]
- TOTP provided by [totp-rs]
- Clipboard support provided by [crossterm] + [arboard]
- Keepass support provided by [keepass]
[ratatui]: https://docs.rs/ratatui
[RustCrypto]: https://github.com/RustCrypto
[sled]: https://docs.rs/sled
[totp-rs]: https://docs.rs/totp-rs
[crossterm]: https://docs.rs/crossterm
[arboard]: https://docs.rs/arboard
[keepass]: https://docs.rs/keepass
## Fuck AI
This application was made with 100% human engineering, entirely without the aid of LLMs.