Giter VIP home page Giter VIP logo

ff's People

Contributors

amaloz avatar daniel-aaron-bloom avatar dignifiedquire avatar ebfull avatar kigawas avatar kwantam avatar labbott avatar nikvolf avatar nuttycom avatar str4d avatar tarcieri avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ff's Issues

Bump MSRV to 1.56.0

Rationale:

  • 2021 edition support:
    • v2 resolver.
    • rust-version in Cargo.toml
  • bitvec 1.0.0 raises its MSRV to 1.56.0.

Bump MSRV to 1.60.0

Rationale:

  • Weak dependency features (so we can conditionally enable ff_derive features based on ff features without force-enabling ff_derive).

1.60.0 was released April 7, so we won't be doing this before July at the earliest. ff 0.12 will have MSRV 1.56 (#74).

Could `Field::pow_vartime` take a slice of word-sized "limbs" as the exponent?

Over on RustCrypto/traits#1024 we're discussing how to represent a parameter which is ultimately passed to Field::pow_vartime.

I was suggesting representing it as a crypto_bigint::UInt which internally uses 32-bit limbs on 32-bit platforms and 64-bit limbs on 64-bit platforms.

Field::pow_vartime accepts a type that impls AsRef<[u64]> as an exponent, regardless of the target pointer width.

I think it might make sense to allow customizing that in some way to make it easier to support 32-bit limbs on 32-bit platforms.

For example, PrimeFieldBits::ReprBits makes this possible. I'm curious if a similar associated type could be added to describe an array-of-limbs which would let implementations vary the word size based on the target.

