|
|
@ -1,8 +1,10 @@
|
|
|
|
//! Data structures for the in-memory map.
|
|
|
|
//! Data structures for the in-memory map.
|
|
|
|
use super::*;
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
|
collections::HashMap,
|
|
|
|
collections::HashMap,
|
|
|
|
|
|
|
|
borrow::Cow,
|
|
|
|
|
|
|
|
error,
|
|
|
|
|
|
|
|
fmt,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
use generational_arena::{
|
|
|
|
use generational_arena::{
|
|
|
|
Arena, Index,
|
|
|
|
Arena, Index,
|
|
|
@ -13,16 +15,19 @@ use cryptohelpers::{
|
|
|
|
RsaPublicKey, RsaPrivateKey,
|
|
|
|
RsaPublicKey, RsaPrivateKey,
|
|
|
|
Signature,
|
|
|
|
Signature,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
aes::AesKey,
|
|
|
|
aes::{self, AesKey,},
|
|
|
|
sha256::Sha256Hash,
|
|
|
|
sha256::Sha256Hash,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
use tokio::io::{
|
|
|
|
|
|
|
|
AsyncRead, AsyncWrite,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/// An absolute (nested) index
|
|
|
|
/// An absolute (nested) index
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
|
|
|
pub struct AbsoluteIndex(Vec<Index>);
|
|
|
|
pub struct AbsoluteIndex(Vec<Index>);
|
|
|
|
|
|
|
|
|
|
|
|
/// Possible value types of the data map
|
|
|
|
/// Possible value types of the data map
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
|
|
pub enum Data
|
|
|
|
pub enum Data
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Byte(u8),
|
|
|
|
Byte(u8),
|
|
|
@ -76,13 +81,196 @@ pub enum Data
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// An entry that may or may not be encrypted
|
|
|
|
/// An entry that may or may not be encrypted
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
|
|
pub enum MaybeEncrypted
|
|
|
|
pub enum MaybeEncrypted
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
/// This is an encrypted serialized `Data`.
|
|
|
|
Encrypted(Vec<u8>),
|
|
|
|
Encrypted(Vec<u8>),
|
|
|
|
|
|
|
|
/// An unencrypted `Data`
|
|
|
|
Unencrypted(Data),
|
|
|
|
Unencrypted(Data),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[non_exhaustive]
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
|
|
|
enum EncryptedEntryErrorKind
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
KeyNeeded,
|
|
|
|
|
|
|
|
Decrypt(aes::Error),
|
|
|
|
|
|
|
|
Deserialize(serde_cbor::Error),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Encrypt(aes::Error),
|
|
|
|
|
|
|
|
Serialize(serde_cbor::Error),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Error type returned when performing encryption/decryption operations on `Data` through `MaybeEncrypted`.
|
|
|
|
|
|
|
|
#[non_exhaustive]
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
|
|
|
pub struct EncryptedEntryError(Box<EncryptedEntryErrorKind>);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl EncryptedEntryError
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/// Consume into a nicely readable `eyre::Report`
|
|
|
|
|
|
|
|
pub fn report(self) -> eyre::Report
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let (whe, sug) = match self.0.as_ref() {
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Serialize(_) => ("Object serialisation", "Bad data?"),
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Deserialize(_) => ("Object deserialisation", "Corrupted data?"),
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Decrypt(_) => ("Data decryption", "Bad key?"),
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Encrypt(_) => ("Data encryption" ,"Bad key?"),
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::KeyNeeded => return eyre::Report::from(self)
|
|
|
|
|
|
|
|
.with_suggestion(|| "Try providing a key"),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Err::<std::convert::Infallible, _>(self)
|
|
|
|
|
|
|
|
.with_section(|| whe.header("In operation"))
|
|
|
|
|
|
|
|
.with_warning(|| sug)
|
|
|
|
|
|
|
|
.unwrap_err()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl error::Error for EncryptedEntryError
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
|
|
|
|
|
|
|
Some(match self.0.as_ref() {
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Decrypt(d) => d,
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Deserialize(d) => d,
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Encrypt(d) => d,
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Serialize(d) => d,
|
|
|
|
|
|
|
|
_ => return None,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for EncryptedEntryError
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
match self.0.as_ref() {
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::KeyNeeded => write!(f, "this entry needed a decryption key but none was provided"),
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Decrypt(_) => write!(f, "decryption failed"),
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Deserialize(_) => write!(f, "deserialisation failed"),
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Encrypt(_) => write!(f, "encryption failed"),
|
|
|
|
|
|
|
|
EncryptedEntryErrorKind::Serialize(_) => write!(f, "serialisation failed"),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl From<EncryptedEntryErrorKind> for EncryptedEntryError
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
#[inline] fn from(from: EncryptedEntryErrorKind) -> Self
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Self(Box::new(from))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Encrypt a `Data` entry into this buffer
|
|
|
|
|
|
|
|
async fn encrypt_data_entry<T>(output: &mut T, data: &Data, key: &AesKey) -> Result<usize, EncryptedEntryError>
|
|
|
|
|
|
|
|
where T: ?Sized + AsyncWrite + Unpin
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let bytes = serde_cbor::to_vec(data).map_err(EncryptedEntryErrorKind::Serialize)?;
|
|
|
|
|
|
|
|
Ok(aes::encrypt_stream(key, &mut &bytes[..], output).await.map_err(EncryptedEntryErrorKind::Encrypt)?)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Decrypt an encrypted `Data` entry
|
|
|
|
|
|
|
|
async fn decrypt_data_entry<T: ?Sized>(input: &mut T, key: &AesKey, init_buf: Option<Vec<u8>>) -> Result<Data, EncryptedEntryError>
|
|
|
|
|
|
|
|
where T: AsyncRead + Unpin
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let mut output = init_buf.unwrap_or_default();
|
|
|
|
|
|
|
|
aes::decrypt_stream(key, input, &mut output).await.map_err(EncryptedEntryErrorKind::Decrypt)?;
|
|
|
|
|
|
|
|
Ok(serde_cbor::from_slice(&output[..]).map_err(EncryptedEntryErrorKind::Deserialize)?)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl MaybeEncrypted
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/// Create a new non-encrypted entry
|
|
|
|
|
|
|
|
#[inline(always)] pub const fn new_raw(data: Data) -> Self
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Self::Unencrypted(data)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create a new encrypted entry
|
|
|
|
|
|
|
|
#[inline] pub fn new_encrypted(data: Data, encrypt: &AesKey) -> Result<Self, EncryptedEntryError>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let mut buffer = Vec::new();
|
|
|
|
|
|
|
|
encrypt_data_entry(&mut buffer, &data, encrypt).now_or_never().unwrap()?;
|
|
|
|
|
|
|
|
Ok(Self::Encrypted(buffer))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Is this data entry encrypted
|
|
|
|
|
|
|
|
#[inline] pub fn is_encrypted(&self) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if let MaybeEncrypted::Encrypted(_) = &self {
|
|
|
|
|
|
|
|
true
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Consume into a decrypted data instance
|
|
|
|
|
|
|
|
#[inline] pub fn into_unencrypted(self, key: Option<&AesKey>) -> Result<Self, EncryptedEntryError>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Ok(Self::Unencrypted(self.into_data(key)?))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Make this entry unencrypted
|
|
|
|
|
|
|
|
pub fn make_unencrypted(&mut self, key: Option<&AesKey>) -> Result<(), EncryptedEntryError>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
match self {
|
|
|
|
|
|
|
|
MaybeEncrypted::Encrypted(bytes) => {
|
|
|
|
|
|
|
|
*self = MaybeEncrypted::Unencrypted(decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?);
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
_ => (),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Make this entry encrypted
|
|
|
|
|
|
|
|
pub fn make_encrypted(&mut self, key: Option<&AesKey>) -> Result<(), EncryptedEntryError>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
match self {
|
|
|
|
|
|
|
|
MaybeEncrypted::Unencrypted(data) => {
|
|
|
|
|
|
|
|
let mut buffer = Vec::new();
|
|
|
|
|
|
|
|
encrypt_data_entry(&mut buffer, data, key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?).now_or_never().unwrap()?;
|
|
|
|
|
|
|
|
*self = Self::Encrypted(buffer);
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
_ => (),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Consume into an encrypted data instance
|
|
|
|
|
|
|
|
pub fn into_encrypted(self, key: Option<&AesKey>) -> Result<Self, EncryptedEntryError>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
match self {
|
|
|
|
|
|
|
|
MaybeEncrypted::Unencrypted(data) => Self::new_encrypted(data, key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?),
|
|
|
|
|
|
|
|
_ => Ok(self),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Attempt to get the `Data`, decrypting it if needed.
|
|
|
|
|
|
|
|
pub fn get_data<'a>(&'a self, key: Option<&AesKey>) -> Result<Cow<'a, Data>, EncryptedEntryError>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Ok(match self {
|
|
|
|
|
|
|
|
Self::Unencrypted(data) => Cow::Borrowed(&data),
|
|
|
|
|
|
|
|
Self::Encrypted(bytes) => {
|
|
|
|
|
|
|
|
// decrypt
|
|
|
|
|
|
|
|
Cow::Owned(decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Consume into the data object, decrypting it if needed.
|
|
|
|
|
|
|
|
pub fn into_data(self, key: Option<&AesKey>) -> Result<Data, EncryptedEntryError>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Ok(match self {
|
|
|
|
|
|
|
|
Self::Encrypted(bytes) => {
|
|
|
|
|
|
|
|
decrypt_data_entry(&mut &bytes[..], key.ok_or(EncryptedEntryErrorKind::KeyNeeded)?, Some(Vec::with_capacity(bytes.len()))).now_or_never().unwrap()?
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Self::Unencrypted(data) => data,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bitflags! {
|
|
|
|
bitflags! {
|
|
|
|
/// And additional metadata for values
|
|
|
|
/// And additional metadata for values
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
@ -102,7 +290,7 @@ bitflags! {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Information about a map entry.
|
|
|
|
/// Information about a map entry.
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
|
|
pub struct Info
|
|
|
|
pub struct Info
|
|
|
|
{
|
|
|
|
{
|
|
|
|
alt_name: Option<(String, String)>,
|
|
|
|
alt_name: Option<(String, String)>,
|
|
|
@ -127,17 +315,33 @@ pub struct Info
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// The root data containing map
|
|
|
|
/// The root data containing map
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
pub struct Datamap
|
|
|
|
pub struct Datamap
|
|
|
|
{
|
|
|
|
{
|
|
|
|
data: Arena<Atom>,
|
|
|
|
data: Arena<Atom>,
|
|
|
|
ident: HashMap<Identifier, Index>,
|
|
|
|
ident: HashMap<Identifier, Index>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl PartialEq for Datamap
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fn eq(&self, other: &Self) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
self.ident == other.ident && {
|
|
|
|
|
|
|
|
for (v1, v2) in self.ident.iter().map(|(_, v)| (self.data.get(*v), other.data.get(*v)))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if v1 != v2 {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// A value in a datamap, contains the information about the value and the value itself.
|
|
|
|
/// A value in a datamap, contains the information about the value and the value itself.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// May also contain previous versions of this atom
|
|
|
|
/// May also contain previous versions of this atom
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
|
|
pub struct Atom(MaybeEncrypted, Info, Vec<Atom>);
|
|
|
|
pub struct Atom(MaybeEncrypted, Info, Vec<Atom>);
|
|
|
|
|
|
|
|
|
|
|
|
/// An identifier for an item in a `Datamap`, or an item nested within many `Datamap`s.
|
|
|
|
/// An identifier for an item in a `Datamap`, or an item nested within many `Datamap`s.
|
|
|
|