Skip to content

Commit

Permalink
merged teophile's changes on branch partial_coordinates.
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Khayam authored and Adam Khayam committed Apr 10, 2024
2 parents 63f3e90 + 1fbb914 commit 4707b91
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 28 deletions.
22 changes: 12 additions & 10 deletions src/core/elgamal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,30 +100,29 @@ impl Serializable for Keypair {

fn read(de: &mut cosmian_crypto_core::bytes_ser_de::Deserializer) -> Result<Self, Self::Error> {
let sk = de.read::<Scalar>()?;
let is_deprecated = de.read_leb128_u64()?;
if 1 == is_deprecated {
let option_flag = de.read_leb128_u64()?;
if 1 == option_flag {
Ok(Self(sk, None))
} else if 0 == is_deprecated {
} else if 0 == option_flag {
let pk = de.read::<EcPoint>()?;
Ok(Self(sk, Some(pk)))
} else {
Err(Error::ConversionFailed(format!(
"invalid option encoding {is_deprecated}"
"invalid option encoding {option_flag}"
)))
}
}
}

/// One-Time Pad (OTP) encryption of the given plaintext.
fn otp_encrypt<const LENGTH: usize>(
ctx: &mut [u8; LENGTH],
key: &SymmetricKey<LENGTH>,
ptx: &Secret<LENGTH>,
) -> [u8; LENGTH] {
let mut ctx = [0; LENGTH];
) {
for pos in 0..LENGTH {
ctx[pos] = key[pos] ^ ptx[pos];
}
ctx
}

/// One-Time Pad (OTP) decryption of the given ciphertext.
Expand Down Expand Up @@ -151,15 +150,16 @@ fn otp_decrypt<const LENGTH: usize>(
/// The security relies on the fact that the same ElGammal keypair is never used
/// on different input bytes.
pub fn mask<const LENGTH: usize>(
ctx: &mut [u8; LENGTH],
ephemeral_sk: &Scalar,
recipient_pk: &EcPoint,
ptx: &Secret<LENGTH>,
) -> [u8; LENGTH] {
) {
let mut shared_secret = recipient_pk * ephemeral_sk;
let mut key = SymmetricKey::<LENGTH>::default();
kdf256!(&mut key, &shared_secret.to_bytes());
shared_secret.zeroize();
otp_encrypt(&key, ptx)
otp_encrypt(ctx, &key, ptx)
}

/// Unmasks the given bytes using the key derived from the ElGamal shared secret.
Expand Down Expand Up @@ -201,7 +201,9 @@ mod tests {
let ptx = Secret::<PTX_LENGTH>::random(&mut rng);
let ephemeral_keypair = keygen(&mut rng);
let recipient_keypair = keygen(&mut rng);
let ctx = mask(
let mut ctx = [0; PTX_LENGTH];
mask(
&mut ctx,
ephemeral_keypair.sk(),
recipient_keypair.pk().unwrap(),
&ptx,
Expand Down
3 changes: 1 addition & 2 deletions src/core/postquantum/kyber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,7 @@ pub fn encrypt(
)));
}
let mut ctx = Ciphertext::default();
let mut coin = Secret::<KYBER_SYMBYTES>::default();
rng.fill_bytes(&mut coin);
let coin = Secret::<KYBER_SYMBYTES>::random(rng);
indcpa_enc(&mut ctx, ptx, postquantum_pk, &coin);
Ok(ctx)
}
Expand Down
31 changes: 15 additions & 16 deletions src/core/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,30 +140,31 @@ pub fn encaps(
mpk: &MasterPublicKey,
encryption_set: &HashSet<Coordinate>,
) -> Result<(Secret<SEED_LENGTH>, Encapsulation), Error> {
let seed = Secret::<SEED_LENGTH>::random(rng);
let ephemeral_random = elgamal::Scalar::new(rng);
let session_key = Secret::<SEED_LENGTH>::random(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 =
elgamal::mask::<SEED_LENGTH>(&ephemeral_random, elgamal_pk, &session_key);
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)?;
// Zeroize the ElGamal ciphertext as it may not be secure in the
// post-quantum world.
//
// TODO: stack copying needs to be avoided when returning from `elgamal::encrypt`.
elgamal_ctx.zeroize();
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 ctx = elgamal::mask(&ephemeral_random, elgamal_pk, &session_key);
coordinate_encapsulations.insert(SeedEncapsulation::Classic(ctx));
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:#?}'"
Expand All @@ -173,11 +174,11 @@ pub fn encaps(
}

let traps = mpk.set_traps(&ephemeral_random);
let (tag, seed) = eakem_hash!(TAG_LENGTH, SEED_LENGTH, &*session_key, KEY_GEN_INFO)
let (tag, key) = eakem_hash!(TAG_LENGTH, SEED_LENGTH, &*seed, KEY_GEN_INFO)
.map_err(Error::CryptoCoreError)?;

Ok((
seed,
key,
Encapsulation {
tag,
traps,
Expand All @@ -203,9 +204,7 @@ pub fn decaps(
});

for enc in &encapsulation.coordinate_encapsulations {
// Iterate over the coordinate keys of the USK in a chronological
// fashion until the encapsulation is opened or the coordinate keys are
// exhausted.
// The breadth-first search tries all coordinate subkeys in a chronological order.
for key in usk.coordinate_keys.bfs() {
let seed: Secret<SEED_LENGTH> = match (key, enc) {
(
Expand Down

0 comments on commit 4707b91

Please sign in to comment.