From a0e399f5a63e4e6cb4a0a0c974fbc704dcebc042 Mon Sep 17 00:00:00 2001 From: David Cook Date: Mon, 27 Nov 2023 16:39:45 -0600 Subject: [PATCH 1/2] Update XOFs to use TurboSHAKE128 --- README.md | 2 +- benches/speed_tests.rs | 4 +- src/dp/distributions.rs | 22 ++--- src/flp.rs | 4 +- src/flp/types/fixedpoint_l2.rs | 28 ++++-- src/idpf.rs | 5 +- src/prng.rs | 28 +++--- src/topology/ping_pong.rs | 20 ++-- src/vdaf.rs | 12 +-- src/vdaf/poplar1.rs | 32 +++--- src/vdaf/prio3.rs | 44 +++++---- src/vdaf/prio3_test.rs | 4 + src/vdaf/test_vec/07/XofFixedKeyAes128.json | 8 -- src/vdaf/test_vec/07/XofShake128.json | 8 -- src/vdaf/test_vec/08/XofFixedKeyAes128.json | 8 ++ src/vdaf/test_vec/08/XofTurboShake128.json | 8 ++ src/vdaf/xof.rs | 82 +++++++++------- tests/discrete_gauss.rs | 10 +- tests/test_vectors/discrete_gauss_100.json | 92 ++++++++--------- tests/test_vectors/discrete_gauss_2.342.json | 54 +++++----- tests/test_vectors/discrete_gauss_3.json | 62 ++++++------ .../test_vectors/discrete_gauss_41293847.json | 98 +++++++++---------- tests/test_vectors/discrete_gauss_9.json | 80 +++++++-------- ...discrete_gauss_9999999999999999999999.json | 98 +++++++++---------- 24 files changed, 428 insertions(+), 385 deletions(-) delete mode 100644 src/vdaf/test_vec/07/XofFixedKeyAes128.json delete mode 100644 src/vdaf/test_vec/07/XofShake128.json create mode 100644 src/vdaf/test_vec/08/XofFixedKeyAes128.json create mode 100644 src/vdaf/test_vec/08/XofTurboShake128.json diff --git a/README.md b/README.md index cb124c1e3..5d9541bad 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ This crate defines the following feature flags: |Name|Default feature?|Description| |---|---|---| -|`crypto-dependencies`|Yes|Enables dependencies on various RustCrypto crates, and uses them to implement `XofShake128` to support VDAFs.| +|`crypto-dependencies`|Yes|Enables dependencies on various RustCrypto crates, and uses them to implement `XofTurboShake128` to support VDAFs.| |`experimental`|No|Certain experimental APIs are guarded by this feature. They may undergo breaking changes in future patch releases, as an exception to semantic versioning.| |`multithreaded`|No|Enables certain Prio3 VDAF implementations that use `rayon` for parallelization of gadget evaluations.| |`prio2`|No|Enables the Prio v2 API, and a VDAF based on the Prio2 system.| diff --git a/benches/speed_tests.rs b/benches/speed_tests.rs index 66458b1ad..ef6eeabae 100644 --- a/benches/speed_tests.rs +++ b/benches/speed_tests.rs @@ -712,7 +712,7 @@ fn poplar1(c: &mut Criterion) { for size in test_sizes.iter() { group.throughput(Throughput::Bytes(*size as u64 / 8)); group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| { - let vdaf = Poplar1::new_shake128(size); + let vdaf = Poplar1::new_turboshake128(size); let mut rng = StdRng::seed_from_u64(RNG_SEED); let nonce = rng.gen::<[u8; 16]>(); @@ -736,7 +736,7 @@ fn poplar1(c: &mut Criterion) { for size in test_sizes.iter() { group.measurement_time(Duration::from_secs(30)); // slower benchmark group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| { - let vdaf = Poplar1::new_shake128(size); + let vdaf = Poplar1::new_turboshake128(size); let mut rng = StdRng::seed_from_u64(RNG_SEED); b.iter_batched( diff --git a/src/dp/distributions.rs b/src/dp/distributions.rs index ba0270df9..5fc42f96e 100644 --- a/src/dp/distributions.rs +++ b/src/dp/distributions.rs @@ -292,7 +292,7 @@ mod tests { use super::*; use crate::dp::Rational; - use crate::vdaf::xof::SeedStreamSha3; + use crate::vdaf::xof::SeedStreamTurboShake128; use num_bigint::{BigUint, Sign, ToBigInt, ToBigUint}; use num_traits::{One, Signed, ToPrimitive}; @@ -306,15 +306,15 @@ mod tests { DiscreteGaussian::new(Ratio::::from_integer(BigUint::from(5u8))).unwrap(); // check samples are consistent - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let samples: Vec = (0..10) .map(|_| i8::try_from(sampler.sample(&mut rng)).unwrap()) .collect(); let samples1: Vec = (0..10) .map(|_| i8::try_from(sampler.sample(&mut rng)).unwrap()) .collect(); - assert_eq!(samples, vec![-3, -11, -3, 5, 1, 5, 2, 2, 1, 18]); - assert_eq!(samples1, vec![4, -4, -5, -2, 0, -5, -3, 1, 1, -2]); + assert_eq!(samples, vec![0, -3, -2, 3, 2, -1, -5, 4, -7, -5]); + assert_eq!(samples1, vec![2, 7, -8, -3, 1, -3, -3, 6, -3, -1]); } #[test] @@ -325,7 +325,7 @@ mod tests { // sample from a manually created distribution let sampler1 = DiscreteGaussian::new(Ratio::::from_integer(BigUint::from(4u8))).unwrap(); - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let samples1: Vec = (0..10) .map(|_| i8::try_from(sampler1.sample(&mut rng)).unwrap()) .collect(); @@ -337,7 +337,7 @@ mod tests { let sampler2 = zcdp .create_distribution(Ratio::::from_integer(1u8.into())) .unwrap(); - let mut rng2 = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng2 = SeedStreamTurboShake128::from_seed([0u8; 16]); let samples2: Vec = (0..10) .map(|_| i8::try_from(sampler2.sample(&mut rng2)).unwrap()) .collect(); @@ -485,7 +485,7 @@ mod tests { .unwrap(); // collect that number of samples - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let samples: Vec = (1..n_samples) .map(|_| { sample_discrete_gaussian(&Ratio::::from_integer(sigma.clone()), &mut rng) @@ -519,7 +519,7 @@ mod tests { #[test] fn empirical_test_gauss() { [100, 2000, 20000].iter().for_each(|p| { - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let sampler = || { sample_discrete_gaussian( &Ratio::::from_integer((*p).to_biguint().unwrap()), @@ -541,7 +541,7 @@ mod tests { #[test] fn empirical_test_bernoulli_mean() { [2u8, 5u8, 7u8, 9u8].iter().for_each(|p| { - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let sampler = || { if sample_bernoulli( &Ratio::::new(BigUint::one(), (*p).into()), @@ -565,7 +565,7 @@ mod tests { #[test] fn empirical_test_geometric_mean() { [2u8, 5u8, 7u8, 9u8].iter().for_each(|p| { - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let sampler = || { sample_geometric_exp( &Ratio::::new(BigUint::one(), (*p).into()), @@ -588,7 +588,7 @@ mod tests { #[test] fn empirical_test_laplace_mean() { [2u8, 5u8, 7u8, 9u8].iter().for_each(|p| { - let mut rng = SeedStreamSha3::from_seed([0u8; 16]); + let mut rng = SeedStreamTurboShake128::from_seed([0u8; 16]); let sampler = || { sample_discrete_laplace( &Ratio::::new(BigUint::one(), (*p).into()), diff --git a/src/flp.rs b/src/flp.rs index ad7b0136e..8c35e8925 100644 --- a/src/flp.rs +++ b/src/flp.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MPL-2.0 //! Implementation of the generic Fully Linear Proof (FLP) system specified in -//! [[draft-irtf-cfrg-vdaf-07]]. This is the main building block of [`Prio3`](crate::vdaf::prio3). +//! [[draft-irtf-cfrg-vdaf-08]]. This is the main building block of [`Prio3`](crate::vdaf::prio3). //! //! The FLP is derived for any implementation of the [`Type`] trait. Such an implementation //! specifies a validity circuit that defines the set of valid measurements, as well as the finite @@ -44,7 +44,7 @@ //! assert!(count.decide(&verifier).unwrap()); //! ``` //! -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ #[cfg(feature = "experimental")] use crate::dp::DifferentialPrivacyStrategy; diff --git a/src/flp/types/fixedpoint_l2.rs b/src/flp/types/fixedpoint_l2.rs index ec62500a4..1ad074633 100644 --- a/src/flp/types/fixedpoint_l2.rs +++ b/src/flp/types/fixedpoint_l2.rs @@ -177,7 +177,7 @@ use crate::flp::gadgets::{Mul, ParallelSumGadget, PolyEval}; use crate::flp::types::fixedpoint_l2::compatible_float::CompatibleFloat; use crate::flp::types::parallel_sum_range_checks; use crate::flp::{FlpError, Gadget, Type, TypeWithNoise}; -use crate::vdaf::xof::SeedStreamSha3; +use crate::vdaf::xof::SeedStreamTurboShake128; use fixed::traits::Fixed; use num_bigint::{BigInt, BigUint, TryFromBigIntError}; use num_integer::Integer; @@ -638,7 +638,11 @@ where agg_result: &mut [Self::Field], _num_measurements: usize, ) -> Result<(), FlpError> { - self.add_noise(dp_strategy, agg_result, &mut SeedStreamSha3::from_entropy()) + self.add_noise( + dp_strategy, + agg_result, + &mut SeedStreamTurboShake128::from_entropy(), + ) } } @@ -681,7 +685,7 @@ mod tests { use crate::field::{random_vector, Field128, FieldElement}; use crate::flp::gadgets::ParallelSum; use crate::flp::types::test_utils::{flp_validity_test, ValidityTestCase}; - use crate::vdaf::xof::SeedStreamSha3; + use crate::vdaf::xof::SeedStreamTurboShake128; use fixed::types::extra::{U127, U14, U63}; use fixed::{FixedI128, FixedI16, FixedI64}; use fixed_macro::fixed; @@ -762,15 +766,23 @@ mod tests { let strategy = ZCdpDiscreteGaussian::from_budget(ZCdpBudget::new( Rational::from_unsigned(100u8, 3u8).unwrap(), )); - vsum.add_noise(&strategy, &mut v, &mut SeedStreamSha3::from_seed([0u8; 16])) - .unwrap(); + vsum.add_noise( + &strategy, + &mut v, + &mut SeedStreamTurboShake128::from_seed([0u8; 16]), + ) + .unwrap(); assert_eq!( vsum.decode_result(&v, 1).unwrap(), match n { // sensitivity depends on encoding so the noise differs - 16 => vec![0.150604248046875, 0.139373779296875, -0.03759765625], - 32 => vec![0.3051439793780446, 0.1226568529382348, 0.08595499861985445], - 64 => vec![0.2896077990915178, 0.16115188007715098, 0.0788390114728425], + 16 => vec![0.288970947265625, 0.168853759765625, 0.085662841796875], + 32 => vec![0.257810294162482, 0.10634658299386501, 0.10149003705009818], + 64 => vec![ + 0.37697368351762867, + -0.02388947667663828, + 0.19813152630930916 + ], _ => panic!("unsupported bitsize"), } ); diff --git a/src/idpf.rs b/src/idpf.rs index f83457173..f2529638c 100644 --- a/src/idpf.rs +++ b/src/idpf.rs @@ -1,7 +1,7 @@ //! This module implements the incremental distributed point function (IDPF) described in -//! [[draft-irtf-cfrg-vdaf-07]]. +//! [[draft-irtf-cfrg-vdaf-08]]. //! -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ use crate::{ codec::{CodecError, Decode, Encode, ParameterizedDecode}, @@ -1901,6 +1901,7 @@ mod tests { } #[test] + #[ignore = "VDAF-08 support is incomplete"] fn idpf_poplar_generate_test_vector() { let test_vector = load_idpfpoplar_test_vector(); let idpf = Idpf::new((), ()); diff --git a/src/prng.rs b/src/prng.rs index 54f8b127b..0325e5256 100644 --- a/src/prng.rs +++ b/src/prng.rs @@ -129,7 +129,7 @@ mod tests { use crate::{ codec::Decode, field::{Field64, FieldPrio2}, - vdaf::xof::{Seed, SeedStreamSha3, Xof, XofShake128}, + vdaf::xof::{Seed, SeedStreamTurboShake128, Xof, XofTurboShake128}, }; #[cfg(feature = "prio2")] use base64::{engine::Engine, prelude::BASE64_STANDARD}; @@ -219,22 +219,22 @@ mod tests { // These constants were found in a brute-force search, and they test that the XOF performs // rejection sampling correctly when the raw output exceeds the prime modulus. let seed = Seed::get_decoded(&[ - 0x29, 0xb2, 0x98, 0x64, 0xb4, 0xaa, 0x4e, 0x07, 0x2a, 0x44, 0x49, 0x24, 0xf6, 0x74, - 0x0a, 0x3d, + 0xd5, 0x3f, 0xff, 0x5d, 0x88, 0x8c, 0x60, 0x4e, 0x9f, 0x24, 0x16, 0xe1, 0xa2, 0x0a, + 0x62, 0x34, ]) .unwrap(); - let expected = Field64::from(2035552711764301796); + let expected = Field64::from(3401316594827516850); - let seed_stream = XofShake128::seed_stream(&seed, b"", b""); + let seed_stream = XofTurboShake128::seed_stream(&seed, b"", b""); let mut prng = Prng::::from_seed_stream(seed_stream); - let actual = prng.nth(33236).unwrap(); + let actual = prng.nth(662).unwrap(); assert_eq!(actual, expected); #[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] { - let mut seed_stream = XofShake128::seed_stream(&seed, b"", b""); + let mut seed_stream = XofTurboShake128::seed_stream(&seed, b"", b""); let mut actual = ::zero(); - for _ in 0..=33236 { + for _ in 0..=662 { actual = ::generate(&mut seed_stream, &()); } assert_eq!(actual, expected); @@ -247,12 +247,12 @@ mod tests { fn left_over_buffer_back_fill() { let seed = Seed::generate().unwrap(); - let mut prng: Prng = - Prng::from_seed_stream(XofShake128::seed_stream(&seed, b"", b"")); + let mut prng: Prng = + Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, b"", b"")); // Construct a `Prng` with a longer-than-usual buffer. - let mut prng_weird_buffer_size: Prng = - Prng::from_seed_stream(XofShake128::seed_stream(&seed, b"", b"")); + let mut prng_weird_buffer_size: Prng = + Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, b"", b"")); let mut extra = [0; 7]; prng_weird_buffer_size.seed_stream.fill_bytes(&mut extra); prng_weird_buffer_size.buffer.extend_from_slice(&extra); @@ -268,8 +268,8 @@ mod tests { #[test] fn into_new_field() { let seed = Seed::generate().unwrap(); - let want: Prng = - Prng::from_seed_stream(XofShake128::seed_stream(&seed, b"", b"")); + let want: Prng = + Prng::from_seed_stream(XofTurboShake128::seed_stream(&seed, b"", b"")); let want_buffer = want.buffer.clone(); let got: Prng = want.into_new_field(); diff --git a/src/topology/ping_pong.rs b/src/topology/ping_pong.rs index 41f1bbdaa..9ceaa2981 100644 --- a/src/topology/ping_pong.rs +++ b/src/topology/ping_pong.rs @@ -4,7 +4,7 @@ //! two aggregators, designated "Leader" and "Helper". This topology is required for implementing //! the [Distributed Aggregation Protocol][DAP]. //! -//! [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 +//! [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 //! [DAP]: https://datatracker.ietf.org/doc/html/draft-ietf-ppm-dap use crate::{ @@ -64,7 +64,7 @@ pub enum PingPongError { /// variants are opaque byte buffers. This is because the ping-pong routines take responsibility for /// decoding preparation shares and messages, which usually requires having the preparation state. /// -/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 +/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 #[derive(Clone, PartialEq, Eq)] pub enum PingPongMessage { /// Corresponds to MessageType.initialize. @@ -183,7 +183,7 @@ impl Decode for PingPongMessage { /// preprocessed prepare message. Their encoding is much smaller than the `(State, Message)` tuple, /// which can always be recomputed with [`Self::evaluate`]. /// -/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 +/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 #[derive(Clone, Debug, Eq)] pub struct PingPongTransition< const VERIFY_KEY_SIZE: usize, @@ -294,7 +294,7 @@ where /// code, and the `Rejected` state is represented as `std::result::Result::Err`, so this enum does /// not include those variants. /// -/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 +/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 #[derive(Clone, Debug, PartialEq, Eq)] pub enum PingPongState< const VERIFY_KEY_SIZE: usize, @@ -332,7 +332,7 @@ pub enum PingPongContinuedValue< /// Extension trait on [`crate::vdaf::Aggregator`] which adds the [VDAF Ping-Pong Topology][VDAF]. /// -/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.8 +/// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.8 pub trait PingPongTopology: Aggregator { @@ -352,7 +352,7 @@ pub trait PingPongTopology Result<(Self::State, PingPongMessage), PingPongError>; /// Initialize helper state using the helper's input share and the leader's first prepare share. - /// Corresponds to `ping_pong_helper_init` in the forthcoming `draft-irtf-cfrg-vdaf-07`. + /// Corresponds to `ping_pong_helper_init` in [VDAF]. /// /// If successful, the returned [`PingPongTransition`] should be evaluated, yielding a /// [`PingPongMessage`], which should be transmitted to the leader, and a [`PingPongState`]. @@ -379,6 +379,8 @@ pub trait PingPongTopology: Vdaf { /// /// Implements `Vdaf::shard` from [VDAF]. /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.1 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.1 fn shard( &self, measurement: &Self::Measurement, @@ -248,7 +248,7 @@ pub trait Aggregator: Vda /// /// Implements `Vdaf.prep_init` from [VDAF]. /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.2 fn prepare_init( &self, verify_key: &[u8; VERIFY_KEY_SIZE], @@ -263,7 +263,7 @@ pub trait Aggregator: Vda /// /// Implements `Vdaf.prep_shares_to_prep` from [VDAF]. /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.2 fn prepare_shares_to_prepare_message>( &self, agg_param: &Self::AggregationParam, @@ -280,7 +280,7 @@ pub trait Aggregator: Vda /// /// Implements `Vdaf.prep_next` from [VDAF]. /// - /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-07#section-5.2 + /// [VDAF]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vdaf-08#section-5.2 fn prepare_next( &self, state: Self::PrepareState, diff --git a/src/vdaf/poplar1.rs b/src/vdaf/poplar1.rs index e8591f204..224b1697d 100644 --- a/src/vdaf/poplar1.rs +++ b/src/vdaf/poplar1.rs @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 -//! Implementation of Poplar1 as specified in [[draft-irtf-cfrg-vdaf-07]]. +//! Implementation of Poplar1 as specified in [[draft-irtf-cfrg-vdaf-08]]. //! -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ use crate::{ codec::{CodecError, Decode, Encode, ParameterizedDecode}, @@ -10,7 +10,7 @@ use crate::{ idpf::{Idpf, IdpfInput, IdpfOutputShare, IdpfPublicShare, IdpfValue, RingBufferCache}, prng::Prng, vdaf::{ - xof::{Seed, Xof, XofShake128}, + xof::{Seed, Xof, XofTurboShake128}, Aggregatable, Aggregator, Client, Collector, PrepareTransition, Vdaf, VdafError, }, }; @@ -34,9 +34,9 @@ const DST_VERIFY_RANDOMNESS: u16 = 4; impl Poplar1 { /// Create an instance of [`Poplar1`]. The caller provides the bit length of each - /// measurement (`BITS` as defined in the [[draft-irtf-cfrg-vdaf-07]]). + /// measurement (`BITS` as defined in [[draft-irtf-cfrg-vdaf-08]]). /// - /// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ + /// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ pub fn new(bits: usize) -> Self { Self { bits, @@ -45,12 +45,12 @@ impl Poplar1 { } } -impl Poplar1 { - /// Create an instance of [`Poplar1`] using [`XofShake128`]. The caller provides the bit length of - /// each measurement (`BITS` as defined in the [[draft-irtf-cfrg-vdaf-07]]). +impl Poplar1 { + /// Create an instance of [`Poplar1`] using [`XofTurboShake128`]. The caller provides the bit length of + /// each measurement (`BITS` as defined in [[draft-irtf-cfrg-vdaf-08]]). /// - /// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ - pub fn new_shake128(bits: usize) -> Self { + /// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ + pub fn new_turboshake128(bits: usize) -> Self { Poplar1::new(bits) } } @@ -1628,7 +1628,7 @@ mod tests { #[test] fn shard_prepare() { let mut rng = thread_rng(); - let vdaf = Poplar1::new_shake128(64); + let vdaf = Poplar1::new_turboshake128(64); let verify_key = rng.gen(); let input = IdpfInput::from_bytes(b"12341324"); let nonce = rng.gen(); @@ -1672,7 +1672,7 @@ mod tests { fn heavy_hitters() { let mut rng = thread_rng(); let verify_key = rng.gen(); - let vdaf = Poplar1::new_shake128(8); + let vdaf = Poplar1::new_turboshake128(8); run_heavy_hitters( &vdaf, @@ -1763,7 +1763,7 @@ mod tests { #[test] fn round_trip_prepare_state() { - let vdaf = Poplar1::new_shake128(1); + let vdaf = Poplar1::new_turboshake128(1); for (agg_id, prep_state) in [ ( 0, @@ -2037,7 +2037,7 @@ mod tests { } // Shard measurement. - let poplar = Poplar1::new_shake128(test_vector.bits); + let poplar = Poplar1::new_turboshake128(test_vector.bits); let (public_share, input_shares) = poplar .shard_with_random(&measurement, &nonce, &idpf_random, &poplar_random) .unwrap(); @@ -2252,21 +2252,25 @@ mod tests { } #[test] + #[ignore = "VDAF-08 support is incomplete"] fn test_vec_poplar1_0() { check_test_vec(include_str!("test_vec/07/Poplar1_0.json")); } #[test] + #[ignore = "VDAF-08 support is incomplete"] fn test_vec_poplar1_1() { check_test_vec(include_str!("test_vec/07/Poplar1_1.json")); } #[test] + #[ignore = "VDAF-08 support is incomplete"] fn test_vec_poplar1_2() { check_test_vec(include_str!("test_vec/07/Poplar1_2.json")); } #[test] + #[ignore = "VDAF-08 support is incomplete"] fn test_vec_poplar1_3() { check_test_vec(include_str!("test_vec/07/Poplar1_3.json")); } diff --git a/src/vdaf/prio3.rs b/src/vdaf/prio3.rs index 4bc99ef12..087729d63 100644 --- a/src/vdaf/prio3.rs +++ b/src/vdaf/prio3.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -//! Implementation of the Prio3 VDAF [[draft-irtf-cfrg-vdaf-07]]. +//! Implementation of the Prio3 VDAF [[draft-irtf-cfrg-vdaf-08]]. //! //! **WARNING:** This code has not undergone significant security analysis. Use at your own risk. //! @@ -9,7 +9,7 @@ //! 2019 [[BBCG+19]], that lead to substantial improvements in terms of run time and communication //! cost. The security of the construction was analyzed in [[DPRS23]]. //! -//! Prio3 is a transformation of a Fully Linear Proof (FLP) system [[draft-irtf-cfrg-vdaf-07]] into +//! Prio3 is a transformation of a Fully Linear Proof (FLP) system [[draft-irtf-cfrg-vdaf-08]] into //! a VDAF. The base type, [`Prio3`], supports a wide variety of aggregation functions, some of //! which are instantiated here: //! @@ -20,14 +20,14 @@ //! //! Additional types can be constructed from [`Prio3`] as needed. //! -//! (*) denotes that the type is specified in [[draft-irtf-cfrg-vdaf-07]]. +//! (*) denotes that the type is specified in [[draft-irtf-cfrg-vdaf-08]]. //! //! [BBCG+19]: https://ia.cr/2019/188 //! [CGB17]: https://crypto.stanford.edu/prio/ //! [DPRS23]: https://ia.cr/2023/130 -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ -use super::xof::XofShake128; +use super::xof::XofTurboShake128; #[cfg(feature = "experimental")] use super::AggregatorWithNoise; use crate::codec::{CodecError, Decode, Encode, ParameterizedDecode}; @@ -72,7 +72,7 @@ const DST_JOINT_RAND_SEED: u16 = 6; const DST_JOINT_RAND_PART: u16 = 7; /// The count type. Each measurement is an integer in `[0,2)` and the aggregate result is the sum. -pub type Prio3Count = Prio3, XofShake128, 16>; +pub type Prio3Count = Prio3, XofTurboShake128, 16>; impl Prio3Count { /// Construct an instance of Prio3Count with the given number of aggregators. @@ -84,7 +84,7 @@ impl Prio3Count { /// The count-vector type. Each measurement is a vector of integers in `[0,2^bits)` and the /// aggregate is the element-wise sum. pub type Prio3SumVec = - Prio3>>, XofShake128, 16>; + Prio3>>, XofTurboShake128, 16>; impl Prio3SumVec { /// Construct an instance of Prio3SumVec with the given number of aggregators. `bits` defines @@ -104,8 +104,11 @@ impl Prio3SumVec { /// time. Note that the improvement is only noticeable for very large input lengths. #[cfg(feature = "multithreaded")] #[cfg_attr(docsrs, doc(cfg(feature = "multithreaded")))] -pub type Prio3SumVecMultithreaded = - Prio3>>, XofShake128, 16>; +pub type Prio3SumVecMultithreaded = Prio3< + SumVec>>, + XofTurboShake128, + 16, +>; #[cfg(feature = "multithreaded")] impl Prio3SumVecMultithreaded { @@ -124,7 +127,7 @@ impl Prio3SumVecMultithreaded { /// The sum type. Each measurement is an integer in `[0,2^bits)` for some `0 < bits < 64` and the /// aggregate is the sum. -pub type Prio3Sum = Prio3, XofShake128, 16>; +pub type Prio3Sum = Prio3, XofTurboShake128, 16>; impl Prio3Sum { /// Construct an instance of Prio3Sum with the given number of aggregators and required bit @@ -160,7 +163,7 @@ pub type Prio3FixedPointBoundedL2VecSum = Prio3< ParallelSum>, ParallelSum>, >, - XofShake128, + XofTurboShake128, 16, >; @@ -191,7 +194,7 @@ pub type Prio3FixedPointBoundedL2VecSumMultithreaded = Prio3< ParallelSumMultithreaded>, ParallelSumMultithreaded>, >, - XofShake128, + XofTurboShake128, 16, >; @@ -211,7 +214,7 @@ impl Prio3FixedPointBoundedL2VecSumMultithreaded>>, XofShake128, 16>; + Prio3>>, XofTurboShake128, 16>; impl Prio3Histogram { /// Constructs an instance of Prio3Histogram with the given number of aggregators, @@ -229,8 +232,11 @@ impl Prio3Histogram { /// time. Note that this improvement is only noticeable for very large input lengths. #[cfg(feature = "multithreaded")] #[cfg_attr(docsrs, doc(cfg(feature = "multithreaded")))] -pub type Prio3HistogramMultithreaded = - Prio3>>, XofShake128, 16>; +pub type Prio3HistogramMultithreaded = Prio3< + Histogram>>, + XofTurboShake128, + 16, +>; #[cfg(feature = "multithreaded")] impl Prio3HistogramMultithreaded { @@ -247,7 +253,7 @@ impl Prio3HistogramMultithreaded { /// The average type. Each measurement is an integer in `[0,2^bits)` for some `0 < bits < 64` and /// the aggregate is the arithmetic average. -pub type Prio3Average = Prio3, XofShake128, 16>; +pub type Prio3Average = Prio3, XofTurboShake128, 16>; impl Prio3Average { /// Construct an instance of Prio3Average with the given number of aggregators and required bit @@ -277,7 +283,7 @@ impl Prio3Average { /// - a [`Xof`] for deriving vectors of field elements from seeds. /// /// New instances can be defined by aliasing the base type. For example, [`Prio3Count`] is an alias -/// for `Prio3, XofShake128, 16>`. +/// for `Prio3, XofTurboShake128, 16>`. /// /// ``` /// use prio::vdaf::{ @@ -1598,7 +1604,7 @@ mod tests { fn test_fixed_vec( fp_0: Fx, - prio3: Prio3, XofShake128, 16>, + prio3: Prio3, XofTurboShake128, 16>, ) where Fx: Fixed + CompatibleFloat + std::ops::Neg, PE: Eq + ParallelSumGadget> + Clone + 'static, @@ -1690,7 +1696,7 @@ mod tests { fp_4_inv: Fx, fp_8_inv: Fx, fp_16_inv: Fx, - prio3: Prio3, XofShake128, 16>, + prio3: Prio3, XofTurboShake128, 16>, ) where Fx: Fixed + CompatibleFloat + std::ops::Neg, PE: Eq + ParallelSumGadget> + Clone + 'static, diff --git a/src/vdaf/prio3_test.rs b/src/vdaf/prio3_test.rs index 372a2c856..ac3673fe4 100644 --- a/src/vdaf/prio3_test.rs +++ b/src/vdaf/prio3_test.rs @@ -175,6 +175,7 @@ where } #[test] +#[ignore = "VDAF-08 support is incomplete"] fn test_vec_prio3_count() { for test_vector_str in [ include_str!("test_vec/07/Prio3Count_0.json"), @@ -189,6 +190,7 @@ fn test_vec_prio3_count() { } #[test] +#[ignore = "VDAF-08 support is incomplete"] fn test_vec_prio3_sum() { for test_vector_str in [ include_str!("test_vec/07/Prio3Sum_0.json"), @@ -204,6 +206,7 @@ fn test_vec_prio3_sum() { } #[test] +#[ignore = "VDAF-08 support is incomplete"] fn test_vec_prio3_sum_vec() { for test_vector_str in [ include_str!("test_vec/07/Prio3SumVec_0.json"), @@ -228,6 +231,7 @@ fn test_vec_prio3_sum_vec() { } #[test] +#[ignore = "VDAF-08 support is incomplete"] fn test_vec_prio3_histogram() { for test_vector_str in [ include_str!("test_vec/07/Prio3Histogram_0.json"), diff --git a/src/vdaf/test_vec/07/XofFixedKeyAes128.json b/src/vdaf/test_vec/07/XofFixedKeyAes128.json deleted file mode 100644 index ea76c50ff..000000000 --- a/src/vdaf/test_vec/07/XofFixedKeyAes128.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "binder": "62696e64657220737472696e67", - "derived_seed": "9cb53deb2feda2f9a7f34fde29a833f4", - "dst": "646f6d61696e2073657061726174696f6e20746167", - "expanded_vec_field128": "9cb53deb2feda2f9a7f34fde29a833f44ade288b2f55f2cd257e5f40595b5069543b40b740dfcf8ab5c863924f4510716b625f633a2f7e55a50b24a5fec9155dec199170f9ebe46768e9d120f7e8f62840441ef53dd5d2ba2d3fd39032e2da99498f4abf815b09c667cef08f0882fa945ba3335d2c7407de1b1650a5f4fe52884caf3ef1f5802eabb8f238c4d9d419bed904dcf79b22da49f68fb547c287a9cd4a38d58017eb2031a6bf1b4defb8905c3b777e9287f62a7fb0f97e4d8a26c4e5b909958bc73a6f7512b5b845488d98a7fcedf711ada6972f4c06818d3c3e7a070a88af60dc0323b59f304935fbbbd3792e590c9b6bce7459deba3599c7f30fe64a638219dde4bde4b1a51df8d85c2f36604c44f5f188148e3ba1dca3fd8073240ee577ef322df19a13d9ffa486a6833f4eb2838a58746707b8bf531cc86098f43809276b5f02914b26cb75938ca16eafa73397920a2f5e607af30e62ff60b83e15699d4d0265affe185b307ed330941a41b2b628e44d9a19412f7d9513cacd7b1fd740b7708e3bc764a0cf2146bca7c94d1901c43f509d7dcc9dfec54476789284e53f3760610a0ac5fce205e9b9aa0355c29702a5c9395bf1de8c974c800e1037a6bf5e0bd2af7d96b7f000ff6ab93299966b6832c493b600f2595a3db99353d2f8889019cd3ec5a73fa457f5442ed5edf349e78c9cf0cbf4f65aea03754c381c3efc206b7f17447cc51ac68eceacab9d92b13b0bc700c99a26ce2b6c3271f7639aa72dc27bbd54984907abb10ef1047ef352d378ddae48bf381804c89aa1847f5027537cf6af1b30aa44cead6495e98ca5b3205d39beb49d2db6752a4e57158e8c83464002b0b4a9838bc381c1dbdc3e9a584554fb76671a15f907c0b395a5", - "length": 40, - "seed": "000102030405060708090a0b0c0d0e0f" -} diff --git a/src/vdaf/test_vec/07/XofShake128.json b/src/vdaf/test_vec/07/XofShake128.json deleted file mode 100644 index edafb1bd4..000000000 --- a/src/vdaf/test_vec/07/XofShake128.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "binder": "62696e64657220737472696e67", - "derived_seed": "87c4d0dd654bf8eec8805c68b5eb0182", - "dst": "646f6d61696e2073657061726174696f6e20746167", - "expanded_vec_field128": "87c4d0dd654bf8eec8805c68b5eb0182b1b8ede598cfb8d8b234038fd0492eb14268bbb2ac15a55d463c8227c2d4fae8607631d13157c4935c5d2d56e4b1e2bdfe0f80b286d82e631704acee29ab6f7acaa316d3623cc3371297604caf57bc2eafe72056143971345901b9fb9f95b6a7384c6a88143124ff693ce9e453675f87a6b6338a1e1c9f72d19e32b51f60a1d7469de1fbe25407cc338d896b34c5fc437d2551297027eeefca9aaccdb78d655a6c220cbc2d76cc4a64b04806ae893c952996abb91f6ec32b6de27fe51be59514352d31af4967c0a85c5823ff73be7f15b9c0769321e4b69cb931a4e88f9da1fde1c5df9d84a7eadb41cf25681fc64a84a1c4accded794c1e6fec1fb26a286712425bfc29521273dcfc76cbab9b3c3c2b840ab6a4f9fd73ea434fc1c22a91943ed38fef0136f0f18f680c191978ab77c750d577c3526a327564da05cfc7bb9ef52c140d9e63b1f39761648772eaa61e2efb15890aed8340e6854b428f16dff5654c8a0852d46e817b49bbe91db3c46620adbd009a0d7d40843c1b6b7786833d3c1ae097b4fa35815dbcfca78e00a34f15936ed6d0f5bf50fc25adbecd3adfa55ba6bc7052f0662595cf7a933dfcc3d0ad5d825ec3bc191586a1c36a037d1c9e73c24777825d6afe59774abdb2918c2147a0436b17bafd967e07c46c3d6240c771f4fd4f9b3fff38b294508b8af5a1b71385f90f407620b7aa636fd2b55435b3688fc26ad3c23b2ad48158c4c475c07eb58569a8d1a906452b82d582397c4c69f5e79d3082d03b4dd85b5277a8b44c933d52d168caae8c602376f5487670a172d138364cb975c569c9c2d79506746090ea8102907c91b66764fd8740ca7bd3acb59173df29b5fa7542e51bce67b97c9ee2", - "length": 40, - "seed": "000102030405060708090a0b0c0d0e0f" -} diff --git a/src/vdaf/test_vec/08/XofFixedKeyAes128.json b/src/vdaf/test_vec/08/XofFixedKeyAes128.json new file mode 100644 index 000000000..6a34d6e32 --- /dev/null +++ b/src/vdaf/test_vec/08/XofFixedKeyAes128.json @@ -0,0 +1,8 @@ +{ + "binder": "62696e64657220737472696e67", + "derived_seed": "3805276060157b7376b069305303669b", + "dst": "646f6d61696e2073657061726174696f6e20746167", + "expanded_vec_field128": "3805276060157b7376b069305303669b92beaaa4afa982314428494ba98f3595d49e76d1301b451d6fd79c9acbe9118717cfd0d4b9ef29806b4dce298a2d6aba17d7025e7964a2d7e24a263bd79d19edb11cd1db4bc07ce0ae1a9c6d1f59233e8d7065a66ce1b123ed773e4b370c9217c7032fc805f3a13f6fe2ef6f7961bf9d20fd22b8cd544cefe8e634d9245db7813ba43f630a123dfda73b6bbad8b11a916090a7d5ba8a4d20853f3f5c8222684050a53119e829313fa8de64f92553a44aa522fc90d9ec75f80547ec9637ce60e74afd51baa1d80b549444c5f0a6283ff494698ea6ffaea65964c4e0c2f9cf72a11310000261ddc85661f5068f505d34273295be9b8549b4c6278a80794929093a17cc017cf0b0e68e32e941708cfa58b9e598ac3d5d2ab4e9b33111c9c9fbc0a3682617d0ed1a0d15c9bfb9d5fd2889d1f56dd3a7f2e61ca59b0705d35f915349ffea0341816532bbdaa6dddba42bf27d1699d9e9ef580f3686ea42d687e54a87c3e6dab4f1ee5e1185faa6b809eb1a1e940692b3ba882684e8440b73e23088411000cf77ba69777b3bfa417050f0cef6cd0c9b6e7a47ab5c3da9a0e3de6ec323aed32f4cc3f51ac719e34f0bd9b0cc617e3034581a708f4a3bba587b4b4cb91529cfd47393893c3b5cd430d0456a245b0c45d4398fe423b67faa8682c764d92c514d7e34a89abc16353e71de7d49895527e632a6163d7362549a8e9ab12277460d30d7892e0a5993a4d3922738f07892764b0ceabf280779894ced52aa7fba94100c2ec0fa1973d2b11044e6844ddcdbd59f26e1b321d02c9189414cace4abece30878ca21d198f2e61b84e7cbebb6a0ad83e2abd5bf69d7f8eed193a8e141088a4b7d41fe23a939f678ba94a1d9c9c2", + "length": 40, + "seed": "000102030405060708090a0b0c0d0e0f" +} diff --git a/src/vdaf/test_vec/08/XofTurboShake128.json b/src/vdaf/test_vec/08/XofTurboShake128.json new file mode 100644 index 000000000..1e48d1f64 --- /dev/null +++ b/src/vdaf/test_vec/08/XofTurboShake128.json @@ -0,0 +1,8 @@ +{ + "binder": "62696e64657220737472696e67", + "derived_seed": "8bac064e720bb1c413040a3f41990075", + "dst": "646f6d61696e2073657061726174696f6e20746167", + "expanded_vec_field128": "8bac064e720bb1c413040a3f419900750ce08494b0f4f2d95171dcf44255ef94606fd5e6ffe3735329f5550e34fe61f0d4704239c107e4beb6623e20cb2e2659662aef8409fcc162a01d2333fc8d8ee7bc31c394c88edeb5904d25bf851d30246d9bf4221a5aec6ff4cb2580dde88dfa726e21b35da18f5b1839a257482ab292615b094b092444013874fce11cbd293fc81fd9a00d1befca7b1aefa2324ad2c84a8d678b02973bd539021e18861647474211e99ccfff5e47483985b25257f83665f44ed3fbce4f5a2b20e5c54239653141f7d5132b255936d33327789e13b145362059f67bd8d5b240dfd1e525d6ac5c0bb6a5b4a0b7b7318a5e22fc91763d2eb9dbd5fd3a3665127ffa63ac5be71a0b67a5ce5ee158d902a4e3a4c580e734ee40682e471373b958853eddee1de30dda6e6f4a3e3a297a79bd7f332ce89b8f0cd50589f03b95408405df362a41f58688e1fb818deaccf36eedbabc1762215102de02125dc79450d47dc04ba88cd507bdf1690ae6c1dbb44352c29687e3f60e0d3d9ed8758aa1495f4976477bda7e3cdbf37078f615dfde8330df46aebe393a665fa3f9b906498ef59ac5a0da50ebeb91c80ac0d8ba3d9bcb4e23f37e416dbe679d633834b8351085a321314d8b0276b24de1dc41091f9bdf765f2879ef0d624927a649bb693386b5a22af2ec5b67b8298abadf1e4ffa10a794ebb9924761d08ad75b595ef11118b33a8f5e649e0b8351600be077a164c806a7ee2aba58de06177ccd18e8822d35c2d6843378f254d64e5a1ee52d9c5b3f63ae262c3d6d5b63baf4e2faf436d51d6318ac9d05cf4fe3e203b2b047bdb1b4f4f8d5645a5d59ab506afc423f3a0ae5691e7f755dc5bff3b6b4f08c61614b62f63b03ce30d35a2c0d", + "length": 40, + "seed": "000102030405060708090a0b0c0d0e0f" +} diff --git a/src/vdaf/xof.rs b/src/vdaf/xof.rs index 85006a063..d16f997e9 100644 --- a/src/vdaf/xof.rs +++ b/src/vdaf/xof.rs @@ -1,8 +1,14 @@ // SPDX-License-Identifier: MPL-2.0 -//! Implementations of XOFs specified in [[draft-irtf-cfrg-vdaf-07]]. +//! Implementations of XOFs specified in [[draft-irtf-cfrg-vdaf-08]]. //! -//! [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +//! [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ + +/// Value of the domain separation byte "D" used by XofTurboShake128 when invoking TurboSHAKE128. +const XOF_TURBO_SHAKE_128_DOMAIN_SEPARATION: u8 = 1; +/// Value of the domain separation byte "D" used by XofFixedKeyAes128 when invoking TurboSHAKE128. +#[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] +const XOF_FIXED_KEY_AES_128_DOMAIN_SEPARATION: u8 = 2; use crate::{ field::FieldElement, @@ -27,7 +33,7 @@ use rand_core::{ }; use sha3::{ digest::{ExtendableOutput, Update, XofReader}, - Shake128, Shake128Core, Shake128Reader, + TurboShake128, TurboShake128Core, TurboShake128Reader, }; #[cfg(feature = "crypto-dependencies")] use std::fmt::Formatter; @@ -105,9 +111,9 @@ impl IntoFieldVec for S { } } -/// An extendable output function (XOF) with the interface specified in [[draft-irtf-cfrg-vdaf-07]]. +/// An extendable output function (XOF) with the interface specified in [[draft-irtf-cfrg-vdaf-08]]. /// -/// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +/// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ pub trait Xof: Clone + Debug { /// The type of stream produced by this XOF. type SeedStream: RngCore + Sized; @@ -189,17 +195,19 @@ impl Debug for SeedStreamAes128 { } } -/// The XOF based on SHA-3 as specified in [[draft-irtf-cfrg-vdaf-07]]. +/// The XOF based on TurboSHAKE128 as specified in [[draft-irtf-cfrg-vdaf-08]]. /// -/// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +/// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ #[derive(Clone, Debug)] -pub struct XofShake128(Shake128); +pub struct XofTurboShake128(TurboShake128); -impl Xof<16> for XofShake128 { - type SeedStream = SeedStreamSha3; +impl Xof<16> for XofTurboShake128 { + type SeedStream = SeedStreamTurboShake128; fn init(seed_bytes: &[u8; 16], dst: &[u8]) -> Self { - let mut xof = Self(Shake128::from_core(Shake128Core::default())); + let mut xof = Self(TurboShake128::from_core(TurboShake128Core::new( + XOF_TURBO_SHAKE_128_DOMAIN_SEPARATION, + ))); Update::update( &mut xof.0, &[dst.len().try_into().expect("dst must be at most 255 bytes")], @@ -213,21 +221,21 @@ impl Xof<16> for XofShake128 { Update::update(&mut self.0, data); } - fn into_seed_stream(self) -> SeedStreamSha3 { - SeedStreamSha3::new(self.0.finalize_xof()) + fn into_seed_stream(self) -> SeedStreamTurboShake128 { + SeedStreamTurboShake128::new(self.0.finalize_xof()) } } -/// The seed stream produced by SHAKE128. -pub struct SeedStreamSha3(Shake128Reader); +/// The seed stream produced by TurboSHAKE128. +pub struct SeedStreamTurboShake128(TurboShake128Reader); -impl SeedStreamSha3 { - pub(crate) fn new(reader: Shake128Reader) -> Self { +impl SeedStreamTurboShake128 { + pub(crate) fn new(reader: TurboShake128Reader) -> Self { Self(reader) } } -impl RngCore for SeedStreamSha3 { +impl RngCore for SeedStreamTurboShake128 { fn fill_bytes(&mut self, dest: &mut [u8]) { XofReader::read(&mut self.0, dest); } @@ -246,13 +254,13 @@ impl RngCore for SeedStreamSha3 { } } -/// A `rand`-compatible interface to construct XofShake128 seed streams, with the domain separation tag -/// and binder string both fixed as the empty string. -impl SeedableRng for SeedStreamSha3 { +/// A `rand`-compatible interface to construct XofTurboShake128 seed streams, with the domain +/// separation tag and binder string both fixed as the empty string. +impl SeedableRng for SeedStreamTurboShake128 { type Seed = [u8; 16]; fn from_seed(seed: Self::Seed) -> Self { - XofShake128::init(&seed, b"").into_seed_stream() + XofTurboShake128::init(&seed, b"").into_seed_stream() } } @@ -271,7 +279,9 @@ pub struct XofFixedKeyAes128Key { impl XofFixedKeyAes128Key { /// Derive the fixed key from the domain separation tag and binder string. pub fn new(dst: &[u8], binder: &[u8]) -> Self { - let mut fixed_key_deriver = Shake128::from_core(Shake128Core::default()); + let mut fixed_key_deriver = TurboShake128::from_core(TurboShake128Core::new( + XOF_FIXED_KEY_AES_128_DOMAIN_SEPARATION, + )); Update::update( &mut fixed_key_deriver, &[dst.len().try_into().expect("dst must be at most 255 bytes")], @@ -295,15 +305,15 @@ impl XofFixedKeyAes128Key { } } -/// XofFixedKeyAes128 as specified in [[draft-irtf-cfrg-vdaf-07]]. This XOF is NOT RECOMMENDED for +/// XofFixedKeyAes128 as specified in [[draft-irtf-cfrg-vdaf-08]]. This XOF is NOT RECOMMENDED for /// general use; see Section 9 ("Security Considerations") for details. /// -/// This XOF combines SHA-3 and a fixed-key mode of operation for AES-128. The key is "fixed" in -/// the sense that it is derived (using SHAKE128) from the domain separation tag and binder -/// strings, and depending on the application, these strings can be hard-coded. The seed is used to -/// construct each block of input passed to a hash function built from AES-128. +/// This XOF combines TurboSHAKE128 and a fixed-key mode of operation for AES-128. The key is +/// "fixed" in the sense that it is derived (using TurboSHAKE128) from the domain separation tag and +/// binder strings, and depending on the application, these strings can be hard-coded. The seed is +/// used to construct each block of input passed to a hash function built from AES-128. /// -/// [draft-irtf-cfrg-vdaf-07]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/07/ +/// [draft-irtf-cfrg-vdaf-08]: https://datatracker.ietf.org/doc/draft-irtf-cfrg-vdaf/08/ #[derive(Clone, Debug)] #[cfg(all(feature = "crypto-dependencies", feature = "experimental"))] #[cfg_attr( @@ -311,7 +321,7 @@ impl XofFixedKeyAes128Key { doc(cfg(all(feature = "crypto-dependencies", feature = "experimental"))) )] pub struct XofFixedKeyAes128 { - fixed_key_deriver: Shake128, + fixed_key_deriver: TurboShake128, base_block: Block, } @@ -320,7 +330,7 @@ impl Xof<16> for XofFixedKeyAes128 { type SeedStream = SeedStreamFixedKeyAes128; fn init(seed_bytes: &[u8; 16], dst: &[u8]) -> Self { - let mut fixed_key_deriver = Shake128::from_core(Shake128Core::default()); + let mut fixed_key_deriver = TurboShake128::from_core(TurboShake128Core::new(2u8)); Update::update( &mut fixed_key_deriver, &[dst.len().try_into().expect("dst must be at most 255 bytes")], @@ -482,10 +492,10 @@ mod tests { } #[test] - fn xof_shake128() { + fn xof_turboshake128() { let t: XofTestVector = - serde_json::from_str(include_str!("test_vec/07/XofShake128.json")).unwrap(); - let mut xof = XofShake128::init(&t.seed.try_into().unwrap(), &t.dst); + serde_json::from_str(include_str!("test_vec/08/XofTurboShake128.json")).unwrap(); + let mut xof = XofTurboShake128::init(&t.seed.try_into().unwrap(), &t.dst); xof.update(&t.binder); assert_eq!( @@ -501,14 +511,14 @@ mod tests { let got: Vec = xof.clone().into_seed_stream().into_field_vec(t.length); assert_eq!(got, want); - test_xof::(); + test_xof::(); } #[cfg(feature = "experimental")] #[test] fn xof_fixed_key_aes128() { let t: XofTestVector = - serde_json::from_str(include_str!("test_vec/07/XofFixedKeyAes128.json")).unwrap(); + serde_json::from_str(include_str!("test_vec/08/XofFixedKeyAes128.json")).unwrap(); let mut xof = XofFixedKeyAes128::init(&t.seed.try_into().unwrap(), &t.dst); xof.update(&t.binder); diff --git a/tests/discrete_gauss.rs b/tests/discrete_gauss.rs index 5b3ef4c5b..e167797a5 100644 --- a/tests/discrete_gauss.rs +++ b/tests/discrete_gauss.rs @@ -4,7 +4,7 @@ use num_bigint::{BigInt, BigUint}; use num_rational::Ratio; use num_traits::FromPrimitive; use prio::dp::distributions::DiscreteGaussian; -use prio::vdaf::xof::SeedStreamSha3; +use prio::vdaf::xof::SeedStreamTurboShake128; use rand::distributions::Distribution; use rand::SeedableRng; use serde::Deserialize; @@ -12,7 +12,7 @@ use serde::Deserialize; /// A test vector of discrete Gaussian samples, produced by the python reference /// implementation for [[CKS20]]. The script used to generate the test vector can /// be found in this gist: -/// https://gist.github.com/ooovi/529c00fc8a7eafd068cd076b78fc424e +/// https://gist.github.com/divergentdave/94cab188e84a4764db6cdd1288e6ead3 /// The python reference implementation is here: /// https://github.com/IBM/discrete-gaussian-differential-privacy /// @@ -43,6 +43,10 @@ fn discrete_gauss_reference() { "test_vectors/discrete_gauss_9999999999999999999999.json" ))) .unwrap(), + serde_json::from_str(include_str!(concat!( + "test_vectors/discrete_gauss_2.342.json" + ))) + .unwrap(), ]; for test_vector in test_vectors { @@ -53,7 +57,7 @@ fn discrete_gauss_reference() { .unwrap(); // check samples are consistent - let mut rng = SeedStreamSha3::from_seed(test_vector.seed); + let mut rng = SeedStreamTurboShake128::from_seed(test_vector.seed); let samples: Vec = (0..test_vector.samples.len()) .map(|_| sampler.sample(&mut rng)) .collect(); diff --git a/tests/test_vectors/discrete_gauss_100.json b/tests/test_vectors/discrete_gauss_100.json index fe8114c25..84425db75 100644 --- a/tests/test_vectors/discrete_gauss_100.json +++ b/tests/test_vectors/discrete_gauss_100.json @@ -1,54 +1,54 @@ { "samples": [ - -74, + -54, + 61, + -113, + -98, + 21, + -91, + 72, + 112, + -29, 68, - -15, - 175, - -120, - -2, - -73, - 108, - 40, - 69, - 81, - -135, - 247, - 32, - 107, + 84, + -27, + -109, + -20, + -24, + -69, + -168, + 199, + -122, + 59, + 35, + 282, + 113, + 4, + -91, -61, - 164, - 22, - 118, - 37, - -58, - 147, - 65, - 53, - 9, - -96, - -130, - 100, - 48, + -28, + 137, + 57, + 109, + 2, + 17, + -20, + 38, + -16, + 18, + -63, + 1, + -20, -30, - -2, - -115, - 56, - 95, - 119, - 28, - -101, - 50, - 39, - 21, - -6, - -70, - 131, - 66, - 81, - -18, - 94, - 55, - 20 + -147, + -73, + -28, + -16, + -31, + 10, + -229, + -56, + -254 ], "seed": "000102030405060708090a0b0c0d0e0f", "std_denom": 1, diff --git a/tests/test_vectors/discrete_gauss_2.342.json b/tests/test_vectors/discrete_gauss_2.342.json index 7d9508c44..c70e3b06e 100644 --- a/tests/test_vectors/discrete_gauss_2.342.json +++ b/tests/test_vectors/discrete_gauss_2.342.json @@ -1,54 +1,54 @@ { "samples": [ -1, - 4, - 2, - 0, - 0, - -2, 1, - -5, + 6, 2, + -4, -1, - 0, - 0, - 0, - 3, - -6, - 5, + -2, 2, - 1, - -1, + -2, -3, 0, - 2, - -3, -2, + -1, + 3, 2, - -3, - 1, 1, 2, - -3, - -1, + -7, -1, + 0, 4, - 2, - -2, 1, -1, 0, - -3, + 1, + -2, + 0, 1, 2, + 0, + 6, + -2, + 2, + 0, + -2, + 2, + 6, 1, + 0, + -4, + -3, + -1, -1, - 3, - 1, 2, - -3, + 0, + 0, -2, - 0 + 0, + 2 ], "seed": "000102030405060708090a0b0c0d0e0f", "std_denom": 500, diff --git a/tests/test_vectors/discrete_gauss_3.json b/tests/test_vectors/discrete_gauss_3.json index d4a3486db..363c136eb 100644 --- a/tests/test_vectors/discrete_gauss_3.json +++ b/tests/test_vectors/discrete_gauss_3.json @@ -1,54 +1,54 @@ { "samples": [ - 1, + -3, -1, -2, 1, + 7, -1, - 0, - 1, - -1, - 0, - 2, - 3, - 4, - 1, - 1, -2, - 4, - 6, + 1, -5, + 1, -3, - -1, - 4, - 0, - 6, - 2, + 3, 2, - -4, - -2, -5, + -2, + 5, + -2, + 5, + -1, -3, 2, - 1, - -3, -2, - 1, + -1, -2, - 1, + -2, + -1, 0, - 3, - -4, - -4, 1, - 3, + -1, 2, - 1, - 0, + -3, + 2, + -6, + -4, + -2, + -2, + -6, -1, - 1, 4, - 1 + -1, + 2, + -3, + 1, + -7, + -1, + 6, + 2, + -3, + 5 ], "seed": "000102030405060708090a0b0c0d0e0f", "std_denom": 1, diff --git a/tests/test_vectors/discrete_gauss_41293847.json b/tests/test_vectors/discrete_gauss_41293847.json index 213e919c6..247b2c245 100644 --- a/tests/test_vectors/discrete_gauss_41293847.json +++ b/tests/test_vectors/discrete_gauss_41293847.json @@ -1,54 +1,54 @@ { "samples": [ - -10157810, - -7944688, - 80361481, - -2601121, - -2098394, - -61204295, - 250399, - 62702361, - -35117486, - 14804891, - -5043613, - 34131059, - -34448923, - -24176095, - 106518772, - 44056972, - 15910928, - 63338376, - 12839729, - 11701052, - -54254959, - -11306071, - -6005727, - 29738939, - -30284246, - -47672638, - 11549070, - -17580447, - -2973754, - -298465, - -15349002, - 56970396, - 35612502, - -78720214, - -6082493, - -2759887, - -11374460, - 177253, - -35234082, - 42256563, - 44219644, - 86984413, - -43711428, - -16031438, - 42572889, - 39464625, - -14433332, - -7735634, - 4403776 + -28705712, + 12839166, + 68574447, + 1993202, + 17416465, + 32526761, + 1212638, + -44876888, + 16502539, + -57954542, + -54567452, + -17421605, + 7569207, + 13482762, + -24573436, + 73067636, + -58069630, + -24924404, + 51409721, + -18659663, + -12752706, + 4308454, + -49095581, + -69009203, + -22975883, + 46983148, + 47341228, + -1860382, + 26901791, + -5079023, + -57635595, + -38560402, + 59065470, + 100046871, + -144954761, + -22089238, + -43816191, + -47986043, + 34106023, + 74194716, + -37681692, + 3946618, + 18344461, + -45770607, + -654004, + 31284526, + -50259979, + 28037461, + 2734567 ], "seed": "000102030405060708090a0b0c0d0e0f", "std_denom": 1, diff --git a/tests/test_vectors/discrete_gauss_9.json b/tests/test_vectors/discrete_gauss_9.json index 408c7489a..b5df20d18 100644 --- a/tests/test_vectors/discrete_gauss_9.json +++ b/tests/test_vectors/discrete_gauss_9.json @@ -1,54 +1,54 @@ { "samples": [ - 2, - 14, - -12, - 10, - -13, - 1, - 6, - -10, + -6, + 7, + -3, + -7, + -14, + 4, + 11, + -22, -1, + 8, + -9, + 12, + -9, + 20, + -16, + -10, + -8, + -15, + 6, + -8, + 7, + 12, + 1, 4, + -3, + -7, + 20, + 2, + 13, + -4, -5, 1, - -20, - 1, - -14, + 2, + -2, + 4, + -6, 2, -5, - 10, - 3, - 9, - 10, - 12, - -4, - 12, - -4, - -13, - 7, - -10, -6, 2, - 6, - 18, - -7, - -11, - 20, - 1, - -4, - 14, - 11, - 5, - 6, - -1, 2, - 5, - 3, - -8, - -1, - 6, - -8 + -5, + -10, + -9, + -15, + -2, + -3, + 1, + -13 ], "seed": "000102030405060708090a0b0c0d0e0f", "std_denom": 1, diff --git a/tests/test_vectors/discrete_gauss_9999999999999999999999.json b/tests/test_vectors/discrete_gauss_9999999999999999999999.json index 396f5a4cf..1b43f758b 100644 --- a/tests/test_vectors/discrete_gauss_9999999999999999999999.json +++ b/tests/test_vectors/discrete_gauss_9999999999999999999999.json @@ -1,54 +1,54 @@ { "samples": [ - 7826646418794481373730, - 4044429794334089153683, - -13887062284591122240746, - 4816851335312673293131, - 1899078604295677453383, - -7819872990828024151405, - 1164017821807881486579, - -25360379570365624087817, - 5906637163630390455939, - 3730592807287609262846, - 1737147847266613603450, - 18593764766679058926154, - 22724295990478919946193, - -4396717652132313983045, - -7933138830987043774425, - 12204708418993708917398, - 10716232788607487693156, - -7423575920998904747964, - -274262846168968742506, - -24595460253341309777726, - 1880635641243101726137, - 10823060437484007979521, - -2525077352000184270857, - -1421364839539048815904, - -2648842672480402351562, - -7783156811031000955203, - -1831198454606609539077, - 905920470298728568753, - -8805882598094077859729, - 2949974625887521817722, - 13071000629486423981714, - 1311702736683393895126, - -14044034250430823347919, - 1421736709768854180193, - 14824744520414922652958, - 10752031849750698732804, - -522118577625103067952, - 2006618532306506057615, - -7573105805904097888275, - -14482966128638641002042, - -11408400475022385123481, - -17555433966245180572099, - -6120185353438187140929, - -4778266138627264471521, - -19325342657405318133711, - 3725950229250476135126, - -7977400544074383347686, - 2738166449787592433931, - -1321521809406566447071 + -7678632936135800555201, + -9832864446958915374632, + 3796223649719723548306, + -10458306547534276720045, + -9593524715689396783652, + -2184509652523057908030, + -6469904065015921866985, + 8555843521262785582921, + -3275061234860213279391, + -1712551617443682313245, + -4176263950279049852314, + -1041488124720108532833, + 2422891656983904955539, + -5406575579403973625234, + 4031989610743156091985, + -15897376981820943559856, + -9495308497775799052592, + -10542231739931574778478, + -811195020079942319200, + -6168725392123782999911, + 3572639345203916100181, + 9572138148079890711898, + 12973597810318272581841, + -10417671747756128178069, + -4499306785200793424437, + 24392853538076877246695, + 490509578119404728479, + -3153758591414179213424, + -2953031165864251687043, + 7687220020362800379045, + -2894825604535601473288, + -2484898457763802405625, + 2506976850588238983075, + -317271622218426183645, + 3771644622097191550823, + 14048201376263257821999, + 1011626374739477364716, + -7985335097085684878144, + -9834946916794550716888, + -7808156770298839154888, + -10888303506419120919014, + 20441738459254393472434, + -1142146934147582936699, + -380992974206599694131, + 14719724965924743443097, + 2738534455216435603182, + 16889459715609520924993, + 8450917371339563018232, + 3461026365290831355984 ], "seed": "000102030405060708090a0b0c0d0e0f", "std_denom": 1, From 8eaf99b29c8c2d2a0231b65bf9c911f4eb599f9f Mon Sep 17 00:00:00 2001 From: David Cook Date: Tue, 28 Nov 2023 11:49:48 -0600 Subject: [PATCH 2/2] Clean up test --- tests/discrete_gauss.rs | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/tests/discrete_gauss.rs b/tests/discrete_gauss.rs index e167797a5..d72138b64 100644 --- a/tests/discrete_gauss.rs +++ b/tests/discrete_gauss.rs @@ -29,24 +29,15 @@ pub struct DiscreteGaussTestVector { #[test] fn discrete_gauss_reference() { let test_vectors: Vec = vec![ - serde_json::from_str(include_str!(concat!("test_vectors/discrete_gauss_3.json"))).unwrap(), - serde_json::from_str(include_str!(concat!("test_vectors/discrete_gauss_9.json"))).unwrap(), - serde_json::from_str(include_str!(concat!( - "test_vectors/discrete_gauss_100.json" - ))) - .unwrap(), - serde_json::from_str(include_str!(concat!( - "test_vectors/discrete_gauss_41293847.json" - ))) - .unwrap(), - serde_json::from_str(include_str!(concat!( + serde_json::from_str(include_str!("test_vectors/discrete_gauss_3.json")).unwrap(), + serde_json::from_str(include_str!("test_vectors/discrete_gauss_9.json")).unwrap(), + serde_json::from_str(include_str!("test_vectors/discrete_gauss_100.json")).unwrap(), + serde_json::from_str(include_str!("test_vectors/discrete_gauss_41293847.json")).unwrap(), + serde_json::from_str(include_str!( "test_vectors/discrete_gauss_9999999999999999999999.json" - ))) - .unwrap(), - serde_json::from_str(include_str!(concat!( - "test_vectors/discrete_gauss_2.342.json" - ))) + )) .unwrap(), + serde_json::from_str(include_str!("test_vectors/discrete_gauss_2.342.json")).unwrap(), ]; for test_vector in test_vectors {