Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pcg32Single state can be brute-forced from three outputs #2

Open
bgrainger opened this issue May 31, 2023 · 0 comments
Open

Pcg32Single state can be brute-forced from three outputs #2

bgrainger opened this issue May 31, 2023 · 0 comments

Comments

@bgrainger
Copy link
Owner

Based on this code linked from this article, the internal state of Pcg32Single can be recovered (in just seconds) given three successive values from Pcg32Single.GenerateNext.

(Note that this uses reflection to work around the Pcg32Single code scrambling the seed with the equivalent of pcg_oneseq_64_srandom_r; however, once the internal state has been recovered, all future PRNG values can be predicted. This also doesn't recover the initial seed passed to the constructor; however, that's not required to predict future output.)

ulong Recover(uint x0, uint x1, uint x2)
{
	Pcg32Single pcg = new(0);
	var stateField = pcg.GetType().GetField("_state", BindingFlags.NonPublic | BindingFlags.Instance);
	for (ulong upper = 0; upper < (1ul << 32); upper++)
	{
		var rot = (int) (upper >> 27);
		uint rotx0 = (x0 << rot) | (x0 >> (32 - rot));

		if (((rotx0 ^ upper >> 13) & ~31u) == (uint)(upper << 5))
		{
			uint high_lower_bits = (uint) ((rotx0 ^ upper >> 13) & 31u) << 27;
			for (uint lower = 0; lower < (1u << 27); lower++)
			{
				var candidate = (ulong)upper << 32 | high_lower_bits | lower;
				stateField.SetValue(pcg, candidate);

				if (pcg.GenerateNext() == x0 && pcg.GenerateNext() == x1 && pcg.GenerateNext() == x2)
					return candidate;
			}
		}
	}
	// Can't happen	
	throw new InvalidOperationException();
}

var random = new Random();
var seed = (ulong) random.NextInt64();
var pcg = new Pcg32Single(seed);

var x0 = pcg.GenerateNext();
var x1 = pcg.GenerateNext();
var x2 = pcg.GenerateNext();

Console.WriteLine(Recover(x0, x1, x2));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant