소스 검색

* Added a new `inherit` field to the Block metadata.
* Fixed issues uncovered in new clippy diagnostics.

Matthew Carr 2 년 전
부모
커밋
ef1d43aa59

+ 77 - 0
TODO.txt

@@ -0,0 +1,77 @@
+# Format: - <task ID>, <task points>, <created by user>, <created on commit>, <finished by user>, <finished on commit>
+
+!- 0, 3, mdcarr941@gmail.com, 2ebb8a
+Fix bug where writing to a block that already has a Writecap in its header using the creds of
+a different node produces an invalid signature (a signature using the creds of the other node).
+
+- 1
+Fix BufSectored so it doesn't have to write to the first sector every flush.
+
+- 2
+Track position and dirty-ness in Trailered.
+
+- 3
+Implement a stream which is both Read and Write and which can transparently compress and decompress
+data written to and read from it.
+
+- 4
+Remove TryCompose?
+
+!- 5, 1, mdcarr941@gmail.com, bd6904, mdcarr941@gmail.com, bd6904
+Move crypto::{encrypt, decrypt} into corresponding {EncrypterExt, DecrypterExt}.
+
+- 6
+Create an enum to eliminate the use of Block trait objects?
+
+- 7
+Add a ser_sign_into method to SignerExt which serializes a value into a provided Vec<u8> and returns
+a signature over this data. Update BlockStream::flush_integ to use this method.
+
+- 8
+Convert all sector sizes to u64 for portability.
+
+- 9
+Create an extension trait for u64 with a method for adding an i64 to it. Use this in
+SecretStream::seek, Trailered::seek and SectoredBuf::seek.
+
+- 10
+Create a struct which digests data written to it before passing it to an underlying Write.
+
+!- 11, 3, mdcarr941@gmail.com, bd6904, mdcarr941@gmail.com, bd6904
+Create a struct called WritecapBody to contain the fields of Writecap which go into the signature
+calculation so that WritecapSigInput is no longer required.
+
+- 12, 8, mdcarr941@gmail.com, 2ebb8a,
+Create a struct for managing the directory used to store blocks in the file system. Design and
+implement an API for creating, opening, moving, copying, deleting and linking blocks. This API must
+be codified by a trait to allow the implementation to be changed in the future.
+
+- 13
+Change the Hash enum so it contains structs for each hash type. Unify these structs with the node
+structs used in the VecMerkleTree.
+
+!- 14, 13, mdcarr941@gmail.com, bd6904
+Refactor btlib so that most of the types are in their own modules. This is
+needed to encourage modularity and weak coupling, as it reduces the amount of code that fields
+and helper functions are visible to.
+
+- 15, 13, mdcarr941@gmail.com, 58d1f6, 
+Create a new crate which implements a FUSE daemon.
+
+- 16, 5, mdcarr941@gmail.com, 866533,
+Add the inherit field, which contains the crypto link from the parent block key to the current
+block key, to the block metadata.
+
+- 17, 13, mdcarr941@gmail.com, 8665339,
+SECURITY: Design and implement a mechanism to protect the keys in block's metadata dictionary from
+being correlated with one another. This mechanism must allow a principal with a readcap to be able
+to find their readcap and to rotate the block and create new readcaps for each of the principals in
+the dictionary, but prevent an attacker from being able to identify when two blocks contains
+readcaps for the same principal.
+
+- 18, 3, mdcarr941@gmail.com, 8665339,
+SECURITY: Remove the path field from BlockMeta. It isn't needed as the block path should be
+independently know by any verified. This will ensure that path names are not stored in cleartext.
+
+- 19, 21, mdcarr941@gmail.com, 8665339,
+Integrate with tokio and add async methods to all of the stream types.

+ 0 - 43
crates/btlib/TODO.txt

