diff --git a/src/kem/kyber/compress.rs b/src/kem/kyber/compress.rs index b9cda5e22..adcf8738f 100644 --- a/src/kem/kyber/compress.rs +++ b/src/kem/kyber/compress.rs @@ -4,6 +4,15 @@ use super::{ conversions::to_unsigned_representative, }; +fn compress_q(fe: u16) -> KyberFieldElement { + debug_assert!(COEFFICIENT_BITS <= BITS_PER_COEFFICIENT); + + let mut compressed = (fe as u32) << (COEFFICIENT_BITS + 1); + compressed += FIELD_MODULUS as u32; + compressed /= (FIELD_MODULUS << 1) as u32; + + (compressed & ((1u32 << COEFFICIENT_BITS) - 1)) as KyberFieldElement +} pub fn compress( mut re: KyberPolynomialRingElement, ) -> KyberPolynomialRingElement { @@ -13,27 +22,6 @@ pub fn compress( re } -pub fn decompress( - mut re: KyberPolynomialRingElement, -) -> KyberPolynomialRingElement { - re.coefficients = re - .coefficients - .map(|coefficient| decompress_q::(coefficient)); - re -} - -fn compress_q(fe: u16) -> KyberFieldElement { - debug_assert!(COEFFICIENT_BITS <= BITS_PER_COEFFICIENT); - - let two_pow_bit_size = 1u32 << COEFFICIENT_BITS; - - let mut compressed = (fe as u32) * (two_pow_bit_size << 1); - compressed += FIELD_MODULUS as u32; - compressed /= (FIELD_MODULUS << 1) as u32; - - (compressed & (two_pow_bit_size - 1)) as KyberFieldElement -} - fn decompress_q(fe: KyberFieldElement) -> KyberFieldElement { debug_assert!(COEFFICIENT_BITS <= BITS_PER_COEFFICIENT); @@ -43,3 +31,11 @@ fn decompress_q(fe: KyberFieldElement) -> KyberFi decompressed as KyberFieldElement } +pub fn decompress( + mut re: KyberPolynomialRingElement, +) -> KyberPolynomialRingElement { + re.coefficients = re + .coefficients + .map(|coefficient| decompress_q::(coefficient)); + re +} diff --git a/src/kem/kyber/ind_cpa.rs b/src/kem/kyber/ind_cpa.rs index 7b179444a..665538014 100644 --- a/src/kem/kyber/ind_cpa.rs +++ b/src/kem/kyber/ind_cpa.rs @@ -16,6 +16,18 @@ use super::{ // The PKE Private Key impl_generic_struct!(PrivateKey); +pub fn serialize_secret_key( + private_key: &[u8], + public_key: &[u8], + implicit_rejection_value: &[u8], +) -> [u8; SERIALIZED_KEY_LEN] { + UpdatableArray::new([0u8; SERIALIZED_KEY_LEN]) + .push(private_key) + .push(public_key) + .push(&H(public_key)) + .push(implicit_rejection_value) + .array() +} #[inline(always)] #[allow(non_snake_case)] @@ -168,19 +180,6 @@ pub(crate) fn generate_keypair< ) } -pub fn serialize_secret_key( - private_key: &[u8], - public_key: &[u8], - implicit_rejection_value: &[u8], -) -> [u8; SERIALIZED_KEY_LEN] { - UpdatableArray::new([0u8; SERIALIZED_KEY_LEN]) - .push(private_key) - .push(public_key) - .push(&H(public_key)) - .push(implicit_rejection_value) - .array() -} - fn compress_then_encode_u< const K: usize, const OUT_LEN: usize, diff --git a/src/kem/kyber/sampling.rs b/src/kem/kyber/sampling.rs index f603d919d..02fe8d45e 100644 --- a/src/kem/kyber/sampling.rs +++ b/src/kem/kyber/sampling.rs @@ -37,19 +37,6 @@ pub fn sample_from_uniform_distribution( (out, Some(BadRejectionSamplingRandomnessError)) } -#[inline(always)] -pub(super) fn sample_from_binomial_distribution( - randomness: &[u8], -) -> KyberPolynomialRingElement { - debug_assert_eq!(randomness.len(), ETA * 64); - - match ETA as u32 { - 2 => sample_from_binomial_distribution_2(randomness), - 3 => sample_from_binomial_distribution_3(randomness), - _ => unreachable!("factor {ETA}"), - } -} - /// Given a series of uniformly random bytes in `|randomness|`, sample /// a ring element from a binomial distribution centered at 0 that uses two sets /// of `|sampling_coins|` coin flips. If, for example, @@ -133,3 +120,16 @@ fn sample_from_binomial_distribution_3(randomness: &[u8]) -> KyberPolynomialRing sampled } + +#[inline(always)] +pub(super) fn sample_from_binomial_distribution( + randomness: &[u8], +) -> KyberPolynomialRingElement { + debug_assert_eq!(randomness.len(), ETA * 64); + + match ETA as u32 { + 2 => sample_from_binomial_distribution_2(randomness), + 3 => sample_from_binomial_distribution_3(randomness), + _ => unreachable!("factor {ETA}"), + } +} diff --git a/src/kem/kyber/serialize.rs b/src/kem/kyber/serialize.rs index d86904d58..15076dfb8 100644 --- a/src/kem/kyber/serialize.rs +++ b/src/kem/kyber/serialize.rs @@ -40,56 +40,6 @@ use super::{ /// function itself; the rest don't since they are called only after `compress_q` /// is called, and `compress_q` also performs this conversion. -#[inline(always)] -pub(super) fn serialize_little_endian( - re: KyberPolynomialRingElement, -) -> [u8; OUT_LEN] { - debug_assert!( - (COEFFICIENTS_IN_RING_ELEMENT * COMPRESSION_FACTOR) / 8 == OUT_LEN, - "{} != {}", - (COEFFICIENTS_IN_RING_ELEMENT * COMPRESSION_FACTOR) / 8, - OUT_LEN - ); - - match COMPRESSION_FACTOR as u32 { - 1 => serialize_little_endian_1(re), - // VECTOR_V_COMPRESSION_FACTOR_768 & VECTOR_V_COMPRESSION_FACTOR_512 - 4 => serialize_little_endian_4(re), - // VECTOR_V_COMPRESSION_FACTOR_1024 - 5 => serialize_little_endian_5(re), - // VECTOR_U_COMPRESSION_FACTOR_768 & VECTOR_U_COMPRESSION_FACTOR_512 - 10 => serialize_little_endian_10(re), - // VECTOR_U_COMPRESSION_FACTOR_1024 - 11 => serialize_little_endian_11(re), - 12 => serialize_little_endian_12(re), - _ => unreachable!("factor {COMPRESSION_FACTOR}"), - } -} - -#[inline(always)] -pub(super) fn deserialize_little_endian( - serialized: &[u8], -) -> KyberPolynomialRingElement { - debug_assert_eq!( - serialized.len(), - (COEFFICIENTS_IN_RING_ELEMENT * COMPRESSION_FACTOR) / 8 - ); - - match COMPRESSION_FACTOR as u32 { - 1 => deserialize_little_endian_1(serialized), - // VECTOR_V_COMPRESSION_FACTOR_768 & VECTOR_V_COMPRESSION_FACTOR_512 - 4 => deserialize_little_endian_4(serialized), - // VECTOR_V_COMPRESSION_FACTOR_1024 - 5 => deserialize_little_endian_5(serialized), - // VECTOR_U_COMPRESSION_FACTOR_768 & VECTOR_U_COMPRESSION_FACTOR_512 - 10 => deserialize_little_endian_10(serialized), - // VECTOR_U_COMPRESSION_FACTOR_1024 - 11 => deserialize_little_endian_11(serialized), - 12 => deserialize_little_endian_12(serialized), - _ => unreachable!("factor {COMPRESSION_FACTOR}"), - } -} - #[inline(always)] fn serialize_little_endian_1( re: KyberPolynomialRingElement, @@ -350,3 +300,53 @@ fn deserialize_little_endian_12(serialized: &[u8]) -> KyberPolynomialRingElement re } + +#[inline(always)] +pub(super) fn serialize_little_endian( + re: KyberPolynomialRingElement, +) -> [u8; OUT_LEN] { + debug_assert!( + (COEFFICIENTS_IN_RING_ELEMENT * COMPRESSION_FACTOR) / 8 == OUT_LEN, + "{} != {}", + (COEFFICIENTS_IN_RING_ELEMENT * COMPRESSION_FACTOR) / 8, + OUT_LEN + ); + + match COMPRESSION_FACTOR as u32 { + 1 => serialize_little_endian_1(re), + // VECTOR_V_COMPRESSION_FACTOR_768 & VECTOR_V_COMPRESSION_FACTOR_512 + 4 => serialize_little_endian_4(re), + // VECTOR_V_COMPRESSION_FACTOR_1024 + 5 => serialize_little_endian_5(re), + // VECTOR_U_COMPRESSION_FACTOR_768 & VECTOR_U_COMPRESSION_FACTOR_512 + 10 => serialize_little_endian_10(re), + // VECTOR_U_COMPRESSION_FACTOR_1024 + 11 => serialize_little_endian_11(re), + 12 => serialize_little_endian_12(re), + _ => unreachable!("factor {COMPRESSION_FACTOR}"), + } +} + +#[inline(always)] +pub(super) fn deserialize_little_endian( + serialized: &[u8], +) -> KyberPolynomialRingElement { + debug_assert_eq!( + serialized.len(), + (COEFFICIENTS_IN_RING_ELEMENT * COMPRESSION_FACTOR) / 8 + ); + + match COMPRESSION_FACTOR as u32 { + 1 => deserialize_little_endian_1(serialized), + // VECTOR_V_COMPRESSION_FACTOR_768 & VECTOR_V_COMPRESSION_FACTOR_512 + 4 => deserialize_little_endian_4(serialized), + // VECTOR_V_COMPRESSION_FACTOR_1024 + 5 => deserialize_little_endian_5(serialized), + // VECTOR_U_COMPRESSION_FACTOR_768 & VECTOR_U_COMPRESSION_FACTOR_512 + 10 => deserialize_little_endian_10(serialized), + // VECTOR_U_COMPRESSION_FACTOR_1024 + 11 => deserialize_little_endian_11(serialized), + 12 => deserialize_little_endian_12(serialized), + _ => unreachable!("factor {COMPRESSION_FACTOR}"), + } +}