Introduction
Welcome to the documentation site for our Secure Storage Software : Qasmat.
Qasmat is a secure distributed storage system based on Shamir's Secret Sharing to split files into pieces and store them on a network of storage servers. It ensures data availability even when some servers are offline, without compromising security as in traditional redundancy. The system prevents an attacker having access to some servers from gaining information on the protected files.
This documentation provides information on how to install and use the software along with explanations on its security features and how it works.
It follows the diátaxis approach: the documentation is split into four parts corresponding to different needs.
Use Qasmat online
⚠️ Warning: Do not store critical information this is still an alpha-version
Qasmat is deployed on our servers and can be used to test the software. The web page is accessible here.
Authentication
If have followed the workflow for the 100 first users you should have the credentials required to authenticated on the website. Otherwise please follow the instruction on our website.
The dashboard
Once authenticated, you can access the dashboard which gathers information about the files, the storage servers and different buttons to manage them.
Deployment
🚧 Work in progress: Deployement scripts and Docker images will be made available soon.
In this tutorial you will learn how to deploy a Qasmat network. Note that it is cloud-agnostic.
Docker image and Kubernetes
The software is packaged in a Docker image: the container assembles a binary version of the software and all the dependencies that are needed for it to run. It is stored in a distribution registry. A Kubernetes entity manages different pods containing the Docker image along with some storage volumes. It is responsible for the deployment of the network and its stability. Finally, an script is written to automate the different deployment phases.
As a user you simply need to install a few packages, download the docker images and the script and run it.
The script
Ansible
We use Ansible to automate the management of remote systems and control their desired state, in particular to deploy the Qasmat network.
A comprehensive diagram can be found here, but here is a description of the main components.
- Control machine (node)
A system on which Ansible is installed. You run Ansible commands such as
ansible
oransible-inventory
on a control node. This should be any UNIX-like machine with python installed. It is possible to use a WSL too. - Inventory
A list of remote (managed) machines that are logically organized. You create an inventory on the control machine to describe host deployments to Ansible. In our case it is a
.yml
file - Managed machine (node)
A remote machine, system, or host, that Ansible controls. Does not require Ansible to be installed, but does require Python. The managed node also needs a user account (
ansible_user
) that can connect via SSH to the node with an interactive shell.
The container registry
The script is made of different files and will be available soon. Here is the documentation to access the files
There are the following Ansible files:
ansible.cfg
: Ansible configuration file.inventory.yml
: Remote hosts listed.playbook.yml
: Ansible tasks list.vars.yaml
: Variables as key-value pairs.
The playbook is the main file, it is a list of tasks that define the order in which Ansible performs operations, from top to bottom, to achieve an overall goal.
Configurations
You can write configuration files for the proxy or the storage servers and complete the script with them. See the configuration section for more information.
Launch the script
Finally, launch the script with
# verify your inventory
ansible-inventory -i inventory.yml --list
# ping vps group in your inventory
ansible vps -m ping -i inventory.yml
# run the ansible playbook to execute the task list on the remote machine
ansible-playbook playbook.yml -i inventory.ymlansible launch
Web client
Once deployed, the software can be used through the web client, see the dashboard section for more information about the interface. You can also check Deploy the web client to see the details on how to configure your client deployment.
Configuration
Each server (proxy or storage) can be started with the default configuration or a custom one.
Default values
Here are the default values :
- discovery : local
- network security : public
- encryption_and_kms : None
- web port : fixed 3000
- web address : 0.0.0.0
- max file size : 1 000 000 000 bytes (1GB)
- allowed cors origins : * (allow everything)
- checking_interval: 1 day
- renewal_duration: 15 days
- expiry_duration: 30 days
- proxy_reconnection_interval: 30 seconds
However it is possible to write a custom configuration.
Proxy
{
"discovery_mode":"Local" or {"Remote": {"proxy_port": <port>}},
"network_security_configuration":{
"network_security":"Public" or {"Private":{"path_to_preshared_key":"<path to key>"}},
"encryption_and_kms": (optional) ["AES" or "OTP", "address":"<address of the kms>","port":<port of the kms>]
},
"web_configuration":{
"bind_port":{"bind_port":{"Fixed":<port>} or "Auto"},
"bind_address":"<address>",
"max_file_size": <positive number>,
"allowed_cors_origins": ["*" or <list of allowed origins>]
},
"time_keeper_configuration": {
"checking_interval": {"secs":<number of seconds>,"nanos":0},
"renewal_duration": {"secs":<number of seconds>,"nanos":0},
"expiry_duration":{"secs":<number of seconds>,"nanos":0}
}
}
Storage
{
"discovery_mode":"Local" or {"Remote": {"proxy_address": "<address>", "proxy_port": <port>}},
"network_security_configuration":{
"network_security":"Public" or {"Private":{"path_to_preshared_key":"<path to key>"}},
"encryption_and_kms": (optional) ["AES" or "OTP", "address":"<address of the kms>","port":<port of the kms>]
},
"proxy_reconnection_interval": <number of seconds>
}
Value descriptions
If you need a pre-shared key, it can be produced with the following command :
openssl rand -hex 32
Deploy the web client
In order to access Qasmat, you can install the official web client on your server. The web client is a SPA (single-page application) built with VueJS 3 and Typescript.
If you're using a private instance of Qasmat (CORS Allowed Origin set to anything other than '*'), then you will need to also add authentication to the web client. The web client must be protected by your authentication layer like your Qasmat instance. See Authentication for more details.
After deploying the client, you can configure it with the config/config.json
file.
The configuration file accepts these options:
{
"authAddress": "https://auth.provider.url/",
"APIAddress": "https://api.qasmat.url/api",
"isPublicInstance": false,
"minThreshold": 2,
"canEditConfig": false
}
authAddress
is the URL of your authentication provider. It is used to make the logout button work in the Settings tab.APIAddress
is the URL of your Qasmat's proxy server.isPublicInstance
toggles whether or not the Qasmat's proxy server you're trying to use is public (CORS Allowed Origins set to Any/*).minThreshold
is the minimum number of servers needed to protect a file. In order to work, it must be positive and not equal to 0. Though, using 1 is not recommended since it is missing the point of using Qasmat.canEditConfig
toggles whether or not the user can edit theauthAddress
,APIAddress
andisPublicInstance
properties of their client.
Cryptography
Here is a list of some of the cryptographic protocols or constant values used in Qasmat.
Communication
The protocol noise
is used instead of TLS to secure the communications.
Confidentiality
All calculations are modular, the modulus used is the one defined in RFC 3526. It of size 2 ^ 8192.
Integrity
Pedersen's commitment scheme with NIST P-256 curve is used for file integrity.
API
The communication between the user and the proxy server is done through this REST API. It is specified as follows :
Endpoint | Request type | Fields to supply (if any) | Description | Response type (see skeleton below) |
---|---|---|---|---|
/api/storage | GET | None | Returns information about connected storage servers | servers: String[], locations: String[], hosts: String[], pings: Number[] |
/api/file | GET | None | Returns the list of currently protected files and a percentage of storage use | files: File[], percentage: Number |
/api/configuration | GET | None | Returns a list of information about the configuration | version: String, limit: Number, max_file_size: Number |
/api/file/protect | POST | - threshold (number): number of parts- file (file): the file to protect | Protects a file | null |
/api/file/retrieve | POST | - name (string): the filename | Retrieves a file | File data as a stream of bytes |
/api/file/remove | POST | - name (string): the filename | Removes a file | null |
JSON response skeletons:
HTTP codes 2xx (except for /api/file/retrieve
)
{
"code": number,
"status": "string",
"data": any // depends on the request, see Response type in the tab
}
HTTP codes 3xx - 5xx
{
"code": number,
"status": "error",
"message": string
}
File specification
In our API, a File is defined by these properties:
Name | Type | Description |
---|---|---|
date_of_protection | Date | Represents when the file was protected by the user. |
expired | Boolean | Represents the expiration state of the shares in the databases. |
filename | String | The name of the file. |
hash | Int[] | Represents the hash of the file, to verify its integrity. |
k | Int | The threshold the file is protected with. |
last_renewal | Date | Last time the file got renewed in the databases. |
Authentication
Qasmat has a "limited" support for authentication: you need to have your own authentication layer on top of it.
Header SSO (Header Single Sign-on)
Qasmat has support for authentication through the usage of the Remote-User
and Remote-Email
header. This header needs to contain a unique string identifying the user, which in our case is an email.
Please note that while the Remote-User
does not need to be unique, the Remote-Email
needs to be unique because it authenticates the user for Qasmat. Your authentication layer must verify that emails are used only for one account.
One of the authentication provider that implements these headers is Authelia, an open-source authentication and authorization server that we used during the development to manage our users.
If you need authentication, you need to make sure Qasmat is not directly accessible from the outside, and that requests to the API are all intercepted by your authentication layer. If you are using Authelia, you should check the Supported Proxies page on their documentation.
During development and testing, we used Caddy for reverse-proxying Qasmat and Authelia, and also to serve the web client. Please note that to use Authelia you need HTTPS to be activated (and, it is a good practice to use HTTPS by default!).
Here's a scheme of how the apps must be on your server from a user point of view. the web client and Qasmat must not be accessible without passing by the authentication provider.
User
|
|
.----- Authentication provider (Authelia, ...) -----.
| |
| .------------------. .--------------. |
| | Web client | | Qasmat | |
| '------------------' '--------------' |
| |
'---------------------------------------------------'
Web client
You'll also need to secure your web client behind your authentication layer to make sure anyone trying to use it is authenticated, since the web client does not have the login/logout/register mechanisms implemented.
In the web client's Settings tab, you'll be able to change the Qasmat server's URL to specify a specific instance of Qasmat that you'd want to use (if your web client provider permits it, see Deploy the web client). By default, it is http://localhost:3000.
CORS (Cross-Origin Resource Sharing)
In order to use authentication in a browser context, you may need to configure Cross-Origin Resource Sharing.
CORS is a way for your browser to know if it's allowed to send requests to your API. Your browser will send a pre-flight request to the server to get the settings of it, and then will decide if it can pursue with the real request.
For Qasmat, you'll only need to specify the allowed origins field and put your allowed URL (for example, https://example.com). Note that if you use *
as an origin, Qasmat will start in public mode and any client that can access your server will be able to access your instance, which could be a security risk.
The CORS configuration used for Qasmat is:
- Allow the origins specified in the configuration.
- Let web browsers access the
X-File-Integrity
header. - Accept any header in the requests received by the server.
- Accept credentials if the origin is anything else than
*
.
For more informations, you can check MDN - Cross-origin resource sharing (CORS).
What is Qasmat ?
Qasmat is a distributed secure storage software. It is based on the protocol Lincos which itself is based on Shamir's secret sharing scheme.
Shamir's Secret Sharing is a cryptographic method that allows a secret to be divided into several shares. The secret can only be reconstructed by combining a certain number of these shares. This is done by creating a polynomial where the secret is a point on the graph, and shares are other points. To reconstruct the secret, a minimum number of shares are used to recreate the polynomial thanks to Lagrange's interpolation. This method ensures security as long as the number of shares combined is less than the threshold.
Lincos is a protocol which includes a secret sharing scheme such as Shamir's which ensures the confidentiality of data at rest. The protocol also describes how to manage confidentiality in transit, integrity and authentication to achieve long-term unconditional security.
Finally, Qasmat is an implementation of this protocol in Rust. It consists of two programs :
- The proxy : It interacts with the user via its API, implements the Shamir and Lagrange algorithms, handles integrity proofs, etc.
- The storage servers: They respond to requests coming from the proxy server by storing or retrieving shares in their database.
The maths behind
Imagine having to draw a line passing through a single point, there is an infinite number of possibilities. However, if two different points are required, one and only one line is now possible. This very simple idea is at the heart of Shamir's secret sharing and Lagrange's interpolation around which Qasmat is built.
The line is replaced by a polynomial of degree k-1 whose value at zero is the secret to be protected and other coefficients are chosen at random. Then at least k distinct points of this polynomial are distributed on distant servers.
To recover the secret, at least k points of the polynomial are retrieved from different servers and the polynomial is constructed with Lagrange's interpolation (visualize here). P(0) corresponding to the secret is then computed.
The number of points distributed (n) must be greater than k. Those two values constitute a threshold (k,n) whose value is determined according to the required security (see Security at rest).
Since the coefficients are integers, everything is modular. The modulus is a prime number which avoids basic attacks.
A file journey
First, the file is sent from the user's browser to the proxy server via HTTP/HTTPS. Then, because of the modulus in all the calculations, the file is split into chunks of size smaller than the modulus : the parts. Each part goes through Shamir: n shares are created. When enough shares are ready to be sent to a specific storage, the communication module triggers a request-response exchange with the storage server.
+----------------+
| |
| User's browser |
| |
+---------+------+ +-------------+
| | |
|HTTP/HTTPS | Storage 1 |
+--+--------------------------------------------------+ | |
| | Proxy server | +------^------+
| | +---------+ | |
| | Share 1,1 |Share 1,1| | |
| | +-------> ... |... +-+----------+
| v | Share 1,n |Share p,1| | +-------------+
| Part 1 +---------+ | | |
| File ------> ... ... -+-------> Storage ... |
| Part p +---------+ | | |
| | Share p,1 |Share 1,n| | +-------------+
| +-------> ... |... +-+----------+
| Share p,n |Share p,n| | |
| +---------+ | |
| | +------v------+
+-----------------------------------------------------+ | |
| Storage p |
| |
+-------------+
Once all part have been processed, a description of the file containing all the necessary information is stored on the proxy server.
Protection of a file (gif)
Retrieval of a file (gif)
Security
The following chapters describe the security features of the software.
- At rest: The security of data once stored on the storage servers.
- In transit: The security of the communication between the proxy and the storage servers.
At rest
The secret file is distributed over the network of storage servers with a threshold (k,n) :
- k : the number of shares required to rebuild the secret
- n : the number of shares distributed (>=k) This threshold offers two main security features :
Redundancy
Since n can be greater than k, a secret can be recovered despite unavailability of some storage servers. For example a secret stored with threshold (k=3,n=5) : the information of only 3 servers is required which means that if 2 servers are unavailable, the secret can still be reconstructed !
Confidentiality against mobile adversary threat
The threat here is an adversary who gains access to less than k storage servers in a given time. The scheme ensures that it will get no information on the file in this given time. The shares are renewed periodically to prevent the adversary from gaining access to more than k servers and thus being able to retrieve the file.
For example if a secret is stored with threshold (k=3,n=5), an adversary who reads the contents of 2 storage servers won't get any information on the secret file.
In transit: the Quantum part
Communication between the proxy server and the storage servers must remain secure to prevent an attacker from retrieving the shares and reconstructing the secret. This can be done with either classical or quantum cryptography.
Classical security uses standard protocols, see the cryptography section for more information.
Quantum cryptography
But Qasmat can also run on top of a QKD system (see Qline): using keys produced with quantum communication and achieve information-theoretic security.
This requires a software stack to apply the protocol and manage the keys. In addition, to be quantum-ready it is possible to simulate the hardware using our software.
Those three pieces of software form a stack that is used with Qasmat to allow quantum-readiness.
ETSI 14
In order to be able to use different QKD systems, Qasmat is based on the standard ETSI 14. This is a REST-based API used by most of QKD system to serve the key produced. Our software retrieves the keys using the requests and responses described in this document and can thus work with most of the QKD systems.