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

random_mod can take a very long time #3

Closed
Sc00bz opened this issue Sep 8, 2021 · 8 comments · Fixed by #36
Closed

random_mod can take a very long time #3

Sc00bz opened this issue Sep 8, 2021 · 8 comments · Fixed by #36

Comments

@Sc00bz
Copy link
Contributor

Sc00bz commented Sep 8, 2021

https://github.com/RustCrypto/utils/blob/710abc8c83a13def1c01958909405976f915e5a5/crypto-bigint/src/uint/rand.rs#L34-L42

If modulus is small compared to the full size ("number of limbs * size of limb") then it can take "forever".

The correct method is to mask off the top bits of the random number to match the size of modulus. This leads to a worst case of a 50% chance of failing and needing to generate another random number. The average for this worst case is needing to generate 2 random numbers.

@Sc00bz
Copy link
Contributor Author

Sc00bz commented Sep 8, 2021

Oh right obviously this can run forever if called with a modulus of zero. For this case it should error similarly to a divide by zero.

@tarcieri
Copy link
Member

tarcieri commented Sep 8, 2021

For now we can add a debug_assert! that the modulus is non-zero.

It'd be nice to eventually capture these sort of cases using the type system so we can ensure implementations are panic free.

@newpavlov
Copy link
Member

I think that ideally modulus should be a const parameter for a higher-level bigint type. This would allow us to either reject such edge cases on the type level or insert branches which would be eliminated at compile time.

@tarcieri
Copy link
Member

tarcieri commented Sep 8, 2021

@newpavlov yep, exactly, unfortunately min_const_generics are nowhere near that expressive

@tarcieri tarcieri changed the title random_mod can take a very long time crypto-bigint: random_mod can take a very long time Sep 8, 2021
@tarcieri tarcieri transferred this issue from RustCrypto/utils Sep 14, 2021
@tarcieri tarcieri changed the title crypto-bigint: random_mod can take a very long time random_mod can take a very long time Sep 14, 2021
@tarcieri
Copy link
Member

Regarding a non-zero modulus, we recently added a NonZero wrapper (#13) which can ensure the modulus is non-zero at the type level, although switching to it would be a breaking change.

It might be good to make some breaking changes soon though and release a v0.3.

@tarcieri tarcieri mentioned this issue Sep 21, 2021
4 tasks
@ashWhiteHat
Copy link
Contributor

I changed the random_mod method here.
modulo is calculated here.

@tarcieri
Copy link
Member

That approach introduces a bias into the output distribution. For cryptographic applications, the distribution of possible outputs needs to be uniformly random, which is why it's using rejection sampling.

@Sc00bz
Copy link
Contributor Author

Sc00bz commented Oct 15, 2021

P.S. That modulo can take a very long time and literally forever if used for after multiply. While also not being time constant (leaks x from x*divisor+remainder, but in the case of random x is worthless).

tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
tarcieri added a commit that referenced this issue Nov 13, 2021
Changes the modulus for `random_mod` to be `NonZero`.

Changes the algorithm used by `random_mod` to generate a number that can
be represented by the same number of bytes as the modulus.

Such a number can still be larger than the modulus, but is much more
likely not to overflow than a "full-width" number provided the modulus
is small relative to the width.

Closes #3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants