Browse Source

Created a wireframe for block encryption.

Matthew Carr 2 years ago
parent
commit
51190904db
3 changed files with 77 additions and 15 deletions
  1. 1 0
      crates/node/.vscode/settings.json
  2. 49 14
      crates/node/src/crypto.rs
  3. 27 1
      crates/node/src/main.rs

+ 1 - 0
crates/node/.vscode/settings.json

@@ -3,6 +3,7 @@
         "Asym",
         "blocktree",
         "bodhi",
+        "Cryptotext",
         "Hashable",
         "newtype",
         "Xsalsa"

+ 49 - 14
crates/node/src/crypto.rs

@@ -9,27 +9,62 @@ pub(crate) enum Error {
 
 type Result<T> = std::result::Result<T, Error>;
 
-fn decrypt<T>(_ciphertext: &Cryptotext<T>, _key: &Key) -> Result<T> {
-    unimplemented!();
-}
-
-fn decrypt_in_place(_ciphertext: &mut [u8], _key: &Key) -> Result<()> {
-    unimplemented!();
+#[allow(dead_code)]
+pub(crate) fn encrypt_block(
+    versioned_block: VersionedBlock, principal: &Principal, key: &Key
+) -> Result<VersionedBlock> {
+    let VersionedBlock::V0(mut block) = versioned_block;
+    let mut body = match block.body {
+        Cryptotext::Cipher(_) => return Ok(VersionedBlock::V0(block)),
+        Cryptotext::Plain(body) => body
+    };
+    let (principal_owned, read_cap) = block.read_caps.remove_entry(principal)
+        .ok_or(Error::NoReadCap)?;
+    let block_key = decrypt(read_cap, key)?;
+    encrypt_in_place(&mut body, &block_key)?;
+    block.body = Cryptotext::Cipher(body);
+    block.read_caps.insert(principal_owned, encrypt(block_key, key)?);
+    Ok(VersionedBlock::V0(block))
 }
 
 #[allow(dead_code)]
 pub(crate) fn decrypt_block(
-    versioned_block: &mut VersionedBlock, principal: &Principal, key: &Key
-) -> Result<()> {
-    let VersionedBlock::V0(block) = versioned_block;
-    let body = match &mut block.body {
-        Cryptotext::Plain(_) => return Ok(()),
+    versioned_block: VersionedBlock, principal: &Principal, key: &Key
+) -> Result<VersionedBlock> {
+    let VersionedBlock::V0(mut block) = versioned_block;
+    let mut body = match block.body {
+        Cryptotext::Plain(_) => return Ok(VersionedBlock::V0(block)),
         Cryptotext::Cipher(body) => body
     };
-    let read_cap = block.read_caps.get(principal).ok_or(Error::NoReadCap)?;
+    let (principal_owned, read_cap) = block.read_caps.remove_entry(principal)
+        .ok_or(Error::NoReadCap)?;
     let block_key = decrypt(read_cap, key)?;
-    decrypt_in_place(body, &block_key)?;
-    Ok(())
+    decrypt_in_place(&mut body, &block_key)?;
+    block.body = Cryptotext::Plain(body);
+    block.read_caps.insert(principal_owned, Cryptotext::Plain(block_key));
+    Ok(VersionedBlock::V0(block))
+}
+
+fn encrypt<T: AsRef<[u8]> + AsMut<[u8]>>(mut data: T, key: &Key) -> Result<Cryptotext<T>> {
+    encrypt_in_place(data.as_mut(), key)?;
+    Ok(Cryptotext::Cipher(data))
+}
+
+fn decrypt<T: AsRef<[u8]> + AsMut<[u8]>>(cryptotext: Cryptotext<T>, key: &Key) -> Result<T> {
+    let mut data = match cryptotext {
+        Cryptotext::Plain(data) => return Ok(data),
+        Cryptotext::Cipher(data) => data
+    };
+    decrypt_in_place(data.as_mut(), key)?;
+    Ok(data)
+}
+
+fn encrypt_in_place(_plaintext: &mut [u8], _key: &Key) -> Result<()> {
+    unimplemented!();
+}
+
+fn decrypt_in_place(_ciphertext: &mut [u8], _key: &Key) -> Result<()> {
+    unimplemented!();
 }
 
 #[cfg(test)]

+ 27 - 1
crates/node/src/main.rs

@@ -106,7 +106,7 @@ struct Principal(Hash);
 
 /// Data that may or may not be encrypted.
 #[derive(Debug, PartialEq, Serialize, Deserialize)]
-enum Cryptotext<T> {
+enum Cryptotext<T: AsRef<[u8]> + AsMut<[u8]>> {
     /// The inner value of `T` is in plaintext.
     Plain(T),
     /// The inner value of `T` is in ciphertext.
@@ -298,6 +298,32 @@ impl<'s> TryFrom<&'s str> for Path {
     }
 }
 
+impl Key {
+    /// Returns the data in the key as a slice.
+    fn as_slice(&self) -> &[u8] {
+        let Key::Xsalsa20Poly1305(array) = self;
+        array
+    }
+
+    /// Returns the data in the key as a mutable slice.
+    fn as_mut_slice(&mut self) -> &mut [u8] {
+        let Key::Xsalsa20Poly1305(array) = self;
+        array
+    }
+}
+
+impl AsRef<[u8]> for Key {
+    fn as_ref(&self) -> &[u8] {
+        self.as_slice()
+    }
+}
+
+impl AsMut<[u8]> for Key {
+    fn as_mut(&mut self) -> &mut [u8] {
+        self.as_mut_slice()
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;