Skip to content

Commit

Permalink
Check all subkeys are of the same hybridation type upon encapsulating
Browse files Browse the repository at this point in the history
  • Loading branch information
tbrezot committed May 17, 2024
1 parent 9b783c7 commit 681d64d
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 29 deletions.
25 changes: 25 additions & 0 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,31 @@ enum CoordinatePublicKey {
},
}

impl CoordinatePublicKey {
pub fn is_hybridized(&self) -> bool {
match self {
Self::Hybridized { .. } => true,
Self::Classic { .. } => false,
}
}

pub fn assert_homogeneity(subkeys: &[&Self]) -> Result<(), Error> {
subkeys.iter().map(|cpk| cpk.is_hybridized()).try_fold(
subkeys[0].is_hybridized(),
|acc, b| -> Result<bool, Error> {
if b != acc {
Err(Error::OperationNotPermitted(
"classic and hybridized access policies cannot be mixed".to_string(),
))
} else {
Ok(acc)
}
},
)?;
Ok(())
}
}

/// ElGamal keypair optionally hybridized with a post-quantum KEM associated to
/// a coordinate.
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
69 changes: 41 additions & 28 deletions src/core/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,38 +140,51 @@ pub fn encaps(
mpk: &MasterPublicKey,
encryption_set: &HashSet<Coordinate>,
) -> Result<(Secret<SEED_LENGTH>, Encapsulation), Error> {
let subkeys = encryption_set
.iter()
.map(|coordinate| {
mpk.coordinate_keys.get(coordinate).ok_or_else(|| {
Error::KeyError(format!("no public key for coordinate '{coordinate:#?}'"))
})
})
.collect::<Result<Vec<_>, _>>()?;

CoordinatePublicKey::assert_homogeneity(&subkeys)?;

let seed = Secret::<SEED_LENGTH>::random(rng);
let ephemeral_random = elgamal::Scalar::new(rng);
let mut coordinate_encapsulations = HashSet::with_capacity(encryption_set.len());
for coordinate in encryption_set {
match mpk.coordinate_keys.get(coordinate) {
Some(CoordinatePublicKey::Hybridized {
postquantum_pk,
elgamal_pk,
}) => {
let mut elgamal_ctx = [0; SEED_LENGTH];
elgamal::mask::<SEED_LENGTH>(
&mut elgamal_ctx,
&ephemeral_random,

let encaps_classical = |pk| {
let mut elgamal_ctx = [0; SEED_LENGTH];
elgamal::mask(&mut elgamal_ctx, &ephemeral_random, pk, &seed);
elgamal_ctx
};

let mut encaps_hybridized =
|postquantum_pk, elgamal_pk| -> Result<postquantum::Ciphertext, Error> {
let mut elgamal_ctx = [0; SEED_LENGTH];
elgamal::mask::<SEED_LENGTH>(&mut elgamal_ctx, &ephemeral_random, elgamal_pk, &seed);
let postquantum_ctx = postquantum::encrypt(rng, postquantum_pk, &elgamal_ctx)?;
elgamal_ctx.zeroize(); // ElGamal ciphertext is not secure in a post-quantum world
Ok(postquantum_ctx)
};

let coordinate_encapsulations = subkeys
.into_iter()
.map(|subkey| -> Result<SeedEncapsulation, _> {
match subkey {
CoordinatePublicKey::Classic { elgamal_pk } => {
Ok(SeedEncapsulation::Classic(encaps_classical(elgamal_pk)))
}
CoordinatePublicKey::Hybridized {
postquantum_pk,
elgamal_pk,
&seed,
);
let postquantum_ctx = postquantum::encrypt(rng, postquantum_pk, &elgamal_ctx)?;
elgamal_ctx.zeroize(); // ElGamal ciphertext is not secure in a post-quantum world
coordinate_encapsulations.insert(SeedEncapsulation::Hybridized(postquantum_ctx));
}
Some(CoordinatePublicKey::Classic { elgamal_pk }) => {
let mut elgamal_ctx = [0; SEED_LENGTH];
elgamal::mask(&mut elgamal_ctx, &ephemeral_random, elgamal_pk, &seed);
coordinate_encapsulations.insert(SeedEncapsulation::Classic(elgamal_ctx));
}
None => {
return Err(Error::KeyError(format!(
"no public key for coordinate '{coordinate:#?}'"
)));
} => {
encaps_hybridized(postquantum_pk, elgamal_pk).map(SeedEncapsulation::Hybridized)
}
}
};
}
})
.collect::<Result<HashSet<_>, Error>>()?;

let traps = mpk.set_traps(&ephemeral_random);
let (tag, key) = eakem_hash!(TAG_LENGTH, SEED_LENGTH, &*seed, KEY_GEN_INFO)
Expand Down
2 changes: 1 addition & 1 deletion src/core/serialization/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ mod tests {
),
(
coordinate_3.clone(),
(EncryptionHint::Classic, AttributeStatus::EncryptDecrypt),
(EncryptionHint::Hybridized, AttributeStatus::EncryptDecrypt),
),
]);

Expand Down

0 comments on commit 681d64d

Please sign in to comment.