clippy lints
This commit is contained in:
parent
de4d4f90b7
commit
3bc4541390
8 changed files with 57 additions and 28 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 || {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in a new issue