File Sharing

In-depth walkthrough of file sharing feature.

File sharing enables you to share the files in your allocation, either publicly or privately. Check Webapps documentation on how to use it from Blimp/Vult webapps. In this page, we'll be going into the internals of file sharing and the implementation of Proxy Re-Encryption for private file sharing.

Sharing Internals

File sharing depend on an AuthTicket generated for the shared file, that is used to authenticate other users' access to the shared files.

AuthTicket format

type AuthTicket struct {
	ClientID        string `json:"client_id"`
	OwnerID         string `json:"owner_id"`
	AllocationID    string `json:"allocation_id"`
	FilePathHash    string `json:"file_path_hash"`
	ActualFileHash  string `json:"actual_file_hash"`
	FileName        string `json:"file_name"`
	RefType         string `json:"reference_type"`
	Expiration      int64  `json:"expiration"`
	Timestamp       int64  `json:"timestamp"`
	ReEncryptionKey string `json:"re_encryption_key,omitempty"`
	Encrypted       bool   `json:"encrypted"`
	Signature       string `json:"signature"`
}

The AuthTicket is usually encoded in Base64 format and signed with the owner's private key. To access the information contained within the AuthTicket, you can decode it to retrieve the following details:

Share a file/folder using zboxcli

You can share a file using the share command in zboxcli:

./zbox share --allocation <allocation-id> --remotepath <path-of-the-file-or-folder-on-the-allocation> [other flags] 

Check the zboxcli repo README for full usage docs of this command. After running the command you'll get an AuthTicket (encrypted in Base64), which you can share with whomever you want to access this file.

Auth token eyJjbGllbnRfaWQiOiIiLCJvd25lcl9pZCI6IjE3ZTExOTQwNmQ4ODg3ZDAyOGIxNDE0YWNmZTQ3ZTg4MDhmNWIzZjk4Njk2OTk4Nzg3YTIwNTVhN2VkYjk3YWYiLCJhbGxvY2F0aW9uX2lkIjoiODlkYjBjZDI5NjE4NWRkOTg2YmEzY2I0ZDBlODE0OTE3NmUxNmIyZGIyMWEwZTVjMDZlMTBmZjBiM2YxNGE3NyIsImZpbGVfcGF0aF9oYXNoIjoiM2NhNzIyNTQwZTY1M2Y3NTQ1NjI5ZjBkYzE5ZGY2ODk5ZTI0MDRjNDI4ZDRiMWZlMmM0NjI3ZGQ3MWY3ZmQ2NCIsImFjdHVhbF9maWxlX2hhc2giOiIyYmM5NWE5Zjg0NDlkZDEyNjFmNmJkNTg3ZjY3ZTA2OWUxMWFhMGJiIiwiZmlsZV9uYW1lIjoidGVzdC5wZGYiLCJyZWZlcmVuY2VfdHlwZSI6ImYiLCJleHBpcmF0aW9uIjoxNjM1ODQ5MzczLCJ0aW1lc3RhbXAiOjE2MjgwNzMzNzMsInJlX2VuY3J5cHRpb25fa2V5IjoiIiwiZW5jcnlwdGVkIjpmYWxzZSwic2lnbmF0dXJlIjoiZDRiOTM4ZTE0MDk0ZmZkOGFiMDcwOWFmN2QyMDAyZTdlMGFmNmU3MWJlNGFmMmRjNmUxMGYxZWJmZTUwOTMxOSJ9

What happens in the background is simply :

  • The client (in this case zboxcli via Zboxcore SDK) creates the AuthTicket and signs it with the private key of the owner.

  • The client submits the ticket in a ShareRequest to one of the blobber of the allocation, via the endpoint: POST /v1/marketplace/shareinfo/ (see in Blobber API documentation).

  • The blobber creates/updates the ShareInfo for the file_path_hash in the AuthTicket, after validating the request.

shareInfo := reference.ShareInfo{
	OwnerID:                   authTicket.OwnerID,
	ClientID:                  authTicket.ClientID,
	FilePathHash:              authTicket.FilePathHash,
	ReEncryptionKey:           authTicket.ReEncryptionKey,
	ClientEncryptionPublicKey: encryptionPublicKey,
	ExpiryAt:                  common.ToTime(authTicket.Expiration).UTC(),
	AvailableAt:               common.ToTime(availableAt).UTC(),
}

Downloading a shared file/folder

