combinepdf-11

pdf

School

University of California, Berkeley *

*We aren’t endorsed by this school

Course

188

Subject

Computer Science

Date

Dec 6, 2023

Type

pdf

Pages

5

Uploaded by PrivatePower11625

Report
Ananth Goyal, Neeraj Rattehalli Data structures: What data structures are you going to use to organize data on Datastore? User { UUID : uuid, Username : string, Files: uuid, key: byte[], } Files {UUID: uuid, files: map[uuid], user: uuid} File {UUID: uuid, user: uuid, owner: uuid, key: byte[], children: map[uuid], first: uuid, last: uuid} Node {UUID: uuid, data: byte[], next: uuid} Invitation {UUID: uuid, File: uuid, Signature: byte[]} Helpers: ClearFile(filename): Deletes that file and removes the UUID signature from the files map of the uses encrypt(uuid, key, struct): encryption key using hash KDF, created encrypted array of bytes, creates HMAC, combines encryption with HMAC, insert UUID and object into datastore User Authentication: How will you authenticate users? How does EvanBot create a new user? When they try to log in, how will you check if the username and password are correct? How do you ensure that a user cannot login with an incorrect password? When Evan creates a new user we first hash the username and generate a UUID using the hash; we will store that UUID in datastore. We pass in the given password into Argon2key where the username will be salt (since no two usernames are the same though passwords technically can be). This will be the primary key for this struct/user object going forward since we know this will always be unique. Datastore is not super secure, so to store the user struct information we will encrypt the user struct and generate an HMAC to detect tampering. We can encrypt the struct by taking the hash KDF of the primary key as the encryption key. We will pass in these values (encrypted object + HMAC) into Datastore along with the previously generated UUID. If EvanBot attempts to login, we first check if the username key even exists. After that (if it does), we generate the Argon2key again but with the information given to us in this login attempt this is then authenticated by looking at the HMAC tags. An incorrect password when passed into Argon2key will result in an incorrect output and thus prevent an incorrect password from allowing access. Multiple Devices: How will you ensure that multiple User objects for the same user always see the latest changes reflected? To allow multiple user objects on different devices to reflect the newest changes we can store a list of the UUID of that user’s files in a files struct. That files struct will contain the corresponding user’s UUID, and thus allowing us to match the correct files with the correct user. This will never need to be changed since only the files in the list themselves will be edited/updated (i.e added to the list, removed, etc.). Each time a load is called we can requery the database for the file from the file list to then ensure we get the updated changes. Any collisions don’t need to be worried about since in the spec it says we can assume no parallel requests will be made, so updates happen independently and thus the above system should work. File Storage and Retrieval: How does a user store and retrieve files? EvanBot is logged in and stores a file. How does the file get stored in Datastore? What key(s) and UUIDs do you use? How do you access the file at a later time? The “Files” struct maps all the UUIDs of file objects that that user has access to. Since we can append info to files it makes sense to store the file bytes as a linked list, so the main “File” struct will contain the UUID to the head and tail node “Node” struct which contains the pointer to the next object (default null) and the bytes themselves. The original main file struct can be encrypted and mac’d to detect tampering. Anytime one of these objects is created we can generate a unique 16-byte key and UUID. To access the file we simply check if the file exists in the users files struct and if it does traverse the links (starting with the initial found in the file struct) until a null is found and
return that information. In the file struct we can also store the original creator of the file so we have the information even when grant file sharing. We also store all children files (i.e the files that are result of this struct’s file sharing_ Efficient Append: What is the total bandwidth used in a call to append? List out every piece of data that you need to upload (DatastoreSet) or download (DatastoreGet) from Datastore in a call to append, and the size of each piece of data. Is the total a constant, or does it scale? Per the design above all we have to do is create a new node with the new data bytes and update the tail node in the file struct to point to the newly developed node and ensure the previous tail node now points to the new one. This does not require traversing the entire LinkedList because we store pointers to the front and back and thus can be considered an O(1)/constant total operation time. File Sharing: What gets created on CreateInvitation, and what changes on AcceptInvitation? EvanBot (the file owner) wants to share the file with CodaBot. What is stored in Datastore when creating the invitation, and what is the UUID returned? When CreateInvitation gets submitted we store the UUID of the invitation, the UUID of the file, the UUID of the user being shared, and the original user UUID, within the invitation struct. For security we can encrypt it with the user’s public key (in keystore) and sign it with the signature key in the user struct and store that into the datastore. When the recipient user accepts the invitation, we locate the invitation struct using the passed in pointer. We will verify this using the signature and we will now have the verified invitation object. Since each user can have their own filename, we will create a new file object but with the head and tail nodes copied to the node structs that are shared. This effectively allows the user to represent the file how they like but the core data will be shared (as intended). We add the UUID of this new file object in the files struct which maps the UUID of the user to the files they have access to. We add the UUID of the new file in the original files map of children UUIDs. If a non-owner shares, we repeat the same process but the owner attribute is the original person. File Revocation: What values need to be updated when revoking? Using the diagram above as reference, suppose A revokes B’s access. What values in Datastore are updated? How do you ensure C and G still have access to the file? How do you ensure that B, D, E, and F lose access to the file? Revoked user concerns? When revoking we check that the owner matches the file’s owner. If so, we DFS on all children of the revoked file (repeatedly) (this ensures only BDEF lose access) and call the clearFile(filename) function once we return back to the current file object or the children map is empty/null. Because the revoked user’s object is gone they no longer have access to the head and tail pointer needed to make edits since that struct is gone.
UUID Encrypted Key Derivation Value at UUID Description/Relationship USER No We hash the value of the username and generate the UUID from the hash This UUID is stored in DataStore User { UUID : uuid, Username : string, Files: uuid, key: byte[], } Files No It will have its own UUID as well as a map to all of the different files a user could own. This struct will also include the owner of the file. This UUID is stored in DataStore Files {UUID: uuid, files: map[uuid], user: uuid} File Yes We will share a symmetric key with the User whom this file belongs to. They can sign this symmetric and can send it to people who they want to invite into this file The file struct at this UUID will have an owner and their relevant UUID, and then a key value which can be a shared symmetric key which would be needed to access this file. There would also be a children map for the file to see who invited access for a relevant user. We are storing the value or contents of the file as a LinkedList to allow for easy appends. We just make a new node at the end. If a user wants to completely start from scratch we could easily do This UUID is stored in DataStore Relevant keys will be stored in KeyStore File {UUID: uuid, user: uuid, owner: uuid, key: byte[], children: map[uuid], first: uuid, last: uuid
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
  • Access to all documents
  • Unlimited textbook solutions
  • 24/7 expert homework help
that by terminating the first in the struct with a null pointer. User is not really a necessary element of the file because the file should not be tied to a user but rather an owner. Node Yes, probably using asymmetric encryption since we just want login access to be able be able to view this file if a user has relevant permissions The content of the nodes should be hashed using a key that is derived from the UUID and a randomly generated IV stored in the keystore. Node {UUID: uuid, data: byte[], next: uuid} Invitation We will include a signature that is signed by the shared key of the file and it will be used to grant access between the file and the signature. We might want to encrypt the file UUID to not leak which file is being shared. We would want to do this with a private key, a randomly Invitation {UUID: uuid, File: uuid, Signature: byte[]}
generated IV.