2 *****************************************************************************
4 Implementation of functions for generating randomness.
8 *****************************************************************************
9 * @author This file is part of libff, developed by SCIPR Lab
10 * and contributors (see AUTHORS).
11 * @copyright MIT license (see LICENSE file)
12 *****************************************************************************/
18 #include <libff/algebra/fields/bigint.hpp>
19 #include <libff/common/rng.hpp>
20 #include <libff/common/utils.hpp>
21 #include <openssl/sha.h>
26 template<typename FieldT> FieldT SHA512_rng(const uint64_t idx)
28 // current Python code cannot handle larger
29 // values, so testing here for some assumptions.
30 assert(GMP_NUMB_BITS == 64);
31 assert(is_little_endian());
33 assert(FieldT::size_in_bits() <= SHA512_DIGEST_LENGTH * 8);
35 bigint<FieldT::num_limbs> rval;
39 [((SHA512_DIGEST_LENGTH * 8) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS];
43 SHA512_Update(&sha512, &idx, sizeof(idx));
44 SHA512_Update(&sha512, &iter, sizeof(iter));
45 SHA512_Final((unsigned char *)hash, &sha512);
47 for (mp_size_t i = 0; i < FieldT::num_limbs; ++i) {
48 rval.data[i] = hash[i];
51 /* clear all bits higher than MSB of modulus */
52 size_t bitno = GMP_NUMB_BITS * FieldT::num_limbs - 1;
54 /* mod is non-zero so the loop will always terminate */
55 while (FieldT::mod.test_bit(bitno) == false) {
56 const std::size_t part = bitno / GMP_NUMB_BITS;
57 const std::size_t bit = bitno - (GMP_NUMB_BITS * part);
59 rval.data[part] &= ~(1ul << bit);
67 /* if r.data is still >= modulus -- repeat (rejection sampling) */
68 while (mpn_cmp(rval.data, FieldT::mod.data, FieldT::num_limbs) >= 0);