To download a shared file, you can utilize the download command from zboxcli, using the authTicket that was provided in the share step:

./zbox download --authticket <the-generated-AuthTicket> --localpath <local-path-to-save-the-file>

Check the zboxcli repo README for full usage docs of this command.

In case of folder download, you'll need to download the files inside the folder one by one, by providing either remotepath or lookuphash flags to the download command.lookuphash is the hash of file path and allocation ID, concatenated, using the Hash function of encryption package in GoSDK.

What happens in the background is simply:

  • The client (in this case zboxcli, via Zboxcore SDK) prepares the request based on the given flags. For example, it creates a lookuphash if the remotepath is given, because lookuphash is required for the download request of the blobber API.

  • The client sends the blobber a series of downloadRequest's, block-by-block, on the endpoint: /v1/file/download/ (see Blobber API), attaching the AuthTicket in that response.

  • The blobber does some validation and verification checks on the request to make sure all is lined up, including:

    • Checks the path in the request is actually inside the allocation in the request.

    • Checks user has enough daily download quota (see Download).

    • Verifies the signature of the AuthTicket.

    • Verifies the owner of the ticket is the same as the owner of the allocation.

    • If the ticket has ClientID (meaning the file is privately shared with this specific client), then the blobber will verify that this client actually has access to this blobber. Otherwise, if ClientID is empty, then the file is publicly shared.

    • Checks the time now is later than availableAfter from ShareInfo above.

    • Checks the expiry, if expiration date is provided. Otherwise, a default expiry date of 90 Days used.

    • Checks the lookuphash provided in the request is the same as the file_path_hash in the AuthTicket, otherwise (in case of directory tickets) checks if the provided lookuphash translates to a ReferenceObject (representation of the file in the database) whose path starts with the file_hash_pathin the ticket (i.e. the requested file lies inside the directory for which the ticket is issued).

    • Checks the time now is later than availableAfter from ShareInfo stored for this ticket.

    • Check the ticket is not revoked (see Revoking).

Listing files in a shared folder

To list the files listed under the shared path in the AuthTicket, you can use the list command from zboxcli:

./zbox list --authticket $AUTH_TICKET

Check the zboxcli repo README for full usage docs of this command.

What happens under the hood is simply:

  • The client (in this case zboxcli, via Zboxcore SDK) build a ListRequest with the AuthTicket and the file_path_hash.

listReq := &ListRequest{Consensus: Consensus{RWMutex: &sync.RWMutex{}}}
listReq.allocationID = a.ID
listReq.allocationTx = a.Tx
listReq.blobbers = a.Blobbers
listReq.fullconsensus = a.fullconsensus
listReq.consensusThresh = a.consensusThreshold
listReq.ctx = a.ctx
listReq.remotefilepathhash = lookupHash
listReq.authToken = at
// It later adds "offset" and "limit" for the request for pagination.
  • The client then sends the list request to the allocation blobbers, seeking a consensus based on the returned results. The blobber API endpoint used is: /v1/file/list/(see Blobber API)

  • The blobber will then verify the AuthTicket (same as in Download) and prepare the list of descendant files/directories of the required path, based on the given parameters.

  • The client collects replies from the blobbers and returns the result in case consensus is achieved.

Revoking Access (Public/Private)

To revoke access for a publicly shared file, you'll need to use the zbox share endpoint with --revokeflag:

./zbox share --allocation <allocation-id> --revoke --remotepath <remote-path-of-the-shared-file> --clientid <client-id> 

Check the zboxcli repo README for full usage docs of this command.

What happens under the hood is simply:

  • The client (in this case zboxcli, via Zboxcore SDK) sends revoke share request to all the blobbers of the allocation. The blobber API endpoint used is: DELETE /v1/marketplace/shareinfo/{allocation} (see Blobber API).

  • The blobber deletes the token related to the mentioned file (and the mentioned client in case of private sharing).

Note on Private Sharing & Proxy Re-encryption

To share files privately, you need to provide the following in order to get the AuthTicket as mentioned above in Sharing section :

  • allocation ID

  • remotePath

  • wallet ID of the receiver

  • encryption public key of the receiver.

Proxy Re-encryption is implemented by encrypting the response of the download request of the privately shared file, when accessed by the client with whom it's shared, by their encryption public key. This keeps the data completely secure and cannot be read except by the owner of the private key corresponding to the PK by which it was encrypted, who should be the owner of the ticket.

Always keep your private keys safe and secure.

Last updated