Skip to content

Commit

Permalink
add index
Browse files Browse the repository at this point in the history
  • Loading branch information
tbrezot committed Jun 18, 2024
1 parent 87f820d commit a214356
Show file tree
Hide file tree
Showing 7 changed files with 289 additions and 122 deletions.
12 changes: 6 additions & 6 deletions src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ impl<const LENGTH: usize> DerefMut for Address<LENGTH> {
}
}

impl<const LENGTH: usize> Default for Address<LENGTH> {
fn default() -> Self {
Self([0; LENGTH])
}
}

impl<const LENGTH: usize> Address<LENGTH> {
pub fn random(rng: &mut impl CryptoRngCore) -> Self {
let mut res = Self([0; LENGTH]);
Expand All @@ -38,14 +44,8 @@ impl<const LENGTH: usize> Add<u64> for Address<LENGTH> {
// add bytes
let lhs = &mut self[pos % LENGTH];
let rhs = adder % 256;

let res = *lhs as i32 + rhs as i32 + carry;

println!(
"(pos, lhs, rhs, carry, res) = {:?}",
(pos, *lhs, (rhs % 256), carry, res)
);

// update states
*lhs = (res % 256) as u8;
carry = res >> 8;
Expand Down
115 changes: 115 additions & 0 deletions src/findex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use std::{
collections::{HashMap, HashSet},
hash::Hash,
sync::{Arc, Mutex},
};

use cosmian_crypto_core::{kdf128, CsRng, Secret};

use crate::{
error::Error, obf::EncryptionLayer, ovec::OVec, Address, Index, Stm, ADDRESS_LENGTH, KEY_LENGTH,
};

pub struct Findex<'a, Memory: 'a + Stm<Address = Address<ADDRESS_LENGTH>, Word = Vec<u8>>> {
el: EncryptionLayer<Memory>,
vectors: Mutex<HashMap<Address<ADDRESS_LENGTH>, OVec<'a, EncryptionLayer<Memory>>>>,
}

impl<'a, Memory: 'a + Stm<Address = Address<ADDRESS_LENGTH>, Word = Vec<u8>>> Findex<'a, Memory> {
pub fn new(seed: Secret<KEY_LENGTH>, rng: Arc<Mutex<CsRng>>, stm: Memory) -> Self {
Self {
el: EncryptionLayer::new(seed, rng, stm),
vectors: Mutex::new(HashMap::new()),
}
}
}

impl<
'a,
Keyword: Hash + PartialEq + Eq + AsRef<[u8]>,
Value: Hash + PartialEq + Eq + From<Vec<u8>>,
Memory: 'a + Stm<Address = Address<ADDRESS_LENGTH>, Word = Vec<u8>>,
> Index<'a, Keyword, Value> for Findex<'a, Memory>
where
for<'z> Vec<u8>: From<&'z Value>,
{
type Error = Error<Address<ADDRESS_LENGTH>, <EncryptionLayer<Memory> as Stm>::Error>;

fn search(
&'a self,
keywords: impl Iterator<Item = Keyword>,
) -> Result<HashMap<Keyword, HashSet<Value>>, Self::Error> {
keywords
.map(|kw| {
let mut a = Address::<ADDRESS_LENGTH>::default();
kdf128!(&mut a, kw.as_ref());
let mut vectors = self.vectors.lock().expect("poisoned mutex");
let vector = vectors
.entry(a.clone())
.or_insert_with(|| OVec::<'a, EncryptionLayer<Memory>>::new(a, &self.el));
let links = vector.read()?;
Ok((
kw,
links.into_iter().map(Value::from).collect::<HashSet<_>>(),
))
})
.collect()
}

fn insert(
&'a self,
bindings: impl Iterator<Item = (Keyword, HashSet<Value>)>,
) -> Result<(), Self::Error> {
bindings
.map(|(kw, vals)| {
let mut a = Address::<ADDRESS_LENGTH>::default();
kdf128!(&mut a, kw.as_ref());
let mut vectors = self.vectors.lock().expect("poisoned mutex");
let vector = vectors
.entry(a.clone())
.or_insert_with(|| OVec::<'a, EncryptionLayer<Memory>>::new(a, &self.el));
vector.push(vals.iter().map(<Vec<u8>>::from).collect::<Vec<_>>())
})
.collect::<Result<Vec<_>, _>>()?;
Ok(())
}

fn delete(
_bindings: impl Iterator<Item = (Keyword, HashSet<Value>)>,
) -> Result<(), Self::Error> {
todo!()
}
}

#[cfg(test)]
mod tests {
use std::{
collections::{HashMap, HashSet},
sync::{Arc, Mutex},
};

use cosmian_crypto_core::{reexport::rand_core::SeedableRng, CsRng, Secret};

use crate::{address::Address, kv::KvStore, Findex, Index, Value, ADDRESS_LENGTH};

#[test]
fn test_insert_search() {
let mut rng = CsRng::from_entropy();
let seed = Secret::random(&mut rng);
let kv = KvStore::<Address<ADDRESS_LENGTH>, Vec<u8>>::default();
let findex = Findex::new(seed, Arc::new(Mutex::new(rng)), kv);
let bindings = HashMap::<&str, HashSet<Value>>::from_iter([
(
"cat",
HashSet::from_iter([Value::from(1), Value::from(3), Value::from(5)]),
),
(
"dog",
HashSet::from_iter([Value::from(0), Value::from(2), Value::from(4)]),
),
]);
findex.insert(bindings.clone().into_iter()).unwrap();
let res = findex.search(bindings.keys().cloned()).unwrap();
assert_eq!(bindings, res);
}
}
11 changes: 3 additions & 8 deletions src/kv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,9 @@ impl Display for MemoryError {

impl std::error::Error for MemoryError {}

#[derive(Clone, Debug, Default)]
pub struct KvStore<Address: Hash + Eq, Value>(Arc<Mutex<HashMap<Address, Value>>>);

impl<Address: Hash + Eq, Value: Clone + Eq> KvStore<Address, Value> {
pub fn new() -> Self {
Self(Arc::new(Mutex::new(HashMap::new())))
}
}

impl<Address: Hash + Eq + Debug, Value: Clone + Eq + Debug> Stm for KvStore<Address, Value> {
type Address = Address;

Expand Down Expand Up @@ -64,7 +59,7 @@ impl<Address: Hash + Eq + Debug, Value: Clone + Eq + Debug> Stm for KvStore<Addr
mod tests {
use std::collections::HashMap;

use crate::stm::Stm;
use crate::Stm;

use super::KvStore;

Expand All @@ -73,7 +68,7 @@ mod tests {
/// - using the wrong value in the guard fails the operation and returns the current value.
#[test]
fn test_vector_push() {
let kv = KvStore::<u8, u8>::new();
let kv = KvStore::<u8, u8>::default();

assert_eq!(
kv.guarded_write((0, None), vec![(0, 2), (1, 1), (2, 1)])
Expand Down
33 changes: 32 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
#![allow(dead_code)]
#![allow(clippy::type_complexity)]

mod address;
mod error;
mod findex;
mod kv;
mod obf;
mod ovec;
mod stm;
mod value;

use std::{
collections::{HashMap, HashSet},
hash::Hash,
};

pub use address::Address;
pub use findex::Findex;
pub use kv::KvStore;
pub use stm::Stm;
pub use value::Value;

pub const ADDRESS_LENGTH: usize = 16;
pub const KEY_LENGTH: usize = 32;

/// An index can insert and delete bindings, and search keywords.
pub trait Index<'a, Keyword: Hash, Value: Hash> {
type Error: std::error::Error;

fn search(
&'a self,
keywords: impl Iterator<Item = Keyword>,
) -> Result<HashMap<Keyword, HashSet<Value>>, Self::Error>;

fn insert(
&'a self,
bindings: impl Iterator<Item = (Keyword, HashSet<Value>)>,
) -> Result<(), Self::Error>;

fn delete(bindings: impl Iterator<Item = (Keyword, HashSet<Value>)>)
-> Result<(), Self::Error>;
}
38 changes: 19 additions & 19 deletions src/obf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use std::{
cmp::Ordering,
collections::{HashMap, HashSet},
ops::DerefMut,
sync::{Mutex, MutexGuard},
sync::{Arc, Mutex, MutexGuard},
};

use crate::{address::Address, error::Error, Stm};
use crate::{address::Address, error::Error, Stm, ADDRESS_LENGTH, KEY_LENGTH};
use aes::{
cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit},
Aes256,
Expand All @@ -15,26 +15,23 @@ use cosmian_crypto_core::{
RandomFixedSizeCBytes, Secret, SymmetricKey,
};

const ADDRESS_LENGTH: usize = 16;
const KEY_LENGTH: usize = 32;

pub struct ObfuscationLayer<Memory: Stm<Address = Address<ADDRESS_LENGTH>, Word = Vec<u8>>> {
pub struct EncryptionLayer<Memory: Stm<Address = Address<ADDRESS_LENGTH>, Word = Vec<u8>>> {
permutation_key: SymmetricKey<KEY_LENGTH>,
encryption_key: SymmetricKey<32>,
cache: Mutex<HashMap<(Address<ADDRESS_LENGTH>, Vec<u8>), Vec<u8>>>,
rng: Mutex<CsRng>,
cache: Arc<Mutex<HashMap<(Address<ADDRESS_LENGTH>, Vec<u8>), Vec<u8>>>>,
rng: Arc<Mutex<CsRng>>,
stm: Memory,
}

impl<Memory: Stm<Address = Address<ADDRESS_LENGTH>, Word = Vec<u8>>> ObfuscationLayer<Memory> {
pub fn new(seed: Secret<KEY_LENGTH>, rng: CsRng, stm: Memory) -> Self {
impl<Memory: Stm<Address = Address<ADDRESS_LENGTH>, Word = Vec<u8>>> EncryptionLayer<Memory> {
pub fn new(seed: Secret<KEY_LENGTH>, rng: Arc<Mutex<CsRng>>, stm: Memory) -> Self {
let permutation_key = SymmetricKey::derive(&seed, &[0]).expect("secret is large enough");
let encryption_key = SymmetricKey::derive(&seed, &[0]).expect("secret is large enough");
Self {
permutation_key,
encryption_key,
cache: Mutex::new(HashMap::new()),
rng: Mutex::new(rng),
cache: Arc::new(Mutex::new(HashMap::new())),
rng,
stm,
}
}
Expand Down Expand Up @@ -135,7 +132,7 @@ impl<Memory: Stm<Address = Address<ADDRESS_LENGTH>, Word = Vec<u8>>> Obfuscation
impl<
Memory: Stm<Address = Address<ADDRESS_LENGTH>, Word = Vec<u8>>, // use a `Vec<u8>` because `const` generics
// are not allowed in `const` operations
> Stm for ObfuscationLayer<Memory>
> Stm for EncryptionLayer<Memory>
{
type Address = Address<ADDRESS_LENGTH>;

Expand Down Expand Up @@ -195,23 +192,26 @@ impl<

#[cfg(test)]
mod tests {
use std::collections::HashSet;
use std::{
collections::HashSet,
sync::{Arc, Mutex},
};

use cosmian_crypto_core::{reexport::rand_core::SeedableRng, CsRng, Secret};

use crate::{
address::Address,
kv::KvStore,
obf::{ObfuscationLayer, ADDRESS_LENGTH},
obf::{EncryptionLayer, ADDRESS_LENGTH},
stm::Stm,
};

#[test]
fn test_encrypt_decrypt() {
let mut rng = CsRng::from_entropy();
let seed = Secret::random(&mut rng);
let kv = KvStore::<Address<ADDRESS_LENGTH>, Vec<u8>>::new();
let obf = ObfuscationLayer::new(seed, rng.clone(), kv);
let kv = KvStore::<Address<ADDRESS_LENGTH>, Vec<u8>>::default();
let obf = EncryptionLayer::new(seed, Arc::new(Mutex::new(rng.clone())), kv);
let tok = Address::<ADDRESS_LENGTH>::random(&mut rng);
let ptx = vec![1];
let ctx = obf.encrypt(&ptx, &tok).unwrap();
Expand All @@ -227,8 +227,8 @@ mod tests {
fn test_vector_push() {
let mut rng = CsRng::from_entropy();
let seed = Secret::random(&mut rng);
let kv = KvStore::<Address<ADDRESS_LENGTH>, Vec<u8>>::new();
let obf = ObfuscationLayer::new(seed, rng.clone(), kv);
let kv = KvStore::<Address<ADDRESS_LENGTH>, Vec<u8>>::default();
let obf = EncryptionLayer::new(seed, Arc::new(Mutex::new(rng.clone())), kv);

let header_addr = Address::<ADDRESS_LENGTH>::random(&mut rng);

Expand Down
Loading

0 comments on commit a214356

Please sign in to comment.