From 67d64ec4b368c48188c746f2dba2967ec4615fe5 Mon Sep 17 00:00:00 2001 From: Ellie Huxtable Date: Mon, 24 Jun 2024 14:54:54 +0100 Subject: feat: add user account verification (#2190) * add verified column to users table * add database functions to check if verified, or to verify * getting there * verification check * use base64 urlsafe no pad * add verification client * clippy * correct docs * fix integration tests --- crates/atuin-common/src/utils.rs | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'crates/atuin-common/src/utils.rs') diff --git a/crates/atuin-common/src/utils.rs b/crates/atuin-common/src/utils.rs index 65f5efc4..869866b0 100644 --- a/crates/atuin-common/src/utils.rs +++ b/crates/atuin-common/src/utils.rs @@ -4,17 +4,30 @@ use std::path::PathBuf; use eyre::{eyre, Result}; -use rand::RngCore; +use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD}; +use getrandom::getrandom; use uuid::Uuid; -pub fn random_bytes() -> [u8; N] { +/// Generate N random bytes, using a cryptographically secure source +pub fn crypto_random_bytes() -> [u8; N] { + // rand say they are in principle safe for crypto purposes, but that it is perhaps a better + // idea to use getrandom for things such as passwords. let mut ret = [0u8; N]; - rand::thread_rng().fill_bytes(&mut ret); + getrandom(&mut ret).expect("Failed to generate random bytes!"); ret } +/// Generate N random bytes using a cryptographically secure source, return encoded as a string +pub fn crypto_random_string() -> String { + let bytes = crypto_random_bytes::(); + + // We only use this to create a random string, and won't be reversing it to find the original + // data - no padding is OK there. It may be in URLs. + BASE64_URL_SAFE_NO_PAD.encode(bytes) +} + pub fn uuid_v7() -> Uuid { Uuid::now_v7() } @@ -178,6 +191,7 @@ impl> Escapable for T {} #[cfg(test)] mod tests { + use pretty_assertions::assert_ne; use time::Month; use super::*; @@ -292,4 +306,17 @@ mod tests { Cow::Owned(_) )); } + + #[test] + fn dumb_random_test() { + // Obviously not a test of randomness, but make sure we haven't made some + // catastrophic error + + assert_ne!(crypto_random_string::<1>(), crypto_random_string::<1>()); + assert_ne!(crypto_random_string::<2>(), crypto_random_string::<2>()); + assert_ne!(crypto_random_string::<4>(), crypto_random_string::<4>()); + assert_ne!(crypto_random_string::<8>(), crypto_random_string::<8>()); + assert_ne!(crypto_random_string::<16>(), crypto_random_string::<16>()); + assert_ne!(crypto_random_string::<32>(), crypto_random_string::<32>()); + } } -- cgit v1.3.1