Skip to content

Commit

Permalink
chore: Merge branch 'release/v11.0.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
Manuthor committed May 3, 2023
2 parents 33bfa08 + bae9773 commit 9e28709
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 59 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ jobs:
needs:
- cargo-lint
uses: Cosmian/reusable_workflows/.github/workflows/cargo-publish.yml@develop
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
if: startsWith(github.ref, 'refs/tags/')
with:
toolchain: stable
secrets: inherit
cleanup:
needs:
- cargo-lint
uses: Cosmian/reusable_workflows/.github/workflows/cleanup_cache.yml@develop
secrets: inherit
21 changes: 19 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,14 @@ repos:
rev: v0.33.0
hooks:
- id: markdownlint-fix
args: [--disable=MD013, --disable=MD024, --disable=MD041]
args: [--disable=MD004, --disable=MD013, --disable=MD024, --disable=MD041]

- repo: https://github.com/Lucas-C/pre-commit-hooks-nodejs
rev: v1.1.2
hooks:
- id: htmlhint
- id: dockerfile_lint
- id: markdown-toc
args: [--bullets="-"] # comment this to refresh TOC

- repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt
rev: 0.2.2
Expand Down Expand Up @@ -96,6 +95,24 @@ repos:
args: [--allow-dirty]
- id: dprint-toml-fix

- repo: https://github.com/Cosmian/git-hooks.git
rev: v1.0.9
hooks:
- id: stable-cargo-format
- id: dprint-toml-fix
- id: cargo-update
- id: cargo-udeps
- id: cargo-tests-all
- id: cargo-test-doc
- id: cargo-check-semver
- id: clippy-autofix-all
- id: clippy-autofix-pedantic
- id: clippy-autofix-nursery
- id: clippy-autofix-others
- id: clippy-all-targets-all-features
- id: cargo-dry-publish
args: [--allow-dirty]

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

All notable changes to this project will be documented in this file.

## [11.0.1] - 2023-05-03

### Documentation

- Fix formulas + describe how partitions work

### Miscellaneous Tasks

- Release 11.0.1 in order to upgrade crypto_core and use ECIES

### Ci

- Missing github caches cleanup

---

