Explorar o código

Started wireframing the crypto module.

Matthew Carr %!s(int64=2) %!d(string=hai) anos
pai
achega
fac63e325c
Modificáronse 4 ficheiros con 65 adicións e 17 borrados
  1. 1 1
      README.md
  2. 37 0
      crates/node/src/crypto.rs
  3. 13 6
      crates/node/src/main.rs
  4. 14 10
      crates/node/src/serde_tests.rs

+ 1 - 1
README.md

@@ -3,7 +3,7 @@ In broad strokes, theses are the phases of development.
 
 
 ## Phase 1: Foundations
 ## Phase 1: Foundations
 * Definition of the main data types.
 * Definition of the main data types.
-* Definition of the binary format used to serialize all data structures.
+* Definition of the binary format used to serialize all data structures. (Done 2022/04/14)
 * Creation of a cryptographic abstraction layer which will defer to openssl for the time being.
 * Creation of a cryptographic abstraction layer which will defer to openssl for the time being.
 This module will include type definitions for hashes, keys and signatures. It will define
 This module will include type definitions for hashes, keys and signatures. It will define
 functions for:
 functions for:

+ 37 - 0
crates/node/src/crypto.rs

@@ -0,0 +1,37 @@
+/// Functions for performing cryptographic operations on the main data structures.
+
+use super::*;
+
+/// Errors that can occur during cryptographic operations.
+pub(crate) enum Error {
+    NoReadCap
+}
+
+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 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(()),
+        Cryptotext::Cipher(body) => body
+    };
+    let read_cap = block.read_caps.get(principal).ok_or(Error::NoReadCap)?;
+    let block_key = decrypt(read_cap, key)?;
+    decrypt_in_place(body, &block_key)?;
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+}

+ 13 - 6
crates/node/src/main.rs

@@ -10,6 +10,8 @@ use serde_big_array::BigArray;
 #[cfg(test)]
 #[cfg(test)]
 mod serde_tests;
 mod serde_tests;
 
 
+mod crypto;
+
 /// A Block tagged with its version number.
 /// A Block tagged with its version number.
 #[allow(dead_code)]
 #[allow(dead_code)]
 #[derive(Debug, PartialEq, Serialize, Deserialize)]
 #[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -26,13 +28,13 @@ struct Block {
     path: Path,
     path: Path,
     /// This field contains a collection of `ReadCap`s indexed by the principal who holds them.
     /// This field contains a collection of `ReadCap`s indexed by the principal who holds them.
     /// `ReadCap`s are envelopments of the key used to encrypt this block.
     /// `ReadCap`s are envelopments of the key used to encrypt this block.
-    read_caps: HashMap<Principal, Ciphertext<Key>>,
+    read_caps: HashMap<Principal, Cryptotext<Key>>,
     /// This field is used to verify that the signer of this block had permission to write it.
     /// This field is used to verify that the signer of this block had permission to write it.
     /// It contains a certificate chain that must lead back to the root key for the tree this block
     /// It contains a certificate chain that must lead back to the root key for the tree this block
     /// is part of.
     /// is part of.
     write_cap: WriteCap,
     write_cap: WriteCap,
     /// The encrypted data contained in this block.
     /// The encrypted data contained in this block.
-    body: Ciphertext<Vec<u8>>,
+    body: Cryptotext<Vec<u8>>,
     /// The contents of the block are covered by a digital signature contained in this field.  
     /// The contents of the block are covered by a digital signature contained in this field.  
     signature: Signature
     signature: Signature
 }
 }
@@ -44,7 +46,7 @@ struct ReadCap {
     /// The principal this `ReadCap` was issued to.
     /// The principal this `ReadCap` was issued to.
     issued_to: Principal,
     issued_to: Principal,
     /// An encipherment of a block key using the public key of the principal.
     /// An encipherment of a block key using the public key of the principal.
-    key: Ciphertext<Key>,
+    key: Cryptotext<Key>,
 }
 }
 
 
 /// Verifies that a principal is authorized to write blocks in a tree.
 /// Verifies that a principal is authorized to write blocks in a tree.
