+Bignum bignum_from_bytes_le(const unsigned char *data, int nbytes)
+{
+ Bignum result;
+ int w, i;
+
+ assert(nbytes >= 0 && nbytes < INT_MAX/8);
+
+ w = (nbytes + BIGNUM_INT_BYTES - 1) / BIGNUM_INT_BYTES; /* bytes->words */
+
+ result = newbn(w);
+ for (i = 1; i <= w; i++)
+ result[i] = 0;
+ for (i = 0; i < nbytes; ++i) {
+ unsigned char byte = *data++;
+ result[1 + i / BIGNUM_INT_BYTES] |=
+ (BignumInt)byte << (8*i % BIGNUM_INT_BITS);
+ }
+
+ while (result[0] > 1 && result[result[0]] == 0)
+ result[0]--;
+ return result;
+}
+
+Bignum bignum_from_decimal(const char *decimal)
+{
+ Bignum result = copybn(Zero);
+
+ while (*decimal) {
+ Bignum tmp, tmp2;
+
+ if (!isdigit((unsigned char)*decimal)) {
+ freebn(result);
+ return 0;
+ }
+
+ tmp = bigmul(result, Ten);
+ tmp2 = bignum_from_long(*decimal - '0');
+ result = bigadd(tmp, tmp2);
+ freebn(tmp);
+ freebn(tmp2);
+
+ decimal++;
+ }
+
+ return result;
+}
+
+Bignum bignum_random_in_range(const Bignum lower, const Bignum upper)
+{
+ Bignum ret = NULL;
+ unsigned char *bytes;
+ int upper_len = bignum_bitcount(upper);
+ int upper_bytes = upper_len / 8;
+ int upper_bits = upper_len % 8;
+ if (upper_bits) ++upper_bytes;
+
+ bytes = snewn(upper_bytes, unsigned char);
+ do {
+ int i;
+
+ if (ret) freebn(ret);
+
+ for (i = 0; i < upper_bytes; ++i)
+ {
+ bytes[i] = (unsigned char)random_byte();
+ }
+ /* Mask the top to reduce failure rate to 50/50 */
+ if (upper_bits)
+ {
+ bytes[i - 1] &= 0xFF >> (8 - upper_bits);
+ }
+
+ ret = bignum_from_bytes(bytes, upper_bytes);
+ } while (bignum_cmp(ret, lower) < 0 || bignum_cmp(ret, upper) > 0);
+ smemclr(bytes, upper_bytes);
+ sfree(bytes);
+
+ return ret;
+}
+