Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add volariscore #1

Merged
merged 4 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
564 changes: 563 additions & 1 deletion Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BSD 2-Clause License

Copyright (c) 2024, brxken128
Copyright (c) 2024, brxken128, greendoescode

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Expand Down
19 changes: 16 additions & 3 deletions crates/volaris-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
[package]
name = "volaris-core"
version = "0.0.0"
version = "0.0.1"
edition = "2021"
authors.workspace = true
license.workspace = true
description = "The core cryptography behind Volaris"
readme = "README.md"
license = "BSD-2-Clause"
authors = ["brxken128 <[email protected]>", "greendoescode <[email protected]>"]
homepage = "https://github.com/volarisapp/volaris"

[dependencies]
anyhow = "1.0.65"
aes-gcm = "0.10.1"
chacha20poly1305 = "0.10.1"
deoxys = { version = "0.1.0" }
aead = { version = "0.5.1", features = ["stream"] }
zeroize = "1.5.0"
argon2 = "0.4.1"
balloon-hash = "0.3.0"
blake3 = { version = "1.3.3", features = ["traits-preview"] }
rand = "0.8.5"
indicatif = { version = "0.16.2", optional = true }
25 changes: 25 additions & 0 deletions crates/volaris-core/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
BSD 2-Clause License

Copyright (c) 2024, brxken128, greendoescode
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
89 changes: 89 additions & 0 deletions crates/volaris-core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
## What is it?

Volaris-Core is a library used for managing cryptographic functions and headers
that adhere to the volaris format.

## Security

Volaris-Core uses modern, secure and audited<sup>1</sup> AEADs for encryption and
decryption.

