Skip to content

Instantly share code, notes, and snippets.

@EDDxample
Last active May 12, 2024 17:52
Show Gist options
  • Save EDDxample/38a9acddcd29f15af034fd91da93b8fa to your computer and use it in GitHub Desktop.
Save EDDxample/38a9acddcd29f15af034fd91da93b8fa to your computer and use it in GitHub Desktop.
Lattice Basics for RNG Seed finding
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Credits to [Matthew Bolan](https://github.com/mjtb49), the big brain behind this concept\n",
"\n",
"# Linear Congruential Generators:\n",
"In short, LCGs can be defined as a function that outputs pseudo-random numbers, where the next output is determined by the previous one with the following formula:\n",
"\n",
"$$ S_{n} = a \\cdot S_{n-1} + b \\pmod{c} $$\n",
"\n",
"Where $a$, $b$ and $c$ are the parameters that define how random the results will be and $S_{0}$ is our starting point (the Seed), which is just a refference since the LCG will eventually get to that value again."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"lcg(0) = 3\n",
"lcg(3) = 4\n",
"lcg(4) = 1\n",
"lcg(1) = 0\n",
"lcg(0) = 3\n"
]
}
],
"source": [
"# Function:\n",
"\n",
"def lcg(seed, a=7, b=3, c=10):\n",
" return (a*seed + b) % c\n",
"\n",
"\n",
"# Example:\n",
"\n",
"seed = 0\n",
"for i in range(5):\n",
" next_seed = lcg(seed)\n",
" print(f'lcg({seed}) = {next_seed}')\n",
" seed = next_seed"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that it can be reversed with the following formula:\n",
"\n",
"$$S_{n-1} = a^\\prime \\cdot (S_{n} - b) \\pmod{c}$$\n",
"\n",
"Where $a^\\prime$ is the equivalent of division in modular arithmetic: the $\\textbf{modular inverse}$, which satisfies:\n",
"\n",
"$$a^\\prime \\cdot a \\equiv 1 \\pmod{c}$$"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"initial: 5\n",
"next: 8\n",
"reversed: 5\n"
]
}
],
"source": [
"# Functions:\n",
"\n",
"def get_inverse(a, m): # naive way to get the modular inverse\n",
" a %= m\n",
" for x in range(m):\n",
" if (a*x) % m == 1:\n",
" return x\n",
" return 1\n",
"\n",
"def reverse_lcg(seed, a=7, b=3, c=10):\n",
" ai = get_inverse(a, c)\n",
" return (ai*(seed - b)) % c\n",
"\n",
"\n",
"# Example:\n",
"\n",
"s0 = 5 ; print('initial: ', s0)\n",
"s1 = lcg(s0) ; print('next: ', s1)\n",
"s0_ = reverse_lcg(s1) ; print('reversed:', s0_)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## From LCG to lattice:\n",
"We can plot N consecutive calls as points in N dimensions like this:\n",
"\n",
"$$ \\vec{S} = \\begin{bmatrix} seed & lcg(seed) & lcg(lcg(seed)) & \\cdots \\end{bmatrix} $$\n",
"\n",
"Now if we replace the formula we get:\n",
"\n",
"$$\n",
"\\begin{align*}\n",
"\\vec{S} & = \\begin{bmatrix} s & a s+b \\pmod{c} & a(as+b)+b \\pmod{c} & \\cdots \\end{bmatrix} \\\\\n",
" & = \\begin{bmatrix} s & a s+b \\pmod{c} & a^2 s + a b + b \\pmod{c} & \\cdots \\end{bmatrix}\n",
"\\end{align*}\n",
"$$\n",
"\n",
"$$\\text{*Here I use $s$ instead of $seed$ for aesthetic reasons}$$\n",
"\n",
"$\\quad$\n",
"\n",
"Then we can define those $\\vec{S}$ points as the linear combination of the following basis vectors:\n",
"\n",
"$$\n",
"\\begin{align*}\n",
" \\vec{A_{}} & = \\begin{bmatrix} 1 & a & a^2 & a^3 & \\cdots \\end{bmatrix} \\\\\n",
" \\vec{C_{1}} & = \\begin{bmatrix} 0 & c & 0 & 0 & \\cdots \\end{bmatrix} \\\\\n",
" \\vec{C_{2}} & = \\begin{bmatrix} 0 & 0 & c & 0 & \\cdots \\end{bmatrix} \\\\\n",
" \\vec{C_{3}} & = \\begin{bmatrix} 0 & 0 & 0 & c & \\cdots \\end{bmatrix} \\\\\n",
" \\cdots \\\\\n",
" \\text{And the offset}\\quad \\vec{B_{}} & = \\begin{bmatrix} 0 & b & a b + b & a^2 b + a b + b & \\cdots \\end{bmatrix}\n",
"\\end{align*}\n",
"$$\n",
"\n",
"$\\quad$\n",
"\n",
"Then we can just plot them like this:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x20aeedf03c8>]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"\n",
"# Example\n",
"\n",
"points = []\n",
"\n",
"for seed in range(50):\n",
" next_seed = lcg(seed, 6, 3, 50)\n",
" points.append([seed, next_seed])\n",
" \n",
"points = np.array(points)\n",
"plt.plot(points[:,0], points[:,1], '.', c='black')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# (Transition text, idk...)"
]
},
{
"attachments": {
"lattice1.png": {
"image/png": "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"
}
},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Seed Finding Example:\n",
"In this example we'll be using the following LCG:\n",
"\n",
"$$S_{n} = (41 \\cdot { S }_{ n-1 }+13)\\quad \\% \\quad 500$$\n",
"\n",
"$\\quad$\n",
"\n",
"$$\\text{And say we're looking for 2 consecutive calls so that:}$$\n",
"\n",
"$$10 < S_{0} < 400$$\n",
"\n",
"$$200 < S_{1} < 250$$\n",
"\n",
"$\\quad$\n",
"\n",
"$$\\text{So our Basis vectors are:}$$\n",
"\n",
"$$\n",
"\\begin{align*}\n",
" \\vec{A_{}} & = \\begin{bmatrix} 1 & 41 \\end{bmatrix} \\\\\n",
" \\vec{C_{1}} & = \\begin{bmatrix} 0 & 500 \\end{bmatrix} \\\\\n",
" \\text{And the offset}\\quad \\vec{B_{}} & = \\begin{bmatrix} 0 & 13 \\end{bmatrix}\n",
"\\end{align*}\n",
"$$\n",
"\n",
"$\\quad$\n",
"\n",
"We have to substract $\\vec{B_{}}$ from the whole lattice (including the area we're looking for) as we need a point at 0 0 to apply linear transformations, then if we plot the lattice we get:\n",
"\n",
"![lattice1.png](attachment:lattice1.png)\n",
"\n",
"And now any point within the red rectangle should fit our requirements!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The Bruteforce way\n",
"We can already see that there are some points within the given range but remember that we don't have such intuition for higher dimensions so if we want a dimension-independant way to find the seed we could:\n",
"\n",
"A) Bruteforce all the seeds from 10 to 400 (390 seeds) and check if the next call is between 200 and 250\n",
"\n",
"B) Bruteforce from 200 to 250 (50 seeds), $\\textbf{reverse}$ to get the previous call and check if it is between 10 and 400"
]
},
{
"attachments": {
"lattice2.png": {
"image/png": "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"
},
"lattice3.png": {
"image/png": "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"
}
},
"cell_type": "markdown",
"metadata": {},
"source": [
"## The lattice reduction way\n",
"Remember the set of basis vectors that define the points in the lattice? we can get a better basis if we apply a lattice reduction algorithm (LLL in this case), so our basis becomes:\n",
"\n",
"$$LLL\\left( \\begin{bmatrix} 1 & a \\\\ 0 & c \\end{bmatrix} \\right) = LLL\\left( \\begin{bmatrix} 1 & 41 \\\\ 0 & 500 \\end{bmatrix} \\right) = \\begin{bmatrix} -12 & 25 \\\\ 8 & 25 \\end{bmatrix}$$\n",
"\n",
"$$\\text{*Note: Wolfram transposes the result of LLL so make sure to transpose it back!}$$\n",
"\n",
"This is useful because the coord system formed by this new basis vectors moves the points of the old lattice to integer coords\n",
"\n",
"### LLL'd space:\n",
"\n",
"Now that we got the reduced (LLLd) basis and the validation range (remember that we substracted $\\vec{B_{}}$ from it), we can translate it to the LLLd space by using its inverse\n",
"\n",
"$$\n",
"\\begin{align*}\n",
"\\text{Range:}&\\begin{bmatrix} 10 \\\\ 187 \\end{bmatrix}<\\begin{bmatrix} S_{0} \\\\ S_{1} \\end{bmatrix}<\\begin{bmatrix} 400 \\\\ 237 \\end{bmatrix} \\\\\n",
"\\text{LLLd Basis:}&\\begin{bmatrix} -12 & 25 \\\\ 8 & 25 \\end{bmatrix} \\\\\n",
"\\text{Transformed Range:}&\\begin{bmatrix} -12 & 25 \\\\ 8 & 25 \\end{bmatrix}^{ -1 }\\begin{bmatrix} 10 & 400 \\\\ 187 & 237 \\end{bmatrix} = \\begin{bmatrix} 8.85 & -8.15 \\\\ 4.648 & 12.088 \\end{bmatrix}\n",
"\\end{align*}\n",
"$$\n",
"\n",
"$\\quad$\n",
"\n",
"So this is how the transformed range looks in the LLL'd space:\n",
"\n",
"![lattice2.png](attachment:lattice2.png)\n",
"\n",
"### The final step\n",
"Now all we have to do is to find the middle point of the range, round it to int coords and check if one of these points fits our requirements, otherwise the conditions we want cannot be reproduced by this LCG.\n",
"\n",
"![lattice3.png](attachment:lattice3.png)\n",
"\n",
"Finally, make sure to add $\\vec{B_{}}$ back to that number and reverse the lcg to get the initial seed that produces those consecutive calls"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### (This is the code I used to get the pictures)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[ 8.85 -8.15 ]\n",
" [ 4.648 12.088]]\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[ 8.85 -8.15 ]\n",
" [ 4.648 12.088]]\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[ 8.85 -8.15 ]\n",
" [ 4.648 12.088]]\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%matplotlib inline\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"\n",
"plt.style.use('seaborn-whitegrid')\n",
"\n",
"B = np.array([[0],[13]])\n",
"\n",
"LLLd = np.array([\n",
" [-12, 25],\n",
" [8, 25]\n",
"])\n",
"\n",
"inv_LLLd = np.linalg.inv(LLLd)\n",
"\n",
"# print(inv_LLLd)\n",
"\n",
"def draw_lattice(LLLspace=False):\n",
" points = []\n",
" \n",
" for seed in range(500):\n",
" next_seed = lcg(seed, 41, 13, 500)\n",
" point = np.array([[seed], [next_seed]]) - B\n",
" points.append(point)\n",
" \n",
" points = np.array(points) # shape = (1000, 2)\n",
" \n",
" if LLLspace:\n",
" points = (inv_LLLd @ points.T).T\n",
" if LLLspace == 2:\n",
" plt.xlim(-11, 12)\n",
" plt.ylim(3, 13)\n",
" \n",
" plt.plot(points[:,0], points[:,1], '.', color='black')\n",
"\n",
" ranges = np.array([\n",
" [10, 187], # [x, y]\n",
" [400,237] # [x, y]\n",
" ])\n",
" \n",
" print(inv_LLLd @ ranges.T)\n",
"\n",
" minX, minY = np.min(ranges, axis=0)\n",
" maxX, maxY = np.max(ranges, axis=0)\n",
"\n",
" corners = np.array([\n",
" [minX, maxY], # [x, y]\n",
" [minX, minY], # [x, y]\n",
" [maxX, minY], # [x, y]\n",
" [maxX, maxY] # [x, y]\n",
" ])\n",
" \n",
" if LLLspace:\n",
" corners = (inv_LLLd @ corners.T).T\n",
" if LLLspace == 2:\n",
" middle = np.mean(corners, axis= 0)\n",
" plt.plot(middle[0], middle[1], 'X', color='blue')\n",
" middle = np.floor(middle)\n",
" \n",
" middle = np.array([\n",
" middle,\n",
" middle + 1,\n",
" middle + [0, 1],\n",
" middle + [1, 0]\n",
" ])\n",
" \n",
" plt.plot(middle[:,0], middle[:,1], 'o', color='blue')\n",
" \n",
" \n",
" plt.plot(corners[:,0], corners[:,1], 'o', color='red')\n",
" \n",
" plt.fill(corners[:,0], corners[:,1], color='red', alpha=.2)\n",
" \n",
" plt.show()\n",
"\n",
"draw_lattice()\n",
"draw_lattice(True)\n",
"draw_lattice(2)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
@chiraagChakravarthy
Copy link

🧠

@vicgalle
Copy link

Thank you for this, one of the best explanations I've seen for this application of LLL!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment