# dove-core
[](https://crates.io/crates/dove-core)
[](https://docs.rs/dove-core)
[](https://github.com/boomctl/dove-core/actions/workflows/ci.yml)
[](LICENSE)
**The library behind [dove](https://dove.sh)** — client-side-encrypted, expiring
file sharing from a cloud you own.
dove-core is the whole engine with the terminal peeled off: the AES-256-GCM
container format, the S3 + access-gate transfer, the provisioner, and the
config → backend registry. It does **no I/O to a terminal** — it takes resolved
inputs and reports progress through a callback — so the [`dove`
CLI](https://github.com/boomctl/dove), a desktop app, and any other front-end
drive the exact same audited code. Encryption keys never leave the library;
`share` hands back a finished link, never raw key material.
## Install
```sh
cargo add dove-core
```
## Usage
Everything routes through one `Transfer` seam. Resolve the active backend from
the local config and share a file — no key material or terminal output crosses
the boundary:
```rust
use dove_core::{resolve, config::Registry, progress::Silent, transfer::ShareRequest};
use std::time::Duration;
fn main() -> dove_core::error::Result<()> {
// The active backend from ~/.config/dove — a self-hosted S3 + gate, or a
// discovered plugin. Building it is I/O-free; only use touches the network.
let registry = Registry::load()?;
let backend = resolve(®istry)?;
let share = backend.share(
ShareRequest {
path: "report.pdf".into(),
expires: Duration::from_secs(3 * 24 * 3600),
encrypt: true,
downloads: Some(1), // one-time link
pin: Some("4917".into()), // second factor, folded into the key
from: Some("Ada".into()),
message: None,
},
&Silent, // swap in your own `Progress` impl to drive a UI
)?;
// Hand this out. The decryption key rides its `#fragment` and never reaches
// a server; recipients decrypt in a browser or with `dove get`.
println!("{}", share.link);
Ok(())
}
```
`Transfer` also gives you `get`, `list`, `revoke`, and `status`. Provisioning
(`dove_core::provision`) stands up the backing infrastructure in your own cloud;
it, too, reports through `Progress` and never prompts.
## What's inside
- **`crypto`** — the chunked **AES-256-GCM** container (per-file nonce prefix,
per-chunk counter, counter + terminal-flag in the AAD to reject reorder,
truncation, and tampering). **Byte-compatible with WebCrypto**, so a browser
decrypts exactly what this crate wrote (locked by `tests/browser_crypto_compat.rs`).
Plus PBKDF2 PIN derivation, MAC'd share/request ids, and the E2E metadata blob.
- **`transfer`** — the `Transfer` trait and the built-in `SelfHosted` backend
(your S3 bucket, optional DynamoDB + access-gate for encrypted, download-limited,
PIN-able links).
- **`factory`** — `resolve`: dispatch to the built-in backend, or discover a
`dove-<kind>` plugin binary, or fail legibly.
- **`config`** — a named-backend registry with an active pointer.
- **`provision`** — non-interactive provisioning of the S3 / DynamoDB / gate
Lambda / CloudFront stack in an account you own.
- **`request`** — file *requests*: mint a PIN-gated link and collect a file
someone else encrypts on their device and uploads to you.
- **`error`** — a typed error enum consumers can match on (needs a PIN, locked,
gone, integrity failure, …).
## Design
The full design and threat model live in [docs/DESIGN.md](docs/DESIGN.md); the
file-request feature in [docs/REQUEST.md](docs/REQUEST.md). The `dove` CLI that
wraps this library is at [boomctl/dove](https://github.com/boomctl/dove).
## Acknowledgments
`dove-core` is co-built with [Claude](https://www.anthropic.com/claude)
(Anthropic's Claude Code) working alongside its author, and is a sibling to
[git-ark](https://github.com/boomctl/git-ark).
## License
[Apache-2.0](LICENSE).