Skip to content

Commit

Permalink
Return all RustCrypto libs but crypto-bigint to stable versions
Browse files Browse the repository at this point in the history
  • Loading branch information
fjarri committed Oct 18, 2024
1 parent 9f4a687 commit d2709b4
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 78 deletions.
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)
}
}

0 comments on commit d2709b4

Please sign in to comment.