71 lines
2.2 KiB
Python
71 lines
2.2 KiB
Python
"""Pluggable PRNG predictors for arena-battle token forensics.
|
|
|
|
The server computes: auth_token = "token_" + id + "_" + std::to_string(rand())
|
|
with NO srand() call => default-seeded PRNG, one draw per fighter, in id order.
|
|
|
|
Two predictors:
|
|
GlibcRandom - glibc TYPE_3 additive-feedback random() (Ubuntu 22.04 target)
|
|
DarwinRandom - macOS/BSD rand() (Schrage multiplicative LCG) for local tests
|
|
"""
|
|
|
|
import sys
|
|
|
|
MASK32 = 0xFFFFFFFF
|
|
|
|
|
|
class GlibcRandom:
|
|
"""glibc random()/rand() TYPE_3: r[i] = (r[i-3] + r[i-31]) mod 2^32, out = r[i]>>1."""
|
|
|
|
name = "glibc"
|
|
|
|
def __init__(self, seed=1, n=200000):
|
|
r = [0] * (344 + n)
|
|
r[0] = seed & MASK32
|
|
for i in range(1, 31):
|
|
# r[i] = 16807 * r[i-1] mod 2147483647 (Schrage), result in [0, 2^31-2]
|
|
hi, lo = divmod(r[i - 1], 127773)
|
|
word = 16807 * lo - 2836 * hi
|
|
if word < 0:
|
|
word += 2147483647
|
|
r[i] = word
|
|
for i in range(31, 34):
|
|
r[i] = r[i - 31]
|
|
for i in range(34, 344 + n):
|
|
r[i] = (r[i - 3] + r[i - 31]) & MASK32
|
|
self.values = [x >> 1 for x in r[344:]]
|
|
|
|
def index_of(self, value):
|
|
return [i for i, v in enumerate(self.values) if v == value]
|
|
|
|
|
|
class DarwinRandom:
|
|
"""macOS rand(): Lehmer LCG next = 16807*next mod (2^31-1), out = next (seed 1)."""
|
|
|
|
name = "darwin"
|
|
|
|
def __init__(self, seed=1, n=200000):
|
|
ctx = seed
|
|
vals = []
|
|
for _ in range(n):
|
|
ctx = (16807 * ctx) % 2147483647
|
|
vals.append(ctx)
|
|
self.values = vals
|
|
|
|
def index_of(self, value):
|
|
return [i for i, v in enumerate(self.values) if v == value]
|
|
|
|
|
|
def get_predictor(name, n=200000):
|
|
cls = {"glibc": GlibcRandom, "darwin": DarwinRandom}[name]
|
|
return cls(1, n)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
g = get_predictor("glibc", 10)
|
|
d = get_predictor("darwin", 10)
|
|
print("glibc :", g.values[:5])
|
|
print("darwin:", d.values[:5])
|
|
assert g.values[:5] == [1804289383, 846930886, 1681692777, 1714636915, 1957747793], "glibc seq wrong"
|
|
assert d.values[:5] == [16807, 282475249, 1622650073, 984943658, 1144108930], "darwin seq wrong"
|
|
print("PREDICTORS OK", flush=True)
|