{ "cells": [ { "cell_type": "markdown", "id": "afc512ca", "metadata": {}, "source": [ "## Speck Simulation" ] }, { "cell_type": "code", "execution_count": 53, "id": "efb373e4", "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as pyplot\n", "import numpy as np\n", "from scipy.stats import pearsonr\n", "import random\n", "from operator import xor\n", "\n", "# Fast implementation of the Hamming weight for 64 bit values\n", "# See book: A Hacker's delight\n", "# not sure if the hamming weight model w0rks for Speck\n", "def popcount(x):\n", " x -= (x >> 1) & 0x5555555555555555\n", " x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333)\n", " x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f\n", " return ((x * 0x0101010101010101) & 0xffffffffffffffff ) >> 56\n" ] }, { "cell_type": "code", "execution_count": 55, "id": "7654d5a2", "metadata": {}, "outputs": [], "source": [ "import math\n", "\n", "NUM_ROUNDS = 22\n", "BLOCK_SIZE = 32\n", "KEY_SIZE = 64\n", "WORD_SIZE = 16\n", "\n", "\n", "# SHIFTs for SPECK\n", "ALPHA = 7\n", "BETA = 2\n", "\n", "mod_mask = (2 ** WORD_SIZE) -1\n", "mod_mask_sub = (2 ** WORD_SIZE)" ] }, { "cell_type": "markdown", "id": "49463c5b", "metadata": {}, "source": [ "## Speck Implementation\n", "\n", "First of all, a very simplified Speck implementation to support Speck 23/64 with 22 rounds and ALPHA = 7 and BETA = 3\n", "\n", "1) Key = bytesToWords16(key)\n", "\n", "2) scheduled_key = key_schedule(Key)\n", "\n", "3) ciphertext = encrypt(plaintext, scheduled_key)\n", "\n", "\n", "-> The encrypt funktion is currently `missing` ... only `simple_speck()`" ] }, { "cell_type": "code", "execution_count": 66, "id": "5c3ade39", "metadata": {}, "outputs": [], "source": [ "'''\n", " Converts a bytestring `0xdeadbeef` to a array of 16-byte integers (len: 4)\n", "'''\n", "def bytesToWords16(b): \n", " return [(b >> (x * WORD_SIZE)) & mod_mask for x in\n", " range(0, math.ceil(KEY_SIZE // WORD_SIZE))]\n", " " ] }, { "cell_type": "code", "execution_count": 68, "id": "953621aa", "metadata": {}, "outputs": [], "source": [ "'''\n", " The 16bit Speck roundfunction, this is where the magic happens\n", "'''\n", "def ER16(x, y, k):\n", "\n", " rs_x = ((x << (16 - ALPHA)) + (x >> ALPHA)) & mod_mask\n", "\n", " add_sxy = (rs_x + y) & mod_mask\n", "\n", " new_x = k ^ add_sxy\n", "\n", " ls_y = ((y >> (16 - BETA)) + (y << BETA)) & mod_mask\n", "\n", " new_y = new_x ^ ls_y\n", "\n", " return new_x, new_y\n" ] }, { "cell_type": "markdown", "id": "4b7a7d5d", "metadata": {}, "source": [ "## Running the key schedule" ] }, { "cell_type": "code", "execution_count": 70, "id": "15e86ae3", "metadata": {}, "outputs": [], "source": [ "key = 0x0102030405060708" ] }, { "cell_type": "code", "execution_count": 71, "id": "dcc0e245", "metadata": {}, "outputs": [], "source": [ "Key = bytesToWords16(key)" ] }, { "cell_type": "code", "execution_count": 72, "id": "93e4fb4a", "metadata": {}, "outputs": [], "source": [ "'''\n", "\n", "The 16 bit python key schedule\n", "\n", "void Speck128256KeySchedule(u64 K[],u64 rk[])\n", "{\n", " u64 i,D=K[3],C=K[2],B=K[1],A=K[0];\n", " for(i=0;i<33;){\n", " rk[i]=A; ER64(B,A,i++);\n", " rk[i]=A; ER64(C,A,i++);\n", " rk[i]=A; ER64(D,A,i++);\n", " }\n", " rk[i]=A;\n", "}\n", "'''\n", "def key_schedule(k):\n", "\n", " D=k[3]\n", " C=k[2]\n", " B=k[1]\n", " A=k[0]\n", " out = []\n", " i = 0\n", " while i < 21:\n", " out.append(A)\n", " B, A = ER16(B, A, i)\n", " i += 1\n", " out.append(A)\n", " C, A = ER16(C, A, i)\n", " i+= 1\n", " out.append(A)\n", " D, A = ER16(D, A, i)\n", " i+= 1\n", " out.append(A)\n", " return out\n", " " ] }, { "cell_type": "code", "execution_count": 73, "id": "0061be29", "metadata": {}, "outputs": [], "source": [ "'''\n", "Simple encryption for speck (only the encryption part, without key scheduling)\n", "\n", "void Speck128256Encrypt(u64 Pt[],u64 Ct[],u64 rk[])\n", "{\n", " u64 i;\n", " Ct[0]=Pt[0]; Ct[1]=Pt[1];\n", " for(i=0;i<34;) ER64(Ct[1],Ct[0],rk[i++]);\n", "}\n", "\n", "\n", "'''\n", "def simple_speck(plaintext, key):\n", " Ct_0 = plaintext[0]\n", " Ct_1 = plaintext[1]\n", " \n", " for i in range(34):\n", " Ct_1, Ct_0 = ER16(Ct_1, Ct_0, key) # fixed 16 bit key of 0x55\n", " return (Ct_1 << WORD_SIZE) + Ct_0" ] }, { "cell_type": "markdown", "id": "e25af6e8", "metadata": {}, "source": [ "## Running tests to verify the output is still fine" ] }, { "cell_type": "code", "execution_count": 74, "id": "1dd758a0", "metadata": {}, "outputs": [], "source": [ "assert key_schedule(Key) == [0x708,0xf32, 0x2bf1,0x8035,0xa48e,0x8482, 0x74ee, 0xf589, 0xb396, 0xb231, 0xdab2, 0x57bc, 0x704e,0x9947,0xe2d2, 0xea6a, 0x4ebe, 0xdd24, 0x6b64, 0x3ab1, 0x1c57, 0x7bde]" ] }, { "cell_type": "code", "execution_count": 75, "id": "1553c623", "metadata": {}, "outputs": [], "source": [ "ciphertext = simple_speck([0xdead, 0xbeef], 0x55)" ] }, { "cell_type": "code", "execution_count": 77, "id": "5b1da8b8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0x6c1a1f2f\n" ] } ], "source": [ "# over simplified Speck encryption (no key schedule)\n", "print(hex(ciphertext))" ] }, { "cell_type": "markdown", "id": "771dc7cc", "metadata": {}, "source": [ "# Simulation" ] }, { "cell_type": "markdown", "id": "2d56be14", "metadata": {}, "source": [ "The following code simulates the Speck encryption process for an randomly choosen plaintext and the choosen key: **0x69**." ] }, { "cell_type": "markdown", "id": "1a786e80", "metadata": {}, "source": [ "It correlates 1000 encryptions for random plaintext and correlates them for execution with every possible keybyte" ] }, { "cell_type": "code", "execution_count": 84, "id": "2f090c78", "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "<Figure size 432x288 with 1 Axes>" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Correct 8-bit key is: 0x69\n" ] } ], "source": [ "num_traces = 1000\n", "\n", "key_space = 256\n", "\n", "\n", "traces = np.empty(num_traces)\n", "hw_traces = np.empty((key_space, num_traces))\n", "\n", "for i in range(0,num_traces):\n", " plaintext = [(i**2) % 0xFFFF, i % 0xFFFF]\n", " traces[i] = popcount(simple_speck(plaintext, 0x69))\n", " for key in range(0, key_space):\n", " hw_traces[key][i] = simple_speck(plaintext, key)\n", " \n", "corr = np.empty(key_space)\n", " \n", "#compute pearson correlation for each key\n", "for key in range(0, key_space):\n", " corr[key],p = pearsonr(hw_traces[key], traces)\n", "\n", "pyplot.plot(corr)\n", "pyplot.show()\n", "\n", "print(\"Correct 8-bit key is: \" + hex(np.argmax(corr)))" ] }, { "cell_type": "code", "execution_count": null, "id": "3d7a82e9", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "973fb6fa", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "3de74cba", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "3fdeaf59", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "440f34b1", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "97350aef", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "73f3d3bb", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "383e2448", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.7" } }, "nbformat": 4, "nbformat_minor": 5 }