Clearmatics Libff  0.1
C++ library for Finite Fields and Elliptic Curves
rng.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of functions for generating randomness.
5 
6  See rng.hpp .
7 
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  *****************************************************************************/
13 
14 #ifndef RNG_TCC_
15 #define RNG_TCC_
16 
17 #include <gmp.h>
18 #include <libff/algebra/fields/bigint.hpp>
19 #include <libff/common/rng.hpp>
20 #include <libff/common/utils.hpp>
21 #include <openssl/sha.h>
22 
23 namespace libff
24 {
25 
26 template<typename FieldT> FieldT SHA512_rng(const uint64_t idx)
27 {
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());
32 
33  assert(FieldT::size_in_bits() <= SHA512_DIGEST_LENGTH * 8);
34 
35  bigint<FieldT::num_limbs> rval;
36  uint64_t iter = 0;
37  do {
38  mp_limb_t hash
39  [((SHA512_DIGEST_LENGTH * 8) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS];
40 
41  SHA512_CTX sha512;
42  SHA512_Init(&sha512);
43  SHA512_Update(&sha512, &idx, sizeof(idx));
44  SHA512_Update(&sha512, &iter, sizeof(iter));
45  SHA512_Final((unsigned char *)hash, &sha512);
46 
47  for (mp_size_t i = 0; i < FieldT::num_limbs; ++i) {
48  rval.data[i] = hash[i];
49  }
50 
51  /* clear all bits higher than MSB of modulus */
52  size_t bitno = GMP_NUMB_BITS * FieldT::num_limbs - 1;
53 
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);
58 
59  rval.data[part] &= ~(1ul << bit);
60 
61  bitno--;
62  }
63 
64  ++iter;
65  }
66 
67  /* if r.data is still >= modulus -- repeat (rejection sampling) */
68  while (mpn_cmp(rval.data, FieldT::mod.data, FieldT::num_limbs) >= 0);
69 
70  return FieldT(rval);
71 }
72 
73 } // namespace libff
74 
75 #endif // RNG_TCC_