diff --git a/Cargo.toml b/Cargo.toml index cd9457b8..b473816c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,3 +87,4 @@ lazy_static = "1" derive_builder = "0.11" once_cell = "1" generic-array = "0.14" +itybity = "0.1" diff --git a/garble/mpz-garble-core/Cargo.toml b/garble/mpz-garble-core/Cargo.toml index 0af1d14f..d1e4fb9d 100644 --- a/garble/mpz-garble-core/Cargo.toml +++ b/garble/mpz-garble-core/Cargo.toml @@ -12,7 +12,6 @@ lto = true [dependencies] mpz-core.workspace = true mpz-circuits.workspace = true -tlsn-utils.workspace = true aes = { workspace = true, features = [] } cipher.workspace = true @@ -27,6 +26,7 @@ serde = { workspace = true, features = ["derive"] } serde_arrays.workspace = true thiserror.workspace = true derive_builder.workspace = true +itybity.workspace = true [dev-dependencies] rstest.workspace = true diff --git a/garble/mpz-garble-core/src/encoding/value.rs b/garble/mpz-garble-core/src/encoding/value.rs index 65a863e1..fb32b536 100644 --- a/garble/mpz-garble-core/src/encoding/value.rs +++ b/garble/mpz-garble-core/src/encoding/value.rs @@ -1,7 +1,7 @@ +use itybity::{FromBits, ToBits}; use rand::{thread_rng, Rng}; use serde::{Deserialize, Serialize}; use std::ops::BitXor; -use utils::bits::{FromBits, ToBitsIter}; use mpz_circuits::types::{StaticValueType, TypeError, Value, ValueType}; use mpz_core::{hash::DomainSeparatedHash, impl_domain_separated_hash, Block}; @@ -23,7 +23,7 @@ pub enum ValueError { } /// A trait for encoding values. -pub trait Encode: ToBitsIter { +pub trait Encode { /// The encoded value type. type Encoded; @@ -320,7 +320,7 @@ macro_rules! define_encoded_variant { /// Returns the active encoding of the plaintext value pub(crate) fn select(&self, value: $PlaintextTy) -> $EncodedTy { - let mut bits = value.into_lsb0_iter(); + let mut bits = value.iter_lsb0(); let delta = self.0.delta(); $EncodedTy::::new(self.0.labels.map(|label| { if bits.next().expect("bit length should match") { @@ -559,7 +559,7 @@ macro_rules! define_decoding_info_variant { impl $value { /// Recovers the full encoding of this value using the decoding information and delta. pub(crate) fn recover(&self, decoding: &$name, delta: Delta) -> $value { - let mut decoding = decoding.0.into_lsb0_iter(); + let mut decoding = decoding.0.iter_lsb0(); $value::::new( delta, self.0.labels.map(|label| { @@ -578,7 +578,7 @@ macro_rules! define_decoding_info_variant { value: $ty, delta: Delta, ) -> $value { - let mut value = value.into_lsb0_iter(); + let mut value = value.iter_lsb0(); $value::::new( delta, self.0.labels.map(|label| { @@ -596,7 +596,7 @@ macro_rules! define_decoding_info_variant { <$ty>::from_lsb0( self.0 .iter() - .zip(decoding.0.into_lsb0_iter()) + .zip(decoding.0.iter_lsb0()) .map(|(label, dec)| label.pointer_bit() ^ dec), ) .into() diff --git a/garble/mpz-garble/Cargo.toml b/garble/mpz-garble/Cargo.toml index 6b7dbd39..f746c6a6 100644 --- a/garble/mpz-garble/Cargo.toml +++ b/garble/mpz-garble/Cargo.toml @@ -30,6 +30,7 @@ thiserror.workspace = true aes = { workspace = true } rayon = { workspace = true } derive_builder.workspace = true +itybity.workspace = true [dev-dependencies] mpz-ot = { workspace = true, features = ["mock"] } diff --git a/garble/mpz-garble/src/ot.rs b/garble/mpz-garble/src/ot.rs index 1dadb136..f6e70ea8 100644 --- a/garble/mpz-garble/src/ot.rs +++ b/garble/mpz-garble/src/ot.rs @@ -1,10 +1,10 @@ //! Traits for transferring encodings via oblivious transfer. use async_trait::async_trait; +use itybity::IntoBits; use mpz_circuits::types::Value; use mpz_core::Block; use mpz_garble_core::{encoding_state, EncodedValue, Label}; -use utils::bits::ToBitsIter; /// A trait for sending encodings via oblivious transfer. #[async_trait] @@ -61,7 +61,7 @@ where id, choice .iter() - .flat_map(|value| value.clone().into_lsb0_iter()) + .flat_map(|value| value.clone().into_iter_lsb0()) .collect(), ) .await?; diff --git a/mpz-circuits/Cargo.toml b/mpz-circuits/Cargo.toml index a0e7735b..393515c7 100644 --- a/mpz-circuits/Cargo.toml +++ b/mpz-circuits/Cargo.toml @@ -14,7 +14,6 @@ aes = [] sha2 = ["dep:sha2"] [dependencies] -tlsn-utils.workspace = true mpz-circuits-macros = { path = "../mpz-circuits-macros" } sha2 = { workspace = true, features = ["compress"], optional = true } @@ -27,6 +26,7 @@ rand.workspace = true regex = { workspace = true, optional = true } once_cell.workspace = true thiserror.workspace = true +itybity.workspace = true [dev-dependencies] aes.workspace = true diff --git a/mpz-circuits/src/builder.rs b/mpz-circuits/src/builder.rs index 92feefc3..c2e1bc0f 100644 --- a/mpz-circuits/src/builder.rs +++ b/mpz-circuits/src/builder.rs @@ -224,7 +224,7 @@ impl BuilderState { let one = self.get_const_one(); let nodes: Vec<_> = value - .into_lsb0_iter() + .into_iter_lsb0() .map(|bit| if bit { one } else { zero }) .collect(); diff --git a/mpz-circuits/src/circuit.rs b/mpz-circuits/src/circuit.rs index d789389a..62beec65 100644 --- a/mpz-circuits/src/circuit.rs +++ b/mpz-circuits/src/circuit.rs @@ -1,4 +1,4 @@ -use utils::bits::ToBits; +use itybity::IntoBits; use crate::{ components::Gate, @@ -136,7 +136,7 @@ impl Circuit { })?; } - for (node, bit) in input.iter().zip(value.clone().into_lsb0()) { + for (node, bit) in input.iter().zip(value.clone().into_iter_lsb0()) { feeds[node.id] = Some(bit); } } diff --git a/mpz-circuits/src/circuits/big_num.rs b/mpz-circuits/src/circuits/big_num.rs index 288c2a53..ac18d397 100644 --- a/mpz-circuits/src/circuits/big_num.rs +++ b/mpz-circuits/src/circuits/big_num.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; -use utils::bits::ToBitsIter; +use itybity::IntoBits; use crate::{ ops::binary::{switch_nbit, wrapping_add_nbit, wrapping_sub_nbit}, @@ -47,7 +47,7 @@ pub fn nbyte_add_mod_trace<'a, const N: usize>( .collect::>(); let mut modulus_bits = modulus .into_iter() - .flat_map(|m| m.into_lsb0_iter()) + .flat_map(|m| m.into_iter_lsb0()) .map(|bit| Node::new(bit as usize)) .collect::>(); diff --git a/mpz-circuits/src/types.rs b/mpz-circuits/src/types.rs index 19a13e3a..1c873aec 100644 --- a/mpz-circuits/src/types.rs +++ b/mpz-circuits/src/types.rs @@ -6,8 +6,8 @@ use std::{ }; use crate::components::{Feed, Node}; +use itybity::{FromBits, IntoBits}; use rand::Rng; -use utils::bits::{FromBits, ToBits, ToBitsIter}; /// An error related to binary type conversions. #[derive(Debug, thiserror::Error)] @@ -24,7 +24,7 @@ pub enum TypeError { /// A type that can be represented in binary form. #[allow(clippy::len_without_is_empty)] -pub trait ToBinaryRepr: ToBitsIter + Into { +pub trait ToBinaryRepr: IntoBits + Into { /// The binary representation of the type. type Repr: Clone + Into; @@ -573,66 +573,34 @@ impl Value { } } -impl ToBitsIter for Value { - type Lsb0Iter = Box + Send + 'static>; - type Msb0Iter = Box + Send + 'static>; +impl IntoBits for Value { + type IterLsb0 = std::vec::IntoIter; + type IterMsb0 = std::vec::IntoIter; - fn into_lsb0_iter(self) -> Self::Lsb0Iter { + fn into_iter_lsb0(self) -> Self::IterLsb0 { match self { - Value::Bit(v) => Box::new(std::iter::once(v)), - Value::U8(v) => Box::new(v.into_lsb0_iter()), - Value::U16(v) => Box::new(v.into_lsb0_iter()), - Value::U32(v) => Box::new(v.into_lsb0_iter()), - Value::U64(v) => Box::new(v.into_lsb0_iter()), - Value::U128(v) => Box::new(v.into_lsb0_iter()), - Value::Array(v) => Box::new(v.into_iter().flat_map(|v| v.into_lsb0_iter())), - } - } - - fn into_msb0_iter(self) -> Self::Msb0Iter { - match self { - Value::Bit(v) => Box::new(std::iter::once(v)), - Value::U8(v) => Box::new(v.into_msb0_iter()), - Value::U16(v) => Box::new(v.into_msb0_iter()), - Value::U32(v) => Box::new(v.into_msb0_iter()), - Value::U64(v) => Box::new(v.into_msb0_iter()), - Value::U128(v) => Box::new(v.into_msb0_iter()), - Value::Array(v) => Box::new(v.into_iter().flat_map(|v| v.into_msb0_iter())), - } + Value::Bit(v) => v.into_lsb0_vec(), + Value::U8(v) => v.into_lsb0_vec(), + Value::U16(v) => v.into_lsb0_vec(), + Value::U32(v) => v.into_lsb0_vec(), + Value::U64(v) => v.into_lsb0_vec(), + Value::U128(v) => v.into_lsb0_vec(), + Value::Array(v) => v.into_iter().flat_map(|v| v.into_iter_lsb0()).collect(), + } + .into_iter() } -} -impl ToBits for Value { - fn into_lsb0(self) -> Vec { + fn into_iter_msb0(self) -> Self::IterMsb0 { match self { - Value::Bit(v) => vec![v], - Value::U8(v) => v.into_lsb0(), - Value::U16(v) => v.into_lsb0(), - Value::U32(v) => v.into_lsb0(), - Value::U64(v) => v.into_lsb0(), - Value::U128(v) => v.into_lsb0(), - Value::Array(v) => v.into_iter().flat_map(|v| v.into_lsb0()).collect(), - } - } - - fn into_lsb0_boxed(self: Box) -> Vec { - self.into_lsb0() - } - - fn into_msb0(self) -> Vec { - match self { - Value::Bit(v) => vec![v], - Value::U8(v) => v.into_msb0(), - Value::U16(v) => v.into_msb0(), - Value::U32(v) => v.into_msb0(), - Value::U64(v) => v.into_msb0(), - Value::U128(v) => v.into_msb0(), - Value::Array(v) => v.into_iter().flat_map(|v| v.into_msb0()).collect(), - } - } - - fn into_msb0_boxed(self: Box) -> Vec { - self.into_msb0() + Value::Bit(v) => v.into_msb0_vec(), + Value::U8(v) => v.into_msb0_vec(), + Value::U16(v) => v.into_msb0_vec(), + Value::U32(v) => v.into_msb0_vec(), + Value::U64(v) => v.into_msb0_vec(), + Value::U128(v) => v.into_msb0_vec(), + Value::Array(v) => v.into_iter().flat_map(|v| v.into_iter_msb0()).collect(), + } + .into_iter() } } diff --git a/mpz-core/Cargo.toml b/mpz-core/Cargo.toml index 5f23f950..72130304 100644 --- a/mpz-core/Cargo.toml +++ b/mpz-core/Cargo.toml @@ -10,8 +10,6 @@ name = "mpz_core" default = [] [dependencies] -tlsn-utils.workspace = true - aes = { workspace = true, features = [] } cipher.workspace = true blake3.workspace = true @@ -19,7 +17,7 @@ rand.workspace = true serde = { workspace = true, features = ["derive"] } thiserror.workspace = true once_cell.workspace = true - +itybity.workspace = true bcs = "0.1.5" [dev-dependencies] diff --git a/mpz-core/src/block.rs b/mpz-core/src/block.rs index a20c9910..61ec91a1 100644 --- a/mpz-core/src/block.rs +++ b/mpz-core/src/block.rs @@ -1,10 +1,10 @@ use aes::BlockDecrypt; use cipher::{consts::U16, generic_array::GenericArray, BlockCipher, BlockEncrypt}; use core::ops::{BitAnd, BitXor}; +use itybity::{BitLength, GetBit, Lsb0, Msb0}; use rand::{CryptoRng, Rng}; use serde::{Deserialize, Serialize}; use std::convert::{From, TryInto}; -use utils::bits::ToBitsIter; /// A block of 128 bits #[repr(transparent)] @@ -151,17 +151,19 @@ pub trait BlockSerialize { fn from_blocks(blocks: Self::Serialized) -> Self; } -impl ToBitsIter for Block { - type Lsb0Iter = ::Lsb0Iter; - - type Msb0Iter = ::Msb0Iter; +impl BitLength for Block { + const BITS: usize = 128; +} - fn into_lsb0_iter(self) -> Self::Lsb0Iter { - self.0.into_lsb0_iter() +impl GetBit for Block { + fn get_bit(&self, index: usize) -> bool { + GetBit::::get_bit(&self.0, index) } +} - fn into_msb0_iter(self) -> Self::Msb0Iter { - self.0.into_msb0_iter() +impl GetBit for Block { + fn get_bit(&self, index: usize) -> bool { + GetBit::::get_bit(&self.0, index) } } diff --git a/ot/mpz-ot-core/Cargo.toml b/ot/mpz-ot-core/Cargo.toml index 77ee2936..f217443e 100644 --- a/ot/mpz-ot-core/Cargo.toml +++ b/ot/mpz-ot-core/Cargo.toml @@ -8,10 +8,11 @@ name = "mpz_ot_core" [dependencies] mpz-core.workspace = true -tlsn-utils.workspace = true clmul.workspace = true matrix-transpose.workspace = true +tlsn-utils.workspace = true + aes.workspace = true blake3.workspace = true cipher.workspace = true @@ -23,6 +24,7 @@ serde = { workspace = true, features = ["derive"] } thiserror.workspace = true derive_builder.workspace = true merlin.workspace = true +itybity.workspace = true [dev-dependencies] rstest.workspace = true diff --git a/ot/mpz-ot-core/benches/ot.rs b/ot/mpz-ot-core/benches/ot.rs index 5f8e3f2f..ded39dc1 100644 --- a/ot/mpz-ot-core/benches/ot.rs +++ b/ot/mpz-ot-core/benches/ot.rs @@ -1,9 +1,9 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; +use itybity::IntoBits; use mpz_core::Block; use mpz_ot_core::{DhOtReceiver, DhOtSender, Kos15Receiver, Kos15Sender}; use rand::{RngCore, SeedableRng}; use rand_chacha::ChaCha12Rng; -use utils::bits::IterToBits; fn base_ot(c: &mut Criterion) { let mut group = c.benchmark_group("base_ot"); @@ -13,7 +13,7 @@ fn base_ot(c: &mut Criterion) { let mut rng = ChaCha12Rng::from_entropy(); let mut choice = vec![0u8; n / 8]; rng.fill_bytes(&mut choice); - let choice = choice.into_msb0(); + let choice = choice.into_msb0_vec(); b.iter(|| { let mut sender = DhOtSender::default(); let sender_setup = sender.setup(&mut rng).unwrap(); @@ -36,7 +36,7 @@ fn ext_ot(c: &mut Criterion) { let mut rng = ChaCha12Rng::from_entropy(); let mut choice = vec![0u8; n / 8]; rng.fill_bytes(&mut choice); - let choice = choice.into_msb0(); + let choice = choice.into_msb0_vec(); b.iter(|| { let receiver = Kos15Receiver::default(); let (receiver, base_sender_setup) = receiver.base_setup().unwrap(); diff --git a/ot/mpz-ot-core/src/base/mod.rs b/ot/mpz-ot-core/src/base/mod.rs index 82482ba3..69924d93 100644 --- a/ot/mpz-ot-core/src/base/mod.rs +++ b/ot/mpz-ot-core/src/base/mod.rs @@ -32,7 +32,7 @@ pub mod tests { use rstest::*; pub mod fixtures { - use utils::bits::IterToBits; + use itybity::IntoBits; use super::*; @@ -48,7 +48,7 @@ pub mod tests { pub fn choice() -> Vec { let mut choice = vec![0u8; 16]; thread_rng().fill_bytes(&mut choice); - choice.into_msb0() + choice.into_msb0_vec() } #[fixture] diff --git a/ot/mpz-ot-core/src/extension/kos15/receiver/mod.rs b/ot/mpz-ot-core/src/extension/kos15/receiver/mod.rs index 7d50b4c7..d22baf21 100644 --- a/ot/mpz-ot-core/src/extension/kos15/receiver/mod.rs +++ b/ot/mpz-ot-core/src/extension/kos15/receiver/mod.rs @@ -15,11 +15,12 @@ use crate::{ }; use aes::{Aes128, NewBlockCipher}; use error::{CommittedOTError, ExtReceiverCoreError}; +use itybity::FromBits; use mpz_core::{utils::blake3, Block}; use rand::{Rng, SeedableRng}; use rand_chacha::ChaCha12Rng; use rand_core::RngCore; -use utils::{bits::FromBits, iter::xor}; +use utils::iter::xor; pub struct Kos15Receiver(S) where @@ -359,15 +360,16 @@ fn extension_setup_from( // KOS extension matrix by 32 columns. After transposition these additional columns turn // into additional rows, namely 32 * 8, where the factor 8 comes from the fact that it is a // bit-level transpose. This is why, in the end we will have to drain 256 rows in total. - let padding = calc_padding(choices.len()); - let mut padding_values = vec![false; padding]; - rng.fill::<[bool]>(&mut padding_values); - - // Extend choice bits - let mut r_bool = choices.to_vec(); - r_bool.extend(&padding_values); + let padding_len = calc_padding(choices.len()); + let ncols = choices.len() + padding_len; + + let padding = (0..padding_len).map(|_| rng.gen::()); + let r_bool = choices + .iter() + .copied() + .chain(padding) + .collect::>(); let r: Vec = Vec::from_msb0(r_bool.iter().copied()); - let ncols = r_bool.len(); let row_length = ncols / 8; let num_elements = BASE_COUNT * row_length; @@ -400,7 +402,7 @@ fn extension_setup_from( let kos15check_results = kos15_check_receiver(&mut rng, &ts, &r_bool); // Remove padding and the last 256 rows which were sacrificed due to the KOS check - ts.split_off_rows(ts.rows() - padding)?; + ts.split_off_rows(ts.rows() - padding_len)?; let message = ExtReceiverSetup { count: choices.len(), diff --git a/ot/mpz-ot-core/src/extension/kos15/utils.rs b/ot/mpz-ot-core/src/extension/kos15/utils.rs index c6d491ca..c7c56315 100644 --- a/ot/mpz-ot-core/src/extension/kos15/utils.rs +++ b/ot/mpz-ot-core/src/extension/kos15/utils.rs @@ -2,12 +2,12 @@ use super::{matrix::KosMatrix, BASE_COUNT}; use aes::{BlockCipher, BlockEncrypt}; use cipher::consts::U16; use clmul::Clmul; +use itybity::FromBits; use matrix_transpose::LANE_COUNT; use mpz_core::Block; use rand::{Rng, SeedableRng}; use rand_chacha::ChaCha12Rng; use std::convert::TryInto; -use utils::bits::{FromBits, IterFromBits}; /// Row length of the transposed KOS15 matrix const ROW_LENGTH_TR: usize = BASE_COUNT / 8; @@ -115,9 +115,7 @@ pub fn kos15_check_sender( check1 ^= chi; } - let mut delta = [0u8; ROW_LENGTH_TR]; - let choice_bytes: Vec = Vec::from_msb0(base_choices.iter().copied()); - delta.copy_from_slice(&choice_bytes); + let delta = <[u8; ROW_LENGTH_TR]>::from_msb0(base_choices.iter().copied()); let delta = Clmul::new(&delta); let x = Clmul::new(x); @@ -154,14 +152,8 @@ pub fn encrypt_values + BlockEncrypt>( } let mut ciphertexts: Vec<[Block; 2]> = Vec::with_capacity(table.len()); - let base_choice: [u8; 16] = choices - .iter() - .copied() - .iter_from_msb0() - .collect::>() - .try_into() - .expect("choices should be 16 bytes long"); - let delta = Block::from(base_choice); + let delta = <[u8; ROW_LENGTH_TR]>::from_msb0(choices.iter().copied()); + let delta = Block::from(delta); // If Receiver used *random* choice bits during OT extension setup, he will now // instruct us to de-randomize, so that the value corresponding to his *actual* // choice bit would be masked by that mask which Receiver knows. diff --git a/share-conversion/mpz-share-conversion-core/Cargo.toml b/share-conversion/mpz-share-conversion-core/Cargo.toml index 65c68738..68748aaa 100644 --- a/share-conversion/mpz-share-conversion-core/Cargo.toml +++ b/share-conversion/mpz-share-conversion-core/Cargo.toml @@ -8,7 +8,6 @@ name = "mpz_share_conversion_core" [dependencies] mpz-core.workspace = true -tlsn-utils.workspace = true thiserror.workspace = true rand.workspace = true @@ -17,6 +16,7 @@ ark-secp256r1.workspace = true num-bigint.workspace = true opaque-debug.workspace = true serde.workspace = true +itybity.workspace = true [dev-dependencies] rstest.workspace = true diff --git a/share-conversion/mpz-share-conversion-core/src/fields/gf2_128.rs b/share-conversion/mpz-share-conversion-core/src/fields/gf2_128.rs index c28c46f0..5a989ee1 100644 --- a/share-conversion/mpz-share-conversion-core/src/fields/gf2_128.rs +++ b/share-conversion/mpz-share-conversion-core/src/fields/gf2_128.rs @@ -2,11 +2,11 @@ use std::ops::{Add, Mul, Neg}; +use itybity::{BitLength, FromBits, GetBit, Lsb0, Msb0}; use rand::{distributions::Standard, prelude::Distribution}; use serde::{Deserialize, Serialize}; use mpz_core::{Block, BlockSerialize}; -use utils::bits::{FromBits, ToBits}; use super::Field; @@ -112,10 +112,6 @@ impl Field for Gf2_128 { Self(1 << rhs) } - fn get_bit(&self, n: usize) -> bool { - (self.0 >> n) & 1 == 1 - } - /// Galois field inversion of 128-bit block fn inverse(self) -> Self { let mut a = self; @@ -136,31 +132,29 @@ impl Field for Gf2_128 { } } -impl FromBits for Gf2_128 { - fn from_lsb0(iter: impl IntoIterator) -> Self { - Self(u128::from_lsb0(iter)) - } - - fn from_msb0(iter: impl IntoIterator) -> Self { - Self(u128::from_msb0(iter)) - } +impl BitLength for Gf2_128 { + const BITS: usize = 128; } -impl ToBits for Gf2_128 { - fn into_lsb0(self) -> Vec { - self.0.into_lsb0() +impl GetBit for Gf2_128 { + fn get_bit(&self, index: usize) -> bool { + GetBit::::get_bit(&self.0, index) } +} - fn into_lsb0_boxed(self: Box) -> Vec { - self.0.into_lsb0() +impl GetBit for Gf2_128 { + fn get_bit(&self, index: usize) -> bool { + GetBit::::get_bit(&self.0, index) } +} - fn into_msb0(self) -> Vec { - self.0.into_msb0() +impl FromBits for Gf2_128 { + fn from_lsb0(iter: impl IntoIterator) -> Self { + Self(u128::from_lsb0(iter)) } - fn into_msb0_boxed(self: Box) -> Vec { - self.0.into_msb0() + fn from_msb0(iter: impl IntoIterator) -> Self { + Self(u128::from_msb0(iter)) } } diff --git a/share-conversion/mpz-share-conversion-core/src/fields/mod.rs b/share-conversion/mpz-share-conversion-core/src/fields/mod.rs index 3cbfa744..4aa9739d 100644 --- a/share-conversion/mpz-share-conversion-core/src/fields/mod.rs +++ b/share-conversion/mpz-share-conversion-core/src/fields/mod.rs @@ -8,9 +8,9 @@ use std::{ ops::{Add, Mul, Neg}, }; +use itybity::{BitLength, FromBits, GetBit, Lsb0, Msb0}; use mpz_core::BlockSerialize; use rand::{distributions::Standard, prelude::Distribution, Rng}; -use utils::bits::{FromBits, ToBits}; /// A trait for finite fields pub trait Field: @@ -30,7 +30,9 @@ pub trait Field: + Eq + BlockSerialize + FromBits - + ToBits + + GetBit + + GetBit + + BitLength { /// The number of bits of a field element const BIT_SIZE: u32; @@ -44,9 +46,6 @@ pub trait Field: /// Return a field element from a power of two. fn two_pow(rhs: u32) -> Self; - /// Return the n-th bit, where n=0 returns the least-significant bit - fn get_bit(&self, n: usize) -> bool; - /// Return the multiplicative inverse fn inverse(self) -> Self; @@ -96,6 +95,7 @@ pub fn compute_product_repeated(powers: &mut Vec, factor: T, count: #[cfg(test)] mod tests { use super::{compute_product_repeated, Field}; + use itybity::{GetBit, Lsb0}; use rand::SeedableRng; use rand_chacha::ChaCha12Rng; @@ -139,9 +139,9 @@ mod tests { let b = T::from_lsb0(b); assert_eq!(a, T::one()); - assert!(a.get_bit(0)); + assert!(GetBit::::get_bit(&a, 0)); assert_eq!(b, T::two_pow(T::BIT_SIZE - 1)); - assert!(b.get_bit((T::BIT_SIZE - 1) as usize)); + assert!(GetBit::::get_bit(&b, (T::BIT_SIZE - 1) as usize)); } } diff --git a/share-conversion/mpz-share-conversion-core/src/fields/p256.rs b/share-conversion/mpz-share-conversion-core/src/fields/p256.rs index 7ef99f0d..3686205f 100644 --- a/share-conversion/mpz-share-conversion-core/src/fields/p256.rs +++ b/share-conversion/mpz-share-conversion-core/src/fields/p256.rs @@ -4,12 +4,12 @@ use std::ops::{Add, Mul, Neg}; use ark_ff::{BigInt, BigInteger, Field as ArkField, FpConfig, MontBackend, One, Zero}; use ark_secp256r1::{fq::Fq, FqConfig}; +use itybity::{BitLength, FromBits, GetBit, Lsb0, Msb0}; use num_bigint::ToBigUint; use rand::{distributions::Standard, prelude::Distribution}; use serde::{Deserialize, Serialize}; use mpz_core::{Block, BlockSerialize}; -use utils::bits::{FromBits, ToBits}; use super::Field; @@ -114,10 +114,6 @@ impl Field for P256 { P256(out) } - fn get_bit(&self, n: usize) -> bool { - MontBackend::::into_bigint(self.0).get_bit(n) - } - fn inverse(self) -> Self { P256(ArkField::inverse(&self.0).expect("Unable to invert field element")) } @@ -131,31 +127,29 @@ impl Field for P256 { } } -impl FromBits for P256 { - fn from_lsb0(iter: impl IntoIterator) -> Self { - P256(BigInt::from_bits_le(&iter.into_iter().collect::>()).into()) - } - - fn from_msb0(iter: impl IntoIterator) -> Self { - P256(BigInt::from_bits_be(&iter.into_iter().collect::>()).into()) - } +impl BitLength for P256 { + const BITS: usize = 256; } -impl ToBits for P256 { - fn into_lsb0(self) -> Vec { - (0..256).map(|i| self.get_bit(i)).collect() +impl GetBit for P256 { + fn get_bit(&self, index: usize) -> bool { + MontBackend::::into_bigint(self.0).get_bit(index) } +} - fn into_lsb0_boxed(self: Box) -> Vec { - (0..256).map(|i| self.get_bit(i)).collect() +impl GetBit for P256 { + fn get_bit(&self, index: usize) -> bool { + MontBackend::::into_bigint(self.0).get_bit(256 - index) } +} - fn into_msb0(self) -> Vec { - (0..256).map(|i| self.get_bit(i)).rev().collect() +impl FromBits for P256 { + fn from_lsb0(iter: impl IntoIterator) -> Self { + P256(BigInt::from_bits_le(&iter.into_iter().collect::>()).into()) } - fn into_msb0_boxed(self: Box) -> Vec { - (0..256).map(|i| self.get_bit(i)).rev().collect() + fn from_msb0(iter: impl IntoIterator) -> Self { + P256(BigInt::from_bits_be(&iter.into_iter().collect::>()).into()) } } diff --git a/share-conversion/mpz-share-conversion-core/src/shares.rs b/share-conversion/mpz-share-conversion-core/src/shares.rs index fd010d9d..245b0269 100644 --- a/share-conversion/mpz-share-conversion-core/src/shares.rs +++ b/share-conversion/mpz-share-conversion-core/src/shares.rs @@ -2,6 +2,7 @@ use crate::fields::Field; +use itybity::IntoBits; use rand::{CryptoRng, Rng}; use serde::{Deserialize, Serialize}; @@ -84,8 +85,8 @@ where /// Returns the binary representation of the share. pub fn binary_encoding(&self) -> Vec { match self { - Self::Add(share) => share.0.into_lsb0(), - Self::Mul(share) => share.0.into_lsb0(), + Self::Add(share) => share.0.into_lsb0_vec(), + Self::Mul(share) => share.0.into_lsb0_vec(), } }