Skip to content

Instantly share code, notes, and snippets.

@junorouse
Forked from szabolor/zer0c4_sol.ipynb
Created April 5, 2018 02:08
Show Gist options
  • Save junorouse/2e617c00dd4314418c75aad775dc4072 to your computer and use it in GitHub Desktop.
Save junorouse/2e617c00dd4314418c75aad775dc4072 to your computer and use it in GitHub Desktop.
0CTF Quals 2018 - zer0C4 solution by szabolor (!SpamAndHex)
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# zer0C4 -- a crypto challenge from 0CTF 2018\n",
"(solved by szabolor)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Modified RC4-32 cipher"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We were given a slightly modified version of an RC4 cipher which operates on a reduced modulo of 32. The important difference of the conventional RC4 cipher can be found at the initialization function (`ksa`): the counter `i` start from 1 instead of 0!\n",
"\n",
"The server-side software generates a secret key and then let the client (you) to try 512\\*1500=768000 pieces of 16 byte data key XOR-ed with its secret key as a new cipher. After that you must guess the secret key that the server used.\n",
"\n",
"Mostly what I have done is more or less \"exploratory data analysis\" based on the correlation of the key and the first two output bytes. But thanks God, it seemed to be worked :)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"import matplotlib\n",
"from matplotlib import pyplot as plt\n",
"\n",
"import os\n",
"import binascii\n",
"\n",
"N = 5\n",
"m = (1 << N)\n",
"mask = (1 << N) - 1\n",
"klen = 16\n",
"\n",
"def ksa(key):\n",
"\t\"\"\"Key-scheduling algorithm for 0ops Cipher 4\"\"\"\n",
"\ts = list(range(1 << N))\n",
"\ti = 0\n",
"\tj = 0\n",
"\twhile 1:\n",
"\t\ti = (i + 1) & mask # <<< Note the starting value of i=1 (!)\n",
"\t\tj = (j + s[i] + key[i%len(key)]) & mask\n",
"\t\ts[i], s[j] = s[j], s[i]\n",
"\t\tif not i:\n",
"\t\t\tbreak\n",
"\treturn s\n",
"\n",
"def prga(s, n):\n",
"\t\"\"\"Pseudo-random generation algorithm for 0ops Cipher 4\"\"\"\n",
"\ti = 0\n",
"\tj = 0\n",
"\tres = bytearray()\n",
"\tfor _ in range(n):\n",
"\t\ti = (i + 1) & mask\n",
"\t\tj = (j + s[i]) & mask\n",
"\t\ts[i], s[j] = s[j], s[i]\n",
"\t\tres.append(s[(s[i]+s[j])&mask])\n",
"\treturn res"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## key[1] and key[2] recovery"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As previously observed[1] the first byte of the pseudorandom stream may have some degree of correlation with a very limited part of the keystream. Roos's observation was based on the conventional RC4 cipher, where the state generation counter starts with 0, but his idea could easly adapted for this case. Since the first state byte touched by the key value is just shifted by one, the most probably values comes with in a shifted expression:\n",
"$$ s[E] = \\sum_{i=1}^E k[i] + \\frac{E(E+1)}{2} $$\n",
"That gives $ s[1] = k[1] + 1 $ and $ s[2] = k[1] + k[2] + 3 $ with high probability.\n",
"\n",
"The following script checks the empirical probabilities of this hypothesis for the first few state bytes.\n",
"\n",
"[1]: https://netfuture.ch/1995/09/weak-keys-in-rc4/ (1995-09-22 by Andrew Roos)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\nLNYkSZIGrNdiLcnBSS5NsibJ8VMs3yHJR9ryLyXZs83fM8lNSS5sX+/uM05JkqSh2ravjpNsA5wC\nPAVYB6xMsqyqLh5p9nvAdVX10CRHAH8JPKct+1ZV7ddXfJIkSXNBn2fWDgTWVNXlVXUzsBQ4dFKb\nQ4Ez2uszgSclSY8xSZIkzSmpqn46Tg4DDq6qF7fpI4GDqurYkTZfb23WtelvAQcBC4CLgG8CNwCv\nr6rPT7GNY4BjABYuXHjA0qVLe8ll1Oqrru+t74U7wdU39dP3vrvtMuO2feYIw8mzTxs2bGDBggWz\nHUbvxiHPccgRzHM+GYccYe7nuWTJklVVtWgmbXsbBgWmOkM2uTKcrs13gQdV1TVJDgA+meSRVXXD\n7RpWnQqcCrBo0aJavHjxzx/1Zhx9/Fm99X3cvhs5eXU/h2Tt8xfPuG2fOcJw8uzTihUruCvej7Nt\nHPIchxzBPOeTccgRxidP6HcYdB2wx8j07sD66dok2RbYBbi2qn5SVdcAVNUq4FvAw3qMVZIkaZD6\nLNZWAnsneUiS7YEjgGWT2iwDjmqvDwM+U1WV5H7tBgWS7AXsDVzeY6ySJEmD1NswaFVtTHIscDaw\nDXBaVV2U5ETg/KpaBrwP+ECSNcC1dAUdwBOBE5NsBG4FXlJV1/YVqyRJ0lD1ec0aVbUcWD5p3htG\nXv8YOHyK9T4OfLzP2CRJkuYCn2AgSZI0YBZrkiRJA2axJkmSNGAWa5IkSQNmsSZJkjRgFmuSJEkD\nZrEmSZI0YBZrkiRJA2axJkmSNGAWa5IkSQNmsSZJkjRgFmuSJEkD1uuD3KUh2/P4s3rr+7h9N3J0\nT/2vPekZvfQrSRomz6xJkiQNmMWaJEnSgFmsSZIkDZjFmiRJ0oBZrEmSJA2YxZokSdKAWaxJkiQN\nmMWaJEnSgFmsSZIkDZjFmiRJ0oBZrEmSJA2YxZokSdKAWaxJkiQNmMWaJEnSgFmsSZIkDZjFmiRJ\n0oBZrEmSJA2YxZokSdKAWaxJkiQNmMWaJEnSgPVarCU5OMmlSdYkOX6K5Tsk+Uhb/qUke44s+5M2\n/9IkT+szTkmSpKHatq+Ok2wDnAI8BVgHrEyyrKouHmn2e8B1VfXQJEcAfwk8J8k+wBHAI4EHAv+R\n5GFVdWtf8Urz1Z7Hn9Vb38ftu5Gje+p/7UnP6KVfSZpr+jyzdiCwpqour6qbgaXAoZPaHAqc0V6f\n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\nSZKkAfv/gQq1bDXLAzoAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 720x432 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"count = 10000\n",
"hip_table = []\n",
"end_idx = 10\n",
"for idx in range(1, end_idx):\n",
" hip = 0;\n",
" for i in range(count):\n",
" key = list(map(lambda x: x & 31, os.urandom(16)))\n",
" test = sum(key[1:idx+1]) + idx*(idx+1) // 2\n",
" res = ksa(key)\n",
" \n",
" if res[idx] == test: \n",
" hip += 1\n",
"\n",
" hip_table.append(hip/float(count))\n",
"\n",
"plt.figure(figsize=(10, 6))\n",
"plt.grid()\n",
"plt.xticks(range(1, end_idx))\n",
"plt.xlabel(\"i-th key byte\")\n",
"plt.ylabel(\"probability\")\n",
"plt.title(\"Probabilities for the modified Roos state-value hypothesis\")\n",
"plt.bar(range(1, end_idx), hip_table);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It can be clearly see, that the probability values are way worse that Roos's ones, (maybe) due to the reduced state-space. But it does work for the first key value at least with around 1/3 chance!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"At the first pseudorandom byte generation the $ s[s[1]+s[s[1]]] $ is returned, and -- continuing Roos's idea -- let's make that value equals with $ s[2] $ with a high probability. That could mean to use $s[1] = 1$, and from that $k[1] = 0$ follows. So finally if we get $s[2]$ that would actually mean (with a relatively high probability) $k[1]+k[2]+3 = k[2]+3$. That shows us the strong connection of the first prng byte and the 3rd byte of the key.\n",
"\n",
"The next script test for some correlation of $k[0]$ and $k[1]$, looking at the distribution of the $b[0]$ values and also checks the previous $b[0] == k[2] + 3$ hypothesis experimentally."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"count = 512\n",
"crest_table=[]\n",
"hip_table=[]\n",
"for key_1 in range(32):\n",
" crest_row = []\n",
" hip_row = []\n",
" for key_2 in range(32):\n",
" stat = {}\n",
" hip = 0\n",
" for _ in range(count):\n",
" key = list(map(lambda x: x & mask, os.urandom(16)))\n",
" key[1] = key_1\n",
" key[2] = key_2\n",
"\n",
" state = ksa(key)\n",
" res = prga(state, 16)\n",
"\n",
" if res[0] in stat:\n",
" stat[res[0]] += 1\n",
" else:\n",
" stat[res[0]] = 1\n",
" \n",
" if res[0] == ((key[2]+3) % m):\n",
" hip += 1\n",
"\n",
" sorted_stat = sorted(stat, key=stat.get, reverse=True)\n",
" crest_factor = stat[sorted_stat[0]] / float(stat[sorted_stat[1]])\n",
" crest_row.append(crest_factor)\n",
" hip_row.append(hip)\n",
" #print(\"key[2]=%d, crest factor: %.4f\" % (key_2, crest_factor))\n",
" crest_table.append(crest_row)\n",
" hip_table.append(hip_row)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABDQAAAIFCAYAAAAtGK1IAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzs3XmcZHdd7//3p7ZepnumZ8skk8lC\nCGAAI2pYRNmDsoMKl31RroiKqJfNBX+Ee0G5ihdFQARkERSMCAgYHhDFAIICISIQAyQkk8lkma2n\nt+mt6pzP74/v6UlNTy9Vn+7pysm8no/HPJKuqs/5fs85360+deqUubsAAAAAAADKpNLrCgAAAAAA\nAHSLhAYAAAAAACgdEhoAAAAAAKB0SGgAAAAAAIDSIaEBAAAAAABKh4QGAAAAAAAoHRIayzCzvWZ2\n6Tpv8zIza5rZlJlt6jDmB2Y2b2YfWs+6rFCem9mFyzx3lZn9z3Uu70VmlhXH5KIOYz5vZrNm9m/B\nMu9jZv9pZpNm9nIzGzCzT5nZuJn9fWSbdwXFsQwdk7K5u5yzBWa2y8y+WLTJPznFZbmZHTOzN3b4\n+tcXr3czq3UYc3ysMLPnmtnn1lLnRdu+1sweWfz/Zes5NprZ75rZe9Zre+gN5u8ln2P+vgu7q87f\nRV+aMbMPdvj6FxftYdm22EXZU2Z2wSp166ifr3Z8zewzZvbCSD07KPtU9L11nVeLbZqZvc/MjprZ\n19Zz20uUdVUxDnyxw9dfWrSHfL3H9k6VaV4xs51m9j0z61+/2i5b1rquw9q222dm3zWzMzp5PQmN\njfd37j7k7sckycweZWb/WkzGexe/2N3vKekPNrqSG+zfi2NynSSZ2QvN7BtmNmFm+83sj9rfSLn7\noyW9dA3lvVrSVe4+7O5vlfR0SbskbXf3Z0Q3eqo69TJlnd/NG8zA9i8r/j3SzK46FWWsUHYnk/96\nnbM1LyKLbby/OCd7g5t5iaTDkja7+yvWUp8O/Yi7/97CH2b2gKLPTRf/fcDCc+7+Okn3ixbk7n/j\n7j+92uuKY/iGDrZ3P3e/KlqftvIeaWb7F237D9x9XReeuFth/j4Z83f3ZZ3S+fsUeLK7P3/hj6L+\n/1rMF99tf5Pn7n/l7kPrUWjRrm4syuxoflhDWY939w+sdTsb1Y46nVe79FOSHitpj7s/aJ23vZSX\nufvDF/4ws21m9nFLH6DcbGbPWXjO3f+5aFf7NqBeG23xvPIqM/tOkbS9ycxe1f7iDueV35b0Pnef\nPUV17oiZ3dfMri6SZEfN7J/N7L5tzy+7r+4+J+m9kl7TSVkkNHrvmNIJe9VqLzyNDEr6TUk7JD1Y\n0mMkvXIdt3+epGsX/f19d2+tYxmntQ1YqN0lztk67ud5kv7b3b3DcqvrVK7MrCHpHyV9SNJWSR+Q\n9I/F43cZJVr84/TB/H0y5u+7mFMwdn5Y0n9K2i7p9yR91Mx2rnMZ2HjnSdq78MZ6NaegXb1d0rxS\ngvK5kv7CzMIfppSYSXqB0nrscZJeZmbP6jjYrE/SC5XWdL12m1LSeZvSnPBJSR9pe361ff1bSS8s\n9mlFJDQ6YGY/VGSOnlX8vdvM/sHMDhWPv7x4/MwiY729LfbHi9fVl9q2u3/N3T8o6cZg3e5p6RLO\nI2Z22Mz+xsxG2p7fa2avNLNvFZ8i/Z21XYJUZMduN7PbzOwXuyj3rGKbryz+3mJmf1Vs61Yze4OZ\nVS1dMjRqZj/cFnuGpUsYl5wA3f0v3P1L7j7v7rdK+htJP9nlcXmSmX3TzMbM7CtmdnHx+OclPUrS\n2yxd4vVhSf+fpGcWf7+4eN0vmtl1RUbxs2Z2Xtu272dmVxb7dcDSZeqPk/S7bdv5r2XqdZGlKxDG\nLF06/5S2595vZm83s38qspVfNbN7LrOLC5fpjRXl/UTbdt5c1PsmM3t82+NLnqMuj+tJ+148fpmZ\nfdTMPmRmE5JeZGYVM/ttS5fHHTGzy81sW/H6/uK1R4pj8XVLX7t4o6SHtZ2fty1Rh9dr0TnroB+c\nY2YfK/riETN7m6VLpN8p6SeK7Yy1Hae/Ll57s5m91swqxXMvMrMvm9lbzGxU0mVdHLuHFvs5Xvz3\nocXj71eafF5d1OOkSxqLtvEXZnaFmR2T9Kiib73ZzPYV5+KdZjZQvH6HmX26OLajZvalhX1YwiMl\n1ST9qbvPFZ96mqRHd7Fvj7X0Sd14cc6s7bnjV8FY8hYzO1i89ltmdn8ze4nSAmbhGHyqeP1eM3uN\nmX1L0jEzq9nJl332WxrXJs3sGjP7kbayT7jsuTiOb7B0aednJO0uypuyNK6f8OmamT3FUj8ds9Rv\nL2p7bsWxFXcNxvy9VLnM33fj+dvWaT5eZtv3lvRjkl7n7jPu/g+Svi3p55fZ18Xxv2DF+F78fYOZ\nXd729y1WXCFoxfhty8wPhQd0MwavcHyPXxlqd87zf15s97tm9pi21+42s08WbegGM/ul4vGV2tF5\nxTYnzexzZrajbXsPKdr5mJn9lxVfqWyry4125yfYz217fMV5dZn9X67uL5b0Ht25Hnr9ErFLrn+W\n629d1muTUhv6fXefcvd/U3rz+/ylXt9rdmrnlT9y92vcveXu31P6wKmbMfTBksbc/fgVqEX7fkPR\nzqYsfU1vu6U5Z6Lo8+e3vX7J9Wrx3D3M7AtFm7xSKVGxJHcfc/e9xYd1JimTdGHb8yvua7EPRyU9\nZNW9dnf+LfFP0l5JlyoN3PskPal4vCLpG0qTaEPSBUqLmZ8pnr9C0q+0bectkv68+P/LJH1omfIu\nVcqMLvXcSnEXKl0i1idpp9JE+aeL9uNrknYrZciuk/TS4rnHSTog6f6SNillwlzShcuUdZWk/ynp\nfEnfl/SStuc+Iekvi+2cUZT5y8Vz75D0f9te+xuSPlX8/4sk/dsq5+ITkt606LFl44pzdlCpU1eV\n3izuldTXvh/LHV9JT5N0g6SLlN7ovVbSV4rnhiXdLukVkvqLvx+82nkqnq8X2/3dou08WtKkpPsU\nz79f0qikBxXl/o2kjyyzrfOLc1VbdEyakn6p2O9fUcqO2mrnqMM+sdq+N4tjV5E0oPQp3X9I2qPU\nPv9S0oeL1/+ypE8pfZpXlfTjSl+3OOn8dNIntEI/KLb/X0p9cVNR959arh1J+mulQXVYd7b1F7e9\nviXp14tzNNDhsdumNCg/v4h7dvH39rZz/4YV4t8vaVxpoK8U+/CnShP+tqKun5L0h8Xr/1ApWVMv\n/j2srR2c0Mcl/Zakzywq79OSXrFSe2t7boekCaUsfL3YXmvhHLYfY0k/ozR+jihNbhdJOmu5Y6DU\nb78p6ZyFY108dumidrdQ9isl3SSpvsy+Hi9DKZGzf7l2JeneSp/AP7bY9quV+m9jtbGVf739J+bv\npcq6Sszfp8X8rfWdj/eqGG+Lv39W0nWLynubin7S9tiSbVGpz40V9TpL0s2Sbm177qikyuJtaPn5\noaMxuIPje5VOnLNaSnNZXdIzlebfbcXzX1DqF/2SHiDpkKTHLNeOim3/QGlOGSj+flPx3NmSjkh6\nQnFMHlv8vbM41xO6s42dJel+i/uQVphXlzgOK9X9+DZXOIYnrH+0cn9bab4/fryLv39U0syi8l6p\nYqxZdM4vXaZ+71BqW0v9+1a3r1ti+3u1gfNK8bwpXQ310kWPLxsn6dck/dMSbfAGSfeUtEXSfyvN\nA5cW5+2vlb6iIq2+Xv13Sf9PaRx5uNI4uOw+FDFjRdvJJb22y339pKSXr7R9d+cKjVU8TOlAvtDd\nP1089kBJO939f3v6BOJGSe+WtHCJzAckPU86fln4syV1dDOlCHe/wd2v9PTJ6iGlRvaIRS97q7vf\n5u6jSpPWwvfj/4dSA/6Op0vMLuugyPsqdYzXufu7JKnI5D9e0m+6+zF3P6jUYduPyXPszk+In68O\nj4mZ/YKkSyS9uZPXF35J0l+6+1fdPfP0vcg5dZLhS35Z6Y3hdZ4uY/0DpU8BzpP0JEl3uPufuPus\nu0+6+1c73O5DJA0pTWTz7v55pTeOz257zcc8ferXUloQPWCJ7azkZnd/t7tnSsf9LEm7OjhHnVht\n3//d3T/h7rm7zygdx99z9/2evgt3maSnW7pMsal0ueqFxTn6hrtPdLmvx63SDx6ktOB5VbHvs56y\n/ycp+uwzJf1OsX97Jf2JTvyU4DZ3/3NPGeWZDqv4REnXu/sHi7gPS/qupCd3sZv/6O5fdvdcqT3/\nkqTfcvdRd59UaqcL57OpdO7Pc/emp09MfZntDikt1tqNKy32O/EEpa/LfNTdm0qJljuWeW2z2O4P\nKS0kr3P321fZ/lvd/ZYVjvU32sr+f0oLtU77+kqeqbQouLLY9puVFnAPbXvNcmMreo/5+2TM36fP\n/H2q5uM1zRdFn5tUOjaPkPRZSbea2Q8Vf3+pmOM61c0YvOTxXea1B5WSi013/ztJ35P0RDM7R+le\nE68p2tA3la5sWO1Kgve5+/eLc3F5Wz2fJ+kKd7+iOFdXSrpaaV6V0hvA+5vZgLvf7u7XnrzpzubV\nNdS93eL1z0r9rZv5fq3rELn7r7r7yDL/Lu72dcvY6HnlMqWEyfs6fL2UEkiTSzz+Pnf/gbuPK12h\n+gNP9yZpSfp7paSStMJ61czOLfb394t564tK/W5F7j6ilEh5mVLSYimXael9nSz2aUV8J3llL5X0\nBXf/17bHzlO6THms7bGqpC8V//+Pkt5p6c7M95Y07u6n7G7Blu7++lalTjas1BiOLnpZ+5uLaaU3\ndyr++422527uoMjnKmX5Ptr22HlKWezbzY5faV6RdIskuftXLV0m/wgzu13pU6lPrlaQmT1N0puU\nsrGHO6hbe31eaGa/3vZYQ3fudyfxf2Yn/tqEKWXSz1HKtEfslnTLosn65mK7Cxafq25vrnU83t2n\ni/MxpJRxXfYcdWi1fV+8rfMkfdzM2vc3U1pAfLDY3kcsXWL9IaXFVnPxRi19reV3iz8/5O4n3VBu\nlX5wjtJCppPvWO9QaivtfWHxOermmC3YrZP71+Ltrqa93J1Kn6Z9o+18mtJYJEl/rDQ5fK54/l3u\n/qZltjslafOixzZr6QlxKbvb6+bubmZLHiN3/7ylr6S8XdK5ZvZxSa9cYfEsrX6828vOLd3os9O+\nvpITzlmx7Vu0cn9dj3KxPpi/T8b8ffrM36dkPtba5wspXSXwSKW29AWlT28fIeknir+70c0YvNzx\nXcqt7id8CHBzse3dkhY+RGh/7pIu67lQ7nmSnmFm7R9u1CX9q7sfM7NnKl2p8Fdm9mWlKye/277h\nLubVaN3bLdWuluxvXc7369GuNsKGzStm9jKl+0s8rEhCduqolk4EHWj7/5kl/l5okyutV3dLOuon\n3mflZqXxY0VFe36npENmdlGRmJW06r4OK40RK+IKjZW9VKkTvqXtsVsk3bQoozfs7k+QJE93lL1c\naeHQ8ScZa/CHSpflXezum5WygLZyyHG368RGeG4HMZcp/RrD39qd39+8RekTlB1tx2Szu7ffzGch\nQ/l8SR/1Ve68a+m7iO9Wurv2tzvamzvdIumNi87RYJFl7DT+lxfFD7j7V4rnlvte7HKfgC+4TdI5\nduK9DM6VdGuH9eqmrMU6OUedbGO5fV+qTrdIevyi49jv7rd6+tTj9e5+X6VPvJ+kNJidtB1Pvzwx\nVPxb7u74K/WDW5T68VIJ3MV1Pqz0qcJ5bY8tPkfdHnspnfvzFj3W7blvL/ew0gR0v7Zju8WLu8t7\n+uTxFe5+gdJVIP/L2r4DvMi1ki62tpWypIt14o33VnLCOFJsZ9nJzd3f6u4/rvTLKffWnTdUXO64\nrna828uuKF1SfVvx0LRS4mfBmV1s94Rz1rZfkf6Kjcf8fbLLxPx9uszf6zUfL3atpAvMrP0N04+o\n8/lCujOh8bDi/7+glNB4hJZPaETm3bU4e9GceK5SG7hN0rZF+9/eDiLn9oOLzsumhQ8g3P2z7v5Y\npatJvqvUr06ywrzabrW6d2KpdrVcf+u0XlL6+kPNzO7V9lhX7crSfcSmlvl3bbevW8aGzCuW7on0\n20pfB9q/2usX+ZbSsY5aab16u6StduJPzHYy9yyoKK3JjieCO9jXi5S+Nr7qhrG8SaXvqT7czBY+\n3fyapAlLN6obsHTjrPub2QPb4v5a6btmT9Eqd5m1dKOmfqWMrFm6OVM3vy4wrJTZHDOzs9Xd3dYv\nV7pZ1H3NbFDS6zqIaUp6htJ3+z5oZhVPl5B9TtKfmNnmYp/uaWbtl85+UOm7l89TOj7LMrNHK12u\n+fOdZDGX8G5JLzWzB1uyycyeuGgQX8k7Jf2OFXdXtnQzroWfg/u0pDPN7Dct3TBt2MweXDx3QNL5\ntvzNF7+q9J38V5tZ3dKNn56sE+/426lDSpciLvsb7e06PEerWWnfl/JOSW+0O28QtdPMnlr8/6PM\n7IeLRfWEUrvKirgDne5Xm5X6wdeUBuE3FW2h38wWbjp0QNKehT7n6VLUy4t6Dxd1/19a+92ir5B0\nbzN7jqUbWz5T6fLvT68StyRPnxK+W9JbrPiNbjM728x+pvj/J1m6mZopHd9Mdx7fxa4qnnt5cV5f\nVjz++Q6r80+S7mdmP1ckjV6uExMHx5nZA4t+WVfqC7Na23mXpB9vK/s3lRb+/1E8902ly+WrxZus\n9vZ+QNJ2M9uyzHYvV7rE+DFFfV9RbPsrgTpi4zF/n4z5+/Sdv6Pz8eK6fF9pXH1d0d5/VikB/g9d\n1OULSjd3HSjewHxJqa9u1/KXo0fnh6gzlObEetF+LlL6asgtSnPAHxb7f7GkFyu1+YV6rtSOFvuQ\n0qX8P1OMR/2WflJ8j6UbpT/F0pvHOaWx4qTzssq8elwHdY9Ytr91Wq+ibsckfUzS/y76/E9Keqq6\nSCq7+0vbPvxa/O9+3b5uGRsxrzxX6as7j/XiZ4u79DVJI8WcErHsetXdb1b6StTrzaxhZj+lFb46\nbemG8T9aHJPNSl+rPKp0v5tV97XYh226c023LBIaq3D3MaWb9DzezP5P8YbnyUrff7tJ6dOO9yh9\nN2gh5stKk9U1nr6Dv5KHK33SeoVSlmtGaeLq1OuVblAzrvTG4mOdBrr7Z5S+7/55pctQO3oD4+7z\nkn5OacB/bzFwv0DpstD/VmqsH1XKKC/E7Jd0jVJ290uLt7nI7ysdzyvszqzpZ7rYr6uVvof7tqIu\nNygNJJ3Gf1zS/1W6/HJC0neUvr8qT5fqPVapDdwh6XqliVlK30GTpCNmds0S251XGswer9Ru3iHp\nBb7o8sEO6zgt6Y2SvmzpztidfL94xXPUQZkr7ftS/kzp0uTPmdmk0oC0sHg8syh/Qmlg+4LuHOT/\nTOm7vUfN7K0dVm/ZftDWZy9UupHTfqX7I0ipzV8r6Q4zW7gs+teVJt8bJf2b0s323tthPZbk7keU\nPvV6hdINv16tdEOpbi7FXuw1Sm37P4p2+s+S7lM8d6/i7ymlGzi9w92vWqZu80o39nqB0mV9vyjp\nacXjqyr24RlKl5cfKcr+8jIv36z0huWo0mWKR3Tn9+v/StJ9i/b8iU7KLvyj0vlcuInVz/mdl0r/\nhtK5H1P6dOT4dot+92FJNxZlnnCpsqc7bj9P0p8r9dcnK33i3NFxQe8xfy8Zx/x9Gs7fis/HS3mW\n0tcUjiqN+0/3dA+YjhRJkSkVbcnTVxBulPTloo8uJTo/RH1VaS47rHSunl7M41K6B8L5Sp9kf1zp\nnjRXFs+t2I4WK5IMT1X6Wu0hpU/7X6X0/qyitGa4TemGs4+Q9KtLbGaleXWxleretZX6W5f1ktK+\nDSjdv+TDSjfS7ObKnw2xAfPKG5SSe19vG0Pf2UX95pVuovu8jnfqxPjV1qvPURo7RpUS6SsluUeU\nzuW40tf9LpT0OL/zKr/V9vU5kj7gHXzlZuHuvlhnln5e7G/d/T1tj71W0u8oZb/P9g5+69nMvqd0\nac7l7t7xz7LdFZnZe5VuKPTatseer3S37XlJP+Hu13WwnSuVbtD1NXdf7jJ6AEsws1mlT3ve6u6/\n38HrX6d0lUqfpE0rLDiBuwXm75Mxf5+eijZ8lqSPu/sLO3j9LyjdsLRf0n2DnzD3lJm9SOkXOH6q\n13W5uzKzzyndM+Vqd1/pg7GF1z9G6SqgPklP8BPvYVEKGzmvWPpZ7S9J+lHv/Ob1dylm1qf0VZOH\ne9v9NpZ9PQmN9VdcZnSlpHP8xJvvnLYs/b7xN5U61029rQ0AACdj/j4Z8zdOJyQ0sN6YV049vnKy\nzszsA0qXev8mjTYxs/+jdBnaH7MYAgDcFTF/n4z5GwDimFc2BldoAAAAAACA0uEKDQAAAAAAUDq1\nXlegE9WhTV7btq37wDVcfFIfaK7+oiU052OH1KrBys7Fc1L1TbF9nJ+uh+J2bRkPxR0cXe5XFVdX\nG4rtY1Q2GTs2klTfHPvxhIFqbB+Ptbr5dcE7ZXm8zeXNjc2h1hrx+1fWKnkobnYu1gZ6MQZ4PVhm\n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\n5dJ8bCQpJia9MVttK1efG/7xka31oeYaO+etnCR1Xl6ws45qm/duTh3zsZGkenHRyjX27rVy0amt\nnCSp8vrv1fSUlXOvH425OSsnSe2jL/WcyfSOf5gilJO9X8uy4T9/1Nk9a+Wmnztl5dZed4WVm3ru\npJWTJE1OWLHOLq8Gas+a54VJfzuuXbPTyjWXzOvfy/41fvLwaStX7/DeBah50rsWNY9485SkvOEN\nVq42r2POeaNf2fT2V/f4WL3ygJWTpMnT3n4+ccyr1dp7vPPqKOSMtz10w0F7zMZS77/P9FXj9Yk7\nNAAAAAAAQHFoaAAAAAAAgOLQ0AAAAAAAAMWhoQEAAAAAAIpDQwMAAAAAABSHhgYAAAAAACgODQ0A\nAAAAAFAcGhoAAAAAAKA4NDQAAAAAAEBxaGgAAAAAAIDi0NAAAAAAAADFoaEBAAAAAACKQ0MDAAAA\nAAAUpznqCVyObHfUObMw3EGrhhXLhbPecLOzVq5eXLRykhRTU3bWGq/hPaaNXTvtMdsvHfOC7lx3\nX+GNJynNbZmdjjdgXXu5PjTm5qxcZlq5ztklKyf5c63X1rzcyqqV64t5nlNrfXPncRly3Ryz9vYd\nVz/b0bkOxBLPSwxTVqHOtomecxMvnPTHnJm2cp1d261ctL1rQ71jxspJUmuPn3VUa951c+Ll4Z+n\nq7PLVq6e8x/TWDxn5dyzUU72fkxJUpjjSZKa3vWvev64lVv70ddZOUmaWPD2uzD3c9fkkZadXT8w\nb+Va+71cY8Wfaz3p7TvN4+bvsm1vO3b2+78/rb6u98e1fsGsKTcBlRAAAAAAACgODQ0AAAAAAFAc\nGhoAAAAAAKA4NDQAAAAAAEBxaGgAAAAAAIDi0NAAAAAAAADFoaEBAAAAAACKQ0MDAAAAAAAUh4YG\nAAAAAAAoDg0NAAAAAABQHBoaAAAAAACgODQ0AAAAAABAcWhoAAAAAACA4jRHPYHLVnd6jjSve709\nXPsHh61cZlq5KsLK9SNbbSsXjYaVq5eXvdzqmpWTpMbcnBecmrJinRMnvPEkhTlmY95bo7s9+pFt\nb5+Tuc+5+2o/Y7rHlcvdb6Q+Hp+md+nIdssbT1K1bZs3pnq/dkhSNTtr5erFRSsnSdnpfa5Z1/Z4\n6F3UqcZi79eknJn2x1w8Z+Uay6vegPt3erk+dKa9c9H0Ye94C/O4iTNnrZwk1fuvsHLtPd65qPmC\n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\n9l55iFQAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 1296x648 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"f, (ax1, ax2) = plt.subplots(1, 2)\n",
"f.set_size_inches(18, 9)\n",
"ax1.imshow(crest_table)\n",
"ax1.set_xlabel(\"key[2]\")\n",
"ax1.set_ylabel(\"key[1]\")\n",
"ax1.set_xticks(range(0, m, 4))\n",
"ax1.set_yticks(range(0, m, 4))\n",
"ax1.set_title(\"key[1] and key[2] effect on the \\\"crest-factor\\\" of res[0] distribution\")\n",
"ax2.imshow(hip_table)\n",
"ax2.set_xlabel(\"key[2]\")\n",
"ax2.set_ylabel(\"key[1]\")\n",
"ax2.set_xticks(range(0, m, 4))\n",
"ax2.set_yticks(range(0, m, 4))\n",
"ax2.set_title(\"key[1] and key[2] effect on the res[0] with hipothesis of res[0] == key[2] (mod 32)\");"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Thus we can see, for $k[1]=0$, $b[0] = k[2] + 3$ holds for a _significant_ probability! (note that with $k[2] = 30$ this hypothesis does not work - that is 1/32 chance). Furthermore there is less chance to meet the hypothesis outside of $k[1]=0$.\n",
"\n",
"That means one can guess with a good probability the $k[1]$ and $k[2]$ values based on observing the $b[0]$ distribution looking for highly frequent elements."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## key[3..15] recovery"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So far we learned a correlation of $b[0]$ and $k[1], k[2]$. Thus it seems to be natural to observe the next prng output byte. (Well, this is my best justifing why I began to search for patterns at $b[1]$, although $b[1]$ isn't specifically considered in the papers I have read). The following observations came after experimenting with random keys where $k[1]$ and $k[2]$ was fixed. (So again, this is a typical \"left as an exercise to the reader\" situation -- sorry)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The idea: what if $k[1] + k[2] \\equiv 29\\ (\\textrm{mod}\\ 32)$?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As we noted at the beginning, at the most probably situation is $s[1] = 1+k[1]$ and $s[2] = 3+k[1]+k[2]$. So $k[1] + k[2] \\equiv 29\\ (\\textrm{mod}\\ 32)$ means, that $s[2] = 0$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's go through the two steps of prng generation:\n",
"\n",
"1st round\n",
"- $i=1$ and $j=s[1]=1+k[1]$\n",
"- $\\textrm{swap}(s[1], s[1+k[1]])$\n",
"- $\\implies\\ s[1+k[1]] = 1+k[1]$\n",
"\n",
"2nd round\n",
"- $i=2$ and $j=1+k[1]+s[2]=1+k[1]$\n",
"- $\\textrm{swap}(s[2], s[1+k[1]])$\n",
"- $\\implies\\ s[1+k[1]] = 0$ and $s[2] = 1+k[1]$\n",
"\n",
"Finally the 2nd round return $b[1]=s[s[2]+s[1+k[1]]] = s[1+k[1]+0]=s[1+k[1]]=0$. So we can conclude that with $k[1] + k[2] \\equiv 29\\ (\\textrm{mod}\\ 32)$ condition $b[1] = 0$ holds with _high_ probability."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But $b[1]=0$ only holds if $s[2]=0$ and $s[2]=0$ is true if something else does not swap values at the key scheduling for $i>2$. For example we can force for $i=3$ to be swapped by $s[2]$ and thus there is a high chance for $s[2]\\not=0$. At the end of 2nd round $j=0$ (because we probably swapped last with 0 to get $s[2]=0$), so for the 3rd round $j = s[3]+k[3]=3+k[3]$. As we want to have $j=2\\implies k[3]=31$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What is it mean in terms of finding the right key? Well, we can try for a fixed $k[1],k[2]$ all the 32 combinations of $k[3]$ (with randomized others parts) and watch for the distribution of $b[1]$: if it has a low \"crest-factor\", then it means we found the $k[3]=31$ state. It is not obvious to set directly this state because of the XOR secret key, so after finding a fixed value, we immediately got the secret key as well."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA4IAAAHwCAYAAADzfNGCAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzt3Xm8ZHdZJ/7PQ8IS0pCwthCQRgcy\nCoFIWhAX7AZEtgFFwDDoEEECCLhMxjGoo6ijxiXO6OBPRAigSIJsGsMaGRrkJ1sHCQmE3VaSQNgT\nGoLQ8MwfdVovl7sUt6vudt7v1+u+uurUOU8999z+1q3PPd9zqro7AAAAjMd1NroBAAAA1pcgCAAA\nMDKCIAAAwMgIggAAACMjCAIAAIyMIAgAADAygiAAc1dVXVX/Ycp1q6qeW1Wfqaq3zbu3JZ5/Z1W9\nsao+V1VnV9UvVtWz5/A8p1XVm+ZQ9+lV9YI51N1TVZfPoe6Bqrq2qv5iyvXvW1UHq+qrVXXfWfcD\nMBZHb3QDAMxPVX1vkt9NcqckX0lyWZKf7e63b2hjK/veJD+Q5Dbd/fkNeP7Tk3wyyY3bh+2ul//U\n3X93+E5VvT7JnZNcP8k/JfmV7v6bJBnW21FVBzaiUYDtQhAE2Kaq6sZJLkjypCR/leR6Sb4vyb/O\n4bmO7u5DMyp3uyQH1hICZ9TH7ZK8RwjcUD+Tyc/gUFXdI8nfVdUdu/ujG90YwHZhaijA9nXHJOnu\nc7v7K919bXe/trvfdXiFqnpsVV02TMN8TVXdbsFjf1hVH6mqa6rqoqr6vgWPPb2qXlJVL6iqa5Kc\nVlVHDdMoPzRMq7yoqm67oJ/7VtUHhuf646qqxQ1X1eOSPDvJPYfpf782LH98VX2wqj5dVedX1a0X\nbNNV9eSq+kCSDyy1I6rqxVX1saq6epj2eadl1nteksck+e/D89934VTLqvrRqvrwELJTVQ8Y6t5i\nuP8fq+rCoc/3VdUjF9S+2dD7NcOU129d5ueWqnp1VT1l0bKLq+phq/1sFm3zddM5h6mY9x1uX6eq\nzhx+Zp+qqr+qqpsu19eiOj9dVe+pqtsM9x9cVe+sqs9W1T9U1V2G5T9fVS9dtO3/qar/vVzt7n7X\ngkDfSa6b5LbLrQ/AN04QBNi+3p/kK1X1/CGw3GThg1X1Q0l+McnDktwiyd8nOXfBKm9PcnKSmyZ5\nYZIXV9UNFjz+0CQvSXJ8kr9M8l+TPCrJA5PcOMljk3xhwfoPTvKdSe6a5JFJfnBxw939nCRPTPLm\n7t7R3b9aVfdO8tvDNrdK8s9Jzlu06Q8luUeSb19mX7wqyR2S3DLJO4Z+v053nzY89rvD8//dosdf\nlOTNSf6oqm6W5DlJfrK7P1FVxya5MJN9dcthX/x/C0LnHyf54vA9PHb4Ws4Lh+2TJFX17ZkcqXzF\nsGi1n820fjqTfff9SW6d5DNDnyuqqv+R5LQk39/dl1fV3ZKck+QJSW6W5E+TnF9V10/ygiT3r6rj\nh22PTvKjSVY8J7CqLqiqLyZ5a5J9Sfav4fsDYBmCIMA21d3XZHK+XSf5sySfGI5I7RxWeUKS3+7u\ny4ajL7+V5OTDRwW7+wXd/anuPtTdZ2dyvtaJC57izd3919391e6+NslPJvnl7n5fT1zc3Z9asP5Z\n3f3Z7v6XJK/PJMhM49FJzunud3T3vyZ5WiZHDHctWOe3u/vTQx9L7Ytzuvtzw/ZPT3LXqjpuyudf\n7MlJ7p1JOPnb7r5gWP7gTKa0PnfYZ+9I8tIkD6+qo5L8SCbnun2+uy9N8vwVnuPlWfCzyGQfvGzo\nf5qfzbSekOSXuvvyBfvm4UNYW0pV1R9kEuL3dvcnhuWPT/Kn3f3W4ejz8zOZgvxdw3TONyZ5xLDu\n/ZN8srsvWqmx7n5wkhtl8oeF13T3V9fw/QGwDEEQYBsbQt5p3X2bTC6+ceskh6fk3S7JHw5T+T6b\n5NNJKskJSVJVZwzTRq8eHj8uyc0XlP/Ioqe7bZIPrdDOxxbc/kKSHVN+G7fO5Cjg4e/pYJJPHe5z\nmV7+zTBl9axh+uM1SQ4MD918uW1W0t2fTfLiTPbn2Qseul2Sexzen8M+e3SSb8rkiOvRi/r85yyj\nuz+XydG/U4dFp2bBUcwpfjbTul2Sly/o97JMLiq0c5n1j8/kYjq/3d1XL6pzxqLv/baZ/OySSej9\nseH2j2WVo4GHdfeXu/tVSX6wqh7yjXxjAKxMEAQYie5+b5LnZRJgkkkoeUJ3H7/g65ju/ofhnLNf\nyGQ65k26+/gkV2cSFP+t5KKn+EhWOO/tCFyZSdBIkgxTMG+W5IoVelnoP2cyjfW+mQSmXYdLraWZ\nqjo5k2md5yb5owUPfSTJGxbtzx3d/aQkn0hyKF97nts3r/JU5yZ5VFXdM8kxmRxFzZQ/m8M+n+SG\n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\nleS1SZ49r6YAAACYn2mvGvrVJM8cvgAAANjCVgyCVfX6TKaCfrq7H74+LQEAADBPqx0RPC2TIPiV\n+bcCAADAelgtCO7LJAh+Isk95t4NAAAAc7diEOzu269XIwAAAKyPaT9HcGaq6sSqeueCr2uq6mcX\nrbOnqq5esM6vrHefAAAA29W0Hx8xM939viQnJ//2wfRXJHn5Eqv+fXc/eD17AwAAGIN1PyK4yH2S\nfKi7/3mD+wAAABiNjQ6CpyY5d5nH7llVF1fVq6rqTuvZFAAAwHZW3b0xT1x1vSRXJrlTd1+16LEb\nJ/lqdx+sqgcm+cPuvsMydU5PcnqS7Ny585Tzzjtvzp1/4y654upV19l5THLVtavXOumE49a1/jS1\nx1J/rfte/e1df7OOXfU3tv5Wem2bd/3NOnbV39j6m3Xsqr+x9ef92jatgwcPZseOHWvadjPYu3fv\nRd29e7X1NjIIPjTJk7v7flOseyDJ7u7+5Err7d69u/fv3z+jDmdn15mvWHWdM046lLMvWf2UzQNn\nPWhd609Teyz117rv1d/e9Tfr2FV/Y+tvpde2edffrGNX/Y2tv1nHrvobW3/er23T2rdvX/bs2bOm\nbTeDqpoqCG7k1NBHZZlpoVX1TVVVw+27Z9Lnp9axNwAAgG1r3a8amiRVdcMkP5DkCQuWPTFJuvuZ\nSR6e5ElVdSjJtUlO7Y06dAkAALDNbEgQ7O4vJLnZomXPXHD7GUmesd59AQAAjMFGXzUUAACAdSYI\nAgAAjIwgCAAAMDKCIAAAwMgIggAAACMjCAIAAIyMIAgAADAygiAAAMDICIIAAAAjIwgCAACMjCAI\nAAAwMoIgAADAyAiCAAAAIyMIAgAAjIwgCAAAMDKCIAAAwMgIggAAACMjCAIAAIyMIAgAADAygiAA\nAMDICIIAAAAjIwgCAACMjCAIAAAwMoIgAADAyAiCAAAAIyMIAgAAjIwgCAAAMDKCIAAAwMgIggAA\nACMjCAIAAIyMIAgAADAygiAAAMDICIIAAAAjIwgCAACMjCAIAAAwMoIgAADAyAiCAAAAIyMIAgAA\njIwgCAAAMDKCIAAAwMgIggAAACMjCAIAAIyMIAgAADAygiAAAMDICIIAAAAjIwgCAACMjCAIAAAw\nMoIgAADAyAiCAAAAIyMIAgAAjMyGBcGqOlBVl1TVO6tq/xKPV1X9UVV9sKreVVV324g+AQAAtpuj\nN/j593b3J5d57AFJ7jB83SPJnwz/AgAAcAQ289TQhyb58554S5Ljq+pWG90UAADAVreRQbCTvLaq\nLqqq05d4/IQkH1lw//JhGQAAAEeguntjnrjq1t19ZVXdMsmFSZ7a3W9c8Pgrkvx2d79puP+6JP+9\nuy9aVOf0JKcnyc6dO08577zB8WbDAAAVL0lEQVTz1u17mNYlV1y96jo7j0muunb1WiedcNy61p+m\n9ljqr3Xfq7+962/Wsav+xtbfSq9t866/Wceu+htbf7OOXfU3tv68X9umdfDgwezYsWNN224Ge/fu\nvai7d6+23oYFwa9pourpSQ529+8vWPanSfZ197nD/fcl2dPdH12uzu7du3v//q+77syG23XmK1Zd\n54yTDuXsS1Y/ZfPAWQ9a1/rT1B5L/bXue/W3d/3NOnbV39j6W+m1bd71N+vYVX9j62/Wsav+xtaf\n92vbtPbt25c9e/asadvNoKqmCoIbMjW0qo6tqhsdvp3kfkkuXbTa+Un+y3D10O9KcvVKIRAAAIDp\nbNRVQ3cmeXlVHe7hhd396qp6YpJ09zOTvDLJA5N8MMkXkvzEBvUKAACwrWxIEOzuDye56xLLn7ng\ndid58nr2BQAAMAab+eMjAAAAmANBEAAAYGQEQQAAgJERBAEAAEZGEAQAABgZQRAAAGBkBEEAAICR\nEQQBAABGRhAEAAAYGUEQAABgZARBAACAkREEAQAARkYQBAAAGBlBEAAAYGQEQQAAgJERBAEAAEZG\nEAQAABgZQRAAAGBkBEEAAICREQQBAABGRhAEAAAYGUEQAABgZARBAACAkREEAQAARkYQBAAAGBlB\nEAAAYGQEQQAAgJERBAEAAEZGEAQAABgZQRAAAGBkBEEAAICREQQBAABGRhAEAAAYGUEQAABgZARB\nAACAkREEAQAARkYQBAAAGBlBEAAAYGQEQQAAgJERBAEAAEZGEAQAABgZQRAAAGBkBEEAAICREQQB\nAABGRhAEAAAYGUEQAABgZARBAACAkREEAQAARkYQBAAAGBlBEAAAYGQEQQAAgJFZ9yBYVbetqtdX\n1WVV9e6q+pkl1tlTVVdX1TuHr19Z7z4BAAC2q6M34DkPJTmju99RVTdKclFVXdjd71m03t9394M3\noD8AAIBtbd2PCHb3R7v7HcPtzyW5LMkJ690HAADAWG3oOYJVtSvJdyR56xIP37OqLq6qV1XVnda1\nMQAAgG2suntjnrhqR5I3JPnN7n7ZosdunOSr3X2wqh6Y5A+7+w7L1Dk9yelJsnPnzlPOO++8OXf+\njbvkiqtXXWfnMclV165e66QTjlvX+tPUHkv9te579bd3/c06dtXf2Ppb6bVt3vU369hVf2Prb9ax\nq/7G1p/3a9u0Dh48mB07dqxp281g7969F3X37tXW25AgWFXXTXJBktd09x9Msf6BJLu7+5Mrrbd7\n9+7ev3//bJqcoV1nvmLVdc446VDOvmT1UzYPnPWgda0/Te2x1F/rvld/e9ffrGNX/Y2tv5Ve2+Zd\nf7OOXfU3tv5mHbvqb2z9eb+2TWvfvn3Zs2fPmrbdDKpqqiC4EVcNrSTPSXLZciGwqr5pWC9VdfdM\n+vzU+nUJAACwfW3EVUO/J8mPJ7mkqt45LPvFJN+cJN39zCQPT/KkqjqU5Nokp/ZGzWEFAADYZtY9\nCHb3m5LUKus8I8kz1qcjAACAcdnQq4YCAACw/gRBAACAkREEAQAARkYQBAAAGBlBEAAAYGQEQQAA\ngJERBAEAAEZGEAQAABgZQRAAAGBkBEEAAICREQQBAABGRhAEAAAYGUEQAABgZARBAACAkREEAQAA\nRkYQBAAAGBlBEAAAYGQEQQAAgJERBAEAAEZGEAQAABgZQRAAAGBkBEEAAICREQQBAABGRhAEAAAY\nGUEQAABgZARBAACAkREEAQAARubojW4AAABg3nad+Yqp1jvjpEM5bYp1D5z1oCNtaUM5IggAADAy\ngiAAAMDICIIAAAAjIwgCAACMjCAIAAAwMoIgAADAyAiCAAAAIyMIAgAAjIwgCAAAMDKCIAAAwMgI\nggAAACMjCAIAAIyMIAgAADAygiAAAMDICIIAAAAjIwgCAACMjCAIAAAwMoIgAADAyAiCAAAAIyMI\nAgAAjIwgCAAAMDKCIAAAwMhsSBCsqvtX1fuq6oNVdeYSj1+/ql40PP7Wqtq1/l0CAABsT+seBKvq\nqCR/nOQBSb49yaOq6tsXrfa4JJ/p7v+Q5H8l+Z317RIAAGD72ogjgndP8sHu/nB3fynJeUkeumid\nhyZ5/nD7JUnuU1W1jj0CAABsWxsRBE9I8pEF9y8fli25TncfSnJ1kputS3cAAADbXHX3+j5h1SOS\n/GB3/+Rw/8eT3L27n7pgnXcP61w+3P/QsM6nlqh3epLTh7snJnnfnL+Febl5kk+qr776W67+Vu5d\nffXVV3+j6m/l3tVXf7O7XXffYrWVjl6PTha5PMltF9y/TZIrl1nn8qo6OslxST69VLHuflaSZ82h\nz3VVVfu7e7f66qu/tepv5d7VV1999Teq/lbuXX31t4uNmBr69iR3qKrbV9X1kpya5PxF65yf5DHD\n7Ycn+b+93ocuAQAAtql1PyLY3Yeq6ilJXpPkqCTndPe7q+rXk+zv7vOTPCfJX1TVBzM5EnjqevcJ\nAACwXW3E1NB09yuTvHLRsl9ZcPuLSR6x3n1tsHlPb1VfffW3Xm311Vdf/e1afyv3rr7628K6XywG\nAACAjbUR5wgCAACwgQTBTaCq7l9V76uqD1bVmTOufU5VfbyqLp1l3QX1b1tVr6+qy6rq3VX1MzOu\nf4OqeltVXTzU/7VZ1h+e46iq+sequmAOtQ9U1SVV9c6q2j+H+sdX1Uuq6r3Dz+CeM6x94tD34a9r\nqupnZ1V/eI6fG36ul1bVuVV1gxnX/5mh9rtn0ftS46mqblpVF1bVB4Z/bzLj+o8Y+v9qVR3RFcyW\nqf97w/+fd1XVy6vq+BnX/42h9jur6rVVdetZ1l/w2H+rqq6qm8+4/6dX1RULxsEDZ91/VT11+B3w\n7qr63Rn3/6IFvR+oqnfOuP7JVfWWw69xVXX3Gde/a1W9eXgd/duquvEaay/5u2pW43eF+jMZvyvU\nn8n4XaH+TMbvcvUXPH5E43eF/mcyflfqfxbjd4X+ZzJ+V6h/xON3hdozGbtDrSXfC9bkwpNvHcbv\ni2pyEcpZ1X5KTd6XH9HvlU2vu31t4FcmF8z5UJJvSXK9JBcn+fYZ1r9XkrsluXRO/d8qyd2G2zdK\n8v4Z919Jdgy3r5vkrUm+a8bfw39N8sIkF8xh/xxIcvM5/v95fpKfHG5fL8nxc3qeo5J8LJPPpZlV\nzROS/FOSY4b7f5XktBnWv3OSS5PcMJPzof8uyR2OsObXjackv5vkzOH2mUl+Z8b1vy2Tz0jdl2T3\nHPq/X5Kjh9u/M4f+b7zg9k8neeYs6w/Lb5vJBcj++UjG2zL9Pz3Jf5vR/8ml6u8d/m9ef7h/y1nv\nnwWPn53kV2bc/2uTPGC4/cAk+2Zc/+1Jvn+4/dgkv7HG2kv+rprV+F2h/kzG7wr1ZzJ+V6g/k/G7\nXP3h/hGP3xX6n8n4XaH+TMbvSvtnwTprHr8r9H/E43eF2jMZu8P2S74XzOR9w6nD8mcmedIMa39H\nkl2Z8/u4jf5yRHDj3T3JB7v7w939pSTnJXnorIp39xuzzGcwzqj+R7v7HcPtzyW5LJM3+LOq3919\ncLh73eFrZie2VtVtkjwoybNnVXO9DH9du1cmV9lNd3+puz87p6e7T5IPdfc/z7ju0UmOqcnnhd4w\nX/+Zokfi25K8pbu/0N2HkrwhyQ8fScFlxtNDMwnkGf79oVnW7+7Luvt9a605Rf3XDvsnSd6SyWe7\nzrL+NQvuHpsjGL8rvJ79ryT//Uhqr1J/Jpap/6QkZ3X3vw7rfHzG9ZMkVVVJHpnk3BnX7ySH/9J/\nXI5gDC9T/8QkbxxuX5jkR9ZYe7nfVTMZv8vVn9X4XaH+TMbvCvVnMn5Xea9wxON3Hd6LLFd/JuN3\ntf6PdPyuUP+Ix+8KtWcydoe6y70XvHeSlwzL1zR+l6vd3f/Y3QfW2vNWIQhuvBOSfGTB/cszwxev\n9VRVuzL5C8pbZ1z3qGE6xMeTXNjds6z/vzP5BfTVGdZcqJO8tqouqqrTZ1z7W5J8IslzazK19dlV\ndeyMn+OwU3MEbyCX0t1XJPn9JP+S5KNJru7u187wKS5Ncq+qullV3TCTv3bedob1D9vZ3R9NJr8Q\nk9xyDs+xXh6b5FWzLlpVv1lVH0ny6CS/str632DthyS5orsvnmXdRZ4yTI87p45g6u8y7pjk+4bp\nTW+oqu+ccf3Dvi/JVd39gRnX/dkkvzf8fH8/ydNmXP/SJA8Zbj8iMxjDi35XzXz8zut34RT1ZzJ+\nF9ef9fhdWH8e43eJ/TPT8buo/szH7zI/35mN30X1Zzp+F9We6dhd/F4wk9l0n13wh5A1v3+e8/vM\nTU0Q3Hi1xLItdynXqtqR5KVJfnbRXxCPWHd/pbtPzuQvnXevqjvPom5VPTjJx7v7olnUW8b3dPfd\nkjwgyZOr6l4zrH10JtOo/qS7vyPJ5zOZ2jRTw5z7hyR58Yzr3iSTv8bfPsmtkxxbVT82q/rdfVkm\nU6UuTPLqTKZdH1pxoxGrql/KZP/85axrd/cvdfdth9pPmVXdIeD/UmYcLhf5kyTfmuTkTP5gcfaM\n6x+d5CaZTEX6+SR/Nfz1f9YelRn/MWfwpCQ/N/x8fy7DDIUZemwmr50XZTLt7EtHUmyev6s2sv6s\nxu9S9Wc5fhfWH/qd6fhdov+Zjt8l6s90/K7w/2cm43eJ+jMbv0vUnunYXfxeMJNZP1+32ixqz+p9\n5lYgCG68y/O1fyW5TWY7PW7uquq6mQz+v+zul83reYZpj/uS3H9GJb8nyUOq6kAmU3LvXVUvmFHt\nJEl3Xzn8+/EkL8/kxWtWLk9y+YK/XL0kk2A4aw9I8o7uvmrGde+b5J+6+xPd/eUkL0vy3bN8gu5+\nTnffrbvvlcmUs1kfDUmSq6rqVkky/LvmqX0bpaoek+TBSR7d3fP8Q9QLcwTTg5bwrZn8IeHiYRzf\nJsk7quqbZvUE3X3V8Cbhq0n+LLMdw8lkHL9smJ70tkxmJ8z0wgTD1OuHJXnRLOsOHpPJ2E0mfyya\n6f7p7vd29/26+5RM3gh/aK21lvldNbPxO+/fhcvVn9X4naL/Ixq/S9Sf6fhdqv9Zjt9l9s/Mxu8K\nP9+ZjN9l6s9k/C6z72c2dhda8F7wu5IcP+yfZAbvn+fwPnPTEwQ33tuT3GG48tH1MpmCd/4G9zS1\n4S9fz0lyWXf/wRzq36KGq6BV1TGZhIf3zqJ2dz+tu2/T3bsy2e//t7tndkSqqo6tqhsdvp3JSf0z\nu3prd38syUeq6sRh0X2SvGdW9ReY15GEf0nyXVV1w+H/0X0yObdgZqrqlsO/35zJL9J5fB/nZ/LL\nNMO/fzOH55ibqrp/kl9I8pDu/sIc6t9hwd2HZEbjN0m6+5LuvmV37xrG8eWZXLTgY7N6jsMhYfDD\nmeEYHvx1Jue5pKrumMlFnz454+e4b5L3dvflM66bTN54ff9w+96Z8R9bFozh6yT55UwuCLGWOsv9\nrprJ+F2H34VL1p/V+F2h/kzG71L1Zzl+V+h/JuN3hZ/vTMbvKv9/jnj8rlD/iMfvCvt+JmN3qLHU\ne8HLkrw+ycOH1dY0fuf5PnNL6E1wxZqxf2Vy7tL7M/lryS/NuPa5mUyH+HImL7KPm3H9783kUPy7\nkrxz+HrgDOvfJck/DvUvzRFc8W6V59mTGV81NJNz+C4evt4965/t8BwnJ9k/7J+/TnKTGde/YZJP\nJTluTvv91zJ5wb00yV9kuPLaDOv/fSbh+OIk95lBva8bT0luluR1mfwCfV2Sm864/g8Pt/81yVVJ\nXjPj+h/M5Dzlw+P3SK7quVT9lw4/33cl+dtMLkAxs/qLHj+QI7tq6FL9/0WSS4b+z09yqxnXv16S\nFwz76B1J7j3r/ZPkeUmeOKf//9+b5KJhjL01ySkzrv8zmfx+fH+Ss5LUGmsv+btqVuN3hfozGb8r\n1J/J+F2h/kzG73L1F62z5vG7Qv8zGb8r1J/J+F1p/8xi/K7Q/xGP3xVqz2TsDs+x5HvBTN5nvW0Y\nBy/OGt5DrFD7p4exeyiTwPzsI/kZbNavGr5ZAAAARsLUUAAAgJERBAEAAEZGEAQAABgZQRAAAGBk\nBEEAAICREQQB2FaqaldVHfHn/VXVaVX1iap69nD/7lX1zuHr4qr64WH5McOyL1XVEX8YfFUdPNIa\nALCaoze6AQDYxF7U3U8Zbl+aZHd3Hxo+qPriqvrb7r42yclVdWDDugSAb5AjggBsW1X1LVX1j1X1\nnVV1VFX9XlW9vareVVVPGNb5i6p66IJt/rKqHrK4Vnd/obsPDXdvkMmHKK/2/L9TVT+14P7Tq+qM\nqtpRVa+rqndU1SULn3/Bunuq6oIF959RVacNt0+pqjdU1UVV9ZohmALA1ARBALalqjoxyUuT/ER3\nvz3J45Jc3d3fmeQ7kzy+qm6f5NlJfmLY5rgk353klcvUvEdVvTvJJUmeuCAYLue8JD+64P4jk7w4\nyReT/HB33y3J3iRnV1VN+X1dN8n/SfLw7j4lyTlJfnOabQHgMFNDAdiObpHkb5L8SHe/e1h2vyR3\nqaqHD/ePS3KH7n5tVf1xVd0yycOSvHSY/vl1Rbv7rUnuVFXfluT5VfWq7v7ick109z9W1S2r6tZD\nT5/p7n8ZwtxvVdW9knw1yQlJdib52BTf24lJ7pzkwqHHo5J8dIrtAODfCIIAbEdXJ/lIku9JcjgI\nVpKndvdrllj/L5I8OsmpSR67WvHuvqyqPp9JINu/yuovSfLwJN+UyRHCDM91iySndPeXh/MLb7Bo\nu0P52pk7hx+vJO/u7nuu1icALMfUUAC2oy8l+aEk/6Wq/vOw7DVJnjQcjUtV3bGqjh0ee16Sn02S\nBUcQv0ZV3b6qjh5u3y6TI3MHpujlvEwC5sMzCYXJ5Gjkx4cQuDfJ7ZbY7p+TfHtVXX+YsnqfYfn7\nktyiqu459HLdqrrTFH0AwL9xRBCAbam7P19VD85kCuXnMzkXcFeSdwzn430ik7CY7r6qqi5L8tcr\nlPzeJGdW1Zczmc75U939ySn6eHdV3SjJFd19eArnXyb526ran+SdSd67xHYfqaq/SvKuJB9I8o/D\n8i8N01v/aAiIRyf53/n3I58AsKrqXvWiZwCwrVXVDTO5AMzduvvqYdlpmXxcxFNW2nZBjQPD+quG\nQwDYaKaGAjBqVXXfTI7I/Z/DIXBwbZIHHP5A+RW2P6aq3pnkupkcKQSATc8RQQAAgJFxRBAAAGBk\nBEEAAICREQQBAABGRhAEAAAYGUEQAABgZARBAACAkfl/nnvtkCZ6Y9UAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 1080x576 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"count = 1000\n",
"crest_row = []\n",
"for key_3 in range(32):\n",
" stat = {}\n",
" hip = 0\n",
" for _ in range(count):\n",
" key = list(map(lambda x: x & mask, os.urandom(16)))\n",
" key[1] = 12 # e.g. 12+17 = 29\n",
" key[2] = 17\n",
" key[3] = key_3\n",
"\n",
" state = ksa(key)\n",
" res = prga(state, 16)\n",
"\n",
" if res[1] in stat:\n",
" stat[res[1]] += 1\n",
" else:\n",
" stat[res[1]] = 1\n",
"\n",
" sorted_stat = sorted(stat, key=stat.get, reverse=True)\n",
" crest_factor = stat[sorted_stat[0]] / float(stat[sorted_stat[1]])\n",
" crest_row.append(crest_factor)\n",
" #print(\"key[2]=%d, crest factor: %.4f\" % (key_3, crest_factor))\n",
"\n",
"plt.figure(figsize=(15, 8))\n",
"plt.grid()\n",
"plt.xticks(range(32))\n",
"plt.xlabel(\"key[3] value\")\n",
"plt.ylabel(\"\\\"crest-factor\\\"\")\n",
"plt.title(\"Search for a fixed value key[3]\")\n",
"plt.bar(range(32), crest_row);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now fix the $k[3]$ value as well, since this less frequent occurance depends on the key positions preceeding the interesting key. Let's just randomly select a value for the range where $s[2]=0$ meets, so strictly not the currently found _detection value_."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Keys to try iteratively (without key[0]!): [12, 17, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 31, 18, 17]\n",
"Detection fixed values (for key[3..15]): [31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 0, 19, 18]\n"
]
}
],
"source": [
"count = 1000\n",
"crest_threshold = 5\n",
"known_keys=[12, 17]\n",
"\n",
"for key_idx in list(range(3, 16)):\n",
" #print(\"processing key[%d]\" % (key_idx))\n",
" detection = -1;\n",
" crest_min_counter = 0;\n",
"\n",
" for new_key in range(32):\n",
" stat = {}\n",
"\n",
" for i in range(count):\n",
" key = list(map(lambda x: x & 31, os.urandom(16)))\n",
"\n",
" key[1:key_idx] = known_keys\n",
" key[key_idx] = new_key\n",
" state = ksa(key)\n",
" res = prga(state, 16)\n",
"\n",
" if res[1] in stat:\n",
" stat[res[1]] += 1\n",
" else:\n",
" stat[res[1]] = 1\n",
"\n",
" sorted_stat = sorted(stat, key=stat.get, reverse=True)\n",
" crest = stat[sorted_stat[0]] / float(stat[sorted_stat[1]])\n",
" #print(\"key[%d]: iter=%d crest=%.4f\" % (key_idx, new_key, crest))\n",
" #print(\"diff:\", [(x, stat[x]) for x in sorted_stat][:5])\n",
"\n",
" if crest < crest_threshold:\n",
" crest_min_counter += 1;\n",
" detection = new_key\n",
"\n",
" if crest_min_counter == 1:\n",
" #print(\"key[%d] detector at: %d\" % (key_idx, detection))\n",
" known_keys.append((detection - 1) % 32) # just select a non-detector value\n",
" else:\n",
" print(\"No or more than one crest min at key[%d]\" % (key_idx))\n",
" break\n",
" \n",
"print(\"Keys to try iteratively (without key[0]!): \", known_keys)\n",
"print(\"Detection fixed values (for key[3..15]): \", list(map(lambda x: (x+1)&mask, known_keys[2:])))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So using the detection fixed values at the given key index, one can found the XOR-ed original secret key byte."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally this way we can gain every byte of the secret key except the first. Well, just simply brute force it! We can brute-force more, if we afraid of the network delays/slowness. (I was brute-forcing 3 indexes, and it wasn't noticable at all!)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Local zer0C4 attack"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"secret key to be guessed: [0, 28, 5, 12, 9, 8, 21, 30, 2, 20, 2, 0, 4, 3, 18, 9]\n",
"key[1]=28, key[2]=5\n",
"processing key[3]\n",
"key[3] detector at: 19\n",
"processing key[4]\n",
"key[4] detector at: 20\n",
"processing key[5]\n",
"key[5] detector at: 20\n",
"processing key[6]\n",
"key[6] detector at: 14\n",
"processing key[7]\n",
"key[7] detector at: 4\n",
"processing key[8]\n",
"key[8] detector at: 27\n",
"processing key[9]\n",
"key[9] detector at: 12\n",
"processing key[10]\n",
"key[10] detector at: 21\n",
"processing key[11]\n",
"key[11] detector at: 22\n",
"processing key[12]\n",
"key[12] detector at: 17\n",
"processing key[13]\n",
"key[13] detector at: 3\n",
"[0, 28, 5, 12, 9, 8, 21, 30, 2, 20, 2, 0, 4, 3, 18, 9]\n",
"This is the same? > True\n"
]
}
],
"source": [
"import os\n",
"\n",
"N = 5\n",
"mask = (1 << N) - 1\n",
"klen = 16\n",
"\n",
"def ksa(key):\n",
"\t\"\"\"Key-scheduling algorithm for 0ops Cipher 4\"\"\"\n",
"\ts = list(range(1 << N))\n",
"\ti = 0\n",
"\tj = 0\n",
"\twhile 1:\n",
"\t\ti = (i + 1) & mask\n",
"\t\tj = (j + s[i] + key[i%len(key)]) & mask\n",
"\t\ts[i], s[j] = s[j], s[i]\n",
"\t\tif not i:\n",
"\t\t\tbreak\n",
"\treturn s\n",
"\n",
"def prga(s, n):\n",
"\t\"\"\"Pseudo-random generation algorithm for 0ops Cipher 4\"\"\"\n",
"\ti = 0\n",
"\tj = 0\n",
"\tres = bytearray()\n",
"\tfor _ in range(n):\n",
"\t\ti = (i + 1) & mask\n",
"\t\tj = (j + s[i]) & mask\n",
"\t\ts[i], s[j] = s[j], s[i]\n",
"\t\tres.append(s[(s[i]+s[j])&mask])\n",
"\treturn res\n",
"\n",
"\n",
"def gen_stream(modifier):\n",
"\tcurrent_key = [ii^jj for ii,jj in zip(key, modifier)]\n",
"\treturn prga(ksa(current_key), 16)\n",
"\n",
"\n",
"def solve():\n",
"\tcrest_threshold_counter = 0\n",
"\tcount = 512\n",
"\n",
"\tfor new_key in range(32):\n",
"\t\t# attacking key[1] and key[2]\n",
"\t\tstat = {}\n",
"\t\tfor _ in range(count):\n",
"\t\t\tmodifier = list(map(lambda x: x & 31, os.urandom(16)))\n",
"\t\t\tmodifier[1] = new_key\n",
"\t\t\tmodifier[2] = 0 # fix, no to change (thus not to generate \"noise\")\n",
"\t\t\tres = gen_stream(modifier)\n",
"\n",
"\t\t\tif res[0] in stat:\n",
"\t\t\t\tstat[res[0]] += 1\n",
"\t\t\telse:\n",
"\t\t\t\tstat[res[0]] = 1\n",
"\n",
"\t\tsorted_stat = sorted(stat, key=stat.get, reverse=True)\n",
"\t\tcrest = stat[sorted_stat[0]] / float(stat[sorted_stat[1]])\n",
"\t\t#print(\"key[%d]: iter=%d crest=%.4f\" % (1, new_key, crest))\n",
"\n",
"\t\tif crest > 2:\n",
"\t\t\tcrest_threshold_counter += 1;\n",
"\t\t\tkey_1 = new_key\n",
"\t\t\tkey_2 = (sorted_stat[0] - 3) % 32\n",
"\n",
"\tif crest_threshold_counter == 1:\n",
"\t\tprint(\"key[1]=%d, key[2]=%d\" % (key_1, key_2))\n",
"\telse:\n",
"\t\tprint(\"no or more than one detection!\")\n",
"\t\tprint(\"roll the dice again ;)\")\n",
"\n",
"\t# attack from key[3] to key[13]\n",
"\trecovered_key = [key_1, key_2]\n",
"\tprobe_keys = [12, 17, 30, 28, 27, 26, 25, 24, 23, 22, 21, 20, 31, 18, 17]\n",
"\tdetectors = [ 0, 0, 31, 29, 28, 27, 26, 25, 24, 23, 22, 21, 0, 19, 18]\n",
"\n",
"\tfor key_idx in range(3, 13+1):\n",
"\t\tprint(\"processing key[%d]\" % (key_idx))\n",
"\t\tdetection = -1;\n",
"\t\tcrest_min_counter = 0;\n",
"\n",
"\t\tfor new_key in range(32):\n",
"\n",
"\t\t\tstat = {}\n",
"\t\t\tfor i in range(count):\n",
"\t\t\t\tmodifier = list(map(lambda x: x & 31, os.urandom(16)))\n",
"\t\t\t\t# now we have to xor with the already found keys in order to have control\n",
"\t\t\t\tmodifier[1:key_idx] = [i^j for i, j in zip(probe_keys, recovered_key)]\n",
"\t\t\t\tmodifier[key_idx] = new_key\n",
"\t\t\t\tres = gen_stream(modifier)\n",
"\t\t\t\t\n",
"\t\t\t\tif res[1] in stat:\n",
"\t\t\t\t\tstat[res[1]] += 1\n",
"\t\t\t\telse:\n",
"\t\t\t\t\tstat[res[1]] = 1\n",
"\n",
"\t\t\tsorted_stat = sorted(stat, key=stat.get, reverse=True)\n",
"\t\t\tcrest = stat[sorted_stat[0]] / float(stat[sorted_stat[1]])\n",
"\t\t\t#print(\"key[%d]: iter=%d crest=%.4f\" % (key_idx, new_key, crest))\n",
"\n",
"\t\t\tif crest < 5:\n",
"\t\t\t\tcrest_min_counter += 1;\n",
"\t\t\t\tdetection = new_key\n",
"\n",
"\t\tif crest_min_counter == 1:\n",
"\t\t\tprint(\"key[%d] detector at: %d\" % (key_idx, detection))\n",
"\t\t\trecovered_key.append((detection ^ detectors[len(recovered_key)]) % 32)\n",
"\t\t\t#print(\"known xorkey so far:\", recovered_key)\n",
"\t\telse:\n",
"\t\t\tprint(\"No or more than one crest min at key[%d]\" % (key_idx))\n",
"\t\t\tbreak\n",
"\n",
"\t# key[0] és key[14], key[15] local brute force attack\n",
"\t# this is because network traffic thought to be slow\n",
"\tfor key_0 in range(32):\n",
"\t\tfor key_14 in range(32):\n",
"\t\t\tfor key_15 in range(32):\n",
"\t\t\t\tmodifier = [0]*16\n",
"\t\t\t\tmodifier[0] = key_0\n",
"\t\t\t\tmodifier[1:14] = recovered_key\n",
"\t\t\t\tmodifier[14] = key_14\n",
"\t\t\t\tmodifier[15] = key_15\n",
"\t\t\t\tif allzero == gen_stream(modifier):\n",
"\t\t\t\t\tsol = [key_0] + recovered_key + [key_14, key_15]\n",
"\t\t\t\t\treturn sol\n",
"\n",
"\n",
"allzero = prga(ksa([0]*16), 16)\n",
"key = list(map(lambda x: x & 31, os.urandom(16)))\n",
"print(\"secret key to be guessed:\", key)\n",
"guessed_key = solve()\n",
"print(guessed_key)\n",
"print(\"This is the same? >\",guessed_key == key)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notes:\n",
"- the current implementation uses 512 probes per index per values, so altogether less than 200000 message used (~100000 on average)\n",
"- the _high probability_ expression here only refers to an experimentally guessed metric, further analysis should be performed on the topic!\n",
"- at the challenge we faced other infrastuctural issues, such as the key at the server doen't remained the original secret key, instead it saved the previous XOR-ed form (thanks to @ngg for his kind help)\n",
"- for the server multiple key had to be collected; maximal batch size was 512 (also thanks to @ngg)"
]
}
],
"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.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment