How to get customized bytes from /dev/urandom?

250 views Asked by At

I am working on a program that finds partial collision in Bitcoin addresses. I have obtained source code for urandom and don't see where to start. So I want to get random bytes from /dev/urandom of length 32 in total (including the masking 0s) because my program expects 256 bit but masked with zeros at the beginning when converted to hex.

The hex output would be like this

000000000000000000000000000000000000000000000000000000000000002d4

Notice the 0s before the actual Hex value( that's what I am calling a mask), in python it is needed by many libraries to get Bitcoin address.

I am struggling with the following code (not from random.c), now I think modifying urandom itself could be more helpful.

   static bool init_rand(void *data, size_t size)
{
    FILE *stream = fopen("/dev/urandom", "r");
    if (stream == NULL)
        return false;
    bool ok = (fread(data, sizeof(uint8_t), size, stream) == size);
    fclose(stream);
    return ok;
}



static bool init_rand(void *data, size_t size)
{
    size_t size0 = size / sizeof(unsigned) + 1;
    assert(size0 * sizeof(unsigned) >= size);
    unsigned data0[size0];
    for (size_t i = 0; i < size0; i++)
    {
        int err = rand_s(data0 + i);
        if (err != 0)
            return false;
    }
    memcpy(data, data0, size);
    return true;
}


static struct seed *make_seed(void)
{
    struct seed *seed = (struct seed *)malloc(sizeof(struct seed));
    assert(seed != NULL);
    seed->counter = 0;
    if (!init_rand(seed, sizeof(struct seed)))
    {
        fprintf(stderr, "error: failed to init random seed\n");
        exit(EXIT_FAILURE);
    }
    if (seed->counter == 0)     // Sanity check...
    {
        fprintf(stderr, "error: random seed initialization failed\n");
        exit(EXIT_FAILURE);
    }
    return seed;
}

For Full code please see Pairgen Here.

Is it possible to modify random.c from Linux kernel drivers to produce bytes already masked with 0s?

2

There are 2 answers

1
diviserbyzero On BEST ANSWER

memset is what can mask bytes with zeroes. that helped me except i had to do it in rand256(seed) function though

static uint256_t rand256(struct seed *seed)
{
    seed->counter++;
    return sha256(seed, sizeof(struct seed));
}

static uint256_t rand256_and_mask(struct seed *seed)
{
    //Generate 256-bit random number using rand256 function
    uint256_t r = rand256(seed);
    memset(&r, 0, 24); //mask first  bytes leaving 8 intact
    return r;
}
18
littleadv On

You are confusing printed representation ("the hex output") with an actual value.

0x2d4 and 0x000000000000000000000000000000000000000000000000000000000000002d4 are the exact same value.

"0x2d4" and "0x000000000000000000000000000000000000000000000000000000000000002d4" are two very different strings.

If you want to format a string - use formating operations (like sprintf).


Looking at your comments, it appears that you're misunderstanding the concept of 0 and what "hex" means.

Hex stands for Hexadecimal, meaning the interpretation of the value in the base-16 system. It is used to represent the value (for readability), it doesn't affect the value itself. For example, 0xA is the base-16 representation of the decimal value 10. These are the same value, written differently.

Similarly, leading zeroes don't change the value. If you see 0x24b in your debugger, and the variable holding it is 32 bits, then the actual memory representation would be 0x0000024b. You can control how the value is printed using the printf formatting flags.

Last but not least, 0 is a valid value. Every bit can be either 0 or 1, and you can have a random generator provide you an absolutely valid randomly generated value which is 0 for all the 256 bits you asked for. While highly unlikely, it is not impossible. Much more likely is that some of the 256 bits would be 0, and it is entirely possible that some of them would be the highest bits, leading your 256 bit value to be misinterpreted as less than 256 bits if you discard these high bits (as printf does by default).

When used for cryptographic purposes, you should not manipulate the values you read from urandom as this would most likely introduce vulnerabilities and is probably not what you really want to do.