Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return all RustCrypto libs but crypto-bigint to stable versions #154

Merged
merged 1 commit into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- `FirstRound::Context` renamed to `Inputs`. ([#102])
- `Payload` and `Artifact` values are hidden in wrapper types where they were previously exposed. ([#102])
- A number of crates set to their `pre` releases hinging on the `pre` release of `crypto-bigint`.
- A number of crates set to their `pre` releases hinging on the `pre` release of `crypto-bigint`. ([#120])
- Signature and elliptic curve dependencies reset back to stable versions. (#[154])


### Added
Expand All @@ -20,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

[#96]: https://github.com/entropyxyz/synedrion/pull/96
[#102]: https://github.com/entropyxyz/synedrion/pull/102
[#120]: https://github.com/entropyxyz/synedrion/pull/120
[#154]: https://github.com/entropyxyz/synedrion/pull/154


## [0.1.0] - 2023-12-07
Expand Down
20 changes: 10 additions & 10 deletions synedrion/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ readme = "README.md"
categories = ["cryptography", "no-std"]

[dependencies]
signature = { version = "2.3.0-pre.4", default-features = false, features = ["alloc"] }
k256 = {version = "0.14.0-pre.2", default-features = false, features = ["ecdsa", "arithmetic"]}
signature = { version = "2", default-features = false, features = ["alloc"] }
k256 = { version = "0.13", default-features = false, features = ["ecdsa", "arithmetic"] }
rand_core = { version = "0.6.4", default-features = false, features = ["getrandom"] }
sha2 = { version = "0.11.0-pre.4", default-features = false }
sha3 = { version = "0.11.0-pre.4", default-features = false }
digest = { version = "0.11.0-pre.9", default-features = false, features = ["alloc"]}
sha2 = { version = "0.10", default-features = false }
sha3 = { version = "0.10", default-features = false }
digest = { version = "0.10", default-features = false, features = ["alloc"]}
hex = { version = "0.4", default-features = false, features = ["alloc"] }
base64 = { version = "0.22.1", default-features = false, features = ["alloc"] }
hashing-serializer = { version = "0.2.0-pre.0", default-features = false }
base64 = { version = "0.22", default-features = false, features = ["alloc"] }
hashing-serializer = { version = "0.1", default-features = false }
secrecy = { version = "0.9.0-pre.0", default-features = false, features = ["serde"] }
zeroize = { version = "1.8", default-features = false, features = ["alloc", "zeroize_derive"] }
bip32 = { version = "0.6.0-pre.0", default-features = false, features = ["alloc", "secp256k1", "k256"] }
bip32 = { version = "0.5", default-features = false, features = ["alloc", "secp256k1", "k256"] }

# Note: `alloc` is needed for `crytpto-bigint`'s dependency `serdect` to be able
# to serialize Uints in human-readable formats.
crypto-bigint = { version = "0.6.0-rc.2", features = ["serde", "alloc", "rand_core"] }
crypto-bigint = { version = "0.6.0-rc.2", features = ["serde", "alloc", "rand_core", "zeroize"] }
crypto-primes = "0.6.0-pre.1"

serde = { version = "1", default-features = false, features = ["derive"] }
Expand All @@ -43,7 +43,7 @@ serde_assert = "0.8"
tokio = { version = "1", features = ["rt", "sync", "time", "macros"] }
rand = "0.8"
criterion = "0.5"
k256 = {version = "0.14.0-pre.2", default-features = false, features = ["ecdsa", "arithmetic", "pem", "serde"]}
k256 = {version = "0.13", default-features = false, features = ["ecdsa", "arithmetic", "pem", "serde"]}
impls = "1"

[features]
Expand Down
76 changes: 68 additions & 8 deletions synedrion/src/cggmp21/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,38 @@ use crate::curve::{Curve, Scalar, ORDER};
use crate::paillier::PaillierParams;
use crate::tools::hashing::{Chain, HashableType};
use crate::uint::{
subtle::ConditionallySelectable, upcast_uint, Bounded, Encoding, NonZero, Signed, U1024Mod,
U2048Mod, U4096Mod, U512Mod, Zero, U1024, U2048, U4096, U512, U8192,
subtle::ConditionallySelectable, Bounded, Encoding, NonZero, Signed, U1024Mod, U2048Mod,
U4096Mod, U512Mod, Uint, Zero, U1024, U2048, U4096, U512, U8192,
};
// We're depending on a pre-release `crypto-bigint` version,
// and `k256` depends on the released one.
// So as long as that is the case, `k256` `Uint` is separate
// from the one used throughout the crate.
use k256::elliptic_curve::bigint::Uint as K256Uint;

use serde::{Deserialize, Serialize};

#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PaillierTest;

const fn upcast_uint<const N1: usize, const N2: usize>(value: K256Uint<N1>) -> K256Uint<N2> {
assert!(
N2 >= N1,
"Upcast target must be bigger than the upcast candidate"
);
let mut result_words = [0; N2];
let mut i = 0;
while i < N1 {
result_words[i] = value.as_words()[i];
i += 1;
}
K256Uint::from_words(result_words)
}

const fn convert_uint<const N: usize>(value: K256Uint<N>) -> Uint<N> {
Uint::from_words(value.to_words())
}

impl PaillierParams for PaillierTest {
/*
The prime size is chosen to be minimal for which the `TestSchemeParams` still work.
Expand Down Expand Up @@ -115,8 +138,7 @@ pub trait SchemeParams: Debug + Clone + Send + PartialEq + Eq + Send + Sync + 's
fn bounded_from_scalar(
value: &Scalar,
) -> Option<Bounded<<Self::Paillier as PaillierParams>::Uint>> {
const ORDER_BITS: u32 = ORDER.bits_vartime();
Bounded::new(Self::uint_from_scalar(value), ORDER_BITS)
Bounded::new(Self::uint_from_scalar(value), ORDER.bits_vartime() as u32)
}

/// Converts a curve scalar to the associated integer type, wrapped in `Signed`.
Expand Down Expand Up @@ -194,9 +216,13 @@ impl SchemeParams for TestParams {
const EPS_BOUND: usize = 320;
type Paillier = PaillierTest;
const CURVE_ORDER: NonZero<<Self::Paillier as PaillierParams>::Uint> =
upcast_uint(ORDER).to_nz().expect("Correct by construction");
convert_uint(upcast_uint(ORDER))
.to_nz()
.expect("Correct by construction");
const CURVE_ORDER_WIDE: NonZero<<Self::Paillier as PaillierParams>::WideUint> =
upcast_uint(ORDER).to_nz().expect("Correct by construction");
convert_uint(upcast_uint(ORDER))
.to_nz()
.expect("Correct by construction");
}

/// Production strength parameters.
Expand All @@ -210,7 +236,41 @@ impl SchemeParams for ProductionParams {
const EPS_BOUND: usize = Self::L_BOUND * 2;
type Paillier = PaillierProduction;
const CURVE_ORDER: NonZero<<Self::Paillier as PaillierParams>::Uint> =
upcast_uint(ORDER).to_nz().expect("Correct by construction");
convert_uint(upcast_uint(ORDER))
.to_nz()
.expect("Correct by construction");
const CURVE_ORDER_WIDE: NonZero<<Self::Paillier as PaillierParams>::WideUint> =
upcast_uint(ORDER).to_nz().expect("Correct by construction");
convert_uint(upcast_uint(ORDER))
.to_nz()
.expect("Correct by construction");
}

#[cfg(test)]
mod tests {
use k256::elliptic_curve::bigint::{U256, U64};

use super::upcast_uint;

#[test]
fn upcast_uint_results_in_a_bigger_type() {
let n = U64::from_u8(10);
let expected = U256::from_u8(10);
let bigger_n: U256 = upcast_uint(n);

assert_eq!(bigger_n, expected);
}

#[test]
#[should_panic(expected = "Upcast target must be bigger than the upcast candidate")]
fn upcast_uint_panics_in_test_if_actually_attempting_downcast() {
let n256 = U256::from_u8(8);
let _n: U64 = upcast_uint(n256);
}

#[test]
fn upcast_uint_allows_casting_to_same_size() {
let n256 = U256::from_u8(8);
let n: U256 = upcast_uint(n256);
assert_eq!(n, n256)
}
}
33 changes: 21 additions & 12 deletions synedrion/src/curve/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use core::ops::{Add, Mul, Neg, Sub};
use digest::Digest;
use k256::elliptic_curve::group::ff::PrimeField;
use k256::elliptic_curve::{
array::{typenum::marker_traits::Unsigned, Array},
bigint::U256, // Note that this type is different from typenum::U256
generic_array::{typenum::marker_traits::Unsigned, GenericArray},
ops::Reduce,
point::AffineCoordinates,
sec1::{EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint},
Expand Down Expand Up @@ -40,7 +40,18 @@ pub(crate) const ORDER: U256 = Secp256k1::ORDER;

impl HashableType for Curve {
fn chain_type<C: Chain>(digest: C) -> C {
digest.chain(&ORDER).chain(&Point::GENERATOR)
let mut digest = digest;

// TODO: `k256 0.14` depends on `crypto-bigint` that supports `Serialize` for `Uint`'s,
// so we can just chain `ORDER`. For now we have to do it manually.
// Note that since only `to_words` is available, we need to chain it
// so that the result is the same on 32- and 64-bit targets - that is, in low-endian order.
let words = ORDER.to_words();
for word in words {
digest = digest.chain(&word.to_le_bytes());
}

digest.chain(&Point::GENERATOR)
}
}

Expand Down Expand Up @@ -81,7 +92,7 @@ impl Scalar {
/// SEC1 specifies to subtract the secp256k1 modulus when the byte array
/// is larger than the modulus.
pub fn from_reduced_bytes(bytes: &[u8; 32]) -> Self {
let arr = Array::<u8, FieldBytesSize<Secp256k1>>::from(*bytes);
let arr = GenericArray::<u8, FieldBytesSize<Secp256k1>>::from(*bytes);
Self(<BackendScalar as Reduce<U256>>::reduce_bytes(&arr))
}

Expand All @@ -107,8 +118,9 @@ impl Scalar {
}

pub(crate) fn try_from_bytes(bytes: &[u8]) -> Result<Self, String> {
let arr = Array::<u8, FieldBytesSize<Secp256k1>>::try_from_iter(bytes.iter().cloned())
.map_err(|e| format!("Invalid length of a curve scalar: {:?}", e))?;
let arr =
GenericArray::<u8, FieldBytesSize<Secp256k1>>::from_exact_iter(bytes.iter().cloned())
.ok_or("Invalid length of a curve scalar")?;

BackendScalar::from_repr_vartime(arr)
.map(Self)
Expand Down Expand Up @@ -200,13 +212,10 @@ impl Point {
.ok_or_else(|| "Invalid curve point representation".into())
}

pub(crate) fn to_compressed_array(self) -> Array<u8, CompressedPointSize> {
self.0
.to_affine()
.to_encoded_point(true)
.as_bytes()
.try_into()
.expect("An AffinePoint is composed of elements of the correct size and their slice repr fits in the `CompressedPointSize`-sized array.")
pub(crate) fn to_compressed_array(self) -> GenericArray<u8, CompressedPointSize> {
GenericArray::<u8, CompressedPointSize>::from_exact_iter(
self.0.to_affine().to_encoded_point(true).as_bytes().iter().cloned(),
).expect("An AffinePoint is composed of elements of the correct size and their slice repr fits in the `CompressedPointSize`-sized array.")
}

pub(crate) fn to_backend(self) -> BackendPoint {
Expand Down
2 changes: 1 addition & 1 deletion synedrion/src/curve/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl RecoverableSignature {
// Normalize the `s` component.
// `BackendSignature`'s constructor does not require `s` to be normalized,
// but consequent usage of it may fail otherwise.
let signature = signature.normalize_s();
let signature = signature.normalize_s().unwrap_or(signature);

let message_bytes = message.to_bytes();
let recovery_id = RecoveryId::trial_recovery_from_prehash(
Expand Down
6 changes: 3 additions & 3 deletions synedrion/src/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ mod traits;

pub(crate) use crypto_bigint::{
modular::Retrieve, subtle, CheckedAdd, CheckedMul, CheckedSub, Encoding, Integer, Invert,
NonZero, PowBoundedExp, RandomMod, ShlVartime, WrappingSub, Zero, U1024, U2048, U4096, U512,
U8192,
NonZero, PowBoundedExp, RandomMod, ShlVartime, Uint, WrappingSub, Zero, U1024, U2048, U4096,
U512, U8192,
};
pub(crate) use crypto_primes::RandomPrimeWithRng;

pub(crate) use bounded::Bounded;
pub(crate) use signed::Signed;
pub(crate) use traits::{
upcast_uint, Exponentiable, HasWide, ToMontgomery, U1024Mod, U2048Mod, U4096Mod, U512Mod,
Exponentiable, HasWide, ToMontgomery, U1024Mod, U2048Mod, U4096Mod, U512Mod,
};
44 changes: 1 addition & 43 deletions synedrion/src/uint/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,12 @@ use crypto_bigint::{
modular::MontyForm,
nlimbs,
subtle::{ConditionallySelectable, CtOption},
Bounded, Encoding, Integer, Invert, PowBoundedExp, RandomMod, Square, Uint, Zero, U1024, U2048,
Bounded, Encoding, Integer, Invert, PowBoundedExp, RandomMod, Square, Zero, U1024, U2048,
U4096, U512, U8192,
};

use crate::uint::Signed;

pub(crate) const fn upcast_uint<const N1: usize, const N2: usize>(value: Uint<N1>) -> Uint<N2> {
assert!(
N2 >= N1,
"Upcast target must be bigger than the upcast candidate"
);
let mut result_words = [0; N2];
let mut i = 0;
while i < N1 {
result_words[i] = value.as_words()[i];
i += 1;
}
Uint::from_words(result_words)
}

pub trait ToMontgomery: Integer {
fn to_montgomery(
self,
Expand Down Expand Up @@ -252,31 +238,3 @@ impl Exponentiable<U512> for U512Mod {}
impl Exponentiable<U1024> for U1024Mod {}
impl Exponentiable<U2048> for U2048Mod {}
impl Exponentiable<U4096> for U4096Mod {}

#[cfg(test)]
mod tests {
use super::upcast_uint;
use crypto_bigint::{U256, U64};
#[test]
fn upcast_uint_results_in_a_bigger_type() {
let n = U64::from_u8(10);
let expected = U256::from_u8(10);
let bigger_n: U256 = upcast_uint(n);

assert_eq!(bigger_n, expected);
}

#[test]
#[should_panic(expected = "Upcast target must be bigger than the upcast candidate")]
fn upcast_uint_panics_in_test_if_actually_attempting_downcast() {
let n256 = U256::from_u8(8);
let _n: U64 = upcast_uint(n256);
}

#[test]
fn upcast_uint_allows_casting_to_same_size() {
let n256 = U256::from_u8(8);
let n: U256 = upcast_uint(n256);
assert_eq!(n, n256)
}
}
Loading