mirror of
https://github.com/bitwarden/browser
synced 2025-12-24 04:04:24 +00:00
Switch to rustcrypto argon2 on desktop (#11753)
* Switch to rustcrypto argon2 on desktop * Make argon2 use zeroize * Remove argon2 native modules from electron-builder config * Clean rust implementation of argon2 * Update cargo.lock * Update apps/desktop/desktop_native/napi/src/lib.rs Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> * Add tests * Clean up test * Remove argon2 external from webpack main * Fix build * Fix argon2 module causing a startup crash --------- Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com>
This commit is contained in:
@@ -5,7 +5,7 @@ use aes::cipher::{
|
||||
BlockEncryptMut, KeyIvInit,
|
||||
};
|
||||
|
||||
use crate::error::{CryptoError, Result};
|
||||
use crate::error::{CryptoError, KdfParamError, Result};
|
||||
|
||||
use super::CipherString;
|
||||
|
||||
@@ -37,3 +37,53 @@ pub fn encrypt_aes256(
|
||||
|
||||
Ok(CipherString::AesCbc256_B64 { iv, data })
|
||||
}
|
||||
|
||||
pub fn argon2(
|
||||
secret: &[u8],
|
||||
salt: &[u8],
|
||||
iterations: u32,
|
||||
memory: u32,
|
||||
parallelism: u32,
|
||||
) -> Result<[u8; 32]> {
|
||||
use argon2::*;
|
||||
|
||||
let params = Params::new(memory, iterations, parallelism, Some(32)).map_err(|e| {
|
||||
KdfParamError::InvalidParams(format!("Argon2 parameters are invalid: {e}",))
|
||||
})?;
|
||||
let argon = Argon2::new(Algorithm::Argon2id, Version::V0x13, params);
|
||||
|
||||
let mut hash = [0u8; 32];
|
||||
argon
|
||||
.hash_password_into(secret, &salt, &mut hash)
|
||||
.map_err(|e| KdfParamError::InvalidParams(format!("Argon2 hashing failed: {e}",)))?;
|
||||
|
||||
// Argon2 is using some stack memory that is not zeroed. Eventually some function will
|
||||
// overwrite the stack, but we use this trick to force the used stack to be zeroed.
|
||||
#[inline(never)]
|
||||
fn clear_stack() {
|
||||
std::hint::black_box([0u8; 4096]);
|
||||
}
|
||||
clear_stack();
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_argon2() {
|
||||
let test_hash: [u8; 32] = [
|
||||
112, 200, 85, 209, 100, 4, 246, 146, 117, 180, 152, 44, 103, 198, 75, 14, 166, 77, 201,
|
||||
22, 62, 178, 87, 224, 95, 209, 253, 68, 166, 209, 47, 218,
|
||||
];
|
||||
let secret = b"supersecurepassword";
|
||||
let salt = b"mail@example.com";
|
||||
let iterations = 3;
|
||||
let memory = 1024 * 64;
|
||||
let parallelism = 4;
|
||||
|
||||
let hash = argon2(secret, salt, iterations, memory, parallelism).unwrap();
|
||||
assert_eq!(hash, test_hash,);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ pub enum Error {
|
||||
|
||||
#[error("Cryptography Error, {0}")]
|
||||
Crypto(#[from] CryptoError),
|
||||
#[error("KDF Parameter Error, {0}")]
|
||||
KdfParam(#[from] KdfParamError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@@ -29,6 +31,12 @@ pub enum CryptoError {
|
||||
KeyDecrypt,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum KdfParamError {
|
||||
#[error("Invalid KDF parameters: {0}")]
|
||||
InvalidParams(String),
|
||||
}
|
||||
|
||||
// Ensure that the error messages implement Send and Sync
|
||||
#[cfg(test)]
|
||||
const _: () = {
|
||||
|
||||
Reference in New Issue
Block a user