@@ -1,43 +0,0 @@
-# Format: - <task ID>, <task points>, <created by user>, <created on commit>, <finished by user>, <finished on commit>
-
-- 1
-Fix BufSectored so it doesn't have to write to the first sector every flush.
-
-- 2
-Track position and dirty-ness in Trailered.
-
-- 3
-Implement a stream which is both Read and Write and which can transparently compress and decompress
-data written to and read from it.
-
-- 4
-Remove TryCompose?
-
-- 6
-Create an enum to eliminate the use of Block trait objects?
-
-- 7
-Add a ser_sign_into method to SignerExt which serializes a value into a provided Vec<u8> and returns
-a signature over this data. Update BlockStream::flush_integ to use this method.
-
-- 8
-Convert all sector sizes to u64 for portability.
-
-- 9
-Create an extension trait for u64 with a method for adding an i64 to it. Use this in
-SecretStream::seek, Trailered::seek and SectoredBuf::seek.
-
-- 10
-Create a struct which digests data written to it before passing it to an underlying Write.
-
-- 12, 8, mdcarr941@gmail.com, 2ebb8a,
-Create a struct for managing the directory used to store blocks in the file system. Design and
-implement an API for creating, opening, moving, copying, deleting and linking blocks. This API must
-be codified by a trait to allow the implementation to be changed in the future.
-
-- 13
-Change the Hash enum so it contains structs for each hash type. Unify these structs with the node
-structs used in the VecMerkleTree.
-
-- 14, 13, mdcarr941@gmail.com, 58d1f6, 
-Create a new crate which implements a FUSE daemon.

+ 0 - 15
crates/btlib/TODONE.txt

@@ -1,15 +0,0 @@
-- 0, 3, mdcarr941@gmail.com, 2ebb8a
-Fix bug where writing to a block that already has a Writecap in its header using the creds of
-a different node produces an invalid signature (a signature using the creds of the other node).
-
-- 14, 13, mdcarr941@gmail.com, bd6904
-Refactor btlib so that most of the types are in their own modules. This is
-needed to encourage modularity and weak coupling, as it reduces the amount of code that fields
-and helper functions are visible to.
-
-- 11, 3, mdcarr941@gmail.com, bd6904, mdcarr941@gmail.com, bd6904
-Create a struct called WritecapBody to contain the fields of Writecap which go into the signature
-calculation so that WritecapSigInput is no longer required.
-
-- 5, 1, mdcarr941@gmail.com, bd6904, mdcarr941@gmail.com, bd6904
-Move crypto::{encrypt, decrypt} into corresponding {EncrypterExt, DecrypterExt}.

+ 2 - 2
crates/btlib/src/block_path.rs

