diff --git a/src/ntt_top/tb/ntt_ref.ipynb b/src/ntt_top/tb/ntt_ref.ipynb deleted file mode 100644 index aa3b769..0000000 --- a/src/ntt_top/tb/ntt_ref.ipynb +++ /dev/null @@ -1,1083 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# NTT Reference Implementation" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import copy\n", - "import random" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Dilithium Parameter" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "DILITHIUM_Q = 8380417 # 2**23 - 2**13 + 1\n", - "DILITHIUM_N = 256\n", - "DILITHIUM_LOGN = 8\n", - "DILITHIUM_ROOT_OF_UNITY = 1753" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Butterfly" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "def ct_bf(u, v, z):\n", - " global DILITHIUM_Q\n", - " t = (v * z) % DILITHIUM_Q\n", - " v = (u - t) % DILITHIUM_Q\n", - " u = (u + t) % DILITHIUM_Q\n", - " return u, v\n", - "\n", - "def gs_bf(u, v, z):\n", - " global DILITHIUM_Q\n", - " t = (u - v) % DILITHIUM_Q\n", - " u = (u + v) % DILITHIUM_Q\n", - " v = (t * z) % DILITHIUM_Q\n", - " return u, v\n", - "\n", - "def gs_bf_div2(u, v, z):\n", - " global DILITHIUM_Q\n", - " t = div2((u - v) % DILITHIUM_Q)\n", - " u = div2((u + v) % DILITHIUM_Q)\n", - " v = (t * z) % DILITHIUM_Q\n", - " return u, v\n", - "\n", - "def div2(x):\n", - " global DILITHIUM_Q\n", - " if x & 1:\n", - " return (x >> 1) + ((DILITHIUM_Q + 1) // 2)\n", - " else:\n", - " return x >> 1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Twiddle factor" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "def bit_reversal(x): \n", - " binary_string = format(x, '08b') \n", - " reversed_binary_string = binary_string[::-1] \n", - " reversed_decimal = int(reversed_binary_string, 2)\n", - " return reversed_decimal\n", - " \n", - "def zeta_generator():\n", - " global DILITHIUM_Q\n", - " global DILITHIUM_N\n", - " global DILITHIUM_ROOT_OF_UNITY\n", - " \n", - " tree=np.zeros(DILITHIUM_N)\n", - " for i in range (DILITHIUM_N):\n", - " tree[i] = bit_reversal(i)\n", - "\n", - " tmp={}\n", - " tmp[0] = 1\n", - "\n", - " zetas={}\n", - " zetas_inv={}\n", - "\n", - " for i in range (1, DILITHIUM_N, 1):\n", - " tmp[i] = (tmp[i-1] * DILITHIUM_ROOT_OF_UNITY) % DILITHIUM_Q\n", - "\n", - " for i in range (0, DILITHIUM_N, 1):\n", - " zetas[i] = tmp[tree[i]]\n", - " zetas[i] = zetas[i]\n", - " zetas_inv[i] = -zetas[i] % DILITHIUM_Q\n", - "\n", - " return zetas, zetas_inv\n", - "\n", - "\n", - "zetas, zetas_inv = zeta_generator()" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "zeta=\n", - "000001\n", - "495E02\n", - "397567\n", - "396569\n", - "4F062B\n", - "53DF73\n", - "4FE033\n", - "4F066B\n", - "76B1AE\n", - "360DD5\n", - "28EDB0\n", - "207FE4\n", - "397283\n", - "70894A\n", - "088192\n", - "6D3DC8\n", - "4C7294\n", - "41E0B4\n", - "28A3D2\n", - "66528A\n", - "4A18A7\n", - "794034\n", - "0A52EE\n", - "6B7D81\n", - "4E9F1D\n", - "1A2877\n", - "2571DF\n", - "1649EE\n", - "7611BD\n", - "492BB7\n", - "2AF697\n", - "22D8D5\n", - "36F72A\n", - "30911E\n", - "29D13F\n", - "492673\n", - "50685F\n", - "2010A2\n", - "3887F7\n", - "11B2C3\n", - "0603A4\n", - "0E2BED\n", - "10B72C\n", - "4A5F35\n", - "1F9D15\n", - "428CD4\n", - "3177F4\n", - "20E612\n", - "341C1D\n", - "1AD873\n", - "736681\n", - "49553F\n", - "3952F6\n", - "62564A\n", - "65AD05\n", - "439A1C\n", - "53AA5F\n", - "30B622\n", - "087F38\n", - "3B0E6D\n", - "2C83DA\n", - "1C496E\n", - "330E2B\n", - "1C5B70\n", - "2EE3F1\n", - "137EB9\n", - "57A930\n", - "3AC6EF\n", - "3FD54C\n", - "4EB2EA\n", - "503EE1\n", - "7BB175\n", - "2648B4\n", - "1EF256\n", - "1D90A2\n", - "45A6D4\n", - "2AE59B\n", - "52589C\n", - "6EF1F5\n", - "3F7288\n", - "175102\n", - "075D59\n", - "1187BA\n", - "52ACA9\n", - "773E9E\n", - "0296D8\n", - "2592EC\n", - "4CFF12\n", - "404CE8\n", - "4AA582\n", - "1E54E6\n", - "4F16C1\n", - "1A7E79\n", - "03978F\n", - "4E4817\n", - "31B859\n", - "5884CC\n", - "1B4827\n", - "5B63D0\n", - "5D787A\n", - "35225E\n", - "400C7E\n", - "6C09D1\n", - "5BD532\n", - "6BC4D3\n", - "258ECB\n", - "2E534C\n", - "097A6C\n", - "3B8820\n", - "6D285C\n", - "2CA4F8\n", - "337CAA\n", - "14B2A0\n", - "558536\n", - "28F186\n", - "55795D\n", - "4AF670\n", - "234A86\n", - "75E826\n", - "78DE66\n", - "05528C\n", - "7ADF59\n", - "0F6E17\n", - "5BF3DA\n", - "459B7E\n", - "628B34\n", - "5DBECB\n", - "1A9E7B\n", - "0006D9\n", - "6257C5\n", - "574B3C\n", - "69A8EF\n", - "289838\n", - "64B5FE\n", - "7EF8F5\n", - "2A4E78\n", - "120A23\n", - "0154A8\n", - "09B7FF\n", - "435E87\n", - "437FF8\n", - "5CD5B4\n", - "4DC04E\n", - "4728AF\n", - "7F735D\n", - "0C8D0D\n", - "0F66D5\n", - "5A6D80\n", - "61AB98\n", - "185D96\n", - "437F31\n", - "468298\n", - "662960\n", - "4BD579\n", - "28DE06\n", - "465D8D\n", - "49B0E3\n", - "09B434\n", - "7C0DB3\n", - "5A68B0\n", - "409BA9\n", - "64D3D5\n", - "21762A\n", - "658591\n", - "246E39\n", - "48C39B\n", - "7BC759\n", - "4F5859\n", - "392DB2\n", - "230923\n", - "12EB67\n", - "454DF2\n", - "30C31C\n", - "285424\n", - "13232E\n", - "7FAF80\n", - "2DBFCB\n", - "022A0B\n", - "7E832C\n", - "26587A\n", - "6B3375\n", - "095B76\n", - "6BE1CC\n", - "5E061E\n", - "78E00D\n", - "628C37\n", - "3DA604\n", - "4AE53C\n", - "1F1D68\n", - "6330BB\n", - "7361B8\n", - "5EA06C\n", - "671AC7\n", - "201FC6\n", - "5BA4FF\n", - "60D772\n", - "08F201\n", - "6DE024\n", - "080E6D\n", - "56038E\n", - "695688\n", - "1E6D3E\n", - "2603BD\n", - "6A9DFA\n", - "07C017\n", - "6DBFD4\n", - "74D0BD\n", - "63E1E3\n", - "519573\n", - "7AB60D\n", - "2867BA\n", - "2DECD4\n", - "58018C\n", - "3F4CF5\n", - "0B7009\n", - "427E23\n", - "3CBD37\n", - "273333\n", - "673957\n", - "1A4B5D\n", - "196926\n", - "1EF206\n", - "11C14E\n", - "4C76C8\n", - "3CF42F\n", - "7FB19A\n", - "6AF66C\n", - "2E1669\n", - "3352D6\n", - "034760\n", - "085260\n", - "741E78\n", - "2F6316\n", - "6F0A11\n", - "07C0F1\n", - "776D0B\n", - "0D1FF0\n", - "345824\n", - "0223D4\n", - "68C559\n", - "5E8885\n", - "2FAA32\n", - "23FC65\n", - "5E6942\n", - "51E0ED\n", - "65ADB3\n", - "2CA5E6\n", - "79E1FE\n", - "7B4064\n", - "35E1DD\n", - "433AAC\n", - "464ADE\n", - "1CFE14\n", - "73F1CE\n", - "10170E\n", - "74B6D7\n" - ] - } - ], - "source": [ - "## print zeta values for NTT\n", - "print(\"zeta=\")\n", - "for i in range (DILITHIUM_N):\n", - " print(hex(zetas[i])[2:].upper().zfill(6))" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "zetas_inv=\n", - "7FE000\n", - "3681FF\n", - "466A9A\n", - "467A98\n", - "30D9D6\n", - "2C008E\n", - "2FFFCE\n", - "30D996\n", - "092E53\n", - "49D22C\n", - "56F251\n", - "5F601D\n", - "466D7E\n", - "0F56B7\n", - "775E6F\n", - "12A239\n", - "336D6D\n", - "3DFF4D\n", - "573C2F\n", - "198D77\n", - "35C75A\n", - "069FCD\n", - "758D13\n", - "146280\n", - "3140E4\n", - "65B78A\n", - "5A6E22\n", - "699613\n", - "09CE44\n", - "36B44A\n", - "54E96A\n", - "5D072C\n", - "48E8D7\n", - "4F4EE3\n", - "560EC2\n", - "36B98E\n", - "2F77A2\n", - "5FCF5F\n", - "47580A\n", - "6E2D3E\n", - "79DC5D\n", - "71B414\n", - "6F28D5\n", - "3580CC\n", - "6042EC\n", - "3D532D\n", - "4E680D\n", - "5EF9EF\n", - "4BC3E4\n", - "65078E\n", - "0C7980\n", - "368AC2\n", - "468D0B\n", - "1D89B7\n", - "1A32FC\n", - "3C45E5\n", - "2C35A2\n", - "4F29DF\n", - "7760C9\n", - "44D194\n", - "535C27\n", - "639693\n", - "4CD1D6\n", - "638491\n", - "50FC10\n", - "6C6148\n", - "2836D1\n", - "451912\n", - "400AB5\n", - "312D17\n", - "2FA120\n", - "042E8C\n", - "59974D\n", - "60EDAB\n", - "624F5F\n", - "3A392D\n", - "54FA66\n", - "2D8765\n", - "10EE0C\n", - "406D79\n", - "688EFF\n", - "7882A8\n", - "6E5847\n", - "2D3358\n", - "08A163\n", - "7D4929\n", - "5A4D15\n", - "32E0EF\n", - "3F9319\n", - "353A7F\n", - "618B1B\n", - "30C940\n", - "656188\n", - "7C4872\n", - "3197EA\n", - "4E27A8\n", - "275B35\n", - "6497DA\n", - "247C31\n", - "226787\n", - "4ABDA3\n", - "3FD383\n", - "13D630\n", - "240ACF\n", - "141B2E\n", - "5A5136\n", - "518CB5\n", - "766595\n", - "4457E1\n", - "12B7A5\n", - "533B09\n", - "4C6357\n", - "6B2D61\n", - "2A5ACB\n", - "56EE7B\n", - "2A66A4\n", - "34E991\n", - "5C957B\n", - "09F7DB\n", - "07019B\n", - "7A8D75\n", - "0500A8\n", - "7071EA\n", - "23EC27\n", - "3A4483\n", - "1D54CD\n", - "222136\n", - "654186\n", - "7FD928\n", - "1D883C\n", - "2894C5\n", - "163712\n", - "5747C9\n", - "1B2A03\n", - "00E70C\n", - "559189\n", - "6DD5DE\n", - "7E8B59\n", - "762802\n", - "3C817A\n", - "3C6009\n", - "230A4D\n", - "321FB3\n", - "38B752\n", - "006CA4\n", - "7352F4\n", - "70792C\n", - "257281\n", - "1E3469\n", - "67826B\n", - "3C60D0\n", - "395D69\n", - "19B6A1\n", - "340A88\n", - "5701FB\n", - "398274\n", - "362F1E\n", - "762BCD\n", - "03D24E\n", - "257751\n", - "3F4458\n", - "1B0C2C\n", - "5E69D7\n", - "1A5A70\n", - "5B71C8\n", - "371C66\n", - "0418A8\n", - "3087A8\n", - "46B24F\n", - "5CD6DE\n", - "6CF49A\n", - "3A920F\n", - "4F1CE5\n", - "578BDD\n", - "6CBCD3\n", - "003081\n", - "522036\n", - "7DB5F6\n", - "015CD5\n", - "598787\n", - "14AC8C\n", - "76848B\n", - "13FE35\n", - "21D9E3\n", - "06FFF4\n", - "1D53CA\n", - "4239FD\n", - "34FAC5\n", - "60C299\n", - "1CAF46\n", - "0C7E49\n", - "213F95\n", - "18C53A\n", - "5FC03B\n", - "243B02\n", - "1F088F\n", - "76EE00\n", - "11FFDD\n", - "77D194\n", - "29DC73\n", - "168979\n", - "6172C3\n", - "59DC44\n", - "154207\n", - "781FEA\n", - "12202D\n", - "0B0F44\n", - "1BFE1E\n", - "2E4A8E\n", - "0529F4\n", - "577847\n", - "51F32D\n", - "27DE75\n", - "40930C\n", - "746FF8\n", - "3D61DE\n", - "4322CA\n", - "58ACCE\n", - "18A6AA\n", - "6594A4\n", - "6676DB\n", - "60EDFB\n", - "6E1EB3\n", - "336939\n", - "42EBD2\n", - "002E67\n", - "14E995\n", - "51C998\n", - "4C8D2B\n", - "7C98A1\n", - "778DA1\n", - "0BC189\n", - "507CEB\n", - "10D5F0\n", - "781F10\n", - "0872F6\n", - "72C011\n", - "4B87DD\n", - "7DBC2D\n", - "171AA8\n", - "21577C\n", - "5035CF\n", - "5BE39C\n", - "2176BF\n", - "2DFF14\n", - "1A324E\n", - "533A1B\n", - "05FE03\n", - "049F9D\n", - "49FE24\n", - "3CA555\n", - "399523\n", - "62E1ED\n", - "0BEE33\n", - "6FC8F3\n", - "0B292A\n" - ] - } - ], - "source": [ - "## print zeta_inv values for INTT\n", - "print(\"zetas_inv=\")\n", - "for i in range (DILITHIUM_N):\n", - " print(hex(zetas_inv[i])[2:].upper().zfill(6))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### ref NTTT/INTT model" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "def fwd_NTT(poly_r):\n", - " global DILITHIUM_Q\n", - " global DILITHIUM_N\n", - " global zetas\n", - "\n", - " r = copy.deepcopy(poly_r)\n", - " \n", - " k = 0\n", - " m = 128\n", - " while (m > 0):\n", - " start = 0\n", - " while (start < DILITHIUM_N):\n", - " k += 1\n", - " zeta = zetas[k]\n", - " for j in range(start, start+m):\n", - " r[j], r[j + m] = ct_bf(r[j], r[j + m], zeta)\n", - " start = start + 2 * m\n", - " m >>= 1\n", - "\n", - " return r\n", - "\n", - "def inv_NTT(poly_r):\n", - " global DILITHIUM_Q\n", - " global DILITHIUM_N\n", - " global zetas_inv\n", - "\n", - " r = copy.deepcopy(poly_r)\n", - " \n", - " k = DILITHIUM_N\n", - " m = 1\n", - " while (m < DILITHIUM_N):\n", - " start = 0\n", - " while (start < DILITHIUM_N):\n", - " k -= 1\n", - " zeta = zetas_inv[k]\n", - " for j in range(start, start+m):\n", - " r[j], r[j + m] = gs_bf(r[j], r[j + m], zeta)\n", - " start = start + 2 * m\n", - " m <<= 1\n", - " \n", - " f = 8347681 # 256^-1 mod DILITHIUM_Q\n", - " for j in range(DILITHIUM_N):\n", - " r[j] = f*r[j] % DILITHIUM_Q\n", - "\n", - " return r" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### 2x2 NTT/INTT model" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "def fwd_NTT2x2(poly_r):\n", - " global DILITHIUM_Q\n", - " global DILITHIUM_N\n", - " global DILITHIUM_LOGN\n", - " global zetas\n", - "\n", - " r = copy.deepcopy(poly_r)\n", - "\n", - " k2={}\n", - " zeta2={}\n", - "\n", - " for l in range(DILITHIUM_LOGN, 0, -2):\n", - " m = 1 << (l - 2)\n", - " for i in range(0, DILITHIUM_N, 1 << l):\n", - " k1 = (DILITHIUM_N + i) >> l\n", - " k2[0] = (DILITHIUM_N + i) >> (l - 1)\n", - " k2[1] = k2[0] + 1\n", - " zeta1 = zetas[k1]\n", - " zeta2[0] = zetas[k2[0]]\n", - " zeta2[1] = zetas[k2[1]]\n", - "\n", - " for j in range(i, i + m):\n", - " u00 = r[j]\n", - " u01 = r[j + m]\n", - " v00 = r[j + 2 * m]\n", - " v01 = r[j + 3 * m]\n", - "\n", - " u10, u11 = ct_bf(u00, v00, zeta1)\n", - " v10, v11 = ct_bf(u01, v01, zeta1)\n", - "\n", - " u20, v20 = ct_bf(u10, v10, zeta2[0])\n", - " u21, v21 = ct_bf(u11, v11, zeta2[1])\n", - "\n", - " r[j] = u20\n", - " r[j + m] = v20\n", - " r[j + 2 * m] = u21\n", - " r[j + 3 * m] = v21\n", - "\n", - " return r\n", - "\n", - "def inv_NTT2x2(poly_r):\n", - " global DILITHIUM_Q\n", - " global DILITHIUM_N\n", - " global DILITHIUM_LOGN\n", - " global zetas_inv\n", - "\n", - " r = copy.deepcopy(poly_r)\n", - " \n", - " k1={}\n", - " zeta1={}\n", - "\n", - " for l in range(0, DILITHIUM_LOGN - (DILITHIUM_LOGN & 1), 2):\n", - " m = 1 << l\n", - " for i in range(0, DILITHIUM_N, 1 << (l + 2)):\n", - " k1[0] = ((DILITHIUM_N - (i >> 1)) >> l) - 1\n", - " k1[1] = k1[0] - 1\n", - " k2 = ((DILITHIUM_N - (i >> 1)) >> (l + 1)) - 1\n", - " zeta1[0] = zetas_inv[k1[0]]\n", - " zeta1[1] = zetas_inv[k1[1]]\n", - " zeta2 = zetas_inv[k2]\n", - "\n", - " for j in range(i, i + m):\n", - " u00 = r[j]\n", - " v00 = r[j + m]\n", - " u01 = r[j + 2 * m]\n", - " v01 = r[j + 3 * m]\n", - "\n", - " u10, u11 = gs_bf(u00, v00, zeta1[0])\n", - " v10, v11 = gs_bf(u01, v01, zeta1[1])\n", - "\n", - " u20, u21 = gs_bf(u10, v10, zeta2)\n", - " v20, v21 = gs_bf(u11, v11, zeta2)\n", - "\n", - " r[j] = u20\n", - " r[j + m] = v20\n", - " r[j + 2 * m] = u21\n", - " r[j + 3 * m] = v21\n", - " \n", - " f = 8347681 # 256^-1 mod DILITHIUM_Q\n", - " for j in range(DILITHIUM_N):\n", - " r[j] = f*r[j] % DILITHIUM_Q\n", - "\n", - " return r\n", - "\n", - "\n", - "def inv_NTT2x2_div2(poly_r):\n", - " global DILITHIUM_Q\n", - " global DILITHIUM_N\n", - " global DILITHIUM_LOGN\n", - " global zetas_inv\n", - "\n", - " r = copy.deepcopy(poly_r)\n", - " \n", - " k1={}\n", - " zeta1={}\n", - "\n", - " for l in range(0, DILITHIUM_LOGN - (DILITHIUM_LOGN & 1), 2):\n", - " m = 1 << l\n", - " for i in range(0, DILITHIUM_N, 1 << (l + 2)):\n", - " k1[0] = ((DILITHIUM_N - (i >> 1)) >> l) - 1\n", - " k1[1] = k1[0] - 1\n", - " k2 = ((DILITHIUM_N - (i >> 1)) >> (l + 1)) - 1\n", - " zeta1[0] = zetas_inv[k1[0]]\n", - " zeta1[1] = zetas_inv[k1[1]]\n", - " zeta2 = zetas_inv[k2]\n", - "\n", - " for j in range(i, i + m):\n", - " u00 = r[j]\n", - " v00 = r[j + m]\n", - " u01 = r[j + 2 * m]\n", - " v01 = r[j + 3 * m]\n", - "\n", - " u10, u11 = gs_bf_div2(u00, v00, zeta1[0])\n", - " v10, v11 = gs_bf_div2(u01, v01, zeta1[1])\n", - "\n", - " u20, u21 = gs_bf_div2(u10, v10, zeta2)\n", - " v20, v21 = gs_bf_div2(u11, v11, zeta2) \n", - "\n", - " r[j] = u20\n", - " r[j + m] = v20\n", - " r[j + 2 * m] = u21\n", - " r[j + 3 * m] = v21\n", - "\n", - " return r\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Test" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "r_init=\n", - "000000 000001 000002 000003 000004 000005 000006 000007 000008 000009 00000A 00000B 00000C 00000D 00000E 00000F\n", - "000010 000011 000012 000013 000014 000015 000016 000017 000018 000019 00001A 00001B 00001C 00001D 00001E 00001F\n", - "000020 000021 000022 000023 000024 000025 000026 000027 000028 000029 00002A 00002B 00002C 00002D 00002E 00002F\n", - "000030 000031 000032 000033 000034 000035 000036 000037 000038 000039 00003A 00003B 00003C 00003D 00003E 00003F\n", - "000040 000041 000042 000043 000044 000045 000046 000047 000048 000049 00004A 00004B 00004C 00004D 00004E 00004F\n", - "000050 000051 000052 000053 000054 000055 000056 000057 000058 000059 00005A 00005B 00005C 00005D 00005E 00005F\n", - "000060 000061 000062 000063 000064 000065 000066 000067 000068 000069 00006A 00006B 00006C 00006D 00006E 00006F\n", - "000070 000071 000072 000073 000074 000075 000076 000077 000078 000079 00007A 00007B 00007C 00007D 00007E 00007F\n", - "000080 000081 000082 000083 000084 000085 000086 000087 000088 000089 00008A 00008B 00008C 00008D 00008E 00008F\n", - "000090 000091 000092 000093 000094 000095 000096 000097 000098 000099 00009A 00009B 00009C 00009D 00009E 00009F\n", - "0000A0 0000A1 0000A2 0000A3 0000A4 0000A5 0000A6 0000A7 0000A8 0000A9 0000AA 0000AB 0000AC 0000AD 0000AE 0000AF\n", - "0000B0 0000B1 0000B2 0000B3 0000B4 0000B5 0000B6 0000B7 0000B8 0000B9 0000BA 0000BB 0000BC 0000BD 0000BE 0000BF\n", - "0000C0 0000C1 0000C2 0000C3 0000C4 0000C5 0000C6 0000C7 0000C8 0000C9 0000CA 0000CB 0000CC 0000CD 0000CE 0000CF\n", - "0000D0 0000D1 0000D2 0000D3 0000D4 0000D5 0000D6 0000D7 0000D8 0000D9 0000DA 0000DB 0000DC 0000DD 0000DE 0000DF\n", - "0000E0 0000E1 0000E2 0000E3 0000E4 0000E5 0000E6 0000E7 0000E8 0000E9 0000EA 0000EB 0000EC 0000ED 0000EE 0000EF\n", - "0000F0 0000F1 0000F2 0000F3 0000F4 0000F5 0000F6 0000F7 0000F8 0000F9 0000FA 0000FB 0000FC 0000FD 0000FE 0000FF\n", - "r_in_ntt=\n", - "7A6F0F 4B87B6 53FAD1 6E487E 3E366C 0DC925 22E609 33B7D3 161800 3BB163 3A7D40 5167F1 798D85 7BE2CD 6D05F1 71D5C8\n", - "7D20D5 563B37 591F39 0007F9 7F1751 230AA3 745664 7668D4 6411D6 25956B 090920 73E8AD 077BDA 45BD32 082A51 5A1D2E\n", - "22A083 006470 00FEFF 5C6898 06ADDF 52F9B1 00B099 375E7E 5A8498 4AA574 4323F8 3217A7 5521CC 1F216B 7C0B11 3CAACF\n", - "0D86E3 507ED5 1A2CAF 24F561 07AF66 262700 3507A4 2081AB 750FC7 759906 5E75E7 1CA4D7 1CAFDE 6FFEA9 4F395B 710C09\n", - "3DBEAA 640591 0D2580 4FFBC6 332561 799341 7DBDB8 2C631B 10714B 6BDB72 103A98 1FC55D 12B912 4ACB2A 5DCF66 44EA6E\n", - "76C946 4AE7D7 25FE60 7AEC39 1B938A 2FEE9A 403DC9 258CA7 61BADD 5C6684 0AADCE 7C4656 028FF5 2AF50D 50FFAA 7708B7\n", - "6F69E6 2B386A 5EFAE0 4099BE 3CCC42 6A58E0 6D9C8E 5D9521 2ED821 726F22 54D49C 6F896E 527A97 4D5A11 32A984 2567E6\n", - "2E6FAB 2ED9F7 3C875E 5F4848 1FCC1F 215B4A 78CE31 5775BA 7F84F5 4941F4 348EC3 624EF9 2FF2AE 446813 3E07EA 1E508F\n", - "7FAF9B 466DED 0234B0 3FC05F 29A45C 6C9E33 12AFC2 2D7750 28E288 27FB88 31B252 714EEB 449A18 60DFC5 69631A 45C1B1\n", - "52E3C3 436464 326A7C 551945 306DD9 5C82B8 7D454D 1219F4 2EF327 77A4CB 2BDD97 1EB9B0 4A962E 5495C5 5DD53D 6B6379\n", - "294220 02447B 11FB28 53D4CA 2BD05A 2489EF 450AE0 098DE6 7C2CDC 1ED54D 2CB813 69F333 32512C 327F03 796D2B 353F2B\n", - "10CF59 21917E 28B5DB 04C06F 466EF3 04185C 780E4C 11C6E2 5F5013 7920C2 346E64 4DDB16 134BEE 5BDF95 326884 01966E\n", - "03D910 620E1D 3D0359 0E052B 4156B9 29E983 1399F9 563C06 6ACB1B 1BBC12 080FFC 268AD9 4D7F52 7A1CF2 20337B 1F5332\n", - "025EA9 38BD4E 582340 695D08 53E808 6EB386 5C451A 611040 0DF7F2 0154BC 138EA8 37A7A5 7F9F93 34AAD9 5EBE1D 1B1BEF\n", - "1139AB 69834D 3F5E93 0F8A3F 6040E6 0EFF89 366052 1395C9 18B194 1219AD 0032D0 0B96FA 61FB37 50C2AA 259148 70BA7B\n", - "6F0655 147FB7 13DAE5 0EEC29 3B921F 02F5C2 4EEE32 15D02E 2502C0 010B93 39A2F1 6BADBE 64073F 0EFBCB 7B36B9 32089B\n", - "r_in_ntt2x2=\n", - "7A6F0F 4B87B6 53FAD1 6E487E 3E366C 0DC925 22E609 33B7D3 161800 3BB163 3A7D40 5167F1 798D85 7BE2CD 6D05F1 71D5C8\n", - "7D20D5 563B37 591F39 0007F9 7F1751 230AA3 745664 7668D4 6411D6 25956B 090920 73E8AD 077BDA 45BD32 082A51 5A1D2E\n", - "22A083 006470 00FEFF 5C6898 06ADDF 52F9B1 00B099 375E7E 5A8498 4AA574 4323F8 3217A7 5521CC 1F216B 7C0B11 3CAACF\n", - "0D86E3 507ED5 1A2CAF 24F561 07AF66 262700 3507A4 2081AB 750FC7 759906 5E75E7 1CA4D7 1CAFDE 6FFEA9 4F395B 710C09\n", - "3DBEAA 640591 0D2580 4FFBC6 332561 799341 7DBDB8 2C631B 10714B 6BDB72 103A98 1FC55D 12B912 4ACB2A 5DCF66 44EA6E\n", - "76C946 4AE7D7 25FE60 7AEC39 1B938A 2FEE9A 403DC9 258CA7 61BADD 5C6684 0AADCE 7C4656 028FF5 2AF50D 50FFAA 7708B7\n", - "6F69E6 2B386A 5EFAE0 4099BE 3CCC42 6A58E0 6D9C8E 5D9521 2ED821 726F22 54D49C 6F896E 527A97 4D5A11 32A984 2567E6\n", - "2E6FAB 2ED9F7 3C875E 5F4848 1FCC1F 215B4A 78CE31 5775BA 7F84F5 4941F4 348EC3 624EF9 2FF2AE 446813 3E07EA 1E508F\n", - "7FAF9B 466DED 0234B0 3FC05F 29A45C 6C9E33 12AFC2 2D7750 28E288 27FB88 31B252 714EEB 449A18 60DFC5 69631A 45C1B1\n", - "52E3C3 436464 326A7C 551945 306DD9 5C82B8 7D454D 1219F4 2EF327 77A4CB 2BDD97 1EB9B0 4A962E 5495C5 5DD53D 6B6379\n", - "294220 02447B 11FB28 53D4CA 2BD05A 2489EF 450AE0 098DE6 7C2CDC 1ED54D 2CB813 69F333 32512C 327F03 796D2B 353F2B\n", - "10CF59 21917E 28B5DB 04C06F 466EF3 04185C 780E4C 11C6E2 5F5013 7920C2 346E64 4DDB16 134BEE 5BDF95 326884 01966E\n", - "03D910 620E1D 3D0359 0E052B 4156B9 29E983 1399F9 563C06 6ACB1B 1BBC12 080FFC 268AD9 4D7F52 7A1CF2 20337B 1F5332\n", - "025EA9 38BD4E 582340 695D08 53E808 6EB386 5C451A 611040 0DF7F2 0154BC 138EA8 37A7A5 7F9F93 34AAD9 5EBE1D 1B1BEF\n", - "1139AB 69834D 3F5E93 0F8A3F 6040E6 0EFF89 366052 1395C9 18B194 1219AD 0032D0 0B96FA 61FB37 50C2AA 259148 70BA7B\n", - "6F0655 147FB7 13DAE5 0EEC29 3B921F 02F5C2 4EEE32 15D02E 2502C0 010B93 39A2F1 6BADBE 64073F 0EFBCB 7B36B9 32089B\n", - "r_from_ntt=\n", - "000000 000001 000002 000003 000004 000005 000006 000007 000008 000009 00000A 00000B 00000C 00000D 00000E 00000F\n", - "000010 000011 000012 000013 000014 000015 000016 000017 000018 000019 00001A 00001B 00001C 00001D 00001E 00001F\n", - "000020 000021 000022 000023 000024 000025 000026 000027 000028 000029 00002A 00002B 00002C 00002D 00002E 00002F\n", - "000030 000031 000032 000033 000034 000035 000036 000037 000038 000039 00003A 00003B 00003C 00003D 00003E 00003F\n", - "000040 000041 000042 000043 000044 000045 000046 000047 000048 000049 00004A 00004B 00004C 00004D 00004E 00004F\n", - "000050 000051 000052 000053 000054 000055 000056 000057 000058 000059 00005A 00005B 00005C 00005D 00005E 00005F\n", - "000060 000061 000062 000063 000064 000065 000066 000067 000068 000069 00006A 00006B 00006C 00006D 00006E 00006F\n", - "000070 000071 000072 000073 000074 000075 000076 000077 000078 000079 00007A 00007B 00007C 00007D 00007E 00007F\n", - "000080 000081 000082 000083 000084 000085 000086 000087 000088 000089 00008A 00008B 00008C 00008D 00008E 00008F\n", - "000090 000091 000092 000093 000094 000095 000096 000097 000098 000099 00009A 00009B 00009C 00009D 00009E 00009F\n", - "0000A0 0000A1 0000A2 0000A3 0000A4 0000A5 0000A6 0000A7 0000A8 0000A9 0000AA 0000AB 0000AC 0000AD 0000AE 0000AF\n", - "0000B0 0000B1 0000B2 0000B3 0000B4 0000B5 0000B6 0000B7 0000B8 0000B9 0000BA 0000BB 0000BC 0000BD 0000BE 0000BF\n", - "0000C0 0000C1 0000C2 0000C3 0000C4 0000C5 0000C6 0000C7 0000C8 0000C9 0000CA 0000CB 0000CC 0000CD 0000CE 0000CF\n", - "0000D0 0000D1 0000D2 0000D3 0000D4 0000D5 0000D6 0000D7 0000D8 0000D9 0000DA 0000DB 0000DC 0000DD 0000DE 0000DF\n", - "0000E0 0000E1 0000E2 0000E3 0000E4 0000E5 0000E6 0000E7 0000E8 0000E9 0000EA 0000EB 0000EC 0000ED 0000EE 0000EF\n", - "0000F0 0000F1 0000F2 0000F3 0000F4 0000F5 0000F6 0000F7 0000F8 0000F9 0000FA 0000FB 0000FC 0000FD 0000FE 0000FF\n", - "r_from_ntt2x2=\n", - "000000 000001 000002 000003 000004 000005 000006 000007 000008 000009 00000A 00000B 00000C 00000D 00000E 00000F\n", - "000010 000011 000012 000013 000014 000015 000016 000017 000018 000019 00001A 00001B 00001C 00001D 00001E 00001F\n", - "000020 000021 000022 000023 000024 000025 000026 000027 000028 000029 00002A 00002B 00002C 00002D 00002E 00002F\n", - "000030 000031 000032 000033 000034 000035 000036 000037 000038 000039 00003A 00003B 00003C 00003D 00003E 00003F\n", - "000040 000041 000042 000043 000044 000045 000046 000047 000048 000049 00004A 00004B 00004C 00004D 00004E 00004F\n", - "000050 000051 000052 000053 000054 000055 000056 000057 000058 000059 00005A 00005B 00005C 00005D 00005E 00005F\n", - "000060 000061 000062 000063 000064 000065 000066 000067 000068 000069 00006A 00006B 00006C 00006D 00006E 00006F\n", - "000070 000071 000072 000073 000074 000075 000076 000077 000078 000079 00007A 00007B 00007C 00007D 00007E 00007F\n", - "000080 000081 000082 000083 000084 000085 000086 000087 000088 000089 00008A 00008B 00008C 00008D 00008E 00008F\n", - "000090 000091 000092 000093 000094 000095 000096 000097 000098 000099 00009A 00009B 00009C 00009D 00009E 00009F\n", - "0000A0 0000A1 0000A2 0000A3 0000A4 0000A5 0000A6 0000A7 0000A8 0000A9 0000AA 0000AB 0000AC 0000AD 0000AE 0000AF\n", - "0000B0 0000B1 0000B2 0000B3 0000B4 0000B5 0000B6 0000B7 0000B8 0000B9 0000BA 0000BB 0000BC 0000BD 0000BE 0000BF\n", - "0000C0 0000C1 0000C2 0000C3 0000C4 0000C5 0000C6 0000C7 0000C8 0000C9 0000CA 0000CB 0000CC 0000CD 0000CE 0000CF\n", - "0000D0 0000D1 0000D2 0000D3 0000D4 0000D5 0000D6 0000D7 0000D8 0000D9 0000DA 0000DB 0000DC 0000DD 0000DE 0000DF\n", - "0000E0 0000E1 0000E2 0000E3 0000E4 0000E5 0000E6 0000E7 0000E8 0000E9 0000EA 0000EB 0000EC 0000ED 0000EE 0000EF\n", - "0000F0 0000F1 0000F2 0000F3 0000F4 0000F5 0000F6 0000F7 0000F8 0000F9 0000FA 0000FB 0000FC 0000FD 0000FE 0000FF\n", - "r_from_ntt2x2_div2=\n", - "000000 000001 000002 000003 000004 000005 000006 000007 000008 000009 00000A 00000B 00000C 00000D 00000E 00000F\n", - "000010 000011 000012 000013 000014 000015 000016 000017 000018 000019 00001A 00001B 00001C 00001D 00001E 00001F\n", - "000020 000021 000022 000023 000024 000025 000026 000027 000028 000029 00002A 00002B 00002C 00002D 00002E 00002F\n", - "000030 000031 000032 000033 000034 000035 000036 000037 000038 000039 00003A 00003B 00003C 00003D 00003E 00003F\n", - "000040 000041 000042 000043 000044 000045 000046 000047 000048 000049 00004A 00004B 00004C 00004D 00004E 00004F\n", - "000050 000051 000052 000053 000054 000055 000056 000057 000058 000059 00005A 00005B 00005C 00005D 00005E 00005F\n", - "000060 000061 000062 000063 000064 000065 000066 000067 000068 000069 00006A 00006B 00006C 00006D 00006E 00006F\n", - "000070 000071 000072 000073 000074 000075 000076 000077 000078 000079 00007A 00007B 00007C 00007D 00007E 00007F\n", - "000080 000081 000082 000083 000084 000085 000086 000087 000088 000089 00008A 00008B 00008C 00008D 00008E 00008F\n", - "000090 000091 000092 000093 000094 000095 000096 000097 000098 000099 00009A 00009B 00009C 00009D 00009E 00009F\n", - "0000A0 0000A1 0000A2 0000A3 0000A4 0000A5 0000A6 0000A7 0000A8 0000A9 0000AA 0000AB 0000AC 0000AD 0000AE 0000AF\n", - "0000B0 0000B1 0000B2 0000B3 0000B4 0000B5 0000B6 0000B7 0000B8 0000B9 0000BA 0000BB 0000BC 0000BD 0000BE 0000BF\n", - "0000C0 0000C1 0000C2 0000C3 0000C4 0000C5 0000C6 0000C7 0000C8 0000C9 0000CA 0000CB 0000CC 0000CD 0000CE 0000CF\n", - "0000D0 0000D1 0000D2 0000D3 0000D4 0000D5 0000D6 0000D7 0000D8 0000D9 0000DA 0000DB 0000DC 0000DD 0000DE 0000DF\n", - "0000E0 0000E1 0000E2 0000E3 0000E4 0000E5 0000E6 0000E7 0000E8 0000E9 0000EA 0000EB 0000EC 0000ED 0000EE 0000EF\n", - "0000F0 0000F1 0000F2 0000F3 0000F4 0000F5 0000F6 0000F7 0000F8 0000F9 0000FA 0000FB 0000FC 0000FD 0000FE 0000FF\n" - ] - } - ], - "source": [ - "test_no = 1\n", - "for test_i in range(test_no):\n", - " r_init = {}\n", - " for i in range (DILITHIUM_N):\n", - " r_init[i] = i % DILITHIUM_Q #random.randrange(DILITHIUM_Q) #\n", - "\n", - " #using ref model\n", - " r_in_ntt = fwd_NTT(r_init)\n", - " r_from_ntt = inv_NTT(r_in_ntt)\n", - " #check ref model\n", - " if (r_init != r_from_ntt):\n", - " print(\"Error in ref model\")\n", - "\n", - " #using 2x2 architecture\n", - " r_in_ntt2x2 = fwd_NTT2x2(r_init)\n", - " r_from_ntt2x2 = inv_NTT2x2(r_in_ntt2x2)\n", - " #check 2x2 architecture\n", - " if (r_in_ntt != r_in_ntt2x2):\n", - " print(\"Error in ntt2x2 model\")\n", - " if (r_from_ntt2x2 != r_init):\n", - " print(\"Error in inv_ntt2x2 model\")\n", - "\n", - " #using 2x2 div2 architecture\n", - " r_from_ntt2x2_div2 = inv_NTT2x2_div2(r_in_ntt2x2)\n", - " #check 2x2 div2 architecture\n", - " if (r_from_ntt2x2_div2 != r_init):\n", - " print(\"Error in inv_ntt2x2 div2 model\")\n", - "\n", - "\n", - "def print_table(label, data, rows, cols):\n", - " print(label)\n", - " values = list(data.values())\n", - " for i in range(0, len(values), cols):\n", - " row_values = values[i:i + cols]\n", - " print(\" \".join(f\"{value:06X}\" for value in row_values))\n", - " \n", - "print_table(\"r_init=\", r_init, rows=16, cols=16)\n", - "print_table(\"r_in_ntt=\", r_in_ntt, rows=16, cols=16)\n", - "print_table(\"r_in_ntt2x2=\", r_in_ntt2x2, rows=16, cols=16)\n", - "print_table(\"r_from_ntt=\", r_from_ntt, rows=16, cols=16)\n", - "print_table(\"r_from_ntt2x2=\", r_from_ntt2x2, rows=16, cols=16)\n", - "print_table(\"r_from_ntt2x2_div2=\", r_from_ntt2x2_div2, rows=16, cols=16)" - ] - } - ], - "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.11.8" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/src/ntt_top/tb/ntt_ref.py b/src/ntt_top/tb/ntt_ref.py new file mode 100644 index 0000000..ab2fc23 --- /dev/null +++ b/src/ntt_top/tb/ntt_ref.py @@ -0,0 +1,316 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# NTT Reference Implementation + +import numpy as np +import copy +import random + +### Dilithium Parameter +DILITHIUM_Q = 8380417 # 2**23 - 2**13 + 1 +DILITHIUM_N = 256 +DILITHIUM_LOGN = 8 +DILITHIUM_ROOT_OF_UNITY = 1753 + +### Butterfly +def ct_bf(u, v, z): + global DILITHIUM_Q + t = (v * z) % DILITHIUM_Q + v = (u - t) % DILITHIUM_Q + u = (u + t) % DILITHIUM_Q + return u, v + +def gs_bf(u, v, z): + global DILITHIUM_Q + t = (u - v) % DILITHIUM_Q + u = (u + v) % DILITHIUM_Q + v = (t * z) % DILITHIUM_Q + return u, v + +def gs_bf_div2(u, v, z): + global DILITHIUM_Q + t = div2((u - v) % DILITHIUM_Q) + u = div2((u + v) % DILITHIUM_Q) + v = (t * z) % DILITHIUM_Q + return u, v + +def div2(x): + global DILITHIUM_Q + if x & 1: + return (x >> 1) + ((DILITHIUM_Q + 1) // 2) + else: + return x >> 1 + +### Twiddle factor +def bit_reversal(x): + binary_string = format(x, '08b') + reversed_binary_string = binary_string[::-1] + reversed_decimal = int(reversed_binary_string, 2) + return reversed_decimal + +def zeta_generator(): + global DILITHIUM_Q + global DILITHIUM_N + global DILITHIUM_ROOT_OF_UNITY + + tree=np.zeros(DILITHIUM_N) + for i in range (DILITHIUM_N): + tree[i] = bit_reversal(i) + + tmp={} + tmp[0] = 1 + + zetas={} + zetas_inv={} + + for i in range (1, DILITHIUM_N, 1): + tmp[i] = (tmp[i-1] * DILITHIUM_ROOT_OF_UNITY) % DILITHIUM_Q + + for i in range (0, DILITHIUM_N, 1): + zetas[i] = tmp[tree[i]] + zetas[i] = zetas[i] + zetas_inv[i] = -zetas[i] % DILITHIUM_Q + + return zetas, zetas_inv + +### ref NTTT/INTT model +def fwd_NTT(poly_r): + global DILITHIUM_Q + global DILITHIUM_N + global zetas + + r = copy.deepcopy(poly_r) + + k = 0 + m = 128 + while (m > 0): + start = 0 + while (start < DILITHIUM_N): + k += 1 + zeta = zetas[k] + for j in range(start, start+m): + r[j], r[j + m] = ct_bf(r[j], r[j + m], zeta) + start = start + 2 * m + m >>= 1 + + return r + +def inv_NTT(poly_r): + global DILITHIUM_Q + global DILITHIUM_N + global zetas_inv + + r = copy.deepcopy(poly_r) + + k = DILITHIUM_N + m = 1 + while (m < DILITHIUM_N): + start = 0 + while (start < DILITHIUM_N): + k -= 1 + zeta = zetas_inv[k] + for j in range(start, start+m): + r[j], r[j + m] = gs_bf(r[j], r[j + m], zeta) + start = start + 2 * m + m <<= 1 + + f = 8347681 # 256^-1 mod DILITHIUM_Q + for j in range(DILITHIUM_N): + r[j] = f*r[j] % DILITHIUM_Q + + return r + +### 2x2 NTT/INTT model +def fwd_NTT2x2(poly_r): + global DILITHIUM_Q + global DILITHIUM_N + global DILITHIUM_LOGN + global zetas + + r = copy.deepcopy(poly_r) + + k2={} + zeta2={} + + for l in range(DILITHIUM_LOGN, 0, -2): + m = 1 << (l - 2) + for i in range(0, DILITHIUM_N, 1 << l): + k1 = (DILITHIUM_N + i) >> l + k2[0] = (DILITHIUM_N + i) >> (l - 1) + k2[1] = k2[0] + 1 + zeta1 = zetas[k1] + zeta2[0] = zetas[k2[0]] + zeta2[1] = zetas[k2[1]] + + for j in range(i, i + m): + u00 = r[j] + u01 = r[j + m] + v00 = r[j + 2 * m] + v01 = r[j + 3 * m] + + u10, u11 = ct_bf(u00, v00, zeta1) + v10, v11 = ct_bf(u01, v01, zeta1) + + u20, v20 = ct_bf(u10, v10, zeta2[0]) + u21, v21 = ct_bf(u11, v11, zeta2[1]) + + r[j] = u20 + r[j + m] = v20 + r[j + 2 * m] = u21 + r[j + 3 * m] = v21 + + return r + +def inv_NTT2x2(poly_r): + global DILITHIUM_Q + global DILITHIUM_N + global DILITHIUM_LOGN + global zetas_inv + + r = copy.deepcopy(poly_r) + + k1={} + zeta1={} + + for l in range(0, DILITHIUM_LOGN - (DILITHIUM_LOGN & 1), 2): + m = 1 << l + for i in range(0, DILITHIUM_N, 1 << (l + 2)): + k1[0] = ((DILITHIUM_N - (i >> 1)) >> l) - 1 + k1[1] = k1[0] - 1 + k2 = ((DILITHIUM_N - (i >> 1)) >> (l + 1)) - 1 + zeta1[0] = zetas_inv[k1[0]] + zeta1[1] = zetas_inv[k1[1]] + zeta2 = zetas_inv[k2] + + for j in range(i, i + m): + u00 = r[j] + v00 = r[j + m] + u01 = r[j + 2 * m] + v01 = r[j + 3 * m] + + u10, u11 = gs_bf(u00, v00, zeta1[0]) + v10, v11 = gs_bf(u01, v01, zeta1[1]) + + u20, u21 = gs_bf(u10, v10, zeta2) + v20, v21 = gs_bf(u11, v11, zeta2) + + r[j] = u20 + r[j + m] = v20 + r[j + 2 * m] = u21 + r[j + 3 * m] = v21 + + f = 8347681 # 256^-1 mod DILITHIUM_Q + for j in range(DILITHIUM_N): + r[j] = f*r[j] % DILITHIUM_Q + + return r + + +def inv_NTT2x2_div2(poly_r): + global DILITHIUM_Q + global DILITHIUM_N + global DILITHIUM_LOGN + global zetas_inv + + r = copy.deepcopy(poly_r) + + k1={} + zeta1={} + + for l in range(0, DILITHIUM_LOGN - (DILITHIUM_LOGN & 1), 2): + m = 1 << l + for i in range(0, DILITHIUM_N, 1 << (l + 2)): + k1[0] = ((DILITHIUM_N - (i >> 1)) >> l) - 1 + k1[1] = k1[0] - 1 + k2 = ((DILITHIUM_N - (i >> 1)) >> (l + 1)) - 1 + zeta1[0] = zetas_inv[k1[0]] + zeta1[1] = zetas_inv[k1[1]] + zeta2 = zetas_inv[k2] + + for j in range(i, i + m): + u00 = r[j] + v00 = r[j + m] + u01 = r[j + 2 * m] + v01 = r[j + 3 * m] + + u10, u11 = gs_bf_div2(u00, v00, zeta1[0]) + v10, v11 = gs_bf_div2(u01, v01, zeta1[1]) + + u20, u21 = gs_bf_div2(u10, v10, zeta2) + v20, v21 = gs_bf_div2(u11, v11, zeta2) + + r[j] = u20 + r[j + m] = v20 + r[j + 2 * m] = u21 + r[j + 3 * m] = v21 + + return r + + +def print_table(label, data, rows, cols): + print(label) + values = list(data.values()) + for i in range(0, len(values), cols): + row_values = values[i:i + cols] + print(" ".join(f"{value:06X}" for value in row_values)) + +zetas, zetas_inv = zeta_generator() +## print zeta values for NTT +print("zeta=") +for i in range (DILITHIUM_N): + print(hex(zetas[i])[2:].upper().zfill(6)) + +## print zeta_inv values for INTT +print("zetas_inv=") +for i in range (DILITHIUM_N): + print(hex(zetas_inv[i])[2:].upper().zfill(6)) + +### Test +test_no = 1 +for test_i in range(test_no): + r_init = {} + for i in range (DILITHIUM_N): + r_init[i] = i % DILITHIUM_Q #random.randrange(DILITHIUM_Q) # + + #using ref model + r_in_ntt = fwd_NTT(r_init) + r_from_ntt = inv_NTT(r_in_ntt) + #check ref model + if (r_init != r_from_ntt): + print("Error in ref model") + + #using 2x2 architecture + r_in_ntt2x2 = fwd_NTT2x2(r_init) + r_from_ntt2x2 = inv_NTT2x2(r_in_ntt2x2) + #check 2x2 architecture + if (r_in_ntt != r_in_ntt2x2): + print("Error in ntt2x2 model") + if (r_from_ntt2x2 != r_init): + print("Error in inv_ntt2x2 model") + + #using 2x2 div2 architecture + r_from_ntt2x2_div2 = inv_NTT2x2_div2(r_in_ntt2x2) + #check 2x2 div2 architecture + if (r_from_ntt2x2_div2 != r_init): + print("Error in inv_ntt2x2 div2 model") + + +print_table("r_init=", r_init, rows=16, cols=16) +print_table("r_in_ntt=", r_in_ntt, rows=16, cols=16) +print_table("r_in_ntt2x2=", r_in_ntt2x2, rows=16, cols=16) +print_table("r_from_ntt=", r_from_ntt, rows=16, cols=16) +print_table("r_from_ntt2x2=", r_from_ntt2x2, rows=16, cols=16) +print_table("r_from_ntt2x2_div2=", r_from_ntt2x2_div2, rows=16, cols=16)