cosmian_cover_crypt v10.0.0
CoverCrypt
Implementation of the CoverCrypt algorithm which allows creating ciphertexts for a set of attributes and issuing user keys with access policies over these attributes.
Getting started
See examples/runme.rs for a code sample that
introduces the main CoverCrypt functionalities. It can be run using
cargo run --example runme.
Building and testing
To build the core only, run:
cargo build --releaseTo build the FFI interface:
cargo build --release --features ffiTo build the WASM interface:
cargo build --release --features wasm_bindgenTo build the Python interface, run:
maturin build --release --features pythonNote: when a new function or class is added to the PyO3 interface, its
signature needs to be added to
__init__.pyi.
To run tests on the Python interface, run:
./python/scripts/test.shTo build everything (including the FFI):
cargo build --release --all-featuresThe latter will build a shared library. On Linux, one can verify that the FFI symbols are present using:
objdump -T target/release/libcosmian_cover_crypt.soThe code contains numerous tests that you can run using:
cargo test --release --all-featuresBenchmarks can be run using (one can pass any feature flag):
cargo benchBuilding the library for a different glibc
Go to the build directory for an example on how to build for GLIBC 2.17
Building the library for cloudproof_java or cloudproof_flutter
From the root directory:
cargo build --release --features ffiBuild the library for cloudproof_js
From the root directory:
cargo build --release --features wasm_bindgenBuild the library for cloudproof_python
From the root directory:
maturin build --release --features pythonFeatures
In CoverCrypt, messages are encrypted using a symmetric scheme. The right management is performed by a novel asymmetric scheme which is used to encapsulate a symmetric key. This encapsulation is stored in an object called encrypted header, along with the symmetric ciphertext.
This design brings several advantages:
- the central authority has a unique key to protect (the master secret key);
- encapsulation can be performed without the need to store any sensitive information (public cryptography);
- encryption is as fast as symmetric schemes can be.
Key generation
Asymmetric keys must be generated beforehand. This is the role of a central authority, which is in charge of:
- generating and updating the master keys according to the right policy;
- generate and update user secret keys.
The CoverCrypt APIs exposes everything that is needed:
CoverCrypt::setup: generate master keysCoverCrypt::join: create a user secret key for the given rightsCoverCrypt::update: update the master keys for the given policyCoverCrypt::refresh: refresh a user secret key from the master secret key
The key generations may be long if the policy contains many rights or if there are many users. But this is usually run once at setup. Key updates and refresh stay fast if the change in the policy is small.
Serialization
The size of the serialized keys and encapsulation is given by the following formulas:
- master secret key:
3 * PRIVATE_KEY_LENGTH + LEB128_sizeof(partitions.len()) \
+ sum(LEB128_sizeof(sizeof(partition)) + sizeof(partition)
+ PRIVATE_KEY_LENGTH + 1 [+ INDCPA_KYBER_PRIVATE_KEY_LENGTH])- public key:
2 * PUBLIC_KEY_LENGTH + LEB128_sizeof(partitions.len()) \
+ sum(LEB128_sizeof(sizeof(partition)) + sizeof(partition)
+ PUBLIC_KEY_LENGTH + 1 [+ INDCPA_KYBER_PUBLIC_KEY_LENGTH])- user secret key:
2 * PRIVATE_KEY_LENGTH + LEB128_sizeof(partitions.len()) \
+ partition.len() * (PRIVATE_KEY_LENGTH + 1 [+ INDCPA_KYBER_PRIVATE_KEY_LENGTH])- encapsulation:
2 * PUBLIC_KEY_LENGTH + TAG_LENGTH + LEB128_sizeof(partitions.len())
+ partition.len() * [INDCPA_KYBER_CIPHERTEXT_LENGTH | PUBLIC_KEY_LENGTH]- encrypted header (see below):
sizeof(encapsulation) + DEM_ENCRYPTION_OVERHEAD + sizeof(plaintext)NOTE: For our implementation CoverCryptX25519Aes256:
PUBLIC_KEY_LENGTHis 32 bytesPRIVATE_KEY_LENGTHis 32 bytesTAG_LENGTHis 32 bytesDEM_ENCRYPTION_OVERHEADis 28 bytes (12 bytes for the MAC tag and 16 bytes for the nonce)LEB128_sizeof(n)is equal to 1 byte ifnis less than2^7
Secret key encapsulation
This is the core of the CoverCrypt scheme. It allows creating a symmetric key and its encapsulation for a given set of rights.
To ease the management of the encapsulations, an object EncryptedHeaderis
provided in the API. An encrypted header holds an encapsulation and a symmetric
ciphertext of an optional additional data. This additional data can be useful
to store metadata.
Classic implementation sizes:
| Nb. of partitions | Encapsulation size (in bytes) | User decryption key size (in bytes) |
|---|---|---|
| 1 | 131 | 98 |
| 2 | 164 | 131 |
| 3 | 197 | 164 |
| 4 | 230 | 197 |
| 5 | 263 | 230 |
Post-quantum implementation sizes:
| Nb. of partitions | Encapsulation size (in bytes) | User decryption key size (in bytes) |
|---|---|---|
| 1 | 1187 | 1250 |
| 2 | 2276 | 2435 |
| 3 | 3365 | 3620 |
| 4 | 4454 | 4805 |
| 5 | 5543 | 5990 |
Note: encapsulations grow bigger with the size of the target set of rights and so does the encapsulation time.
Secret key decapsulation
A user can retrieve the symmetric key needed to decrypt a CoverCrypt ciphertext
by decrypting the associated EncryptedHeader. This is only possible if the
user secret keys contains the appropriate rights.
Benchmarks
The benchmarks presented in this section are run on a Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz.
CoverCrypt classic implementation CoverCrypt post-quantum implementation
Documentation
A formal description and proof of the CoverCrypt scheme is given in this paper. It also contains an interesting discussion about the implementation.
The developer documentation can be found on doc.rs
Releases
All releases can be found in the public URL package.cosmian.com.