1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-03-22 14:39:24 -05:00

mpint: add mp_random_upto().

This is a third random-number generation function, with an API in
between the too-specific mp_random_bits and the too-general
mp_random_in_range. Now you can generate a value between 0 and n
without having to either make n a power of 2, or tediously allocate a
zero mp_int to be the lower limit for mp_random_in_range.

Implementation is done by sawing the existing mp_random_in_range into
two pieces and exposing the API between them.
This commit is contained in:
Simon Tatham 2020-02-23 14:45:19 +00:00
parent d4a4111fec
commit 957f14088f
2 changed files with 17 additions and 7 deletions

21
mpint.c
View File

@ -2423,10 +2423,8 @@ mp_int *mp_random_bits_fn(size_t bits, random_read_fn_t random_read)
return toret; return toret;
} }
mp_int *mp_random_in_range_fn(mp_int *lo, mp_int *hi, random_read_fn_t rf) mp_int *mp_random_upto_fn(mp_int *limit, random_read_fn_t rf)
{ {
mp_int *n_outcomes = mp_sub(hi, lo);
/* /*
* It would be nice to generate our random numbers in such a way * It would be nice to generate our random numbers in such a way
* as to make every possible outcome literally equiprobable. But * as to make every possible outcome literally equiprobable. But
@ -2436,10 +2434,19 @@ mp_int *mp_random_in_range_fn(mp_int *lo, mp_int *hi, random_read_fn_t rf)
* is acceptable on the grounds that you'd have to examine so many * is acceptable on the grounds that you'd have to examine so many
* outputs to even detect it. * outputs to even detect it.
*/ */
mp_int *unreduced = mp_random_bits_fn(mp_max_bits(n_outcomes) + 128, rf); mp_int *unreduced = mp_random_bits_fn(mp_max_bits(limit) + 128, rf);
mp_int *reduced = mp_mod(unreduced, n_outcomes); mp_int *reduced = mp_mod(unreduced, limit);
mp_add_into(reduced, reduced, lo);
mp_free(unreduced); mp_free(unreduced);
mp_free(n_outcomes);
return reduced; return reduced;
} }
mp_int *mp_random_in_range_fn(mp_int *lo, mp_int *hi, random_read_fn_t rf)
{
mp_int *n_outcomes = mp_sub(hi, lo);
mp_int *addend = mp_random_upto_fn(n_outcomes, rf);
mp_int *result = mp_make_sized(hi->nw);
mp_add_into(result, addend, lo);
mp_free(addend);
mp_free(n_outcomes);
return result;
}

View File

@ -399,13 +399,16 @@ mp_int *mp_rshift_fixed(mp_int *x, size_t shift);
* then _they_ have link-time dependencies on both modules.) * then _they_ have link-time dependencies on both modules.)
* *
* mp_random_bits[_fn] returns an integer 0 <= n < 2^bits. * mp_random_bits[_fn] returns an integer 0 <= n < 2^bits.
* mp_random_upto[_fn](limit) returns an integer 0 <= n < limit.
* mp_random_in_range[_fn](lo,hi) returns an integer lo <= n < hi. * mp_random_in_range[_fn](lo,hi) returns an integer lo <= n < hi.
*/ */
typedef void (*random_read_fn_t)(void *, size_t); typedef void (*random_read_fn_t)(void *, size_t);
mp_int *mp_random_bits_fn(size_t bits, random_read_fn_t randfn); mp_int *mp_random_bits_fn(size_t bits, random_read_fn_t randfn);
mp_int *mp_random_upto_fn(mp_int *limit, random_read_fn_t randfn);
mp_int *mp_random_in_range_fn( mp_int *mp_random_in_range_fn(
mp_int *lo_inclusive, mp_int *hi_exclusive, random_read_fn_t randfn); mp_int *lo_inclusive, mp_int *hi_exclusive, random_read_fn_t randfn);
#define mp_random_bits(bits) mp_random_bits_fn(bits, random_read) #define mp_random_bits(bits) mp_random_bits_fn(bits, random_read)
#define mp_random_upto(limit) mp_random_upto_fn(limit, random_read)
#define mp_random_in_range(lo, hi) mp_random_in_range_fn(lo, hi, random_read) #define mp_random_in_range(lo, hi) mp_random_in_range_fn(lo, hi, random_read)
#endif /* PUTTY_MPINT_H */ #endif /* PUTTY_MPINT_H */