timvisee před 7 roky
rodič
revize
c8cb0d7e2e
1 změnil soubory, kde provedl 49 přidání a 27 odebrání
  1. 49 27
      src/main.rs

+ 49 - 27
src/main.rs

@@ -127,22 +127,32 @@ fn main() {
     open::that(url);
 }
 
+/// Run HKDF crypto.
+///
+/// # Arguments
+/// * length - Length of the derived key value that is returned.
+/// * ikm - The input keying material.
+/// * info - Optional context and application specific information to use.
+///
+/// # Returns
+/// The output keying material, with the length as as specified in the `length`
+/// argument.
 fn hkdf<'a>(
     length: usize,
     ikm: &[u8],
-    salt: Option<&[u8]>,
     info: Option<&[u8]>
 ) -> Vec<u8> {
-    // Get the salt and info parameters, use defaults if undefined
-    let salt = salt.unwrap_or(b"");
+    // Unwrap info or use empty info
     let info = info.unwrap_or(b"");
 
-    // Define the digest to use
+    // Construct the digest to use
     let digest = Sha256::new();
 
+    // Invoke HKDF extract, create a pseudo random key
     let mut pkr: Vec<u8> = vec![0u8; digest.output_bytes()];
-    hkdf_extract(digest, salt, ikm, &mut pkr);
+    hkdf_extract(digest, b"", ikm, &mut pkr);
 
+    // Invoke HKDF expand, create the output keying material
     let mut okm: Vec<u8> = vec![0u8; length];
     hkdf_expand(digest, &pkr, info, &mut okm);
 
@@ -150,12 +160,12 @@ fn hkdf<'a>(
 }
 
 fn derive_file_key(secret: &[u8]) -> Vec<u8> {
-    hkdf(16, secret, None, Some(b"encryption"))
+    hkdf(16, secret, Some(b"encryption"))
 }
 
 fn derive_auth_key(secret: &[u8], password: Option<String>, url: Option<String>) -> Vec<u8> {
     if password.is_none() {
-        hkdf(64, secret, None, Some(b"authentication"))
+        hkdf(64, secret, Some(b"authentication"))
     } else {
         // TODO: implement this
         unimplemented!();
@@ -163,18 +173,19 @@ fn derive_auth_key(secret: &[u8], password: Option<String>, url: Option<String>)
 }
 
 fn derive_meta_key(secret: &[u8]) -> Vec<u8> {
-    hkdf(16, secret, None, Some(b"metadata"))
+    hkdf(16, secret, Some(b"metadata"))
 }
 
+/// File metadata, which is send to the server.
 #[derive(Serialize)]
 struct Metadata {
-    /// The input vector
+    /// The input vector.
     iv: String,
 
-    /// The file name
+    /// The file name.
     name: String,
 
-    /// The file mimetype
+    /// The file mimetype.
     #[serde(rename="type")]
     mime: String,
 }
@@ -200,6 +211,11 @@ impl Metadata {
     }
 }
 
+/// A X-File-Metadata header for reqwest, that is used to pass encrypted
+/// metadata to the server.
+///
+/// The encrypted metadata (bytes) is base64 encoded when constructing this
+/// header using `from`.
 #[derive(Clone)]
 struct XFileMetadata {
     /// The metadata, as a base64 encoded string.
@@ -207,15 +223,12 @@ struct XFileMetadata {
 }
 
 impl XFileMetadata {
-    pub fn new(metadata: String) -> Self {
+    /// Construct the header from the given encrypted metadata.
+    pub fn from(bytes: &[u8]) -> Self {
         XFileMetadata {
-            metadata,
+            metadata: base64_encode(bytes),
         }
     }
-
-    pub fn from(bytes: &[u8]) -> Self {
-        XFileMetadata::new(base64_encode(bytes))
-    }
 }
 
 impl Header for XFileMetadata {
@@ -234,12 +247,15 @@ impl Header for XFileMetadata {
     }
 }
 
-/// A file reader, that encrypts the file with the given cipher, and appends
-/// the raw cipher tag.
+/// A file reader, that encrypts the file that is read with the given
+/// `cipher`, and appends the cipher tag to the end of it.
 ///
-/// This reader is lazy, and reads/encrypts the file on the fly.
+/// This reader is not lazy, and loads the whole file in memory to
+/// encrypt it at once. Also, a buffer is created to copy the encrypted file
+/// into.
 ///
-/// TODO: the current implementation is not lazy
+/// This object requires about twice the memory as the size of the file that is
+/// encrypted when constructed.
 struct EncryptedFileReaderTagged {
     /// A cursor that reads encrypted file data.
     data: Cursor<Vec<u8>>,
@@ -249,18 +265,24 @@ struct EncryptedFileReaderTagged {
 }
 
 impl EncryptedFileReaderTagged {
-    /// Construct a new reader.
+    /// Construct a new reader for the given `file` with the given `cipher`.
+    ///
+    /// This method consumes twice the size of the file in memory while
+    /// constructing, and constructs a reader that has a size similar to the
+    /// file.
     pub fn new(mut file: File, mut cipher: AesGcm<'static>) -> Self {
-        // Get the file length
+        // Get the length of the file
         let len = file.metadata().unwrap().len() as usize;
 
-        // Create a file data buffer and an encrypted buffer
+        // Read the whole file in a data buffer
         let mut data = Vec::with_capacity(len);
         file.read_to_end(&mut data).unwrap();
-        let mut encrypted = vec![0u8; data.len()];
 
-        // Encrypt the data, get the tag
+        // Create an encrypted and tag buffer
+        let mut encrypted = vec![0u8; data.len()];
         let mut tag = vec![0u8; TAG_LEN];
+
+        // Encrypt the file, set the tag
         cipher.encrypt(&data, &mut encrypted, &mut tag);
 
         // Construct the reader and return
@@ -298,7 +320,7 @@ impl Read for EncryptedFileReaderTagged {
 /// include the required secret in the URL.
 #[derive(Debug, Deserialize)]
 struct UploadResponse {
-    /// The URL the file is reachable at.
+    /// unkhe URL the file is reachable at.
     /// This includes the file ID, but does not include the secret.
     url: String,