# File Sharing

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.&#x20;

### Sharing Internals <a href="#id-5fkfvyecdwr6" id="id-5fkfvyecdwr6"></a>

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 <a href="#lroxpwrce1dd" id="lroxpwrce1dd"></a>

```go
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:

| Parameter           | Description                                                                                                                                                                                                          |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `client_id`         | The client of the user with whom you want to share this file/folder, or empty in case of public sharing.                                                                                                             |
| `owner_id`          | The ID (or wallet address) of the owner of the allocation.                                                                                                                                                           |
| `allocation_id`     | The ID of the allocation containing this file.                                                                                                                                                                       |
| `file_path_hash`    | Hash of the file/folder path.                                                                                                                                                                                        |
| `actual_file_hash`  | The actual hash of the contents of the shared file, which is used in the [file system](https://docs.zus.network/zus-docs/system-overview/storage/file-operations/broken-reference), or just empty in case of folder. |
| `file_name`         | The name of the shared file/folder.                                                                                                                                                                                  |
| `reference_type`    | Indicates whether it is a file or a folder.                                                                                                                                                                          |
| `expiration`        | The duration for which the AuthTicket remains valid.                                                                                                                                                                 |
| `timestamp`         | The timestamp when the AuthTicket was created.                                                                                                                                                                       |
| `re_encryption_key` | This is the Re-Encryption key used in case of private sharing. Discussed below in [Private Sharing](#nvpayhmkau3u).                                                                                                  |
| `encrypted`         | Indicates whether the file should be encrypted by the recipient public key on retrieval. Discussed below in [Private Sharing](#nvpayhmkau3u).                                                                        |
| `signature`         | The signature of the AuthTicket, used for validation.                                                                                                                                                                |

### Share a file/folder using zboxcli <a href="#id-4wu9mu9tlcul" id="id-4wu9mu9tlcul"></a>

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](https://github.com/0chain/zboxcli?tab=readme-ov-file#share)  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](https://docs.zus.network/zus-docs/sdks/go-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](https://docs.zus.network/zus-docs/http-apis#blobber-api) documentation).
* The blobber creates/updates the `ShareInfo` for the `file_path_hash` in the `AuthTicket`, after validating the request.

```go
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 <a href="#id-4wu9mu9tlcul" id="id-4wu9mu9tlcul"></a>

To download a shared file, you can utilize the `download` command from [zboxcli](https://docs.zus.network/zus-docs/clis/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](https://github.com/0chain/zboxcli?tab=readme-ov-file#download) for full usage docs of this command.&#x20;

{% hint style="info" %}
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`](https://github.com/0chain/gosdk/blob/doc/initial/core/encryption/README.md#func-hash) function of  encryption package in GoSDK.
{% endhint %}

What happens in the background is simply:

* The client (in this case zboxcli, via [Zboxcore SDK](https://docs.zus.network/zus-docs/sdks/go-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](https://docs.zus.network/zus-docs/http-apis#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](https://docs.zus.network/zus-docs/system-overview/storage/file-operations/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.&#x20;
  * Checks the expiry, if expiration date is provided. Otherwise, a default expiry date of **90 Days&#x20;**&#x20;use&#x64;*.*
  * 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](https://docs.zus.network/zus-docs/system-overview/storage/protocol/reference-objects) (representation of the file in the database) whose path starts with the `file_hash_path`in the ticket (i.e. the requested file lies inside the directory for which the ticket is issued).
  * &#x20;Checks the time now is later than `availableAfter` from `ShareInfo` stored for this ticket.
  * Check the ticket is not revoked (see [Revoking](#revoking-tickets)).

### Listing files in a shared folder <a href="#id-4wu9mu9tlcul" id="id-4wu9mu9tlcul"></a>

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](https://github.com/0chain/zboxcli?tab=readme-ov-file#list) for full usage docs of this command.&#x20;

What happens under the hood is simply:

* The client (in this case zboxcli, via [Zboxcore SDK](https://docs.zus.network/zus-docs/sdks/go-sdk)) build a ListRequest with the AuthTicket and the `file_path_hash.`

```go
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](https://docs.zus.network/zus-docs/http-apis#blobber-api))
* The blobber will then verify the AuthTicket (same as in [Download](#id-4wu9mu9tlcul-1)) 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 `--revoke`flag:

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

Check the [zboxcli repo README](https://github.com/0chain/zboxcli/tree/doc/update?tab=readme-ov-file#share) for full usage docs of this command.

What happens under the hood is simply:

* The client (in this case zboxcli, via [Zboxcore SDK](https://docs.zus.network/zus-docs/sdks/go-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](https://docs.zus.network/zus-docs/http-apis#blobber-api)).
* The blobber deletes the token related to the mentioned file (and the mentioned client in case of private sharing).

### Private Sharing & Proxy Re-encryption <a href="#nvpayhmkau3u" id="nvpayhmkau3u"></a>

Our storage system enables secure private file sharing through **authorization tickets (auth tickets)** while maintaining access control and data confidentiality.&#x20;

When a user shares a file privately, they generate an auth ticket tied to a specific recipient (client ID). This ensures that only the intended user can access the shared file without exposing the data to unauthorized parties.

For encrypted files, the system utilizes a **proxy re-encryption (PRE) scheme** that allows file sharing without requiring the owner to download and manually re-encrypt the data. This ensures a secure and efficient sharing process while maintaining end-to-end encryption.

#### **1. Referee Key Generation**

Before a file is shared, the recipient, referred to as the **referee**, generates an encryption key pair.

* The key pair consists of a **private key** and a **public encryption key**.
* The public encryption key is derived from the referee's private key, ensuring that only the referee can decrypt the final re-encrypted file.

#### **2. Re-Encryption Key Computation**

To enable proxy re-encryption, the **file owner** generates a re-encryption key using the following inputs:

* Their **private key**.
* The **public encryption key** of the referee.
* The **original encryption key** of the file, which is unique for every encrypted file.

This computed **re-encryption key** is included in the **auth ticket** and stored on the **blobbers** responsible for holding the file.

**3. Proxy Re-Encryption by Blobbers**

When the referee initiates the file download, the blobbers apply the **re-encryption key** to transform the encrypted file.

* The blobbers perform the re-encryption process without decrypting the file.
* The transformed file remains encrypted and is accessible only to the referee.
* Since the blobbers never gain access to the decrypted data, end-to-end encryption is preserved.

**4. Decryption by the Referee**

Once the re-encrypted file is retrieved, the referee decrypts it using their **private key**.

* The private key used for decryption corresponds to the public encryption key that was provided for re-encryption.
* The referee can seamlessly access the shared file without requiring any additional steps from the file owner.

Proxy re-encryption ensures that file sharing remains both secure and efficient without compromising data confidentiality.

* The file owner does not need to manually re-encrypt the data before sharing it with different users.
* Data remains encrypted throughout the entire process, ensuring security even during re-encryption.
* Blobbers facilitate the re-encryption process without having access to the actual file contents.
* Only the intended recipient can decrypt and access the file, preventing unauthorized access.

{% hint style="warning" %}
Always keep your private keys safe and secure.
{% endhint %}
