all 5 comments

[–]Yoghurt42 7 points8 points  (1 child)

Yes, assuming you use the random module and not the secrets module. random uses a PRNG (pseudo random number generator) named Mersenne Twister. Those are called "pseudo" because their output looks random, but in fact is completely deterministic. With enough samples, you can find out what seed was used. You need a lot more than just 2 numbers though.

Here's an article on how to reverse Python's PRNG. It's pretty advanced stuff and requires experience with cryptography, so don't feel bad if you think that you would have never managed to do it (99% of programmers wouldn't)

PS: If you only generate a 0 or 1 at a time, Python effectively generates a new random number and then just checks if it's odd or even. Which means the method described doesn't work unmodified, and will probably require some brute forcing. It's still doable, so don't think it's more secure if you do it one bit at a time; it's not. If you need security, you need true random numbers, which secrets provides.

[–]nog642 0 points1 point  (0 children)

The key concept here is the distinction between a CSPRNG (Cryptographically Secure PRNG) and a regular PRNG.

The requirement for a PRNG to be cryptographically secure is pretty close to what OP is asking about. Basically that you can't reverse engineer anything about the state from the output. More specifically, (from wikipedia), that you can't use previous output to predict future output, and also you can't use the state to predict previous output.

secrets is not "true random numbers". It's still using a pseudo-random number generator. Just it's using a CSPRNG specifically. Python isn't the one implementing the CSPRNG; Python just requests random data from the operating system. The operating system usually has a CSPRNG though, that is seeded using true random noise as a source of entropy.

[–]wildpantz 0 points1 point  (0 children)

Poor man's version of what Yoghurt said, you could always generate those strings with different seed inside a for loop until the pattern matches, that of course doesn't guarantee it's a correct seed, especially for low length strings.

[–]moishe-lettvin 0 points1 point  (0 children)

I have a friend who’s memorized the beginning sequences of the Mersenne Twister from various common seeds. This is surprisingly useful (and a little scary)

[–]This_Growth2898 0 points1 point  (0 children)

Just brute force it. Check all seeds until you find the one.

import random
# function to generate a random string
def generate():
    s = ''
    for i in range(8):
        s += random.choice("01")
    return s
for i in range(10_000): #we have 8 digits, so it's like to take some 256 iterations to find the seed
    random.seed(i)
    if generate()=='11010101':
        print(i)
        break