A cryptographically secure file sharing system implemented in Go that enables users to store, share, and manage files with strong security guarantees including confidentiality, integrity, and authentication.
Live Demo: The site is deployed at https://mananb77.github.io/file-sharing-system/
This system provides a client-side implementation for secure file storage and sharing with the following key features:
- End-to-End Encryption: All files are encrypted before storage using symmetric encryption (AES)
- User Authentication: Secure user registration and login with password-based authentication using Argon2
- File Sharing: Share files with other users through cryptographically secure invitations
- Access Revocation: File owners can revoke access from previously shared users
- Integrity Protection: All data structures are protected with HMACs to detect tampering
- Digital Signatures: Invitations are digitally signed to verify sender authenticity
- Efficient Storage: Files are stored as linked lists of encrypted chunks for efficient appending
- Registration: Creates new users with unique usernames and secure password-based key derivation
- Authentication: Verifies user credentials and retrieves encrypted user data from the datastore
- Key Management: Each user has RSA key pairs for encryption and digital signature key pairs for authentication
Files are stored as encrypted linked lists of nodes:
- File Struct: Contains metadata including owner information, encryption keys, and pointer to the tail node
- Node Struct: Represents a chunk of file content with links to previous nodes
- Accessor Struct: Provides access to files with pointers to file structures and sharing metadata
- AccessorInfo Struct: Maps filenames to accessor UUIDs for user-specific file namespaces
- Invitations: Encrypted and signed tokens that grant file access
- Shared Users Tracking: Maintains list of users with access to each file
- Hierarchical Sharing: Supports both direct sharing (owner to user) and transitive sharing (user to user)
- Revocation: Re-encrypts all file content with new keys when access is revoked
-
Confidentiality
- AES-CTR symmetric encryption for all file content
- RSA public-key encryption for sharing invitations
- Unique encryption keys per file and per node
-
Integrity
- HMAC authentication for all encrypted structures
- Verification of HMACs before decryption (encrypt-then-MAC)
-
Authentication
- Digital signatures (DSA) for invitation verification
- Argon2 key derivation for password-based authentication
- Public key infrastructure for user identity verification
-
Authorization
- Owner-based access control
- Fine-grained sharing with explicit invitations
- Secure revocation with re-encryption
Creates a new user account with the given credentials.
Parameters:
username: Unique username (must be non-empty)password: User password for authentication
Returns:
- Pointer to User struct
- Error if username already exists or other initialization failure
Authenticates and retrieves an existing user.
Parameters:
username: Username to authenticatepassword: Password for authentication
Returns:
- Pointer to User struct if authentication succeeds
- Error if credentials are invalid
Stores a new file or overwrites an existing file in the user's namespace.
Parameters:
filename: Name of the file (must be non-empty)content: File content as byte array
Returns:
- Error if operation fails
Behavior:
- Creates a new file if it doesn't exist
- Overwrites existing file content completely
- Maintains file access permissions
Retrieves and decrypts file content from the datastore.
Parameters:
filename: Name of the file to load
Returns:
- File content as byte array
- Error if file doesn't exist or integrity check fails
Implementation:
- Traverses linked list of encrypted nodes backward from tail
- Verifies HMAC for each node
- Concatenates decrypted content in correct order
Efficiently appends content to an existing file.
Parameters:
filename: Name of the file to append tocontent: Content to append
Returns:
- Error if file doesn't exist or operation fails
Efficiency:
- O(1) operation - only accesses tail node
- Creates new encrypted node linked to previous tail
- Updates file metadata to point to new tail
Creates a secure invitation to share a file with another user.
Parameters:
filename: Name of the file to sharerecipientUsername: Username of the recipient
Returns:
- UUID of the invitation for the recipient to accept
- Error if file doesn't exist or recipient doesn't exist
Behavior:
- File owners create new accessor structs for direct shares
- Non-owners can reshare their access (transitive sharing)
- Encrypts invitation with recipient's public key
- Signs invitation with sender's private signing key
Accepts an invitation and adds the shared file to the user's namespace.
Parameters:
senderUsername: Username of the user who sent the invitationinvitationPtr: UUID of the invitationfilename: Local name to give the file in this user's namespace
Returns:
- Error if invitation is invalid, filename already exists, or verification fails
Security Checks:
- Verifies digital signature from sender
- Decrypts invitation with user's private key
- Validates invitation hasn't been revoked
Revokes a user's access to a file (owner only).
Parameters:
filename: Name of the filerecipientUsername: Username of user to revoke
Returns:
- Error if operation fails or user is not the owner
Implementation:
- Re-encrypts all file content with new keys
- Moves all nodes to new UUIDs
- Updates all remaining users' accessor structs
- Deletes revoked user's accessor and invitation
type User struct {
Username string
Password string
PrivateKey userlib.PKEDecKey
SignKey userlib.DSSignKey
Random []byte
}type File struct {
FileOwnerHash []byte
ContentEncKey []byte
TailNodePointer uuid.UUID
}type Accessor struct {
FileStructPointer uuid.UUID
FileSymKey []byte
SharedUsers uuid.UUID
SharedUsersEncKey []byte
SharedKeys uuid.UUID
SharedKeysEncKey []byte
}type Node struct {
Value []byte
Prev uuid.UUID
PrevNodeSymKey []byte
}type Invitation struct {
AccessorUUID uuid.UUID
AccessorEncKey []byte
}The system includes comprehensive test suites:
Navigate to the client_test directory and run:
cd client_test
go test -vThis executes:
- Unit tests in
client/client_unittest.gofor helper functions - Integration tests in
client_test/client_test.gofor full workflows
- User registration and authentication
- File storage and retrieval
- File appending operations
- Sharing and invitation acceptance
- Access revocation
- Concurrent operations
- Security properties (integrity, confidentiality, authentication)
- Edge cases and error handling
The system uses the following cryptographic libraries:
-
userlib: Custom cryptographic library providing:
Argon2Key: Password-based key derivationSymEnc/SymDec: AES-CTR symmetric encryptionPKEKeyGen/PKEEnc/PKEDec: RSA public-key encryptionDSKeyGen/DSSign/DSVerify: Digital signaturesHMACEval/HMACEqual: HMAC generation and verificationHash: SHA-256 hashingRandomBytes: Cryptographically secure random number generation
-
uuid: UUID generation and parsing for unique identifiers
.
├── client/
│ ├── client.go # Main implementation
│ └── client_unittest.go # Unit tests
├── client_test/
│ └── client_test.go # Integration tests
├── go.mod # Go module definition
├── go.sum # Dependency checksums
├── CHANGELOG.md # Version history
└── README.md # This file
The system is designed to protect against:
- Datastore Adversary: Cannot read, modify, or corrupt stored data meaningfully
- Malicious Users: Cannot access files without proper authorization
- Network Adversary: Cannot intercept or modify invitations in transit
- Defense in Depth: Multiple layers of security (encryption + HMAC + signatures)
- Zero Trust: All data is verified before use
- Least Privilege: Users only access files explicitly shared with them
- Key Isolation: Unique keys for each file and encryption operation
- Forward Security: Revocation renders old keys useless
- Requires trusted keystore for public key distribution
- No built-in key rotation mechanism
- Revocation requires re-encrypting entire file
- No support for concurrent writes to the same file
This is an educational implementation demonstrating cryptographic principles in a practical system. The code prioritizes security correctness and clarity over performance optimization.
This project is provided for educational purposes.