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

Use constant size generic parameter for random bytes generation #2910

Merged
merged 2 commits into from
Nov 27, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion src/api/core/two_factor/authenticator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async fn generate_authenticator(data: JsonUpcase<PasswordData>, headers: Headers

let (enabled, key) = match twofactor {
Some(tf) => (true, tf.data),
_ => (false, BASE32.encode(&crypto::get_random(vec![0u8; 20]))),
_ => (false, crypto::encode_random_bytes::<20>(BASE32)),
};

Ok(Json(json!({
Expand Down
2 changes: 1 addition & 1 deletion src/api/core/two_factor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ async fn recover(data: JsonUpcase<RecoverTwoFactor>, mut conn: DbConn) -> JsonRe

async fn _generate_recover_code(user: &mut User, conn: &mut DbConn) {
if user.totp_recover.is_none() {
let totp_recover = BASE32.encode(&crypto::get_random(vec![0u8; 20]));
let totp_recover = crypto::encode_random_bytes::<20>(BASE32);
user.totp_recover = Some(totp_recover);
user.save(conn).await.ok();
}
Expand Down
2 changes: 1 addition & 1 deletion src/api/notifications.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ fn negotiate(_headers: Headers) -> Json<JsonValue> {
use crate::crypto;
use data_encoding::BASE64URL;

let conn_id = BASE64URL.encode(&crypto::get_random(vec![0u8; 16]));
let conn_id = crypto::encode_random_bytes::<16>(BASE64URL);
let mut available_transports: Vec<JsonValue> = Vec::new();

if CONFIG.websocket_enabled() {
Expand Down
21 changes: 14 additions & 7 deletions src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//
use std::num::NonZeroU32;

use data_encoding::HEXLOWER;
use data_encoding::{Encoding, HEXLOWER};
use ring::{digest, hmac, pbkdf2};

static DIGEST_ALG: pbkdf2::Algorithm = pbkdf2::PBKDF2_HMAC_SHA256;
Expand Down Expand Up @@ -38,17 +38,24 @@ pub fn hmac_sign(key: &str, data: &str) -> String {
//

pub fn get_random_64() -> Vec<u8> {
get_random(vec![0u8; 64])
get_random_bytes::<64>().to_vec()
samueltardieu marked this conversation as resolved.
Show resolved Hide resolved
}

pub fn get_random(mut array: Vec<u8>) -> Vec<u8> {
/// Return an array holding `N` random bytes.
pub fn get_random_bytes<const N: usize>() -> [u8; N] {
use ring::rand::{SecureRandom, SystemRandom};

let mut array = [0; N];
SystemRandom::new().fill(&mut array).expect("Error generating random values");

array
}

/// Encode random bytes using the provided function.
pub fn encode_random_bytes<const N: usize>(e: Encoding) -> String {
e.encode(&get_random_bytes::<N>())
}

/// Generates a random string over a specified alphabet.
pub fn get_random_string(alphabet: &[u8], num_chars: usize) -> String {
// Ref: https://rust-lang-nursery.github.io/rust-cookbook/algorithms/randomness.html
Expand Down Expand Up @@ -77,18 +84,18 @@ pub fn get_random_string_alphanum(num_chars: usize) -> String {
get_random_string(ALPHABET, num_chars)
}

pub fn generate_id(num_bytes: usize) -> String {
HEXLOWER.encode(&get_random(vec![0; num_bytes]))
pub fn generate_id<const N: usize>() -> String {
encode_random_bytes::<N>(HEXLOWER)
}

pub fn generate_send_id() -> String {
// Send IDs are globally scoped, so make them longer to avoid collisions.
generate_id(32) // 256 bits
generate_id::<32>() // 256 bits
}

pub fn generate_attachment_id() -> String {
// Attachment IDs are scoped to a cipher, so they can be smaller.
generate_id(10) // 80 bits
generate_id::<10>() // 80 bits
}

/// Generates a numeric token for email-based verifications.
Expand Down
4 changes: 2 additions & 2 deletions src/db/models/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl Device {
use crate::crypto;
use data_encoding::BASE64;

let twofactor_remember = BASE64.encode(&crypto::get_random(vec![0u8; 180]));
let twofactor_remember = crypto::encode_random_bytes::<180>(BASE64);
self.twofactor_remember = Some(twofactor_remember.clone());

twofactor_remember
Expand All @@ -69,7 +69,7 @@ impl Device {
use crate::crypto;
use data_encoding::BASE64URL;

self.refresh_token = BASE64URL.encode(&crypto::get_random_64());
self.refresh_token = crypto::encode_random_bytes::<64>(BASE64URL);
}

// Update the expiration of the device and the last update date
Expand Down