留学生代考 Section 1: System Design

Section 1: System Design
01.How is each client initialized?
a. We first compute the hash using username and password, which will be used to compute the UUID deterministically. This prevents from attacker from guessing the UUID of a user. Also, we save the randomly generated salt and hashed password inside userdata, to later verify the password again.
b. We generate random UUID for MAC of this userdata and random key for this MAC, and save them in the struct. We initialize file variables used later and save private keys in the struct.
c. This user data should be encrypted in the database, so I need a symmetric key. Also this needs to be deterministic, since I should be able to decrypt with no other information. Therefore, I compute an encryption key with a hash using password and a UUID, so that it’s different from a hash used for UUID, and contains sufficient entropy. I save this inside the struct too, since it is needed later for encrypting the updated userdata.
02.How is a file stored on the server?
a. First, FileMetadata is created with a random UUID and this metadata is stored in database. Users keep a map from filenames to metadata UUIDs, and keys for encrypting this metadata. Instead of storing the metadata completely inside user, I decided to store directly in database because this metadata, as well as files, should be accessible to all users when sharing.
b. File is split into blocks of 1KB, for easier append (just take last block). Files are encrypted with random keys, and mac is generated for each block with random keys. Mac Key and File Keys are stored in FileMetadata. File blocks, Mac blocks UUID are generated randomly and also stored in FileMetadata.
03.How are file names on the server determined?
a. File names are never stored without encryption. File names are only stored in userdata for a mapping of filenames to fileMetadata UUID, and userdata is completely encrypted, so eavesdropper cannot see the filenames, without hacking into that user’s account.
04.What is the process of sharing a file with a user?
a. We first create a share struct, which contains file metadata UUID, symmetric key used to encrypt that metadata, and a UUID of a signature of this share struct. Magic string is publicly encrypted with receiver’s public key and contains information about this share struct UUID, symmetric key used to encrypt this share struct, and the signature on the previous two information. This way, receiver can verify not only the share struct but the magic string itself.
b. Receiver stores all the relevant UUIDs and keys inside its own userdata, after checking authenticity.

05.What is the process of revoking a user’s access to a file?
a. We first use the filename to get the UUID of FileMetadata and using that to get the encrypted FileMetadata. We use the symmetric key we stored in user struct to get the FileMetadata.
b. We generate a new sym key for the filemetadata, and encrypt the metadata using the new key, and store the new key in user struct. We replace the encrypted file metadata in database by newly encrypted FileMetadata, so when other people try to access that file. It won’t get decrypted correctly
06.How were each of these components tested?
a. We created custom tests for each component, see if error is correctly returned and the data is confidentially stored in database, as well as checking each functionalities.
b. Then we combine the operations to see if there is any bizarre behavior.
Section 2: Security Analysis Attack1:
A man in the middle attacker could modify the magic string while Alice is sharing a new file with Bob.
Protection1:
We have HMAC and signature over the fileMetadata, everytime we access the file, we check it’s integrity so if some one in the middle modifies the message sent and received we would be notified and the access is denied.
Malicious users want to overwrite the files that they have no access to.
Protection2:
Users with no access to certain files would not possess the symmetric key for the encrypted filemetadata. If it actually overwrite the file with malicious content, when the user with access the file the Mac check would file and the content would not be loaded.
Malicious users want to revoke everything despite they dont have the
ownership.
Protection:
The revoke would be denied since they could not brute force the uuid and the sym key to encrypted Metadata at the same time. This would take np time.

Data Storage
– User UUID => SymEnc(User Data)
– Mac UUID => Mac(SymEnc(User Data))
– File block UUID => SymEnc(file data)
– Mac of File block UUID => Mac(SymEnc(file data))
– File Metadata UUID => SymEnc(File Metadata)
– Mac of File Metadata UUID =>Mac(SymEnc(File Metadata))
– Shared Metadata UUID => PubEnc(Shared Struct)
– Signature of Shared Metadata UUID => RSA(PubEnc(Shared Struct))
Key Storage
– User Public Key for asymmetric encryption : username + “_PKEEncKey”
– User Verify Key for RSA : username + “_DSVerifyKey”
Data Structure
– username
– userUUID : UUID_FromBytes(Argon2Key(password, username, 16))
– salt: RandomBytes(128). Used to generate hashed_password
– hashed_password : Argon2Key(password, salt, 128)
– signinKey : DSKeyGen
– privateKey : PKEKeyGen
– MacUUID : UUID.NewRandom()
– MacKey : RandomBytes(16)
– Files : map of filenames to fileMetaData UUID
– UserEncKey: a key used for encrypting this user data
– Argon2Key(password, userUUID, 16)
– Cannot be random because getUser needs to calculate this key
– const BLOCKSIZE: 1000 // 1KB block
– FileMetadata: {
– fileUUIDList: [FileUUID1, FileUUID2, …]
– fileKey: random 16 bytes
– it’s okay to have just one key for fileblocks since we are using different IVs?
– fileMacUUID: [MacUUID1, MacUUID2, …]
– fileMacKey: random 16 bytes
– SpaceAvailable: boolean
– true if the last block has some space available. Otherwise, when appending, allocate new block

● Appending to the file -> just take the last file UUID
– SymEnc(User Data)
– Key : Argon2Key(password, UserUUID, 16) – IV : RandomBytes(16)
– Mac (User Data) :
– MacKey : userdata.MacKey – HMAC(MacKey, User Data)
Level of Security
1. Filenames should be hidden even if the attacker knows UUID.
a. Filenames are stored inside filemetadata inside userdata, which is encrypted.
2. UUID should be hard to guess in polynomial time. 3.

Struct share:
File uuid Mac uuid File key
File mac key
Check the file’s existence Check the file’s integrity
Retrieve the public key of the recipients
Create a new share struct for the file which contain the original file uuid, mac and encryption key.
Generate two new keys and use the two keys to encrypt the share struct
Use the recipient’s public key to encrypt (nounce || share uuid || new keys)
Above implementation only works between 2 users..
According to Piazza, we should allow to share between multiple users.
What magic string should contain: uuid of share.
– sharingRecord: {
– FileMetadata UUID
– FileMetadata symKey
– SignatureUUID: where signature of this sharingRecord is stored
– Encrypt this sharingRecord with a random symmetric key
– (We used symmetric key encryption rather than public key, so when
sender tries to share the same record twice with the same user, ciphertext
will be different.
– We chose signature rather than hmac here, since we have to also verify
the sender. )
– Magic_string = PKE (symmetric_key || mac_symmetric_key || sharingRecord
UUID) || Signed(previous two arguments)
– This way, we can guarantee that the magic string, as well as the
sharingRecord, is originated from Alice.
TODO: appended change does not propagate between users… need design change. Need to change filemetdata structure. Instead of keeping a list of fileUUIDS,

Allocate a new UUID, where the list of file UUIDs will be stored Revoke:
Main idea: re-encrypt the file with new keys.