You may find the audits for both AES-256-GCM and XChaCha20-Poly1305 on
[the NCC Group's website](https://research.nccgroup.com/2020/02/26/public-report-rustcrypto-aes-gcm-and-chacha20poly1305-implementation-review/).

<sup>1</sup> Deoxys-II-256 does not have an official audit, so use it at your
own risk

## Who uses volaris-Core?

This library is implemented by [volaris](https://github.com/volarisapp/volaris), a
secure multi-interface file encryption utility.

Volaris-Core makes it easy to integrate the volaris format into your own projects
(and if there's a feature that you'd like to see, please don't hesitate to
[open a Github issue](https://github.com/volarisapp/volaris/issues)).

## Features

- Convenience functions for encrypting/decrypting
- 3 AEADs (XChaCha20-Poly1305, AES-256-GCM, Deoxys-II-256)
- Easy management of encrypted headers (no more worrying about where to store a
nonce!)
- Easy `argon2id` hashing with secure parameters
- Easy `balloon` hashing with secure parameters and BLAKE3
- Frequent updates and feature additions!

## Examples

Deserializing a header:

```rust
let header_bytes: [u8; 64] = [
222, 2, 14, 1, 12, 1, 142, 88, 243, 144, 119, 187, 189, 190, 121, 90, 211, 56, 185, 14, 76,
45, 16, 5, 237, 72, 7, 203, 13, 145, 13, 155, 210, 29, 128, 142, 241, 233, 42, 168, 243,
129, 0, 0, 0, 0, 0, 0, 214, 45, 3, 4, 11, 212, 129, 123, 192, 157, 185, 109, 151, 225, 233,
161,
];

let mut cursor = Cursor::new(header_bytes);

// the cursor may be a file, this is just an example

let (header, aad) = Header::deserialize(&mut cursor).unwrap();
```

Writing a header to a file:

```rust
let mut output_file = File::create("test").unwrap();
header.write(&mut output_file).unwrap();
```

Encrypting and decrypting in-memory:

```rust
// obviously the key should contain data, not be an empty vec
let raw_key = Protected::new(vec![0u8; 128]);
let salt = gen_salt();
let key = balloon_hash(raw_key, &salt, &HeaderVersion::V4).unwrap();
let cipher = Ciphers::initialize(key, &Algorithm::XChaCha20Poly1305).unwrap();

let secret = "super secret information";

let nonce = gen_nonce(&Algorithm::XChaCha20Poly1305, &Mode::MemoryMode);
let encrypted_data = cipher.encrypt(&nonce, secret.as_bytes()).unwrap();

let decrypted_data = cipher.decrypt(&nonce, encrypted_data.as_slice()).unwrap();

assert_eq!(secret, decrypted_data);
```

You can read more about volaris, Volaris-Core and the technical details
[in the project's main documentation](https://github.com/volarisapp/volaris/)!

## Thank you!

Volaris-Core exclusively uses AEADs provided by the
[RustCrypto Team](https://github.com/RustCrypto), so I'd like to give them a
huge thank you for their hard work (this wouldn't have been possible without
them!)
124 changes: 124 additions & 0 deletions crates/volaris-core/src/cipher.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//! This module is used for standard, typical encryption and decryption.
//!
//! The data is fully loaded into memory before encryption/decryption, and it is processed within the same "block"
//!
//! # Examples
//! ```rust,ignore
//! // obviously the key should contain data, not be an empty vec
//! let raw_key = Protected::new(vec![0u8; 128]);
//! let salt = gen_salt();
//! let key = balloon_hash(raw_key, &salt, &HeaderVersion::V4).unwrap();
//! let cipher = Ciphers::initialize(key, &Algorithm::XChaCha20Poly1305).unwrap();
//!
//! let secret = "super secret information";
//!
//! let nonce = gen_nonce(&Algorithm::XChaCha20Poly1305, &Mode::MemoryMode);
//! let encrypted_data = cipher.encrypt(&nonce, secret.as_bytes()).unwrap();
//!
//! let decrypted_data = cipher.decrypt(&nonce, encrypted_data.as_slice()).unwrap();
//!
//! assert_eq!(secret, decrypted_data);
//! ```

use aead::{Aead, AeadInPlace, KeyInit, Payload};
use aes_gcm::Aes256Gcm;
use chacha20poly1305::XChaCha20Poly1305;
use deoxys::DeoxysII256;

use crate::primitives::Algorithm;
use crate::protected::Protected;

/// This `enum` defines all possible cipher types, for each AEAD that is supported by `Volaris-core`
pub enum Ciphers {
Aes256Gcm(Box<Aes256Gcm>),
XChaCha(Box<XChaCha20Poly1305>),
DeoxysII(Box<DeoxysII256>),
}

impl Ciphers {
/// This can be used to quickly initialise a `Cipher`
///
/// The returned `Cipher` can be used for both encryption and decryption
///
/// You just need to provide the `argon2id`/`balloon` hashed key, and the algorithm to use
///
/// # Examples
/// ```rust,ignore
/// // obviously the key should contain data, not be an empty vec
/// let raw_key = Protected::new(vec![0u8; 128]);
/// let salt = gen_salt();
/// let key = balloon_hash(raw_key, &salt, &HeaderVersion::V4).unwrap();
/// let cipher = Ciphers::initialize(key, &Algorithm::XChaCha20Poly1305).unwrap();
/// ```
///
pub fn initialize(key: Protected<[u8; 32]>, algorithm: &Algorithm) -> anyhow::Result<Self> {
let cipher = match algorithm {
Algorithm::Aes256Gcm => {
let cipher = Aes256Gcm::new_from_slice(key.expose())
.map_err(|_| anyhow::anyhow!("Unable to create cipher with hashed key."))?;

Ciphers::Aes256Gcm(Box::new(cipher))
}
Algorithm::XChaCha20Poly1305 => {
let cipher = XChaCha20Poly1305::new_from_slice(key.expose())
.map_err(|_| anyhow::anyhow!("Unable to create cipher with hashed key."))?;

Ciphers::XChaCha(Box::new(cipher))
}
Algorithm::DeoxysII256 => {
let cipher = DeoxysII256::new_from_slice(key.expose())
.map_err(|_| anyhow::anyhow!("Unable to create cipher with hashed key."))?;

Ciphers::DeoxysII(Box::new(cipher))
}
};

drop(key);
Ok(cipher)
}

/// This can be used to encrypt data with a given `Ciphers` object
///
/// It requires the nonce, and either some plaintext, or an `aead::Payload` (that contains the plaintext and the AAD)
pub fn encrypt<'msg, 'aad>(
&self,
nonce: &[u8],
plaintext: impl Into<Payload<'msg, 'aad>>,
) -> aead::Result<Vec<u8>> {
match self {
Ciphers::Aes256Gcm(c) => c.encrypt(nonce.as_ref().into(), plaintext),
Ciphers::XChaCha(c) => c.encrypt(nonce.as_ref().into(), plaintext),
Ciphers::DeoxysII(c) => c.encrypt(nonce.as_ref().into(), plaintext),
}
}

pub fn encrypt_in_place(
&self,
nonce: &[u8],
aad: &[u8],
buffer: &mut dyn aead::Buffer,
) -> Result<(), aead::Error> {
match self {
Ciphers::Aes256Gcm(c) => c.encrypt_in_place(nonce.as_ref().into(), aad, buffer),
Ciphers::XChaCha(c) => c.encrypt_in_place(nonce.as_ref().into(), aad, buffer),
Ciphers::DeoxysII(c) => c.encrypt_in_place(nonce.as_ref().into(), aad, buffer),
}
}

/// This can be used to decrypt data with a given `Ciphers` object
///
/// It requires the nonce used for encryption, and either some plaintext, or an `aead::Payload` (that contains the plaintext and the AAD)
///
/// NOTE: The data will not decrypt successfully if an AAD was provided for encryption, but is not present/has been modified while decrypting
pub fn decrypt<'msg, 'aad>(
&self,
nonce: &[u8],
ciphertext: impl Into<Payload<'msg, 'aad>>,
) -> aead::Result<Vec<u8>> {
match self {
Ciphers::Aes256Gcm(c) => c.decrypt(nonce.as_ref().into(), ciphertext),
Ciphers::XChaCha(c) => c.decrypt(nonce.as_ref().into(), ciphertext),
Ciphers::DeoxysII(c) => c.decrypt(nonce.as_ref().into(), ciphertext),
}
}
}
Loading
Loading