feat: zeroize encryption_key for seed

This commit is contained in:
nazeh
2023-12-12 17:52:49 +03:00
parent a7260f745d
commit b193cb516a
5 changed files with 33 additions and 15 deletions

7
Cargo.lock generated
View File

@@ -161,6 +161,7 @@ dependencies = [
"rand",
"thiserror",
"z32",
"zeroize",
]
[[package]]
@@ -300,3 +301,9 @@ name = "z32"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4e62ec361f7259399a83b7983270dd0249067d94600c50475e65dca64e24083"
[[package]]
name = "zeroize"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"

View File

@@ -12,3 +12,4 @@ bytes = "1.5.0"
rand = "0.8.5"
thiserror = "1.0.50"
z32 = "1.0.2"
zeroize = "1.7.0"

View File

@@ -1,8 +0,0 @@
//! Keypairs.
use crate::crypto::Key;
/// Generate a random secret seed.
pub fn generate_seed() -> Key {
rand::random()
}

View File

@@ -1,5 +1,4 @@
pub mod encryption;
pub mod keys;
pub mod passphrase;
pub mod seed;
@@ -7,3 +6,13 @@ pub mod seed;
pub type Key = [u8; bessie::KEY_LEN];
/// A 24 bytes Nonce or salt.
pub type Nonce = [u8; bessie::NONCE_LEN];
/// Generate a random secret seed.
pub fn generate_seed() -> Key {
rand::random()
}
/// Generate a random secret seed.
pub fn generate_salt() -> Nonce {
rand::random()
}

View File

@@ -3,6 +3,7 @@
//! Seed file contains a seed encrypted with a strong passphrase.
use bytes::{Bytes, BytesMut};
use zeroize::Zeroize;
use crate::{
crypto::{
@@ -19,7 +20,7 @@ const VERSION: u8 = 0;
/// Encrypt the seed with a strong passphrase, and return an [encrypted seed
/// file](../../../design/seed.md).
pub fn encrypt_seed(seed: &Key, passphrase: &str) -> Bytes {
let encryption_key = derive_encrypiton_key(passphrase);
let mut encryption_key = derive_encryption_key(passphrase);
let mut seed_file = BytesMut::with_capacity(SEED_SCHEME.len() + 33);
seed_file.extend_from_slice(SEED_SCHEME);
@@ -32,9 +33,12 @@ pub fn encrypt_seed(seed: &Key, passphrase: &str) -> Bytes {
seed_file.extend_from_slice(z32::encode(&suffix).as_bytes());
encryption_key.zeroize();
seed_file.freeze()
}
/// Decrypt the [seed file](../../../design/seed.md).
pub fn decrypt_seed(seed_file: Bytes, passphrase: &str) -> Result<Vec<u8>> {
if !seed_file.starts_with(SEED_SCHEME) {
return Err(Error::Generic("Not a Kytz seed".to_string()));
@@ -52,14 +56,19 @@ pub fn decrypt_seed(seed_file: Bytes, passphrase: &str) -> Result<Vec<u8>> {
}
fn decrypted_seed_v0(suffix: &[u8], passphrase: &str) -> Result<Vec<u8>> {
let encryption_key = derive_encrypiton_key(passphrase);
let mut encryption_key = derive_encryption_key(passphrase);
let encrypted_seed = &suffix[1..];
decrypt(&encryption_key, encrypted_seed)
let decrypted_seed = decrypt(&encryption_key, encrypted_seed);
// Empty the encryption key in memory.
encryption_key.zeroize();
decrypted_seed
}
/// Derive a secret key from a strong passphrase for encrypting/decrypting the seed.
fn derive_encrypiton_key(passphrase: &str) -> Key {
fn derive_encryption_key(passphrase: &str) -> Key {
// Argon2 with default params (Argon2id v19)
let hasher = argon2::Argon2::default();
@@ -84,8 +93,8 @@ mod test {
use std::time::Instant;
use super::*;
use crate::crypto::keys::*;
use crate::crypto::passphrase::*;
use crate::crypto::*;
#[test]
fn test_encrypt_decrypt_seed() {
@@ -94,7 +103,7 @@ mod test {
let encrypted_seed_file = encrypt_seed(&seed, &passphrase);
dbg!(&encrypted_seed_file);
// dbg!(&encrypted_seed_file);
let start = Instant::now();
let decrypted_seed = decrypt_seed(encrypted_seed_file, &passphrase)