@@ -6,7 +6,7 @@ mod private {
     use std::fmt::Display;
 
     /// An identifier for a block in a tree.
-    #[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
+    #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Default)]
     pub struct BlockPath {
         root: Principal,
         components: Vec<String>,
@@ -154,7 +154,7 @@ mod private {
     }
 
     /// Errors which can occur when converting a string to a `Path`.
-    #[derive(Debug, PartialEq)]
+    #[derive(Debug, PartialEq, Eq)]
     pub enum BlockPathError {
         /// Occurs when the number of bytes in a string is greater than `Path::BYTE_LIMIT`.
         PathTooLong(usize),

+ 12 - 10
crates/btlib/src/crypto/mod.rs

@@ -29,7 +29,7 @@ use std::{marker::PhantomData, num::TryFromIntError, str::FromStr};
 use strum_macros::{Display, EnumDiscriminants, EnumString};
 use zeroize::ZeroizeOnDrop;
 
-#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
+#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
 pub struct Ciphertext<T> {
     data: Vec<u8>,
     phantom: PhantomData<T>,
@@ -335,7 +335,7 @@ impl Display for Hash {
 }
 
 /// A cryptographic signature.
-#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
+#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Default)]
 pub struct Signature {
     kind: Sign,
     data: Vec<u8>,
@@ -493,7 +493,7 @@ impl AeadKey {
     }
 }
 
-#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, EnumDiscriminants, ZeroizeOnDrop)]
+#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, EnumDiscriminants, ZeroizeOnDrop)]
 #[strum_discriminants(name(SymKeyKind))]
 pub enum SymKey {
     /// A key for the AES 256 cipher in Cipher Block Chaining mode. Note that this includes the
@@ -620,7 +620,7 @@ pub enum SchemeKind {
     Encrypt(Encrypt),
 }
 
-#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
+#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Copy)]
 pub enum Encrypt {
     RsaEsOaep(RsaEsOaep),
 }
@@ -681,7 +681,7 @@ impl Encrypt {
     });
 }
 
-#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
+#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Copy)]
 pub enum Sign {
     RsaSsaPss(RsaSsaPss),
 }
@@ -769,7 +769,7 @@ impl Rsa {
     }
 }
 
-#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
+#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Copy)]
 pub struct RsaEsOaep {
     key_len: KeyLen,
     hash_kind: HashKind,
@@ -813,7 +813,7 @@ impl From<RsaEsOaep> for Encrypt {
     }
 }
 
-#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
+#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Copy)]
 pub struct RsaSsaPss {
     key_bits: KeyLen,
     hash_kind: HashKind,
@@ -1185,6 +1185,8 @@ pub trait Encrypter {
 }
 
 pub trait EncrypterExt: Encrypter {
+    /// Serializes the given value into a new vector, then encrypts it and returns the resulting
+    /// ciphertext.
     fn ser_encrypt<T: Serialize>(&self, value: &T) -> Result<Ciphertext<T>> {
         let data = to_vec(value)?;
         let data = self.encrypt(&data)?;
@@ -1332,7 +1334,7 @@ impl BlockMeta {
 
 /// The types of errors which can occur when verifying a writecap chain is authorized to write to
 /// a given path.
-#[derive(Debug, PartialEq, Display)]
+#[derive(Debug, PartialEq, Eq, Display)]
 pub enum WritecapAuthzErr {
     /// The chain is not valid for use on the given path.
     UnauthorizedPath,
@@ -1422,8 +1424,8 @@ mod tests {
     fn encrypt_decrypt_block() {
         const SECT_SZ: usize = 16;
         const SECT_CT: usize = 8;
-        let key = make_key_pair();
-        let readcap = make_readcap_for(&key);
+        let creds = make_key_pair();
+        let readcap = make_readcap_for(&creds);
         let mut block = make_block_with(readcap);
         write_fill(&mut block, SECT_SZ, SECT_CT);
         block.seek(SeekFrom::Start(0)).expect("seek failed");

+ 9 - 5
crates/btlib/src/lib.rs

@@ -226,11 +226,14 @@ impl<T: Read> ReadExt for T {}
 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
 pub struct BlockMetaBody {
     path: BlockPath,
+    /// A copy of the block key encrypted using this block's parent's key. If this is None, then
+    /// this block is not encrypted.
+    inherit: Option<Ciphertext<SymKey>>,
     readcaps: BTreeMap<Principal, Ciphertext<SymKey>>,
     writecap: Option<Writecap>,
     /// A hash which provides integrity for the contents of the block body.
     integrity: Option<Hash>,
-    /// The public key that corresponds to the private key used to sign this header.
+    /// The public key that corresponds to the private key used to sign these metadata.
     signing_key: AsymKeyPub<Sign>,
 }
 
@@ -238,6 +241,7 @@ impl BlockMetaBody {
     fn new<C: Creds>(creds: &C) -> BlockMetaBody {
         BlockMetaBody {
             path: BlockPath::default(),
+            inherit: None,
             readcaps: BTreeMap::new(),
             writecap: creds.writecap().map(|e| e.to_owned()),
             integrity: None,
@@ -487,7 +491,7 @@ impl<T: Read> TryCompose<T, Decompressor<T>> for BrotliParams {
 }
 
 /// An envelopment of a key, which is tagged with the principal who the key is meant for.
-#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
+#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
 pub struct Readcap {
     /// The principal this `Readcap` was issued to.
     issued_to: Principal,
@@ -529,7 +533,7 @@ pub struct Writecap {
 
 /// Fragments are created from blocks using Erasure Encoding and stored with other nodes in the
 /// network to provide availability and redundancy of data.
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
 pub struct Fragment {
     /// The path to the block this fragment is from.
     path: BlockPath,
@@ -557,7 +561,7 @@ impl Fragment {
 }
 
 /// The body of every non-leaf node in a tree contains this data structure.
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
 pub struct Directory {
     /// The nodes that are attached to the tree at this block.
     nodes: Vec<Principal>,
@@ -566,7 +570,7 @@ pub struct Directory {
 }
 
 /// Keeps track of which principal is storing a fragment.
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
 pub struct FragmentRecord {
     /// The fragment serial number this record is for.
     serial: FragmentSerial,

+ 1 - 1
crates/btlib/src/msg.rs

@@ -106,7 +106,7 @@ mod private {
 
     impl TryClone<PipeWriter> for PipeWriter {
         fn try_clone(&self) -> Result<PipeWriter> {
-            Ok(PipeWriter::try_clone(&self)?)
+            Ok(PipeWriter::try_clone(self)?)
         }
     }
 

+ 2 - 2
crates/btlib/src/sectored_buf.rs

@@ -179,7 +179,7 @@ mod private {
                     dest = &mut self.buf[..];
                 }
                 let sz = src.len().min(dest.len());
-                (&mut dest[..sz]).copy_from_slice(&src[..sz]);
+                dest[..sz].copy_from_slice(&src[..sz]);
                 dest = &mut dest[sz..];
                 src = &src[sz..];
                 self.dirty = sz > 0;
@@ -267,7 +267,7 @@ mod private {
                     src = &self.buf[..byte_ct];
                 }
                 let sz = src.len().min(dest.len());
-                (&mut dest[..sz]).copy_from_slice(&src[..sz]);
+                dest[..sz].copy_from_slice(&src[..sz]);
                 dest = &mut dest[sz..];
                 src = &src[sz..];
                 self.pos += sz;

+ 25 - 3
crates/btlib/src/test_helpers.rs

@@ -62,17 +62,38 @@ pub const SIGNATURE: [u8; 384] = [
     0x42, 0xD7, 0xFE, 0x7D, 0x10, 0x02, 0xBD, 0x31, 0x21, 0xCD, 0xD1, 0x32, 0x04, 0x22, 0xE2, 0x36,
 ];
 
+/// The key of the parent of test blocks.
+pub(crate) static PARENT_KEY: SymKey = {
+    let key = [
+        0x35, 0x3D, 0x8C, 0x95, 0x6C, 0x8D, 0xE6, 0xC0, 0xB0, 0xD5, 0x1C, 0xE9, 0x94, 0xB0, 0x58,
+        0xD3, 0x80, 0x46, 0x12, 0x1C, 0xF3, 0x9B, 0x8A, 0xEC, 0x38, 0xD5, 0x8B, 0x05, 0x92, 0x8D,
+        0xA1, 0x18,
+    ];
+    let iv = [
+        0xDA, 0x96, 0x0E, 0xF5, 0x00, 0xDB, 0xC8, 0x4E, 0xFB, 0x83, 0x59, 0x99, 0x6C, 0x18, 0xD1,
+        0x27,
+    ];
+    SymKey::Aes256Cbc { key, iv }
+};
+
+lazy_static! {
+    static ref INHERIT: Ciphertext<SymKey> = PARENT_KEY
+        .ser_encrypt(&BLOCK_KEY)
+        .expect("failed to encrypt block key");
+}
+
+/// The key used to encrypt test blocks.
 pub(crate) static BLOCK_KEY: SymKey = {
-    const KEY: [u8; 32] = [
+    let key = [
         0xB2, 0xB3, 0xDA, 0x5A, 0x1A, 0xF6, 0xB3, 0x78, 0x30, 0xAB, 0x1D, 0x33, 0x33, 0xE7, 0xE3,
         0x5B, 0xBB, 0xF9, 0xFE, 0xD0, 0xC1, 0xF7, 0x90, 0x34, 0x69, 0xB7, 0xE7, 0xC6, 0x1C, 0x46,
         0x85, 0x48,
     ];
-    const IV: [u8; 16] = [
+    let iv = [
         0xEC, 0x19, 0x59, 0x3A, 0x1D, 0x1E, 0x4A, 0x58, 0x66, 0xC1, 0xD1, 0x9A, 0x61, 0x6E, 0xBA,
         0x16,
     ];
-    SymKey::Aes256Cbc { key: KEY, iv: IV }
+    SymKey::Aes256Cbc { key, iv }
 };
 
 lazy_static! {
@@ -188,6 +209,7 @@ pub(crate) fn make_block_with(readcap: Readcap) -> Box<dyn Block> {
     let root_writecap = writecap.next.as_ref().unwrap();
     let header = BlockMetaBody {
         path: make_path_with_root(root_writecap.body.issued_to.clone(), vec!["apps", "verse"]),
+        inherit: Some(INHERIT.clone()),
         readcaps,
         writecap: Some(writecap),
         integrity: Some(Hash::Sha2_256([0u8; HashKind::Sha2_256.len()])),

+ 1 - 1
crates/btlib/src/trailered.rs

@@ -11,7 +11,7 @@ mod private {
 
     use crate::{BoxInIoErr, Decompose, MetaAccess, Result, WriteInteg};
 
-    /// A struct which wraps a stream and which writes a trailing data structure to when flushed.
+    /// A struct which wraps a stream and which writes a trailing data structure to it when flushed.
     pub struct Trailered<T, D> {
         inner: T,
         body_len: u64,