table store encryption
This commit is contained in:
parent
01df18c081
commit
4994f54039
@ -56,9 +56,7 @@ impl fmt::Display for KeyPair {
|
|||||||
|
|
||||||
impl fmt::Debug for KeyPair {
|
impl fmt::Debug for KeyPair {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, concat!(stringify!($name), "("))?;
|
write!(f, "KeyPair({})", self.encode())
|
||||||
write!(f, "{}", self.encode())?;
|
|
||||||
write!(f, ")")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use rustls::internal::msgs::handshake::EncryptedExtensions;
|
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
@ -27,7 +25,6 @@ impl CryptInfo {
|
|||||||
pub struct TableDBUnlockedInner {
|
pub struct TableDBUnlockedInner {
|
||||||
table: String,
|
table: String,
|
||||||
table_store: TableStore,
|
table_store: TableStore,
|
||||||
crypto: Crypto,
|
|
||||||
database: Database,
|
database: Database,
|
||||||
// Encryption and decryption key will be the same unless configured for an in-place migration
|
// Encryption and decryption key will be the same unless configured for an in-place migration
|
||||||
encrypt_info: Option<CryptInfo>,
|
encrypt_info: Option<CryptInfo>,
|
||||||
@ -67,7 +64,6 @@ impl TableDB {
|
|||||||
unlocked_inner: Arc::new(TableDBUnlockedInner {
|
unlocked_inner: Arc::new(TableDBUnlockedInner {
|
||||||
table,
|
table,
|
||||||
table_store,
|
table_store,
|
||||||
crypto,
|
|
||||||
database,
|
database,
|
||||||
encrypt_info,
|
encrypt_info,
|
||||||
decrypt_info,
|
decrypt_info,
|
||||||
@ -92,10 +88,26 @@ impl TableDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Encrypt buffer using encrypt key and prepend nonce to output
|
/// Encrypt buffer using encrypt key and prepend nonce to output
|
||||||
fn maybe_encrypt(&self, data: &[u8]) -> Vec<u8> {
|
/// Keyed nonces are unique because keys must be unique
|
||||||
|
/// Normally they must be sequential or random, but the critical
|
||||||
|
/// requirement is that they are different for each encryption
|
||||||
|
/// but if the contents are guaranteed to be unique, then a nonce
|
||||||
|
/// can be generated from the hash of the contents and the encryption key itself
|
||||||
|
fn maybe_encrypt(&self, data: &[u8], keyed_nonce: bool) -> Vec<u8> {
|
||||||
if let Some(ei) = &self.unlocked_inner.encrypt_info {
|
if let Some(ei) = &self.unlocked_inner.encrypt_info {
|
||||||
let mut out = unsafe { unaligned_u8_vec_uninit(NONCE_LENGTH + data.len()) };
|
let mut out = unsafe { unaligned_u8_vec_uninit(NONCE_LENGTH + data.len()) };
|
||||||
|
|
||||||
|
if keyed_nonce {
|
||||||
|
// Key content nonce
|
||||||
|
let mut noncedata = Vec::with_capacity(data.len() + PUBLIC_KEY_LENGTH);
|
||||||
|
noncedata.extend_from_slice(data);
|
||||||
|
noncedata.extend_from_slice(&ei.key.bytes);
|
||||||
|
let noncehash = ei.vcrypto.generate_hash(&noncedata);
|
||||||
|
out[0..NONCE_LENGTH].copy_from_slice(&noncehash[0..NONCE_LENGTH])
|
||||||
|
} else {
|
||||||
|
// Random nonce
|
||||||
random_bytes(&mut out[0..NONCE_LENGTH]);
|
random_bytes(&mut out[0..NONCE_LENGTH]);
|
||||||
|
}
|
||||||
|
|
||||||
let (nonce, encout) = out.split_at_mut(NONCE_LENGTH);
|
let (nonce, encout) = out.split_at_mut(NONCE_LENGTH);
|
||||||
ei.vcrypto.crypt_b2b_no_auth(
|
ei.vcrypto.crypt_b2b_no_auth(
|
||||||
@ -133,8 +145,8 @@ impl TableDB {
|
|||||||
pub async fn get_keys(&self, col: u32) -> VeilidAPIResult<Vec<Vec<u8>>> {
|
pub async fn get_keys(&self, col: u32) -> VeilidAPIResult<Vec<Vec<u8>>> {
|
||||||
let db = self.unlocked_inner.database.clone();
|
let db = self.unlocked_inner.database.clone();
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
db.iter(col, None, |kv| {
|
db.iter_keys(col, None, |k| {
|
||||||
out.push(self.maybe_decrypt(&kv.0));
|
out.push(self.maybe_decrypt(k));
|
||||||
Ok(Option::<()>::None)
|
Ok(Option::<()>::None)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@ -152,7 +164,11 @@ impl TableDB {
|
|||||||
pub async fn store(&self, col: u32, key: &[u8], value: &[u8]) -> VeilidAPIResult<()> {
|
pub async fn store(&self, col: u32, key: &[u8], value: &[u8]) -> VeilidAPIResult<()> {
|
||||||
let db = self.unlocked_inner.database.clone();
|
let db = self.unlocked_inner.database.clone();
|
||||||
let mut dbt = db.transaction();
|
let mut dbt = db.transaction();
|
||||||
dbt.put(col, self.maybe_encrypt(key), self.maybe_encrypt(value));
|
dbt.put(
|
||||||
|
col,
|
||||||
|
self.maybe_encrypt(key, true),
|
||||||
|
self.maybe_encrypt(value, false),
|
||||||
|
);
|
||||||
db.write(dbt).await.map_err(VeilidAPIError::generic)
|
db.write(dbt).await.map_err(VeilidAPIError::generic)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,16 +177,8 @@ impl TableDB {
|
|||||||
where
|
where
|
||||||
T: RkyvSerialize<DefaultVeilidRkyvSerializer>,
|
T: RkyvSerialize<DefaultVeilidRkyvSerializer>,
|
||||||
{
|
{
|
||||||
let v = to_rkyv(value)?;
|
let value = to_rkyv(value)?;
|
||||||
|
self.store(col, key, &value).await
|
||||||
let db = self.unlocked_inner.database.clone();
|
|
||||||
let mut dbt = db.transaction();
|
|
||||||
dbt.put(
|
|
||||||
col,
|
|
||||||
self.maybe_encrypt(key),
|
|
||||||
self.maybe_encrypt(v.as_slice()),
|
|
||||||
);
|
|
||||||
db.write(dbt).await.map_err(VeilidAPIError::generic)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Store a key in json format with a value in a column in the TableDB. Performs a single transaction immediately.
|
/// Store a key in json format with a value in a column in the TableDB. Performs a single transaction immediately.
|
||||||
@ -178,24 +186,16 @@ impl TableDB {
|
|||||||
where
|
where
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
{
|
{
|
||||||
let v = serde_json::to_vec(value).map_err(VeilidAPIError::internal)?;
|
let value = serde_json::to_vec(value).map_err(VeilidAPIError::internal)?;
|
||||||
|
self.store(col, key, &value).await
|
||||||
let db = self.unlocked_inner.database.clone();
|
|
||||||
let mut dbt = db.transaction();
|
|
||||||
dbt.put(
|
|
||||||
col,
|
|
||||||
self.maybe_encrypt(key),
|
|
||||||
self.maybe_encrypt(v.as_slice()),
|
|
||||||
);
|
|
||||||
db.write(dbt).await.map_err(VeilidAPIError::generic)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a key from a column in the TableDB immediately.
|
/// Read a key from a column in the TableDB immediately.
|
||||||
pub async fn load(&self, col: u32, key: &[u8]) -> VeilidAPIResult<Option<Vec<u8>>> {
|
pub async fn load(&self, col: u32, key: &[u8]) -> VeilidAPIResult<Option<Vec<u8>>> {
|
||||||
let db = self.unlocked_inner.database.clone();
|
let db = self.unlocked_inner.database.clone();
|
||||||
let ekey = self.maybe_encrypt(key);
|
let key = self.maybe_encrypt(key, true);
|
||||||
Ok(db
|
Ok(db
|
||||||
.get(col, &ekey)
|
.get(col, &key)
|
||||||
.await
|
.await
|
||||||
.map_err(VeilidAPIError::from)?
|
.map_err(VeilidAPIError::from)?
|
||||||
.map(|v| self.maybe_decrypt(&v)))
|
.map(|v| self.maybe_decrypt(&v)))
|
||||||
@ -209,9 +209,7 @@ impl TableDB {
|
|||||||
for<'t> CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
|
for<'t> CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
|
||||||
<T as RkyvArchive>::Archived: RkyvDeserialize<T, VeilidSharedDeserializeMap>,
|
<T as RkyvArchive>::Archived: RkyvDeserialize<T, VeilidSharedDeserializeMap>,
|
||||||
{
|
{
|
||||||
let ekey = self.maybe_encrypt(key);
|
let out = match self.load(col, key).await? {
|
||||||
|
|
||||||
let out = match self.load(col, &ekey).await?.map(|v| self.maybe_decrypt(&v)) {
|
|
||||||
Some(v) => Some(from_rkyv(v)?),
|
Some(v) => Some(from_rkyv(v)?),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
@ -223,9 +221,7 @@ impl TableDB {
|
|||||||
where
|
where
|
||||||
T: for<'de> serde::Deserialize<'de>,
|
T: for<'de> serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
let ekey = self.maybe_encrypt(key);
|
let out = match self.load(col, key).await? {
|
||||||
|
|
||||||
let out = match self.load(col, &ekey).await?.map(|v| self.maybe_decrypt(&v)) {
|
|
||||||
Some(v) => Some(serde_json::from_slice(&v).map_err(VeilidAPIError::internal)?),
|
Some(v) => Some(serde_json::from_slice(&v).map_err(VeilidAPIError::internal)?),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
@ -234,11 +230,11 @@ impl TableDB {
|
|||||||
|
|
||||||
/// Delete key with from a column in the TableDB
|
/// Delete key with from a column in the TableDB
|
||||||
pub async fn delete(&self, col: u32, key: &[u8]) -> VeilidAPIResult<Option<Vec<u8>>> {
|
pub async fn delete(&self, col: u32, key: &[u8]) -> VeilidAPIResult<Option<Vec<u8>>> {
|
||||||
let ekey = self.maybe_encrypt(key);
|
let key = self.maybe_encrypt(key, true);
|
||||||
|
|
||||||
let db = self.unlocked_inner.database.clone();
|
let db = self.unlocked_inner.database.clone();
|
||||||
let old_value = db
|
let old_value = db
|
||||||
.delete(col, &ekey)
|
.delete(col, &key)
|
||||||
.await
|
.await
|
||||||
.map_err(VeilidAPIError::from)?
|
.map_err(VeilidAPIError::from)?
|
||||||
.map(|v| self.maybe_decrypt(&v));
|
.map(|v| self.maybe_decrypt(&v));
|
||||||
@ -253,15 +249,7 @@ impl TableDB {
|
|||||||
for<'t> CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
|
for<'t> CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
|
||||||
<T as RkyvArchive>::Archived: RkyvDeserialize<T, VeilidSharedDeserializeMap>,
|
<T as RkyvArchive>::Archived: RkyvDeserialize<T, VeilidSharedDeserializeMap>,
|
||||||
{
|
{
|
||||||
let ekey = self.maybe_encrypt(key);
|
let old_value = match self.delete(col, key).await? {
|
||||||
|
|
||||||
let db = self.unlocked_inner.database.clone();
|
|
||||||
let old_value = match db
|
|
||||||
.delete(col, &ekey)
|
|
||||||
.await
|
|
||||||
.map_err(VeilidAPIError::from)?
|
|
||||||
.map(|v| self.maybe_decrypt(&v))
|
|
||||||
{
|
|
||||||
Some(v) => Some(from_rkyv(v)?),
|
Some(v) => Some(from_rkyv(v)?),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
@ -273,29 +261,12 @@ impl TableDB {
|
|||||||
where
|
where
|
||||||
T: for<'de> serde::Deserialize<'de>,
|
T: for<'de> serde::Deserialize<'de>,
|
||||||
{
|
{
|
||||||
let ekey = self.maybe_encrypt(key);
|
let old_value = match self.delete(col, key).await? {
|
||||||
|
|
||||||
let db = self.unlocked_inner.database.clone();
|
|
||||||
let old_value = match db
|
|
||||||
.delete(col, &ekey)
|
|
||||||
.await
|
|
||||||
.map_err(VeilidAPIError::from)?
|
|
||||||
.map(|v| self.maybe_decrypt(&v))
|
|
||||||
{
|
|
||||||
Some(v) => Some(serde_json::from_slice(&v).map_err(VeilidAPIError::internal)?),
|
Some(v) => Some(serde_json::from_slice(&v).map_err(VeilidAPIError::internal)?),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
Ok(old_value)
|
Ok(old_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform commit
|
|
||||||
async fn do_commit(&self, dbt: TableDBTransaction) -> VeilidAPIResult<()> {
|
|
||||||
let db = self.unlocked_inner.database.clone();
|
|
||||||
xxx translate transaction to encrypt
|
|
||||||
db.write(dbt)
|
|
||||||
.await
|
|
||||||
.map_err(|e| VeilidAPIError::generic(format!("commit failed, transaction lost: {}", e)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -342,7 +313,11 @@ impl TableDBTransaction {
|
|||||||
.take()
|
.take()
|
||||||
.ok_or_else(|| VeilidAPIError::generic("transaction already completed"))?
|
.ok_or_else(|| VeilidAPIError::generic("transaction already completed"))?
|
||||||
};
|
};
|
||||||
self.db.do_commit(dbt).await
|
|
||||||
|
let db = self.db.unlocked_inner.database.clone();
|
||||||
|
db.write(dbt)
|
||||||
|
.await
|
||||||
|
.map_err(|e| VeilidAPIError::generic(format!("commit failed, transaction lost: {}", e)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rollback the transaction. Does nothing to the TableDB.
|
/// Rollback the transaction. Does nothing to the TableDB.
|
||||||
@ -353,8 +328,10 @@ impl TableDBTransaction {
|
|||||||
|
|
||||||
/// Store a key with a value in a column in the TableDB
|
/// Store a key with a value in a column in the TableDB
|
||||||
pub fn store(&self, col: u32, key: &[u8], value: &[u8]) {
|
pub fn store(&self, col: u32, key: &[u8], value: &[u8]) {
|
||||||
|
let key = self.db.maybe_encrypt(key, true);
|
||||||
|
let value = self.db.maybe_encrypt(value, false);
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.dbt.as_mut().unwrap().put(col, key, value);
|
inner.dbt.as_mut().unwrap().put_owned(col, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Store a key in rkyv format with a value in a column in the TableDB
|
/// Store a key in rkyv format with a value in a column in the TableDB
|
||||||
@ -362,9 +339,12 @@ impl TableDBTransaction {
|
|||||||
where
|
where
|
||||||
T: RkyvSerialize<DefaultVeilidRkyvSerializer>,
|
T: RkyvSerialize<DefaultVeilidRkyvSerializer>,
|
||||||
{
|
{
|
||||||
let v = to_rkyv(value)?;
|
let value = to_rkyv(value)?;
|
||||||
|
let key = self.db.maybe_encrypt(key, true);
|
||||||
|
let value = self.db.maybe_encrypt(&value, false);
|
||||||
|
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.dbt.as_mut().unwrap().put(col, key, v.as_slice());
|
inner.dbt.as_mut().unwrap().put_owned(col, key, value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,16 +353,20 @@ impl TableDBTransaction {
|
|||||||
where
|
where
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
{
|
{
|
||||||
let v = serde_json::to_vec(value).map_err(VeilidAPIError::internal)?;
|
let value = serde_json::to_vec(value).map_err(VeilidAPIError::internal)?;
|
||||||
|
let key = self.db.maybe_encrypt(key, true);
|
||||||
|
let value = self.db.maybe_encrypt(&value, false);
|
||||||
|
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.dbt.as_mut().unwrap().put(col, key, v.as_slice());
|
inner.dbt.as_mut().unwrap().put_owned(col, key, value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete key with from a column in the TableDB
|
/// Delete key with from a column in the TableDB
|
||||||
pub fn delete(&self, col: u32, key: &[u8]) {
|
pub fn delete(&self, col: u32, key: &[u8]) {
|
||||||
|
let key = self.db.maybe_encrypt(key, true);
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
inner.dbt.as_mut().unwrap().delete(col, key);
|
inner.dbt.as_mut().unwrap().delete_owned(col, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user