3. Design Requirements¶
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
3.1. Usernames and Passwords¶
Usernames
The client SHOULD assume that each user has a unique username.
Usernames are case-sensitive:
Bob
andbob
are different users.Usernames can be any length greater than zero (they CANNOT be empty).
Passwords
The client MUST NOT assume each user has a unique password. Like the real world, users may happen to choose the same password.
The client MAY assume each user’s password generally is a good source of entropy. However, the attackers possess a precomputed lookup table containing hashes of common passwords downloaded from the internet.
3.2. User Sessions¶
The client application MUST allow many different users to use the application at the same time. For example, Bob and Alice can each run the client application on their own devices at the same time.
The client MUST support a single user having multiple active sessions at the same time. All file changes MUST be reflected in all current user sessions immediately (i.e. without terminating the current session and re-authenticating).
For example:
User
bob
runs the client application on his laptop and callsGetUser()
to create sessionbob_laptop
.User
bob
runs the client application on his tablet and callsGetUser()
to create sessionbob_tablet
.Using the
bob_laptop
session,bob
stores a filefile1.txt
. Sessionbob_tablet
must be able to downloadfile1.txt
.Using the
bob_laptop
session,bob
appends tofile1.txt
. Sessionbob_tablet
must be able to download the updated version.Using the
bob_laptop
session,bob
accepts an invitation to access a file and calls the filefile2.txt
in his personal namespace. Sessionbob_tablet
must be able to load the corresponding filefile2.txt
.
The client DOES NOT need to support concurrency. Globally, across all users and user-sessions, all operations in the client application will be done serially.
3.3. Cryptography and keys¶
Each public key SHOULD be used for a single purpose, which means that each user is likely to have more than one public key.
A single user MAY have multiple entries in Keystore. However, the number of keys per user MUST be a small constant; it MUST NOT depend on the number of files stored or length of any file, how many users a file has been shared with, or the number of users already in the system.
The following SHOULD be avoided because they are dangerous design patterns that often lead to subtle vulnerabilities. We test for them and treat any instance of them as a breach of confidentiality/integrity.
reusing the same key for multiple purposes (e.g. encryption, authentication, key- derivation, etc); and
authenticate-then-encrypt; and
decrypt-then-verify.
3.4. No Persistent Local State¶
3.5. Files¶
Any breach of IND-CPA security constitutes loss of confidentiality.
The client MUST ensure confidentiality and integrity of file contents.
The client MUST ensure the integrity of filenames.
The client MUST prevent adversaries from learning filenames and the length of filenames. The client MAY use and store filenames in a deterministic manner.
The client MUST prevent the revoked user adversary from learning anything about future writes or appends to the file after their access has been revoked.
The client MAY leak any information except filenames, lengths of filenames, and file contents. For example, the client design MAY leak the size of file contents or the number of files associated with a user.
Filenames MAY be any length, including zero (empty string).
The client MUST NOT assume that filenames are globally unique.
For example, user
bob
can have a file namedfoo.txt
and useralice
can have a file namedfoo.txt
. There is a single instance of the Datastore server that is used by all users, but the client application MUST keep each user’s file namespace independent from one another.
3.7. Efficiency¶
The client MUST allow users to efficiently append new content to previously stored files.
We measure efficiency in terms of the bandwidth used by the
AppendToFile()
operation (the total size of the data uploaded and downloaded via calls toDatastoreGet()
andDatastoreSet()
).The bandwidth of the
AppendToFile()
operation MUST scale linearly with only the size of data being appended and the number of users the file is shared with, and nothing else. Logarithmic and constant scaling in other terms is fine.For example, appending 100 B to a 10 TB file should not use 10 TB of bandwidth. The 1,000th and 10,000th append operations to the same file should not use significantly more bandwidth than the 1st append operation. This is not an exhaustive list of restrictions.
AppendToFile()
is the only function that has an explicit requirement for efficiency. However, the client MUST implement other functions such that they do not time out the autograder (e.g. they cannot be grossly inefficient).You can submit to Gradescope as often as you like to verify whether your tests finish within the allotted time (usually about ~10 minutes max).
3.8. Golang¶
The client application code MUST NOT use global variables (except for basic constants).
Your Go functions MUST return an error if malicious action prevents them from functioning properly. Do not panic, do not segfault; return an error.
Return
nil
as the error if and only if an operation succeeds. Return a value other thannil
as the error if and only if an operation fails.