@@ -102,9 +104,14 @@ struct FragmentRecord {
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hashable)]
 #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hashable)]
 struct Principal(Hash);
 struct Principal(Hash);
 
 
-/// Encrypted data.
+/// Data that may or may not be encrypted.
 #[derive(Debug, PartialEq, Serialize, Deserialize)]
 #[derive(Debug, PartialEq, Serialize, Deserialize)]
-struct Ciphertext<T>(T);
+enum Cryptotext<T> {
+    /// The inner value of `T` is in plaintext.
+    Plain(T),
+    /// The inner value of `T` is in ciphertext.
+    Cipher(T),
+}
 
 
 /// An identifier for a block in a tree.
 /// An identifier for a block in a tree.
 #[derive(Debug, PartialEq, Serialize, Deserialize)]
 #[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -159,7 +166,7 @@ fn main() {
 
 
 impl ReadCap {
 impl ReadCap {
     #[allow(dead_code)]
     #[allow(dead_code)]
-    fn new(issued_to: Hash, key: Ciphertext<Key>) -> ReadCap {
+    fn new(issued_to: Hash, key: Cryptotext<Key>) -> ReadCap {
         ReadCap { issued_to: Principal(issued_to), key }
         ReadCap { issued_to: Principal(issued_to), key }
     }
     }
 }
 }

+ 14 - 10
crates/node/src/serde_tests.rs

@@ -96,7 +96,7 @@ fn roundtrip_write_cap() -> Result<()> {
 }
 }
 
 
 fn make_read_cap() -> ReadCap {
 fn make_read_cap() -> ReadCap {
-    ReadCap::new(Hash::Sha2_256(PRINCIPAL), Ciphertext(Key::Xsalsa20Poly1305(KEY)))
+    ReadCap::new(Hash::Sha2_256(PRINCIPAL), Cryptotext::Plain(Key::Xsalsa20Poly1305(KEY)))
 }
 }
 
 
 #[test]
 #[test]
@@ -108,21 +108,25 @@ fn roundtrip_read_cap() -> Result<()> {
     Ok(())
     Ok(())
 }
 }
 
 
-#[test]
-fn roundtrip_versioned_block() -> Result<()> {
+fn make_block() -> Result<Block> {
     let mut read_caps = HashMap::new();
     let mut read_caps = HashMap::new();
     {
     {
         let read_cap = make_read_cap();
         let read_cap = make_read_cap();
         read_caps.insert(read_cap.issued_to, read_cap.key);
         read_caps.insert(read_cap.issued_to, read_cap.key);
     }
     }
     let write_cap = make_write_cap()?;
     let write_cap = make_write_cap()?;
-    let expected = VersionedBlock::V0(Block {
-        path: Path::try_from("apps/verse").map_err(|err| Error::Message(err.to_string()))?,
-        read_caps,
-        write_cap,
-        body: Ciphertext(Vec::from(PAYLOAD)),
-        signature: Signature::Ed25519(SIGNATURE)
-    });
+    Ok(Block {
+            path: Path::try_from("apps/verse").map_err(|err| Error::Message(err.to_string()))?,
+            read_caps,
+            write_cap,
+            body: Cryptotext::Plain(Vec::from(PAYLOAD)),
+            signature: Signature::Ed25519(SIGNATURE)
+    })
+}
+
+#[test]
+fn roundtrip_versioned_block() -> Result<()> {
+    let expected = VersionedBlock::V0(make_block()?);
     let ser_result = to_vec(&expected);
     let ser_result = to_vec(&expected);
     let de_result = from_vec(&ser_result?);
     let de_result = from_vec(&ser_result?);
     assert_eq!(expected, de_result?);
     assert_eq!(expected, de_result?);