1

For example:

int main()
{
  int p;

  ::std::cout << ::std::uintptr_t(&p) << ::std::endl;
}

This will consistently produce "random" numbers if executed repeatedly. Something similar could be accomplished in C. I don't see anything UB about it.

user1095108
  • 14,119
  • 9
  • 58
  • 116

4 Answers4

4

I quite depends on requirements you set on the distribution of the random numbers. Is the sequence 1,1,1,1,1,1,1,1 random ? Actually hard to tell, but if you make a test for a normal distribution it will certainly fail. Pseudo random number generators are specifically designed to match the properties of the random distribution you want to get from them.

If you do some trickery to get a previously unknown number (on purpose I dont call it random), this number might appear random to you, but it is very likely that there are patterns that you just dont spot.

TL;DR: it is not easy to write a good rng. Use the ones that are available if you need random numbers.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Mmmm, how about using the stack pointer as a seed to a "proper" pseudo RNG? – user1095108 Jul 28 '16 at 15:23
  • 6
    This snippet on some environments will just return the same value *always*. It is a **BAD** entropy source no matter how you put it. – Eugene Sh. Jul 28 '16 at 15:24
  • 2
    @user1095108 then you will have a poor quality seed which might defeat the point of using a rng in the first place – 463035818_is_not_an_ai Jul 28 '16 at 15:25
  • @EugeneSh. yes, but the snippet only. The "RNG" could be used in a function way down or up a call tree. – user1095108 Jul 28 '16 at 15:25
  • 3
    @user1095108 It really doesn't matter. Same code on same environment will always produce the same result. – Eugene Sh. Jul 28 '16 at 15:26
  • @user1095108 I'd say that would be acceptable *iff* it was combined with multiple other (higher) quality sources in a `std::seed_seq` which was then ultimately used to seed the generator. – Jesper Juhl Jul 28 '16 at 16:12
  • @user1095108 simply don't. there's no reason to do something stupid like this. Using determinable things is nr1 reasons why weak crypto/auth gets hacked. Simply don't. If you need a seed, use an OS-supplied random number. Most OSes have that, and it's **good**, usually. – Marcus Müller Jul 29 '16 at 11:17
  • @MarcusMüller Some people appreciate the idea, as you can see. Note, that I asked a question, whether this was OK. – user1095108 Jul 29 '16 at 11:58
  • @user1095108 some people really shouldn't appreciate the idea. Eugene put it perfectly: "*It is a **BAD** entropy source no matter how you put it.*" So simply don't. – Marcus Müller Jul 29 '16 at 12:00
  • @MarcusMüller They aren't children, if they know C++ well. I think it's a nice addition to C++ lore. – user1095108 Jul 29 '16 at 12:26
  • no, it's not. It's a pattern of bad ideas. Don't do. Don't establish it as practice. I repeat: simply don't. It doesn't do what it's supposed to do, and if it did, that was because it invoces C++ undef behaviour, which you can't rely on, because that might change at any point. So really, it's not a nice addition to anything but a list of things that can be abused. – Marcus Müller Jul 29 '16 at 15:02
4

No, no, no.

You cannot use variable addresses, values of uninitialized variables and the like as sources of random numbers.

Some of those uses will earn you a ticket straight to "undefined behaviour land" where your compiler is allowed to do horrible, horrible things to your code.

Some are just not really all that random.

If you want random numbers, use what's provided in < random > and make sure you seed your generator properly if you are not using random_device directly (which you probably don't want to for non-crypto-safe numbers).

And don't even consider rand() - forget it exists. It is horrible.

