This repository contains my implementation of a secure file sharing system. The project builds a client-side encrypted file store on top of an untrusted datastore and a trusted keystore for public keys. Users can store, append to, load, share, and revoke access to files while preserving confidentiality and integrity against a malicious datastore.
Spec link: Project 2 spec
Quick Summary
- Client-side encryption and integrity for all file and user data.
- Efficient append via an encrypted linked-list of file nodes.
- Share and revoke access using signed, encrypted invitations.
How It Works
- User initialization and login
InitUserderives a base key from the password using Argon2 with a random salt, then derives separate encryption, MAC, and root keys.- The user struct is serialized, encrypted, MACed, and stored at a deterministic UUID derived from the username.
- Public keys are stored in the keystore under names like
username_pkeandusername_dsv.
- File storage
- Each file has a
FileMetarecord stored at a deterministic UUID derived from the user’s root key and the filename. FileMetacontains per-file symmetric keys plus pointers to the head/tail of a linked list ofFileNodeobjects.- Each
FileNodestores encrypted content and a pointer to the next node, allowing O(1) append.
- Each file has a
- Append
AppendToFilecreates a new encryptedFileNode, updates the previous tail node’sNextpointer, and updatesFileMeta.
- Load
- Owners decrypt
FileMetaand traverse the linked list, verifying a MAC on each node. - Shared users decrypt a local “handle,” verify the invitation signature, decrypt the invitation to obtain per-file keys, then traverse nodes.
- Owners decrypt
- Sharing
CreateInvitationpackages per-file keys and a base-node pointer into anInvitation, encrypts it to the recipient, and signs it.- The recipient stores a local
SharedFilehandle (encrypted/MACed under their root key) that points to the invitation UUID.
- Revocation
- Only the original owner can revoke.
RevokeAccessrekeys the file by decrypting each node with old keys and re-encrypting with fresh keys.- Invitations for remaining users are reissued with new keys; the revoked user’s invitation is overwritten with a revoked marker.
Public API (package client)
InitUser(username, password)GetUser(username, password)StoreFile(filename, content)LoadFile(filename)AppendToFile(filename, content)CreateInvitation(filename, recipientUsername)AcceptInvitation(senderUsername, invitationPtr, filename)RevokeAccess(filename, recipientUsername)
Repository Layout
client/client.go– implementationclient/client_unittest.go– optional white-box unit testsclient_test/client_test.go– black-box integration testsmy_tests/my_test.go– additional tests
Running Tests
go test ./...Notes
- This is a course project and is not production hardened.
- The system relies on
github.com/cs161-staff/project2-userlibfor cryptographic primitives and the datastore/keystore API.