Skip to content

Commit

Permalink
Merge pull request #2910 from samueltardieu/const-crypto
Browse files Browse the repository at this point in the history
Use constant size generic parameter for random bytes generation
  • Loading branch information
dani-garcia authored Nov 27, 2022
2 parents 7a76731 + 7445ee4 commit dfe1e30
Show file tree
Hide file tree
Showing 8 changed files with 21 additions and 19 deletions.
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
3 changes: 1 addition & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -981,8 +981,7 @@ impl Config {
if let Some(akey) = self._duo_akey() {
akey
} else {
let akey = crate::crypto::get_random_64();
let akey_s = data_encoding::BASE64.encode(&akey);
let akey_s = crate::crypto::encode_random_bytes::<64>(data_encoding::BASE64);

// Save the new value
let builder = ConfigBuilder {
Expand Down
23 changes: 13 additions & 10 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 @@ -37,18 +37,21 @@ pub fn hmac_sign(key: &str, data: &str) -> String {
// Random values
//

pub fn get_random_64() -> Vec<u8> {
get_random(vec![0u8; 64])
}

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 +80,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
2 changes: 1 addition & 1 deletion src/db/models/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl Send {

if let Some(password) = password {
self.password_iter = Some(PASSWORD_ITER);
let salt = crate::crypto::get_random_64();
let salt = crate::crypto::get_random_bytes::<64>().to_vec();
let hash = crate::crypto::hash_password(password.as_bytes(), &salt, PASSWORD_ITER as u32);
self.password_salt = Some(salt);
self.password_hash = Some(hash);
Expand Down
2 changes: 1 addition & 1 deletion src/db/models/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl User {
email_new_token: None,

password_hash: Vec::new(),
salt: crypto::get_random_64(),
salt: crypto::get_random_bytes::<64>().to_vec(),
password_iterations: CONFIG.password_iterations(),

security_stamp: crate::util::get_uuid(),
Expand Down

0 comments on commit dfe1e30

Please sign in to comment.