You should use a std::seed_seq to mix up multiple entropy sources and then use that to seed the generator. Taking the address of a variable as one of many inputs for seed_seq would be ok, assuming you also include other sources of higher quality (notably std::random_device).

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • 1
    As a comment stressing the point of your answers: **no, it's not a good source**. – Marcus Müller Jul 29 '16 at 11:16
  • 1
    Also, it's **a bad source.** As well as it not being good. Or using it as a source of randomness being a wrong approach. Or actually, the thought of that the address of a variable being random is incorrect. I'm running out of ways to put this. – Marcus Müller Jul 29 '16 at 15:20
  • You guys are, of course, both right. Which is why I said it is ok only as part of a `seed_seq` where you also add multiple other sources of higher quality. In that case it won't hurt - but won't *help* much either... – Jesper Juhl Jul 29 '16 at 15:33
  • seriously, that's like having the constant `3` as part of your `seed_seq`, just that you hide `3` behind `functon_that_does_something_spectacularly_random()`. It obfuscates the fact that `3` isn't random. – Marcus Müller Jul 29 '16 at 15:36
  • @Marcus Müller I actually think we agree, so I don't want to start an argument. But let me try to clarify; the whole point of a `seed_seq` is that you can mix up multiple **bad** sources of entropy and get a reasonably good seed out. Now we agree that using the address of a stack variable is horrible as an entropy source, but mixed with other, better sources, it doesn't hurt - and there may actually be a tiny bit of entropy in there when the program is run on different machines (OS'es) and if ASLR is in play, so it's not *quite* as bad as a literal `3` (although close). See what I mean? – Jesper Juhl Jul 29 '16 at 15:42
  • 1
    Yeah, I see what you mean :) I do think you also see what I mean! So let's shake hands over this. – Marcus Müller Jul 29 '16 at 15:46
  • @Marcus Müller Done :) – Jesper Juhl Jul 29 '16 at 15:51
  • Reference for uninitialized variables for random number here: [Is uninitialized local variable the fastest random number generator?](http://stackoverflow.com/q/31739792/1708801) – Shafik Yaghmour Sep 06 '16 at 21:27
4

If your OS randomizes the stack address of your program, you can extract several random bits from the address of your local variable. These will probably be high-quality random bits (if your OS is good), but there will be only a few, because:

  • there are strict requirements on alignment (so the low bits will be constant, not random)
  • any OS probably constrains the address space of user programs for convenience reasons (so the high bits will be constant)

So this method is not good because its result relies heavily on OS (as an extreme example, a user can disable ASLR, and your random number generator will stop working for that user).

anatolyg
  • 26,506
  • 9
  • 60
  • 134
  • And also, instead of using the same randomness that the ASLR uses, you use a restricted, partly determinable result of that randomness. Simply use your system's random source; Unixoids usually have /dev/random that works pretty well as source of entropy. – Marcus Müller Jul 29 '16 at 11:19
3
  • As a source of random numbers on its own, it's pretty bad because it will be very predictable for a serious adversary. As others have said, the address space is limited, the addresses that satisfy the alignment requirements for an int are much fewer and, on top of that, the algorithm by which your program gets loaded into memory, if not documented, it at least is not built for much randomness.
  • As a source of entropy, it depends on the OS. If the OS doesn't randomize, it will hurt readability -- because someone reading your code may mistakenly think that you're adding entropy at that point. If the OS does randomize, it still won't be a great source of entropy, and you'd have to combine it with other better sources to compensate -- and those must be completely independent from the source of entropy of the random address.

In any case, this is all assuming you use the address of the variable (perfectly valid) and not its value (undefined behavior if uninitialized). If you invoke undefined behavior, the operation could throw away all your entropy.

Theodoros Chatzigiannakis
  • 28,773
  • 8
  • 68
  • 104
  • 2
    well, the source of entropy really only lies in the memory layout, so without address randomization, it's 0 bit of entropy, so yes, by not adding entropy but obfuscating that fact, it *would* hurt, and if there is address radnomization, you should use whatever source of entropy was used to generate that – you'd be wasting bits of entropy, again, otherwise. My guess is that OSes with ASLR will use the same source of entropy at initialization as is available as random device, eg /dev/random, and then will give you a RNG sequence, which doesn't *add* entropy if you can deduct the original seed. – Marcus Müller Jul 29 '16 at 12:04
  • 2
    So, yeah, I think, it should not be done because it's obfuscating the fact that it doesn't help. – Marcus Müller Jul 29 '16 at 12:05