## [11.0.0] - 2023-03-01
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cosmian_cover_crypt"
version = "11.0.0"
version = "11.0.1"
authors = [
"Théophile Brezot <[email protected]>",
"Bruno Grieder <[email protected]>",
Expand Down Expand Up @@ -28,7 +28,7 @@ hybridized_bench = []

[dependencies]
base64 = { version = "0.21.0", optional = true }
cosmian_crypto_core = "7.0"
cosmian_crypto_core = "7.1.0"
# TODO (TBZ): why do we need `std` feature here?
pqc_kyber = { version = "0.4", features = ["std", "hazmat"] }
serde = { version = "1.0", features = ["derive"] }
Expand Down
173 changes: 119 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ policies over these attributes.
- [Getting started](#getting-started)
- [Building and testing](#building-and-testing)
- [Features](#features)
- [Key generation](#key-generation)
- [Serialization](#serialization)
- [Secret key encapsulation](#secret-key-encapsulation)
- [Secret key decapsulation](#secret-key-decapsulation)
* [Key generation](#key-generation)
* [Policies and partitions](#policies-and-partitions)
* [Serialization](#serialization)
* [Symmetric key encapsulation](#symmetric-key-encapsulation)
* [Secret key decapsulation](#secret-key-decapsulation)
- [Benchmarks](#benchmarks)
- [Documentation](#documentation)

Expand Down Expand Up @@ -56,9 +57,9 @@ bash ./benches/generate.sh
## Features

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.
management is performed by a novel asymmetric scheme used to encapsulate a
symmetric key for a set of attributes. This encapsulation is stored in an
object called encrypted header, along with the symmetric ciphertext.

This design brings several advantages:

Expand All @@ -67,74 +68,138 @@ This design brings several advantages:
information (public cryptography);
- encryption is as fast as symmetric schemes can be.

CoverCrypt encryption is post-quantum secure (with a post-quantum security
level of 128 bits):

- all encapsulations can be hybridized using INDCPA-KYBER, the INDCPA (a
security level) version of the NIST standard for the post-quantum KEM,
[Kyber](https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=8406610);
the formal proof of the security can be found in the [CoverCrypt
paper](#documentation).
- the actual data is encrypted using AES-GCM with a 256-bit key.

The CoverCrypt scheme also ensures that:

- user secret keys are unique;
- user secret keys are traceable (under some assumption, cf
[CoverCrypt paper](#documentation)).

### 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.
- generate and update user secret keys according to its rights.

The CoverCrypt APIs exposes everything that is needed:
The CoverCrypt API exposes 4 functions:

- `CoverCrypt::setup` : generate master keys
- `CoverCrypt::join` : create a user secret key for the given rights
- `CoverCrypt::update` : update the master keys for the given policy
- `CoverCrypt::refresh` : refresh a user secret key from the master secret key
- `CoverCrypt::generate_master_keys`: generate master keys
- `CoverCrypt::update_master_keys`: update the master keys
- `CoverCrypt::generate_user_secret_key`: create a user secret key
- `CoverCrypt::refresh_user_secret_key`: update a user 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.
are many users. But this is usually run once at setup. Key update and refresh
stay fast if the changes are small.

### Policies and partitions

CoverCrypt is an attribute-based encryption algorithm. This means that an
encrypted header produced for the attributes `France` and `Top Secret` can only
be decrypted by the user holding a key corresponding to these attributes.

In order to transform this high-level view into encapsulations, the following
objects are defined:

- **policy**: defines all possible rights; a policy is built from a set of
axes which are composed of sets of attributes.
- **encryption policy**: subset of the policy used to encrypt; an encryption
policy is expressed as a boolean expression of attributes.
- **user policy**: subset of the policy for which a user key enables
decryption; a user policy is expressed as a boolean expression of attributes.
- **partition**: combination of one attribute from each policy axis.

When generating the master keys, the global policy is converted into the set of
all possible partitions and a keypair is generated for each one of these
partitions. The master public key holds all the public key of all these
keypairs and the master secret key holds the secret key of all these keypairs.

When encrypting for a given encryption policy, this policy is converted into a
set of partitions. Then, one key encapsulation is generated per partition using
the corresponding public sub-key in the master public key.

Similarly, when generating a user secret key for a given user policy, this
policy is converted into the set of corresponding partitions and the user
receives the secret sub-key associated to each partitions.

**Example**: the following policy is composed of two axes. The `Security` axis
composed of three attributes and the `Country` axis composed of 4 attributes.

```txt
Polixy: {
Security: { // <- first axis
None,
Medium,
High
},
Country: { // <- second axis
France,
Germany,
UK,
Spain
}
}
```

The encryption policy `Security::Medium && ( Country::France ||
Country::Spain)` would be converted into two partitions. The encryption policy
`Security::High` would be expanded into `Security::High && (Country::France ||
... || Country::Spain)` then converted into 4 partitions.

### Serialization

The size of the serialized keys and encapsulation is given by the following formulas:

- master secret key:

```c
3 * PRIVATE_KEY_LENGTH + LEB128_sizeof(partitions.len()) \
+ sum(LEB128_sizeof(sizeof(partition)) + sizeof(partition)
+ PRIVATE_KEY_LENGTH + 1 [+ INDCPA_KYBER_PRIVATE_KEY_LENGTH])
```
$$3 \cdot L_{sk} + \texttt{LEB128sizeof}(n_{p}) + \sum\limits_{p~\in~partitions} \left( \texttt{LEB128sizeof}(\texttt{sizeof}(p)) + \texttt{sizeof}(p) + 1 + L_{sk} + \delta_{p,~h} \cdot L_{sk}^{pq}\right)$$

- public key:

```c
2 * PUBLIC_KEY_LENGTH + LEB128_sizeof(partitions.len()) \
+ sum(LEB128_sizeof(sizeof(partition)) + sizeof(partition)
+ PUBLIC_KEY_LENGTH + 1 [+ INDCPA_KYBER_PUBLIC_KEY_LENGTH])
```
$$3 \cdot L_{pk} + \texttt{LEB128sizeof}(n_{p}) + \sum\limits_{p~\in~partitions} \left( \texttt{LEB128sizeof}(\texttt{sizeof}(p)) + \texttt{sizeof}(p) + 1 + L_{pk} + \delta_{p,~h} \cdot L_{pk}^{pq}\right)$$

- user secret key:

```c
2 * PRIVATE_KEY_LENGTH + LEB128_sizeof(partitions.len()) \
+ partition.len() * (PRIVATE_KEY_LENGTH + 1 [+ INDCPA_KYBER_PRIVATE_KEY_LENGTH])
```
$$2 \cdot L_{sk} + \texttt{LEB128sizeof}(n_{p}) + \sum\limits_{p~\in~partitions} \left( 1 + L_{sk} + \delta_{p,~h} \cdot L_{sk}^{pq}\right)$$

- encapsulation:

```c
2 * PUBLIC_KEY_LENGTH + TAG_LENGTH + LEB128_sizeof(partitions.len())
+ partition.len() * [INDCPA_KYBER_CIPHERTEXT_LENGTH | PUBLIC_KEY_LENGTH]
```
$$2 \cdot L_{pk} + T + \texttt{LEB128sizeof}(n_{p}) + \sum\limits_{p~\in~partitions} \left(1 + \delta_{p,~c} \cdot L_{pk} + \delta_{p,~h} \cdot L_c^{pq}\right)$$

- encrypted header (see below):
- encrypted header (encapsulation and symmetrically encrypted metadata):

```c
sizeof(encapsulation) + DEM_ENCRYPTION_OVERHEAD + sizeof(plaintext)
```
$$\texttt{sizeof}(encapsulation) + \texttt{LEB128sizeof} \left(C_{overhead} + \texttt{sizeof}(metadata)\right) + C_{overhead} + \texttt{sizeof}(metadata)$$

where:

- $n_p$ is the number of partitions related to the encryption policy
- $\delta_{p,~c} = 1$ if $p$ is a classic partition, 0 otherwise
- $\delta_{p,~h} = 1 - \delta_{p,~c}$ (i.e. 1 if $p$ is a hybridized partition,
0 otherwise)
- $\texttt{sizeof}: n \rightarrow$ size of $n$ in bytes
- $\texttt{LEB128sizeof}: n \rightarrow \left\lceil \frac{8 \cdot \texttt{sizeof}(n)}{7}\right\rceil$

**NOTE**: For our implementation `CoverCryptX25519Aes256`:

- `PUBLIC_KEY_LENGTH` is 32 bytes
- `PRIVATE_KEY_LENGTH` is 32 bytes
- `TAG_LENGTH` is 32 bytes
- `DEM_ENCRYPTION_OVERHEAD` is 28 bytes (12 bytes for the MAC tag and 16 bytes for the nonce)
- `LEB128_sizeof(n)` is equal to 1 byte if `n` is less than `2^7`
- Curve25519 public key length: $L_{pk} = 32~\textnormal{bytes}$
- Curve25519 secret key length: $L_{sk} = 32~\textnormal{bytes}$
- INDCPA-Kyber public key length: $L_{pk}^{pq} = 1184$
- INDCPA-Kyber secret key length: $L_{sk}^{pq} = 1152$
- INDCPA-Kyber ciphertext length: $L_c^{pq} = 1088$
- EAKEM tag length: $T = 16~\textnormal{bytes}$
- Symmetric encryption overhead: $C_{overhead} = 28~\textnormal{bytes}$ (16 bytes for the MAC tag and 12 bytes for the nonce)

### Secret key encapsulation
### Symmetric 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.
Expand All @@ -148,21 +213,21 @@ 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 |
| 1 | 130 | 98 |
| 2 | 163 | 131 |
| 3 | 196 | 164 |
| 4 | 229 | 197 |
| 5 | 262 | 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 |
| 1 | 1186 | 1250 |
| 2 | 2275 | 2435 |
| 3 | 3364 | 3620 |
| 4 | 4453 | 4805 |
| 5 | 5542 | 5990 |

**Note**: encapsulations grow bigger with the size of the target set of rights
and so does the encapsulation time.
Expand Down

0 comments on commit 9e28709

Please sign in to comment.