(and really, in practice I'd use the same type as PrimeFieldBits::ReprBits)

ff_derive panics for Fermat primes

For a Fermat prime, i.e., a prime of the form 2^k + 1, ff_derive correctly computes s = k and t = 1. But t == 1 is an issue when generating the Tonelli-Shanks implementation, because t_minus_1_over_2 == 0, which causes a panic in the addchain generation.

The following tweak to prime_field_constants_and_sqrt fixes the panic. I have not thoroughly tested the resulting sqrt function, though!

    let sqrt_impl =

      ...

        } else if (modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() {
            // Addition chain for (t - 1) // 2
            let t_minus_1_over_2 = if t == BigUint::one() {
                quote!( #name::one() )
            } else {
                pow_fixed::generate(&quote! {self}, (&t - BigUint::one()) >> 1)
            };

    ...

This issue is quite low urgency, given that the largest known Fermat prime is 65537 :)

ff_derive fails with no sqrt for p = 5 (mod 8) and p = 9 (mod 16)

The ff_derive derived PrimeField implementation fails to derive a sqrt function for primes p = 5 (mod 8) and p = 9 (mod 16), resulting in a compile-time error for these cases. According to the introduction of IACR Preprint 2012/685 (the cited reference for the algorithms used for the p = 3 (mod 4) and p = 1 (mod 16) cases), efficient algorithms do exist for computing square roots over these primes; however, these algorithms are not currently implemented here.

In Issue #33, this limitation is noted explicitly, so it may be that the desired use cases for this library don't require full coverage of odd primes. I just wanted to check whether this is an intentional omission for maintainability, or if it's simply a feature that hasn't been added yet. If it's the latter and maintainers are interested, I might be able to assemble a pull request.

`PrimeField::Repr` ambiguous endianness

It is unsafe in downstream use cases for PrimeField::to_repr and PrimeField::from_repr to have ambiguous endianness. (E.g., it's oftentimes hard to implement something for ff::PrimeField without assuming something about endianness.)

Can you either add an ENDIANNESS const or functions like to_bytes_le and from_bytes_le?

Eigen-style metaprogramming in ff_derive

This is an idea I've been toying with in my head for a little while (and discussed with @str4d at RWC), but I'm not sure whether whether it would work out in practice, so I'm posting it here for discussion. At a high level, the idea is for ff_derive to use a similar strategy as is used by Eigen, particularly its basic internals and lazy evaluation mechanism to provide optimized implementations of entire subexpressions. For instance, in a C++ expression like

mat1 = -mat2 + mat3 + 5 * mat4;

Eigen will skip producing temporaries and instead produce a single fused evaluation loop. Eigen does this using C++ template metaprogramming, while ff_derive would use type-level programming with various trait bounds. This is (thankfully) a less powerful model than C++ templates but I think that it's still possible to do something similar to what Eigen does.

How would this work for ff_derive? Here's one idea. Rather than generating a single type for the finite field (let's call it Fp: Field), ff_derive would generate a main user-facing type (let's call it Fp as before), but the generated type Fp would have impls of Add, Mul, etc whose Outputs would be inner types implementing Into<Fp>. These inner types would also have ops impls of their own, so that a user could write expressions like

let a = (x + y) * z;

and have this produce an optimized implementation of the entire expression. (One thing we cannot do in Rust compared to C++ is overload the assignment operator, so we would likely need users to add .into() to each expression they want to evaluate to an Fp, but I think this isn't a big deal).

There are varying levels of sophistication for this on the ff_derive side, but the obstacle on the ff side is that with this approach it's not possible to implement Field, because the Field trait requires that the Output of the required ops traits is Self. Weakening this to Into<Self> would (I think) remove this obstacle.

Add cube method for field elements

This can be a default implementation that just makes code simpler in some cases, even though it doesn't perform any better than writing x.square() * x.

ff_derive is not updated on crates.io

+ ?Sized exists in ff but not in ff_derive (On crates.io, local version is fine), this has brought compilation problems in zkcrypto/pairing even after adding ?Sized constraint to the random() functions' type parameters.
Maybe try updating ff_derive's version from 0.4.0 to 0.4.1?
Thanks!

EC help, signed ff?

I'm attempting to improve the performance of my EC library, by migrating to this library. I know I'm not supposed to write my own and I do understand that ff does not offer consistent time.
https://gitlab.com/cheako/jtm-rs/-/commit/714b6d624c485882d3c64b7d6b3b0b8cb38ec92f#b24749917179fb5e3e613ed2a703fcdcc6cdf9da_291_226
Here I'm checking if the value module q is negative, my usual calculations are done module p. So my question is, can ff implement signed finite fields? I'm so confused about finite fields in general... I basically brute forced my way through implementing this using num-bigint-dig.

derive(Copy) vs ZeroizeOnDrop

Something of a usage question. We're using zkcrypto/ff to derive a prime field for a shared-secret implementation, and also wanted to derive ZeroizeOnDrop from the zeroize crate to limit the time key material is available in memory. However this conflicts with PrimeField's Copy trait, necessitating manual .zeroize() method calls which are more expensive to review.

Is the blanket Copy necessary? What's the best practice here?

Optionally export derive macros

Right now we just export this stuff but libraries won't need ff_derive to implement generic code using the ff traits, so those users shouldn't need to pull it in.

Also, learn what's changing with macros in rust 2018 and figure out how to properly handle it.

Consider promoting `Field::{zero, one}` to associated constants

Right now Field::zero() and Field::one() are static methods of the Field trait.

If they were instead associated constants, e.g. Field::ZERO/Field::ONE, they can be used in const contexts such as defining other constants:

pub struct ProjectivePoint<Fe: Field> { x: Fe, y: Fe, z: Fe }

impl<Fe: Field> ProjectivePoint<Fe> {
    pub const IDENTITY: Self = Self {
        x: Fe::ZERO,
        y: Fe::ONE,
        z: Fe::ZERO,
    };
}

Add `Field: ConstantTimeEq` bound

Field is already bound on ConditionallySelectable, so trait implementors are already required to pull in subtle. Having this bound would have simplified #61.

This constricts the Field definition, so requires a minor release.

Overhaul traits

This is a sub-task of zcash/librustzcash#41. We can discuss the trait refactor specifically here.

The current plan (as of 2020-09-04):

  • Rework ff::Field to follow the current bls12_381 and jubjub APIs.
  • Add serialization APIs to either ff::Field or ff::PrimeField.
  • Remove ff::PrimeFieldRepr.
  • Add ff::PrimeField::ReprEndianness type
  • Remove ff::Field::frobenius_map
  • Remove ff::SqrtField
  • Add ff::PrimeField::ReprBits type (replacing ff::PrimeField::ReprEndianness)

Remove fmt::Display bound on Field?

(NOTE: this question applies to the group crate traits like Group as well, but I thought I'd start here)

The ff::Field trait bounds on both fmt::Debug and fmt::Display.

Looking at bls128_381, it seems all the Display impls are equivalent to Debug:

https://github.com/zkcrypto/bls12_381/blob/0d2c06d/src/scalar.rs#L33-L37

So why not just bound on Debug?

My main motivation for requesting this is I feel Display is something I want to add when there's a somewhat well-defined string representation of a given type, e.g. something a human would reasonably try to compare with a similarly printed string representing the same object, but output from a different library.

With the blanket impl of ToString for T: Display, I also like to make sure that if a corresponding FromStr impl is ever added to the type, it can round trip the output of Display/ToString.

Bug in PrimeField for Multiplication operation

Code:

#[macro_use]
extern crate ff;

#[derive(PrimeField)]
#[PrimeFieldModulus = "18446744069414584321"]
#[PrimeFieldGenerator = "7"]
#[PrimeFieldReprEndianness = "little"]
struct Fpx([u64; 2]);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    pub fn test() {
        let val1: Fpx = Fpx([3u64, 0u64]);
        let val2: Fpx = Fpx([7u64, 0u64]);
        let sum_a = val1 + val2;
        let sub_a = val1 - val2;
        let mul_a = val1 * val2;
        assert_eq!(10u64, sum_a.0[0], "Add fails");
        assert_eq!(18446744069414584317u64, sub_a.0[0], "Sub fails");
        assert_eq!(21u64, mul_a.0[0], "Mul fails");
    }
}


Output:
---- tests::test stdout ----
thread 'tests::test' panicked at 'assertion failed: (left == right)
left: 21,
right: 90194313195: Mul fails', src/lib.rs:23:9
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace


I noticed that `90194313195` is `21` in Montgomery form. Is there a way to fix it?

Remove u128-support feature

This is stable now. We shouldn't export anything that exposes u128 as a type in the API though, which we aren't doing.

Fails to compile for some moduli lesser than 2^64

Fails to compile for some moduli lesser than 2^64

Minimal example:

#[derive(PrimeField)]
#[PrimeFieldModulus = "103"]
#[PrimeFieldGenerator = "102"]
struct Fp(FpRepr);

Compilation error:

error[E0425]: cannot find value `r0` in this scope
  --> src/main.rs:16:10
   |
16 | #[derive(PrimeField)]
   |          ^^^^^^^^^^ not found in this scope

Feature `derive` and `bits` are not exclusive

Using the following does not compile:

ff = { version = "0.11.0", default-features = false, features = ["derive", "alloc"] }

because derive depends on bitvec which is only included with the bits feature enabled.

Compile error, and relevant code snippet:

<...>.cargo/registry/src/github.com-1ecc6299db9ec823/ff-0.11.0/src/lib.rs:269:14
    |
269 |     pub use {bitvec, byteorder, rand_core, subtle};
    |              ^^^^^^ no external crate `bitvec`
ff-0.11.0/src/lib.rs:

/// Functions and re-exported crates used by the [`PrimeField`] derive macro.
#[cfg(feature = "derive")]
#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
pub mod derive {
    pub use crate::arith_impl::*;
    pub use {bitvec, byteorder, rand_core, subtle};
}

rand_core v0.6

rand_core v0.6 has been released with first-class WASM support via getrandom v0.2.

It'd be great to get a version bump of this dependency in the next breaking release.

Use of `std::ops` traits?

This would be a pretty large change, but I'm wondering if it makes sense to build the ff traits around the std::ops traits, instead of having custom methods for every operation.

This could be something like:

pub trait FiniteField
where
    Self: Add<Self, Output = Self>,
    Self: Sub<Self, Output = Self>,
    Self: Mul<Self, Output = Self>,
    Self: AddAssign<Self>,
    Self: SubAssign<Self>,
    Self: Copy + Clone + Sized + Debug + PartialEq + Eq + Neg,
    Self: ConstantTimeEq + ConditionallyAssignable,
{
    fn zero() -> Self;
    fn one() -> Self;
    /// Returns 0 on input 0, or UB
    fn invert(&self) -> Self;
}

impl<F: FiniteField> Default for F {
    fn default() -> Self {
        F::zero()
    }
}

/// Marker trait
pub trait PrimeField: FiniteField {}

pub trait SqrtField: FiniteField {
    /// Computes sqrt(u/v)
    fn sqrt_ratio(u: &Self, v: &Self) -> Self;

    /// Computes 1/sqrt(self)
    fn invsqrt(&self) -> Self {
        Self::sqrt_ratio(&Self::one(), self)
    }

    /// Computes sqrt(self)
    fn sqrt(&self) -> Self {
        Self::sqrt_ratio(self, &Self::one())
    }
}

/// A `FiniteField` that can be encoded in 32 bytes.
///
/// The `TryFrom` should reject non-canonical encodings.
pub trait FieldEncoding32
where
    Self: FiniteField + TryFrom<[u8; 32]> + Into<[u8; 32]>,
    for<'a> Self: TryFrom<&'a [u8; 32]>,
    for<'a> Self: TryFrom<&'a [u8]>,
{
}

/// FieldEncoding48, FieldEncoding56, etc

I'm concerned about `bitvec` dependency

I come here because we use ff (thanks a lot, BTW!) and when testing builds with cargo update -Z minimal-versions we encounter a problem with its dependencies.

I started looking into it, and got a bit concerned.

First bitvec comes with a chain of dependencies that seems a bit ... vague & unnecessary. I mean they do make sense, but for a staple crate I would cut them just to not have them and minimize dependencies.

Then it occurred to me that they are not in a great shape. First, AFAICT there's not even a single CI testing if the build is even passing, not to mention running unit-tests.

When I looked at wyz it didn't seem like the latest published version is even in the repo: https://github.com/myrrlyn/wyz . The last commit&tag that I can see is for 0.4: myrrlyn/wyz@183b577 so I have no idea where is latest 0.5 release coming from: https://crates.io/crates/wyz .

The problem that I was aiming at fixing does even have a PR open: myrrlyn/wyz#6 . But it wasn't merged for 1.5 year now, which seems very long for an obvious change that adds 4 characters. https://github.com/myrrlyn/wyz/pull/6/files

So... yeah. It doesn't build my confidence. I hope don't come off too negative, as it's not my intention. I know that Open Source maintenance is laborious and often ungrateful, and I appreciate (usually unpaid) effort everyone is putting in making Rust ecosystem so great. But for a crate that will most definitely be used for serious crypto stuff, it is something to address - maybe we could help the maintainer, eliminate the extra deps, etc.

Other possible sqrt-related operations

We removed the SqrtField trait in ff 0.7.0, as all fields that we intend the Field trait to apply to support a sqrt operation (ff_derive is able to derive implementations for p = 3 (mod 4) and p = 1 (mod 16)). More precisely, SqrtField was a separate trait because Field was previously implemented on the pairing::bls12_381::{Fq6, Fq12} extension fields of BLS12-381, which didn't have square-root operations; these are not part of the bls12_381 crate's public API.

In #6, @hdevalence had separately suggested adding several sqrt-related operations to the then-existing SqrtField trait:

pub trait SqrtField: FiniteField {
    /// Computes sqrt(u/v)
    fn sqrt_ratio(u: &Self, v: &Self) -> Self;

    /// Computes 1/sqrt(self)
    fn invsqrt(&self) -> Self {
        Self::sqrt_ratio(&Self::one(), self)
    }

    /// Computes sqrt(self)
    fn sqrt(&self) -> Self {
        Self::sqrt_ratio(self, &Self::one())
    }
}

If these would be sufficiently widely-useful, they could be added to the Field trait. If not, we could consider re-introducing the SqrtField trait.

ff_derive: unnecessary limb required for large modulus (e.g. for NIST P-curves)

When using ff_derive with the base or scalar field modulus of elliptic curves like P-256 or P-384, ff_derive requires one more limb than is strictly necessary.

Example:

use ff::PrimeField;

#[derive(PrimeField)]
#[PrimeFieldModulus = "115792089210356248762697446949407573530086143415290314195533631308867097853951")
#[PrimeFieldGenerator = "6"]
#[PrimeFieldReprEndianness = "big"]
struct P256FieldElement([u64; 4]);

...fails with the following error:

error: The given modulus requires 5 limbs.
 --> src/lib.rs:7:31
  |
7 | struct P256FieldElement([u64; 4]);

Should Field::invert fail if the input is zero, or return Field::zero?

The current API is fn invert(&self) -> CtOption<Self>; this is flexible, as it allows the caller to choose to handle the zero-input case manually by mapping it to Field::zero, or treat it as an invalid case. Is this flexibility leveraged in any cryptographic protocols that we support (or want to support), or should we short-circuit this to have a consistent default?

Enable constant-time usage of trait methods

Currently, the following trait methods cannot be used in constant-time code:

  • Field::is_zero (returns bool)
    • As of #62 this can now be emulated with f.ct_eq(&F::zero()).
  • PrimeField::from_str (returns Option<Self>)
  • PrimeField::from_repr (returns Option<Self>)
  • PrimeField::is_odd (returns bool)
  • PrimeField::is_even (returns bool)

The main problematic one is PrimeField::from_repr which prevents constant-time parsing logic, and can't be implemented in terms of other APIs (which is why we have separate constant-time APIs in the pasta_curves crate's FieldExt trait).

Meanwhile we also have PrimeField::pow_vartime which is explicitly advertised as using variable-time logic internally (even though it is effectively constant-time if using a fixed exponent).

My preference is that in a future breaking release, we change the default APIs to be constant time, and add *_vartime APIs that default to calling the constant-time impls, but that trait implementors can choose to optimise if they wish.

Add `Field::sum_of_products`

The general operation c = (a_0 * b_0) + (a_1 * b_1) + ... (i.e. an inner product, but "sum of products" is a more obvious name) is used all over the place in cryptography. We can provide a default slow implementation of the function, and then downstream crates can override it with more efficient implementations (e.g. zkcrypto/bls12_381#84).

Basic README example does not work

The basic README example

extern crate rand;
#[macro_use]
extern crate ff;

#[derive(PrimeField)]
#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
#[PrimeFieldGenerator = "7"]
struct Fp(FpRepr);

does not work anymore. Error:

error[E0433]: failed to resolve: use of undeclared type or module PrimeFieldDecodingError
--> src/main.rs:5:10
|
5 | #[derive(PrimeField)]
| ^^^^^^^^^^ use of undeclared type or module PrimeFieldDecodingError

error[E0433]: failed to resolve: could not find rand_core in {{root}}
--> src/main.rs:5:10
|
5 | #[derive(PrimeField)]
| ^^^^^^^^^^ could not find rand_core in {{root}}

error[E0412]: cannot find type PrimeFieldDecodingError in this scope
--> src/main.rs:5:10
|
5 | #[derive(PrimeField)]
| ^^^^^^^^^^ not found in this scope
|
help: possible candidate is found in another module, you can import it into scope
|
6 | use ff::PrimeFieldDecodingError;
|

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0412, E0433.
For more information about an error, try rustc --explain E0412.
error: could not compile ff.


with use ff::PrimeFieldDecodingError; the next error is:

Error:

error[E0433]: failed to resolve: could not find rand_core in {{root}}
--> src/main.rs:7:10
|
7 | #[derive(PrimeField)]
| ^^^^^^^^^^ could not find rand_core in {{root}}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.