clippy lints

master
Edward Shen 2021-10-31 12:34:26 -07:00
parent de4d4f90b7
commit 3bc4541390
Signed by: edward
GPG Key ID: 19182661E818369F
8 changed files with 57 additions and 28 deletions

View File

@ -17,7 +17,7 @@ cargo build --release --bin omegaupload-server
# Prepare assets for upload to webserver
mkdir -p dist/static
# Move everything that's not index.html into a `static` subdir
find dist -type f -exec mv {} dist/static/ ";"
find dist -not -name index.html -type f -exec mv {} dist/static/ ";"
strip target/release/omegaupload-server
cp target/release/omegaupload-server dist/omegaupload-server

View File

@ -6,6 +6,11 @@ pub fn encode(input: impl AsRef<[u8]>) -> String {
}
/// URL-safe Base64 decoding.
///
/// # Errors
///
/// Returns an error if a buffer cannot be decoded, such as if there's an
/// incorrect number of bytes.
pub fn decode(input: impl AsRef<[u8]>) -> Result<Vec<u8>, DecodeError> {
base64::decode_config(input, URL_SAFE)
}

View File

@ -6,7 +6,7 @@ use chacha20poly1305::aead::generic_array::GenericArray;
use chacha20poly1305::aead::{AeadInPlace, NewAead};
use chacha20poly1305::XChaCha20Poly1305;
use chacha20poly1305::XNonce;
use rand::{thread_rng, Rng};
use rand::{CryptoRng, Rng};
use secrecy::{ExposeSecret, Secret, SecretVec, Zeroize};
use typenum::Unsigned;
@ -27,6 +27,7 @@ pub enum Error {
pub struct Key(chacha20poly1305::Key);
impl Key {
/// Encloses a secret key in a secret `Key` struct.
pub fn new_secret(vec: Vec<u8>) -> Option<Secret<Self>> {
chacha20poly1305::Key::from_exact_iter(vec.into_iter())
.map(Self)
@ -58,11 +59,14 @@ impl Zeroize for Key {
}
}
/// Seals the provided message with an optional message. The resulting sealed
/// message has the nonce used to encrypt the message appended to it as well as
/// a salt string used to derive the key. In other words, the modified buffer is
/// one of the following to possibilities, depending if there was a password
/// provided:
/// Seals the provided message with an optional password, returning the secret
/// key used to encrypt the message and mutating the buffer to contain necessary
/// metadata.
///
/// The resulting sealed message has the nonce used to encrypt the message
/// appended to it as well as a salt string used to derive the key. In other
/// words, the modified buffer is one of the following to possibilities,
/// depending if there was a password provided:
///
/// ```
/// modified = C(message, rng_key, nonce) || nonce
@ -77,6 +81,17 @@ impl Zeroize for Key {
/// `XChaCha20Poly1305`.
/// - `rng_key` represents a randomly generated key.
/// - `kdf(pw, salt)` represents a key derived from Argon2.
/// - `nonce` represents a randomly generated nonce.
///
/// Note that the lengths for the nonce, key, and salt follow recommended
/// values. As of writing this doc (2021-10-31), the nonce size is 24 bytes, the
/// salt size is 16 bytes, and the key size is 32 bytes.
///
/// # Errors
///
/// This message will return an error if and only if there was a problem
/// encrypting the message or deriving a secret key from the password, if one
/// was provided.
pub fn seal_in_place(
message: &mut Vec<u8>,
pw: Option<SecretVec<u8>>,
@ -104,6 +119,12 @@ pub fn seal_in_place(
Ok(key)
}
/// Opens a message that has been sealed with `seal_in_place`.
///
/// # Errors
///
/// Returns an error if there was a decryption failure or if there was a problem
/// deriving a secret key from the password.
pub fn open_in_place(
data: &mut Vec<u8>,
key: &Secret<Key>,
@ -140,10 +161,9 @@ pub fn open_in_place(
Ok(())
}
/// Securely generates a random key and nonce.
#[must_use]
fn gen_key_nonce() -> (Secret<Key>, Nonce) {
let mut rng = thread_rng();
let mut rng = get_csrng();
let mut key = GenericArray::default();
rng.fill(key.as_mut_slice());
let mut nonce = Nonce::default();
@ -154,15 +174,9 @@ fn gen_key_nonce() -> (Secret<Key>, Nonce) {
// Type alias; to ensure that we're consistent on what the inner impl is.
type NonceImpl = XNonce;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
struct Nonce(NonceImpl);
impl Default for Nonce {
fn default() -> Self {
Self(GenericArray::default())
}
}
impl Deref for Nonce {
type Target = NonceImpl;
@ -207,7 +221,7 @@ impl Salt {
fn random() -> Self {
let mut salt = [0_u8; Self::SIZE];
thread_rng().fill(&mut salt);
get_csrng().fill(&mut salt);
Self(salt)
}
}
@ -227,3 +241,12 @@ fn kdf(password: &SecretVec<u8>) -> Result<(Secret<Key>, Salt), argon2::Error> {
Ok((Secret::new(key), salt))
}
/// 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
/// non-cryptographically secure RNGs from being used.
#[must_use]
pub fn get_csrng() -> impl CryptoRng + Rng {
rand::thread_rng()
}

View File

@ -18,7 +18,8 @@ futures = "0.3"
# We just need to pull in whatever axum is pulling in
headers = "*"
lazy_static = "1"
rand = "0.8"
# Disable `random()` and `thread_rng()`
rand = { version = "0.8", default_features = false }
rocksdb = { version = "0.17", default_features = false, features = ["zstd"] }
serde = { version = "1", features = ["derive"] }
signal-hook = "0.3"

View File

@ -16,8 +16,8 @@ use chrono::Utc;
use futures::stream::StreamExt;
use headers::HeaderMap;
use lazy_static::lazy_static;
use omegaupload_common::crypto::get_csrng;
use omegaupload_common::{Expiration, API_ENDPOINT};
use rand::thread_rng;
use rand::Rng;
use rocksdb::{ColumnFamilyDescriptor, IteratorMode};
use rocksdb::{Options, DB};
@ -41,6 +41,7 @@ lazy_static! {
#[tokio::main]
async fn main() -> Result<()> {
const INDEX_PAGE: Html<&'static str> = Html(include_str!("../../dist/index.html"));
const PASTE_DB_PATH: &str = "database";
const SHORT_CODE_SIZE: usize = 12;
@ -68,8 +69,6 @@ async fn main() -> Result<()> {
let root_service = service::get(ServeDir::new("static"))
.handle_error(|_| Ok::<_, Infallible>(StatusCode::NOT_FOUND));
const INDEX_PAGE: Html<&'static str> = Html(include_str!("../../dist/index.html"));
axum::Server::bind(&"0.0.0.0:8080".parse()?)
.serve(
Router::new()
@ -206,7 +205,7 @@ async fn upload<const N: usize>(
// Try finding a code; give up after 1000 attempts
// Statistics show that this is very unlikely to happen
for i in 0..1000 {
let code: ShortCode<N> = thread_rng().sample(short_code::Generator);
let code: ShortCode<N> = get_csrng().sample(short_code::Generator);
let db = Arc::clone(&db);
let key = code.as_bytes();
let query = task::spawn_blocking(move || {

View File

@ -1,6 +1,7 @@
use std::fmt::Debug;
use rand::prelude::Distribution;
use rand::Rng;
use serde::de::{Unexpected, Visitor};
use serde::Deserialize;
@ -109,7 +110,7 @@ pub struct Generator;
const ALPHABET: &[u8; 32] = b"23456789CFGHJMPQRVWXcfghjmpqrvwx";
impl Distribution<ShortCodeChar> for Generator {
fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> ShortCodeChar {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> ShortCodeChar {
let value = rng.gen_range(0..32);
assert!(value < 32);
ShortCodeChar(ALPHABET[value] as char)
@ -117,7 +118,7 @@ impl Distribution<ShortCodeChar> for Generator {
}
impl<const N: usize> Distribution<ShortCode<N>> for Generator {
fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> ShortCode<N> {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> ShortCode<N> {
let mut arr = [ShortCodeChar('\0'); N];
for c in arr.iter_mut() {

View File

@ -12,7 +12,7 @@ use web_sys::{Blob, BlobPropertyBag};
#[derive(Clone, Serialize)]
pub struct ArchiveMeta {
name: String,
file_size: usize,
file_size: u64,
}
#[derive(Clone)]
@ -86,7 +86,7 @@ pub fn decrypt(
match zip.by_index(i) {
Ok(file) => entries.push(ArchiveMeta {
name: file.name().to_string(),
file_size: file.size() as usize,
file_size: file.size(),
}),
Err(err) => match err {
zip::result::ZipError::UnsupportedArchive(s) => {

View File

@ -96,6 +96,8 @@ fn main() {
Ok(Some(password)) if !password.is_empty() => {
break Some(SecretVec::new(password.into_bytes()));
}
// Empty message was entered.
Ok(Some(_)) => (),
// Cancel button was entered.
Ok(None) => {
render_message("This paste requires a password.".into());
@ -112,8 +114,6 @@ fn main() {
None
};
log!(location().pathname().unwrap());
spawn_local(async move {
if let Err(e) = fetch_resources(request_uri, key, password).await {
log!(e.to_string());