2

in python i do :

import random

while True:
    x = random.randint(0xF,0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140)
    print hex(x)[2:66].lower()

how to do that using C or C++ ?

xoom
  • 63
  • 1
  • 9
  • 2
    If you actually need a random value that large and this isn't just a school exercise or something, you'd better look into a real cryptographic library instead of relying on built-in random methods. You could cobble one together with a basic rand()-type method, but it would not be of true 256 bit quality. – Paul Kienitz Oct 25 '15 at 03:21
  • @xoom: Does it need to be a generator passing "real" randomness tests? The simplest `rand()` function often uses some weak LCG which can calculate very fast, but not very good random numbers (Python uses MT, that`s better, but a bit more complicated in C++). Does it need to be crypt. secure? (MT isn't) – deviantfan Oct 25 '15 at 03:24
  • How about using [GNU MP](https://gmplib.org/manual/) library? – MikeCAT Oct 25 '15 at 04:13
  • 1
    i do not look for secure crypto, just need fast way to generate randoms, no need for entropy or other crypto methods, just random 256bit hex between 0xF and 0XFF...., thanks – xoom Oct 25 '15 at 04:43
  • Pure curiosity: what the hex *is* that huge number in Python? – Jongware Oct 26 '15 at 20:34
  • Here is someone asking the same thing: https://stackoverflow.com/questions/41075444/generate-128-bituint128-t-randomly-in-c-via-boostrandom https://stackoverflow.com/questions/1188939/representing-128-bit-numbers-in-c – Jerry Jeremiah Jun 20 '19 at 03:14

3 Answers3

3

Using GNU MP library, this can be done like this:

#include <stdio.h>
#include <ctype.h>
#include <gmp.h>

void randint(mpz_t rop, gmp_randstate_t state, mpz_t from, mpz_t to) {
    mpz_t range;
    mpz_init(range);
    /* range = to - from + 1 */
    mpz_sub(range, to, from);
    mpz_add_ui(range, range, 1);
    /* rop = random number in [0, range) */
    mpz_urandomm(rop, state, range);
    /* rop += from */
    mpz_add(rop, rop, from);
    mpz_clear(range);
}

int main(void) {
    char str[1024]; /* allocate enough memory */
    gmp_randstate_t state;
    mpz_t low, high;
    mpz_t ret;
    gmp_randinit_default(state);
    mpz_init(ret);

    mpz_init_set_str(low, "F", 16);
    mpz_init_set_str(high, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140", 16);
    for(;;) {
        randint(ret, state, low, high);
        str[0]='0'; str[1]='x';
        mpz_get_str(str + 2, 16, ret);
        if (str[0] != '\0' && str[1] != '\0') {
            int i;
            for (i = 2; i < 66 && str[i] != '\0'; i++) putchar(tolower(str[i]));
        }
        putchar('\n');
    }
    /* the control won't come here */
#if 0
    mpz_clear(low);
    mpz_clear(high);
    mpz_clear(ret);
    gmp_randclear(state);
    return 0;
#endif
}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
0

A very simple solution:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define StringLength    (256/4) // (Bits you want)/4 (Thanks, chux)

int main(void){
    char cStrHex[(StringLength+1)] = {0};

    // Seed random:
    srand((unsigned int) time(0));

    // Fill the char buffer
    int i=0;
    for(; i < StringLength; i++){
        sprintf(cStrHex+i, "%x", rand() % 16);
    }

    // Print hex string:
    printf("%s\n", cStrHex);

    return 0;
}

Please note that rand() is not considered to be cryptographically secure, so replace calls to rand() with a CSPRNG if you want to use this for anything requiring completely unpredictable random number. Nonetheless, this is a short, simple, and efficient solution to your problem.

Spencer D
  • 3,376
  • 2
  • 27
  • 43
  • `rand() is not considered to be cryptographically secure` Not even MT is secure, but at least it generates proper numbers. Usually `rand()` is just *bad*, and nowhere near uniform distribution – deviantfan Oct 25 '15 at 05:27
  • 1
    @deviantfan, I'm by no means saying `rand()` is a good solution for randomness. There are much high quality PRNGs available; however, for the OP's needs, `rand()` is sufficient. – Spencer D Oct 25 '15 at 05:32
  • @deviantfan, given that the OP's question states *"How to loop generate random 256bit hex in c or c++?"* He never explicitly limited the scope of his question to just MT. Just because Python's default PRNG uses MT, doesn't mean the OP is concerned with that. Please refer to the OP's comment: *"I do not look for secure crypto, just need fast way to generate randoms, no need for entropy or other crypto methods"*. – Spencer D Oct 25 '15 at 05:44
  • @deviantfan, regardless, it's 1:50 am and I don't feel like arguing the semantics of the OP's question with you. Debating the scope of the OP's question will not produce any constructive comments for either the OP or future readers. So, have a swell night. – Spencer D Oct 25 '15 at 05:51
  • 1
    Minor: Should be `#define StringLength (256/4)` as 4 bits are appended per each `sprintf(cStrHex+i, "%x", rand() % 16)` – chux - Reinstate Monica Oct 26 '15 at 20:22
  • @chux, whoops. Thanks for pointing that out. I was fairly tired when I was writing that code. – Spencer D Oct 26 '15 at 20:38
-1

Here's an approach that uses random(). It attempts to use as many digits as possible. In case of POSIX random(), that's 31 bits, so 7 full digits. With, say, arc4random, you could use 8.

int max_usable_digits = 7;
uint64_t mask = (1 << (4 * max_usable_digits)) - 1;
const char *hex_digits = "0123456789abcdef";

std::string get_random_hex(int digits) {
    char buffer[65] = {};
    int offset = 0;
    while (offset < sizeof(buffer)) {
        long r = random() & mask;
        offset += snprintf(buffer + offset, sizeof(buffer) - offset,
                           "%0*lx", max_usable_digits, r);
    }
    return std::string(buffer);
}

If you can use Boost library, generating_a_random_password example solves your problem with minor modifications.


UPDATE: This returns random strings between 64 zeros and 64 F's. The specific limits in OP's question (of 0xF and 0xFF..140) are a range of valid EDCSA keys. Nearly all 64-digit strings are valid. You can guarantee a number in the range with:

std::string min = "000000000000000000000000000000000000000000000000000000000000000F";
std::string max = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140";
std::string get_random_ecdsa_key() {
  while (true) {
    std::string s = get_random_hex(64);
    if (s >= min && s < max) {
      return s;
    }
  }
}
DS.
  • 22,632
  • 6
  • 47
  • 54
  • The upper and lower limit aren't `0x0` and `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF`. You should check and drop invalid values. – MikeCAT Oct 25 '15 at 04:33
  • Apologies: last-minute edit had changed "& mask" into "% mask", making it all wrong. It's correct now. The upper/lower limits are indeed as you list (you can verify by using a random() that returns all 0s or all RAND_MAX). – DS. Oct 25 '15 at 04:39
  • 1
    @DS. MikeCAT didn't mean that your limits are not 0x0 and 0xff..ff, but the limits the OP wants are not. – deviantfan Oct 25 '15 at 04:44
  • Gotcha. OPs limits don't make sense anyway. I decided against proposing a "precise" solution and instead added an explanation to my answer. I think the title question ("generate random 256-bit hex") is meaningful and will be more useful to others if the weird limits are ignored. – DS. Oct 25 '15 at 05:16
  • `OPs limits don't make sense anyway.` And that's for you to decide? ... With a proper solution with limits, the limits can be changed easily, so it's not just OPs "weird" limits, but a general solution for everyone. – deviantfan Oct 25 '15 at 05:22
  • Btw., hitting a invalid number is not as unlikely as you think. – deviantfan Oct 25 '15 at 05:24
  • the OP limit is range of valid ECDSA key. – xoom Oct 25 '15 at 05:24
  • @xoom Key generation? And you`re telling us that security is not important? – deviantfan Oct 25 '15 at 05:34
  • its indeed important, but for me its not as i'm not using this for real work. – xoom Oct 25 '15 at 05:38
  • Thanks for making sense of the limit (I'll fix the comment). @deviantfan: I still claim that it's less than 1e-37 chance of generating 31 Fs or 0s in a row randomly, which is what's needed for a value that's not in the range. – DS. Oct 26 '15 at 19:55