Crate keyper

Crate keyper 

Source
Expand description

§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):

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):

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:

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.

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_PLAINTEXT = TITLE_LEN | TITLE | CONTENT_LEN | CONTENT

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

§Fuck AI

This application was made with 100% human engineering, entirely without the aid of LLMs.

Macros§

field_access
Helper to define field access functions for types.

Structs§

App
The main application which holds the state and logic of the application.
DbKey
Represents a key used for database entries.
Entry
Represents a user entry.
EntryState
Represents the Entry state.
EventHandler
Terminal event handler.
ExtraField
Represents an extra entry field with a customizable title.
ExtraFieldList
Represents a items of ExtraFields.
ExtraFieldListState
Represents the state of an input list.
InputField
Represents a user input field.
InputList
Represents a list of InputFields.
InputListState
Represents the state of an input list.
Keepass
Represents Keepass database information.
Nonce
Represents a cryptographic nonce used to encrypt database entries.
Password
Represents a salt used for password-based key derivation.
Popup
Represents a popup screen.
Salt
Represents a salt used for password-based key derivation.
SessionKey
Represents a salt used for password-based key derivation.

Enums§

AppEvent
Application events.
AppState
Represents the application state.
EntryEncryption
Represents the Entry encryption status.
EntryMode
Represents the Entry mode.
EntrySelection
Represents the Entry selection status.
EntryVisibility
Represents the Entry visibility.
Error
Represents the error variants for the library.
ErrorKind
Represents the error kind variants for the library.
Event
Representation of all possible events.
InputMode
Represents the input mode for user input.
InputVisibility
Represents the InputField visibility.

Type Aliases§

Result
Represents the Result type for the library.
Terminal
Convenience alias for app’s terminal type.