Compare commits

..

2 commits

Author SHA1 Message Date
22e3ebed43
Update readme 2021-10-31 15:42:22 -07:00
5bb3ad2d0d
Use stronger argon2id params 2021-10-31 15:42:15 -07:00
2 changed files with 136 additions and 3 deletions

112
README.md Normal file
View file

@ -0,0 +1,112 @@
# OmegaUpload
OmegaUpload is a zero-knowledge temporary file hosting service.
## Examples
```bash
# Uploading a file:
$ omegaupload-cli upload https://paste.example.com path/to/file
https://paste.example.com/PgRG8Hfrr9rR#I1FG2oejo2gSjB3Ym1mEmRfcN4X8GXc2pZtZeiSsWFo=
# Uploading a file with a password:
$ omegaupload-cli upload -p https://paste.example.com path/to/file
Please set the password for this paste:
https://paste.crabravers.club/862vhXVp3v9R#key:tbGxzHBNnXjS2eq89X9uvZKz_i8bvapLPEp8g0waQrc=!pw
# Downloading a file:
$ omegaupload-cli download https://paste.example.com/PgRG8Hfrr9rR#I1FG2oejo2gSjB3Ym1mEmRfcN4X8GXc2pZtZeiSsWFo=
```
## Features
- Server has zero knowledge of uploaded data when uploading through a supported
frontend (Direct, plaintext upload is possible but unsupported).
- Only metadata stored on server is expiration time. This is a strong guarantee.
- All cryptographic functions are performed on the client side and are done via
a single common library, to minimize risk of programming error.
- Modern crypto functions are used with recommended parameters:
XChaCha20Poly1305 for encryption and Argon2id for KDF.
- Customizable expiration times, from burn-after-read to 1 day.
## Getting Started
Prerequisites:
- `yarn` 1.22.17 or later (Earlier versions untested but likely to work)
- [`trunk`](https://trunkrs.dev/)
- Cargo, with support for the latest Rust version
- _(Optional)_ zstd, for zipping up the file for distribution
First, run `git submodule update --init --recursive`.
Then, run `./bin/build.sh` for a `dist.tar.zst` to be generated, where you can
simply extract that folder and run the binary provided. The server will listen
on port `8080`.
### Development
For development, building is as simple as `cargo build`. Note that you may need
to run `trunk build` first before building the server. To run the server (even
for testing) requires uploading `dist.tar.zst` to a remote server.
## Why OmegaUpload?
OmegaUpload's primary benefit is that the frontends use a unified common library
utilizing XChaCha20Poly1305 to encrypt and decrypt files.
### Security
The primary goal was to provide a unified library across both a CLI tool and
through the web frontend to minimize risk of compromise. As a result, the CLI
tool and the web frontend both utilize a Rust library whose crypto module
exposes two functions to encrypt and decrypt that only accept a message and
necessarily key material or return only necessary key material. This small API
effectively makes it impossible to have differences between the frontend, and
ensures that the attack surface is limited to these functions.
#### Password KDF
If a password is provided at encryption time, argon2 is used as a key derivation
function. Specifically, the library meets or exceeds OWASP recommended
parameters:
- Argon2id is used.
- Algorithm version is `0x13`.
- Parameters are `m = 15MiB`, `t = 2`, `p = 2`.
Additionally, a salt size of 16 bytes are used.
#### Blob Encryption
XChaCha20Poly1305 was used as the encryption method as it is becoming the
mainstream recommended method for encrypting messages. This was chosen over AES
primarily due to its strength in related-key attacks, as well as its widespread
recognition and usage in WireGuard, Quic, and TLS.
As this crate uses `XChaCha20`, a 24 byte nonce and a 32 bytes key are used.
#### Secrecy
Encryption and decryption functions offered by the common crate only accept or
return key material that will be properly zeroed on destruction. This is
enforced by the `secrecy` crate, which, on top of offering type wrappers that
zero the memory on drop, provide an easy way to audit when secrets are exposed.
This also means that to use these two functions necessarily requires the caller
to enclose key material in the wrapped type first, reducing possibility for key
material to remain in memory.
#### Memory Safety
Rust eliminates an entire class of memory-related bugs, and any `unsafe` block
is documented with a safety comment. This allows for easy auditing of memory
suspect code, and permits
## Why not OmegaUpload?
There are a few reasons to not use OmegaUpload:
- Limited to 3GB uploads—this is a soft limit of RocksDB.
- Cannot download files larger than 512 MiB through the web frontend—this
is a technical limitation of the current web frontend not using a web worker
in addition to the fact that browsers are not optimized for XChaCha20.
- Right now, you must upload via the CLI tool.
- The frontend uses WASM, which is a novel attack surface.

View file

@ -20,7 +20,7 @@
use std::ops::{Deref, DerefMut};
use argon2::Argon2;
use argon2::{Argon2, ParamsBuilder};
use chacha20poly1305::aead::generic_array::sequence::GenericSequence;
use chacha20poly1305::aead::generic_array::GenericArray;
use chacha20poly1305::aead::{AeadInPlace, NewAead};
@ -152,7 +152,7 @@ pub fn open_in_place(
) -> Result<(), Error> {
let pw_key = if let Some(password) = password {
let salt_buf = data.split_off(data.len() - Salt::SIZE);
let argon = Argon2::default();
let argon = get_argon2();
let mut pw_key = Key::default();
argon
.hash_password_into(password.expose_secret(), &salt_buf, &mut pw_key)
@ -255,13 +255,34 @@ impl AsRef<[u8]> for Salt {
/// Hashes an input to output a usable key.
fn kdf(password: &SecretVec<u8>) -> Result<(Secret<Key>, Salt), argon2::Error> {
let salt = Salt::random();
let hasher = Argon2::default();
let hasher = get_argon2();
let mut key = Key::default();
hasher.hash_password_into(password.expose_secret().as_ref(), salt.as_ref(), &mut key)?;
Ok((Secret::new(key), salt))
}
/// Returns Argon2id configured as follows:
/// - 15MiB of memory (`m`),
/// - an iteration count of 2 (`t`),
/// - and 2 degrees of parallelism (`p`).
///
/// This follows the [minimum recommended parameters suggested by OWASP][rec].
///
/// [rec]: https://link.eddie.sh/vaQ6a.
fn get_argon2() -> Argon2<'static> {
let mut params = ParamsBuilder::new();
params
.m_cost(15 * 1024) // 15 MiB
.expect("Hard coded params to work")
.t_cost(2)
.expect("Hard coded params to work")
.p_cost(2)
.expect("Hard coded params to work");
let params = params.params().expect("Hard coded params to work");
Argon2::new(argon2::Algorithm::Argon2id, argon2::Version::V0x13, params)
}
/// Fetches a cryptographically secure random number generator. This indirection
/// is used for better auditing the quality of rng. Notably, this function
/// returns a `Rng` with the `CryptoRng` marker trait, preventing