mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-21 11:31:08 +03:00
[Floonet] Encrypt private slate data upon storage in DB (#2189)
* xor encrypt stored nonce and blind sum in transaction data * rustfmt * stop doc tests splatting wallet files throughout
This commit is contained in:
parent
a42250445d
commit
7812a9e892
2 changed files with 68 additions and 6 deletions
|
@ -99,6 +99,7 @@ where
|
||||||
/// use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
/// use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
||||||
///
|
///
|
||||||
/// let mut wallet_config = WalletConfig::default();
|
/// let mut wallet_config = WalletConfig::default();
|
||||||
|
/// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned();
|
||||||
///
|
///
|
||||||
/// // A NodeClient must first be created to handle communication between
|
/// // A NodeClient must first be created to handle communication between
|
||||||
/// // the wallet and the node.
|
/// // the wallet and the node.
|
||||||
|
@ -148,6 +149,7 @@ where
|
||||||
/// # use wallet::libwallet::api::APIOwner;
|
/// # use wallet::libwallet::api::APIOwner;
|
||||||
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
||||||
/// # let mut wallet_config = WalletConfig::default();
|
/// # let mut wallet_config = WalletConfig::default();
|
||||||
|
/// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned();
|
||||||
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
||||||
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||||
/// # Arc::new(Mutex::new(
|
/// # Arc::new(Mutex::new(
|
||||||
|
@ -203,6 +205,7 @@ where
|
||||||
/// # use wallet::libwallet::api::APIOwner;
|
/// # use wallet::libwallet::api::APIOwner;
|
||||||
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
||||||
/// # let mut wallet_config = WalletConfig::default();
|
/// # let mut wallet_config = WalletConfig::default();
|
||||||
|
/// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned();
|
||||||
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
||||||
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||||
/// # Arc::new(Mutex::new(
|
/// # Arc::new(Mutex::new(
|
||||||
|
@ -256,6 +259,7 @@ where
|
||||||
/// # use wallet::libwallet::api::APIOwner;
|
/// # use wallet::libwallet::api::APIOwner;
|
||||||
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
||||||
/// # let mut wallet_config = WalletConfig::default();
|
/// # let mut wallet_config = WalletConfig::default();
|
||||||
|
/// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned();
|
||||||
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
||||||
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||||
/// # Arc::new(Mutex::new(
|
/// # Arc::new(Mutex::new(
|
||||||
|
@ -313,6 +317,7 @@ where
|
||||||
/// # use wallet::libwallet::api::APIOwner;
|
/// # use wallet::libwallet::api::APIOwner;
|
||||||
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
||||||
/// # let mut wallet_config = WalletConfig::default();
|
/// # let mut wallet_config = WalletConfig::default();
|
||||||
|
/// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned();
|
||||||
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
||||||
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||||
/// # Arc::new(Mutex::new(
|
/// # Arc::new(Mutex::new(
|
||||||
|
@ -389,6 +394,7 @@ where
|
||||||
/// # use wallet::libwallet::api::APIOwner;
|
/// # use wallet::libwallet::api::APIOwner;
|
||||||
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
||||||
/// # let mut wallet_config = WalletConfig::default();
|
/// # let mut wallet_config = WalletConfig::default();
|
||||||
|
/// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned();
|
||||||
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
||||||
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||||
/// # Arc::new(Mutex::new(
|
/// # Arc::new(Mutex::new(
|
||||||
|
@ -462,6 +468,7 @@ where
|
||||||
/// # use wallet::libwallet::api::APIOwner;
|
/// # use wallet::libwallet::api::APIOwner;
|
||||||
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
||||||
/// # let mut wallet_config = WalletConfig::default();
|
/// # let mut wallet_config = WalletConfig::default();
|
||||||
|
/// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned();
|
||||||
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
||||||
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||||
/// # Arc::new(Mutex::new(
|
/// # Arc::new(Mutex::new(
|
||||||
|
@ -575,6 +582,7 @@ where
|
||||||
/// # use wallet::libwallet::api::APIOwner;
|
/// # use wallet::libwallet::api::APIOwner;
|
||||||
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
/// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig};
|
||||||
/// # let mut wallet_config = WalletConfig::default();
|
/// # let mut wallet_config = WalletConfig::default();
|
||||||
|
/// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned();
|
||||||
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
/// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None);
|
||||||
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
/// # let mut wallet:Arc<Mutex<WalletBackend<HTTPNodeClient, ExtKeychain>>> =
|
||||||
/// # Arc::new(Mutex::new(
|
/// # Arc::new(Mutex::new(
|
||||||
|
|
|
@ -26,6 +26,8 @@ use serde_json;
|
||||||
use failure::ResultExt;
|
use failure::ResultExt;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::blake2::blake2b::Blake2b;
|
||||||
|
|
||||||
use crate::keychain::{ChildNumber, ExtKeychain, Identifier, Keychain};
|
use crate::keychain::{ChildNumber, ExtKeychain, Identifier, Keychain};
|
||||||
use crate::store::{self, option_to_not_found, to_key, to_key_u64};
|
use crate::store::{self, option_to_not_found, to_key, to_key_u64};
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ use crate::libwallet::types::*;
|
||||||
use crate::libwallet::{internal, Error, ErrorKind};
|
use crate::libwallet::{internal, Error, ErrorKind};
|
||||||
use crate::types::{WalletConfig, WalletSeed};
|
use crate::types::{WalletConfig, WalletSeed};
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
use crate::util::secp::constants::SECRET_KEY_SIZE;
|
||||||
use crate::util::secp::pedersen;
|
use crate::util::secp::pedersen;
|
||||||
|
|
||||||
pub const DB_DIR: &'static str = "db";
|
pub const DB_DIR: &'static str = "db";
|
||||||
|
@ -62,6 +65,39 @@ pub fn wallet_db_exists(config: WalletConfig) -> bool {
|
||||||
db_path.exists()
|
db_path.exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper to derive XOR keys for storing private transaction keys in the DB
|
||||||
|
/// (blind_xor_key, nonce_xor_key)
|
||||||
|
fn private_ctx_xor_keys<K>(
|
||||||
|
keychain: &K,
|
||||||
|
slate_id: &[u8],
|
||||||
|
) -> Result<([u8; SECRET_KEY_SIZE], [u8; SECRET_KEY_SIZE]), Error>
|
||||||
|
where
|
||||||
|
K: Keychain,
|
||||||
|
{
|
||||||
|
let root_key = keychain.derive_key(0, &K::root_key_id())?;
|
||||||
|
|
||||||
|
// derive XOR values for storing secret values in DB
|
||||||
|
// h(root_key|slate_id|"blind")
|
||||||
|
let mut hasher = Blake2b::new(SECRET_KEY_SIZE);
|
||||||
|
hasher.update(&root_key.0[..]);
|
||||||
|
hasher.update(&slate_id[..]);
|
||||||
|
hasher.update(&"blind".as_bytes()[..]);
|
||||||
|
let blind_xor_key = hasher.finalize();
|
||||||
|
let mut ret_blind = [0; SECRET_KEY_SIZE];
|
||||||
|
ret_blind.copy_from_slice(&blind_xor_key.as_bytes()[0..SECRET_KEY_SIZE]);
|
||||||
|
|
||||||
|
// h(root_key|slate_id|"nonce")
|
||||||
|
let mut hasher = Blake2b::new(SECRET_KEY_SIZE);
|
||||||
|
hasher.update(&root_key.0[..]);
|
||||||
|
hasher.update(&slate_id[..]);
|
||||||
|
hasher.update(&"nonce".as_bytes()[..]);
|
||||||
|
let nonce_xor_key = hasher.finalize();
|
||||||
|
let mut ret_nonce = [0; SECRET_KEY_SIZE];
|
||||||
|
ret_nonce.copy_from_slice(&nonce_xor_key.as_bytes()[0..SECRET_KEY_SIZE]);
|
||||||
|
|
||||||
|
Ok((ret_blind, ret_nonce))
|
||||||
|
}
|
||||||
|
|
||||||
pub struct LMDBBackend<C, K> {
|
pub struct LMDBBackend<C, K> {
|
||||||
db: store::Store,
|
db: store::Store,
|
||||||
config: WalletConfig,
|
config: WalletConfig,
|
||||||
|
@ -232,11 +268,19 @@ where
|
||||||
|
|
||||||
fn get_private_context(&mut self, slate_id: &[u8]) -> Result<Context, Error> {
|
fn get_private_context(&mut self, slate_id: &[u8]) -> Result<Context, Error> {
|
||||||
let ctx_key = to_key(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec());
|
let ctx_key = to_key(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec());
|
||||||
option_to_not_found(
|
let (blind_xor_key, nonce_xor_key) = private_ctx_xor_keys(self.keychain(), slate_id)?;
|
||||||
|
|
||||||
|
let mut ctx: Context = option_to_not_found(
|
||||||
self.db.get_ser(&ctx_key),
|
self.db.get_ser(&ctx_key),
|
||||||
&format!("Slate id: {:x?}", slate_id.to_vec()),
|
&format!("Slate id: {:x?}", slate_id.to_vec()),
|
||||||
)
|
)?;
|
||||||
.map_err(|e| e.into())
|
|
||||||
|
for i in 0..SECRET_KEY_SIZE {
|
||||||
|
ctx.sec_key.0[i] = ctx.sec_key.0[i] ^ blind_xor_key[i];
|
||||||
|
ctx.sec_nonce.0[i] = ctx.sec_nonce.0[i] ^ nonce_xor_key[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn acct_path_iter<'a>(&'a self) -> Box<dyn Iterator<Item = AcctPathMapping> + 'a> {
|
fn acct_path_iter<'a>(&'a self) -> Box<dyn Iterator<Item = AcctPathMapping> + 'a> {
|
||||||
|
@ -501,11 +545,21 @@ where
|
||||||
self.save(out.clone())
|
self.save(out.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Keys stored unencrypted in DB.. not good
|
|
||||||
// should store keys as derivation paths instead
|
|
||||||
fn save_private_context(&mut self, slate_id: &[u8], ctx: &Context) -> Result<(), Error> {
|
fn save_private_context(&mut self, slate_id: &[u8], ctx: &Context) -> Result<(), Error> {
|
||||||
let ctx_key = to_key(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec());
|
let ctx_key = to_key(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec());
|
||||||
self.db.borrow().as_ref().unwrap().put_ser(&ctx_key, &ctx)?;
|
let (blind_xor_key, nonce_xor_key) = private_ctx_xor_keys(self.keychain(), slate_id)?;
|
||||||
|
|
||||||
|
let mut s_ctx = ctx.clone();
|
||||||
|
for i in 0..SECRET_KEY_SIZE {
|
||||||
|
s_ctx.sec_key.0[i] = s_ctx.sec_key.0[i] ^ blind_xor_key[i];
|
||||||
|
s_ctx.sec_nonce.0[i] = s_ctx.sec_nonce.0[i] ^ nonce_xor_key[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.put_ser(&ctx_key, &s_ctx)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue