microkv 0.2.0

a minimal and persistent key-value store designed with security in mind.
Documentation
# microkv

[![Actions][actions-badge]][actions-url]
[![crates.io version][crates-microkv-badge]][crates-microkv]
[![Docs][docs-badge]][docs.rs]

[actions-badge]: https://github.com/ex0dus-0x/microkv/workflows/CI/badge.svg?branch=master
[actions-url]: https://github.com/ex0dus-0x/microkv/actions

[crates-microkv-badge]: https://img.shields.io/crates/v/microkv.svg
[crates-microkv]: https://crates.io/crates/microkv

[docs-badge]: https://docs.rs/microkv/badge.svg
[docs.rs]: https://docs.rs/microkv

> NOTE: Functionally complete, but still WIP!

a minimal and persistent key-value store designed with security in mind.

## intro

__microkv__ is a persistent key-value store implemented in Rust, aiming to maintain a balance between security and performance. It is built out of a yearning to learn more about the intricacies of distributed systems, databases, and secure persistent storage.

While __microkv__ shouldn't be used in large-scale environments that facilitate an insane volume of transactional interactions,
it is still optimal for use in a production-grade system/application that may not require the complex luxuries of a
full-blown database or even industry-standard KV-store like Redis or LevelDB.

## use cases

Here are some specific use-cases that you may want to use __microkv__ for:

* Local persistent serialization for sensitive configurations
* Secrets management for a single-process application
* License key management

## features

* __Performant__

__microkv__'s underlying map structure is based off of @bluss's [indexmap](https://github.com/bluss/indexmap) implementation, which offers performance on par with built-in `HashMap`'s amortized constant runtime, but can also provided sorted key iteration, similar to the less-performant `BTreeMap`. This provides a strong balance between performance and functionality.

When reading and persisting to disk, the key-value store Uses `bincode` for fast de/serialization of the underlying structures, allowing users to insert any serializable structure without worrying about incurred overhead for storing complex data structures.

* __Secure__

__microkv__ acts almost in the sense of a secure enclave with any stored information. First, inserted values are immediately encryped using authenticated encryption with XSalsa20 (stream cipher) and Poly1305 (HMAC) from `sodiumoxide`, guarenteeing security and integrity. Encryped values in-memory are also memory-locked with `mlock`, and securely zeroed when destroyed to avoid persistence in memory pages.

__microkv__ also provides locking support with `RwLock`s, which utilize mutual exclusion like mutexes, but robust in the sense that concurrent read locks can be held, but only one writer lock can be held at a time. This helps remove thread-safey and data race concerns, but also enables multiple read accesses safely.

* __Small__

At its core, __microkv__ is implemented in ~500 LOCs, making the implementation portable and auditable. It does not offer extensions to other serializable formats, or any other user-involved configurability, meaning it will work right out of the box.

## design

(Still WIP)

To see details about how microkv is internally implemented check out the `docs/` folder for the following documentation:

* [Threat Model]https://github.com/ex0dus-0x/microkv/blob/master/docs/threat_model.md
* [Internal Design]https://github.com/ex0dus-0x/microkv/blob/master/docs/internal_design.md


## usage

You can use microkv as both a library crate for your implementation, or a standalone CLI.

To install locally, simply clone the repository and install with `cargo`:

```
# .. from crates.io
$ cargo install microkv

# .. or locally
$ git clone https://github.com/ex0dus-0x/microkv
$ cargo install --path .
```

Run `cargo test` to validate that the test suite works:

```
$ cargo test
```

### library

Here's example usage of the `microkv` library crate:

```rust
extern crate microkv;

use microkv::MicroKV;

#[derive(Serialize, Deserialize, Debug)]
struct Identity {
    uuid: u32,
    name: String,
    sensitive_data: String,
}


fn main() -> {
    let unsafe_pwd: String = "my_password_123";

    // initialize database with (unsafe) cleartext password
    let db: MicroKV = MicroKV::new("my_db")
        .with_password_clear(unsafe_pwd);

    // simple interaction
    db.put("simple", 1);
    print("{}", db.get::<i32>("simple").unwrap());
    db.delete("simple");

    // more complex interaction
    let identity = Identity {
        uuid: 123,
        name: String::from("Alice"),
        sensitive_data: String::from("something_important_here")
    };
    db.put("complex", identity);
    print("{:?}", db.get::<Identity>("complex").unwrap());
    db.delete("complex");
}
```

### cli

(TODO)

## inspirations

* [rustbreak]https://github.com/TheNeikos/rustbreak
* [Writing a simple database in Rust]https://nikhilism.com/post/2016/writing-simple-database-in-rust-part-1/

## TODO

* [ ] Unit tests
* [ ] Client CLI
* [ ] Performance Benchmarks against other ADTs
* [x] Other helper DB operations
* [ ] Incorporate write-append logging/snapshotting
* [ ] Threat model and design docs

## license

[mit license](https://codemuch.tech/license.txt)