Skip to content

Commit

Permalink
fix: rename Partition into Coordinate
Browse files Browse the repository at this point in the history
  • Loading branch information
tbrezot committed Feb 2, 2024
1 parent 775c557 commit 47be160
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 268 deletions.
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ policies over these attributes.
- [Building and testing](#building-and-testing)
- [Features](#features)
* [Key generation](#key-generation)
* [Policies and partitions](#policies-and-partitions)
* [Policies and coordinates](#policies-and-coordinates)
* [Serialization](#serialization)
* [Symmetric key encapsulation](#symmetric-key-encapsulation)
* [Secret key decapsulation](#secret-key-decapsulation)
Expand Down Expand Up @@ -103,7 +103,7 @@ 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 update and refresh
stay fast if the changes are small.

### Policies and partitions
### Policies and coordinates

CoverCrypt is an attribute-based encryption algorithm. This means that an
encrypted header produced for the attributes `France` and `Top Secret` can only
Expand All @@ -118,20 +118,20 @@ objects are defined:
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.
- **coordinate**: 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
all possible coordinates and a keypair is generated for each one of these
coordinates. 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
set of coordinates. Then, one key encapsulation is generated per coordinate 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.
policy is converted into the set of corresponding coordinates and the user
receives the secret sub-key associated to each coordinates.

**Example**: the following policy is composed of two axes. The `Security` axis
composed of three attributes and the `Country` axis composed of 4 attributes.
Expand All @@ -153,9 +153,9 @@ Policy: {
```

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

### Serialization

Expand All @@ -166,17 +166,17 @@ $$3 \cdot L_{sk} + \texttt{LEB128sizeof}(|\mathcal{P}|) + \sum\limits_{p~\in~\ma
- public key:
$$2 \cdot L_{pk} + \texttt{LEB128sizeof}(|\mathcal{P}|) + \sum\limits_{p~\in~\mathcal{P}} \left( \texttt{LEB128sizeof}(\texttt{sizeof}(p)) + \texttt{sizeof}(p) + 1 + L_{pk} + \delta_{p,~h} \cdot L_{pk}^{pq}\right)$$
- user secret key:
$$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)$$
$$2 \cdot L_{sk} + \texttt{LEB128sizeof}(n_{p}) + \sum\limits_{p~\in~coordinates} \left( 1 + L_{sk} + \delta_{p,~h} \cdot L_{sk}^{pq}\right)$$
- encapsulation:
$$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)$$
$$2 \cdot L_{pk} + T + \texttt{LEB128sizeof}(n_{p}) + \sum\limits_{p~\in~coordinates} \left(1 + \delta_{p,~c} \cdot L_{pk} + \delta_{p,~h} \cdot L_c^{pq}\right)$$
- encrypted header (encapsulation and symmetrically encrypted metadata):
$$\texttt{sizeof}(encapsulation) + \texttt{LEB128sizeof} \left(C_{overhead} + \texttt{sizeof}(metadata)\right) + C_{overhead} + \texttt{sizeof}(metadata)$$

where:

- $|\mathcal{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,
- $|\mathcal{P}|$ is the number of coordinates related to the encryption policy
- $\delta_{p,~c} = 1$ if $p$ is a classic coordinate, 0 otherwise
- $\delta_{p,~h} = 1 - \delta_{p,~c}$ (i.e. 1 if $p$ is a hybridized coordinate,
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$
Expand Down Expand Up @@ -204,7 +204,7 @@ to store metadata.

Classic implementation sizes:

| Nb. of partitions | Encapsulation size (in bytes) | User decryption key size (in bytes) |
| Nb. of coordinates | Encapsulation size (in bytes) | User decryption key size (in bytes) |
|-------------------|-------------------------------|-------------------------------------|
| 1 | 130 | 98 |
| 2 | 163 | 131 |
Expand All @@ -214,7 +214,7 @@ Classic implementation sizes:

Post-quantum implementation sizes:

| Nb. of partitions | Encapsulation size (in bytes) | User decryption key size (in bytes) |
| Nb. of coordinates | Encapsulation size (in bytes) | User decryption key size (in bytes) |
|-------------------|-------------------------------|-------------------------------------|
| 1 | 1186 | 1250 |
| 2 | 2275 | 2435 |
Expand Down
26 changes: 13 additions & 13 deletions src/abe_policy/partitions.rs → src/abe_policy/coordinates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ use cosmian_crypto_core::bytes_ser_de::Serializer;

use crate::Error;

/// Partition associated to a subset. It corresponds to a combination
/// Coordinate associated to a subset. It corresponds to a combination
/// of attributes across all dimensions.
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Clone, Hash)]
pub struct Partition(pub(crate) Vec<u8>);
pub struct Coordinate(pub(crate) Vec<u8>);

impl Partition {
/// Creates a `Partition` from the given list of values.
impl Coordinate {
/// Creates a `Coordinate` from the given list of values.
pub fn from_attribute_ids(mut attribute_ids: Vec<u32>) -> Result<Self, Error> {
// guard against overflow of the 1024 bytes buffer below
if attribute_ids.len() > 200 {
return Err(Error::InvalidAttribute(
"The current implementation does not currently support more than 200 attributes \
for a partition"
for a coordinate"
.to_string(),
));
}
// the sort operation allows to get the same `Partition` for :
// the sort operation allows to get the same `Coordinate` for :
// `Department::HR && Level::Secret`
// and
// `Level::Secret && Department::HR`
Expand All @@ -34,21 +34,21 @@ impl Partition {
}
}

impl Deref for Partition {
impl Deref for Coordinate {
type Target = [u8];

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl From<Vec<u8>> for Partition {
impl From<Vec<u8>> for Coordinate {
fn from(value: Vec<u8>) -> Self {
Self(value)
}
}

impl From<&[u8]> for Partition {
impl From<&[u8]> for Coordinate {
fn from(value: &[u8]) -> Self {
Self(value.to_vec())
}
Expand All @@ -61,12 +61,12 @@ mod tests {
use super::*;

#[test]
fn test_partitions() -> Result<(), Error> {
fn test_coordinates() -> Result<(), Error> {
let mut values: Vec<u32> = vec![12, 0, u32::MAX, 1];
let partition = Partition::from_attribute_ids(values.clone())?;
// values are sorted n Partition
let coordinate = Coordinate::from_attribute_ids(values.clone())?;
// values are sorted n Coordinate
values.sort_unstable();
let mut de = Deserializer::new(&partition);
let mut de = Deserializer::new(&coordinate);
for v in values {
let val = de.read_leb128_u64().unwrap() as u32;
assert_eq!(v, val);
Expand Down
4 changes: 2 additions & 2 deletions src/abe_policy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
mod access_policy;
mod attribute;
mod coordinates;
mod dimension;
mod partitions;
mod policy;
mod policy_versions;

pub use access_policy::AccessPolicy;
pub use attribute::{Attribute, AttributeStatus, Attributes, EncryptionHint};
pub use coordinates::Coordinate;
pub use dimension::{AttributeParameters, Dimension, DimensionBuilder};
pub use partitions::Partition;
pub use policy_versions::{LegacyPolicy, PolicyV1, PolicyV2 as Policy};
use serde::{Deserialize, Serialize};

Expand Down
34 changes: 17 additions & 17 deletions src/abe_policy/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use std::{
use serde_json::Value;

use super::{
AccessPolicy, Attribute, AttributeParameters, AttributeStatus, Dimension, DimensionBuilder,
EncryptionHint, LegacyPolicy, Partition, Policy, PolicyV1, PolicyVersion,
AccessPolicy, Attribute, AttributeParameters, AttributeStatus, Coordinate, Dimension,
DimensionBuilder, EncryptionHint, LegacyPolicy, Policy, PolicyV1, PolicyVersion,
};
use crate::Error;

Expand Down Expand Up @@ -177,12 +177,12 @@ impl Policy {
/// activation status.
pub fn generate_universal_coordinates(
&self,
) -> Result<HashMap<Partition, (EncryptionHint, AttributeStatus)>, Error> {
) -> Result<HashMap<Coordinate, (EncryptionHint, AttributeStatus)>, Error> {
let universe = self.dimensions.iter().collect::<Vec<_>>();
combine(universe.as_slice())
.into_iter()
.map(|(combination, is_hybridized, is_readonly)| {
Partition::from_attribute_ids(combination)
Coordinate::from_attribute_ids(combination)
.map(|coordinate| (coordinate, (is_hybridized, is_readonly)))
})
.collect()
Expand All @@ -200,7 +200,7 @@ impl Policy {
pub fn generate_semantic_space_coordinates(
&self,
ap: AccessPolicy,
) -> Result<HashSet<Partition>, Error> {
) -> Result<HashSet<Coordinate>, Error> {
let dnf = ap.to_dnf();
let mut coordinates = HashSet::new();
for conjunction in dnf {
Expand All @@ -216,7 +216,7 @@ impl Policy {
.collect::<Result<HashMap<_, _>, Error>>()?;
// TODO: Some coordinates may be computed twice (the lower dimensions).
for (ids, _, _) in combine(&semantic_space.iter().collect::<Vec<_>>()) {
coordinates.insert(Partition::from_attribute_ids(ids)?);
coordinates.insert(Coordinate::from_attribute_ids(ids)?);
}
}
Ok(coordinates)
Expand All @@ -232,11 +232,11 @@ impl Policy {
pub fn generate_point_coordinates(
&self,
ap: AccessPolicy,
) -> Result<HashSet<Partition>, Error> {
) -> Result<HashSet<Coordinate>, Error> {
let dnf = ap.to_dnf();
let mut coordinates = HashSet::with_capacity(dnf.len());
for conjunction in dnf {
let coo = Partition::from_attribute_ids(
let coo = Coordinate::from_attribute_ids(
conjunction
.into_iter()
.map(|attr| self.get_attribute(&attr).map(|params| params.id))
Expand Down Expand Up @@ -367,33 +367,33 @@ mod tests {
{
let mut coordinates = HashSet::new();

coordinates.insert(Partition::from_attribute_ids(vec![])?);
coordinates.insert(Coordinate::from_attribute_ids(vec![])?);

coordinates.insert(Partition::from_attribute_ids(vec![policy
coordinates.insert(Coordinate::from_attribute_ids(vec![policy
.get_attribute_id(&Attribute {
dimension: "Department".to_string(),
name: "HR".to_string(),
})?])?);

coordinates.insert(Partition::from_attribute_ids(vec![policy
coordinates.insert(Coordinate::from_attribute_ids(vec![policy
.get_attribute_id(&Attribute {
dimension: "Department".to_string(),
name: "FIN".to_string(),
})?])?);

coordinates.insert(Partition::from_attribute_ids(vec![policy
coordinates.insert(Coordinate::from_attribute_ids(vec![policy
.get_attribute_id(&Attribute {
dimension: "Security Level".to_string(),
name: "Protected".to_string(),
})?])?);

coordinates.insert(Partition::from_attribute_ids(vec![policy
coordinates.insert(Coordinate::from_attribute_ids(vec![policy
.get_attribute_id(&Attribute {
dimension: "Security Level".to_string(),
name: "Low Secret".to_string(),
})?])?);

coordinates.insert(Partition::from_attribute_ids(vec![
coordinates.insert(Coordinate::from_attribute_ids(vec![
policy.get_attribute_id(&Attribute {
dimension: "Department".to_string(),
name: "HR".to_string(),
Expand All @@ -404,7 +404,7 @@ mod tests {
})?,
])?);

coordinates.insert(Partition::from_attribute_ids(vec![
coordinates.insert(Coordinate::from_attribute_ids(vec![
policy.get_attribute_id(&Attribute {
dimension: "Department".to_string(),
name: "HR".to_string(),
Expand All @@ -415,7 +415,7 @@ mod tests {
})?,
])?);

coordinates.insert(Partition::from_attribute_ids(vec![
coordinates.insert(Coordinate::from_attribute_ids(vec![
policy.get_attribute_id(&Attribute {
dimension: "Department".to_string(),
name: "FIN".to_string(),
Expand All @@ -426,7 +426,7 @@ mod tests {
})?,
])?);

coordinates.insert(Partition::from_attribute_ids(vec![
coordinates.insert(Coordinate::from_attribute_ids(vec![
policy.get_attribute_id(&Attribute {
dimension: "Department".to_string(),
name: "FIN".to_string(),
Expand Down
2 changes: 1 addition & 1 deletion src/abe_policy/policy_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub struct PolicyV2 {
pub(crate) version: PolicyVersion,
/// Last value taken by the attribute.
/// TODO: after some mutations, this counter will become very high, which implies the size of
/// the partitions will become huge (d * log_2(id) * 8/7).
/// the coordinate will become huge (d * log_2(id) * 8/7).
pub(crate) last_attribute_value: u32,

/// Policy axes: maps axes name to the list of associated attribute names
Expand Down
10 changes: 5 additions & 5 deletions src/core/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ impl Covercrypt {

/// Updates the master keys according to this new policy.
///
/// When a partition exists in the new policy but not in the master keys,
/// a new key pair is added to the master keys for that partition.
/// When a partition exists on the master keys, but not in the new policy,
/// When a coordinate exists in the new policy but not in the master keys,
/// a new key pair is added to the master keys for that coordinate.
/// When a coordinate exists on the master keys, but not in the new policy,
/// it is removed from the master keys.
///
/// - `policy` : Policy to use to generate the keys
Expand Down Expand Up @@ -143,8 +143,8 @@ impl Covercrypt {
/// Refreshes the user key according to the given master key and user
/// policy.
///
/// The user key will be granted access to the current partitions, as
/// determined by its access policy. If `preserve_old_partitions_access`
/// The user key will be granted access to the current coordinates, as
/// determined by its access policy. If `preserve_old_coordinates_access`
/// is set, the old user access will be preserved.
///
/// - `usk` : the user key to refresh
Expand Down
8 changes: 4 additions & 4 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use pqc_kyber::{KYBER_INDCPA_BYTES, KYBER_INDCPA_PUBLICKEYBYTES, KYBER_INDCPA_SE
use zeroize::ZeroizeOnDrop;

use crate::{
abe_policy::Partition,
abe_policy::Coordinate,
data_struct::{RevisionMap, RevisionVec},
};

Expand Down Expand Up @@ -67,7 +67,7 @@ pub(super) type PublicSubkey = (Option<KyberPublicKey>, R25519PublicKey);
pub struct MasterPublicKey {
g1: R25519PublicKey,
g2: R25519PublicKey,
pub(crate) subkeys: HashMap<Partition, PublicSubkey>,
pub(crate) subkeys: HashMap<Coordinate, PublicSubkey>,
}

pub(super) type SecretSubkey = (Option<KyberSecretKey>, R25519PrivateKey);
Expand All @@ -77,15 +77,15 @@ pub struct MasterSecretKey {
s: R25519PrivateKey,
s1: R25519PrivateKey,
s2: R25519PrivateKey,
pub(crate) subkeys: RevisionMap<Partition, SecretSubkey>,
pub(crate) subkeys: RevisionMap<Coordinate, SecretSubkey>,
kmac_key: Option<SymmetricKey<KMAC_KEY_LENGTH>>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct UserSecretKey {
a: R25519PrivateKey,
b: R25519PrivateKey,
pub(crate) subkeys: RevisionVec<Partition, SecretSubkey>,
pub(crate) subkeys: RevisionVec<Coordinate, SecretSubkey>,
kmac: Option<KmacSignature>,
}

Expand Down
Loading

0 comments on commit 47be160

Please sign in to comment.