MastersThesis/PQ_TIIGER_TLS/lib/ibe/tls_pqibe.cpp
2024-04-19 14:16:07 +02:00

642 lines
52 KiB
C++

//
// Lattice-based B&F IBE 128-bit API Functions
// Ducas et al. Method
// Implementation by M.Scott
// For code to set up TA and issue secret keys, contact me - michael.scott@tii.ae
#include <iostream>
#include <stdlib.h>
#include <cstdint>
#include "tls_pqibe.h"
using namespace std;
using namespace core;
#define PRIME 0x8020001
#define ONE 0x7C1FFE1
#define R2MODP 0xFA047E
#define LIM 128 // should be 256? But could be 64 if we went unsigned
#define LGN 10
#define ND 0x801FFFF
#define DEGREE (1<<LGN)
#define DLQ ((DEGREE/LIM)*PRIME)
#define UBITS 28
#define VBITS 3
#define ULEN (UBITS*DEGREE/8)
#define VLEN (VBITS*DEGREE/8)
#define byte unsigned char
const int32_t inv= 0x400000;
const int32_t invpr= 0x60ff677;
const int32_t roots[]= {0x7c1ffe1,0x6362708,0x45401e8,0x60207e,0x272355d,0x233006,0x9d6d36,0x3d02f9a,0x771d6e8,0x661ea3e,0x1b2a2f,0x487c668,0x56ec3e9,0x563ea0e,0x71ef93f,0x46af7ca,0x431e77b,0x219e6a7,0x33e88d8,0x68edbb5,0x587f588,0x77d7677,0x6ef458c,0x33d0371,0x74055eb,0xad4ed7,0x52224a3,0x67ab958,0x54281c9,0x1e39f16,0x28403d4,0x6fff0a3,0x4173ac0,0x50139dd,0x7594613,0x715165a,0x1dda5b6,0x22a9f4f,0x4063386,0x3da7712,0x1878088,0x3e26ff1,0x684d588,0x111c526,0x5723b3,0x41546ba,0x58f9bee,0x20e749c,0x6575666,0x708d971,0x7048652,0x5e6d01b,0x661ab01,0xb5c31c,0x767e192,0x5bc96f,0x7c4edaf,0x3be6cea,0x3355c75,0x1b35ff7,0x7a0a781,0x7d3ca83,0x2db976e,0x36881de,0x5fbebb3,0x47b73cc,0x6975af0,0x610bf6a,0x740a9dd,0x117a783,0x6d75314,0x260368f,0x25dd6f9,0x118eb2,0x731d94b,0x657e164,0x7eb3daa,0xc97fb6,0x502d1ab,0x13418a0,0x3c2363d,0x54d8e23,0x1032621,0x2e8905a,0x5fdabc8,0x780c630,0x2474ee,0x42fae99,0x186acc9,0x497adcb,0x2042f33,0x3262a8f,0x7cc5a40,0x203d094,0x4ee931e,0x4ed448b,0x1115636,0x1c18918,0x1d828b,0x7bf1c61,0x12b3ab6,0x2d57990,0x30f45,0x7649bc5,0x6a2146,0x8c800c,0x46fab1f,0x7741b5d,0xe32f75,0x3d0e352,0xb8d0c6,0x2cc08a,0x2e0a850,0x1adfb1f,0x5e1e299,0x8a5028,0x648ec62,0x581adad,0x53023c0,0x1b503f2,0x7826bb5,0xb3f6f5,0x351c21e,0x4991a0d,0x1147223,0x40def85,0x6be2de0,0x387163,0x4bb22e6,0x2eba55e,0x3fadf24,0x5609ebe,0x1dfdd31,0x53fbbe,0x5094fbf,0x91104d,0x719a691,0x196daa3,0x6c3179d,0x7ebf37f,0x239bbec,0x4fb5764,0x6ed689b,0x3a0fdce,0x239175e,0x5acd5ef,0x1bfa82b,0x5143035,0x294f431,0x270683,0x3625660,0xd159ba,0x32633e4,0x41d0706,0x1fb0544,0x5e75b4,0x65d50a7,0x2d042de,0x5badff,0x551c2bf,0x735c056,0x5f8428f,0x4c9e9f6,0x821991,0x1d8cf36,0x6ca4a8b,0x11f2c27,0x313d03c,0x1996452,0x2107370,0x5d2e4a9,0x4612494,0x4097732,0x282aaeb,0x2d38f9f,0x6ba7a8e,0x3d59450,0x6b85240,0x1cdf1e4,0x65bbec8,0xdb39f2,0x451971c,0x7f03bd2,0x6e4a4d0,0x74f8d97,0x7035ad9,0x695321d,0x6c2493,0x725b0fb,0x1096e3e,0x71681b2,0x57647be,0x6bff3be,0x297dc11,0x7c01a06,0x6bae8c8,0x5f3ec37,0x6a06a45,0x4f046d3,0x6b35f00,0x4d1c9e7,0x53a6282,0x3bd9efb,0x6057dd7,0x65d048c,0x2cd242d,0x450924c,0x21a9bb6,0x2ed604c,0x6b0e157,0x630b785,0x68e451b,0x50a0bbe,0x42dde0e,0x6ce8a37,0x5ceee9,0x78c51a3,0x7187991,0x244f75b,0x736d41,0xea6968,0x6f0d951,0x741fe2f,0x7d8e6a3,0x26a2143,0x35d30e8,0x39668,0x3052302,0x3920332,0x5f3debe,0x6e9b06,0x2839909,0x5224455,0x5305ebe,0x1ed7bfd,0x626943a,0x6a0b01e,0x106f1d5,0x8e8e2e,0x4cd1bff,0x96b09e,0x5fc992a,0x27d655b,0x100c33a,0x51bbfe3,0x5ead0ea,0xa6b1fb,0x41869df,0x7f9cd9a,0x199daa,0x26656a1,0x1c9185,0x2c429ea,0x1076c9e,0x4f874ab,0x4488c7d,0x55c6eac,0x5b8750f,0x5d18a95,0x3fee28b,0x665c466,0x2ce7927,0x671042,0x7806ab2,0x3f53bcd,0x4780c89,0x7096f1d,0x238017e,0x56c858c,0x6ef3fce,0x6809f09,0x32c79f5,0x4f386b,0x32313aa,0x8ffe22,0x31a2aec,0x65769df,0x2102bb7,0xaea89e,0x24000fc,0x48972af,0x707f6f0,0x7d39d84,0x24782dd,0x6c11eff,0x20d8ebf,0x7420bf9,0x1e6b929,0x2e7d2c8,0x482cfc1,0x645d2e5,0x44d9435,0x5e3ba72,0x3910df,0x132a89d,0x504162d,0x3f607ba,0x94ed1d,0x7cbdd40,0x70d86ea,0x76e369a,0x5aa8d15,0x1948566,0x5ba66d4,0x1872901,0x67e2700,0x195af5d,0x4394e59,0x279e163,0x401a4b0,0x6914ba0,0x3a32be5,0x601b550,0x1412f99,0x961169,0x28cd9fa,0x3ba58ad,0x1ff88eb,0x36d9167,0x2c70d6f,0x1c5d3dd,0x62a7022,0x5106f33,0x7891cd8,0x67d937,0x126ccb9,0x7d1244f,0x3fb2737,0x1a299e9,0xf1777b,0x637d472,0x2c70798,0x6c275f1,0x5acd1fa,0x486b52f,0x366a133,0x43f3bc6,0x47fb230,0x4be7ce8,0x4733305,0x75388a,0x64da47,0x3ce0fea,0x39bba0f,0x309fb0a,0x38b6b6d,0x22c3a83,0xdfc544,0x4824353,0x1070e76,0x39b82ea,0xb2416e,0x26a094c,0x6306ffc,0x4e11a8b,0x3c98963,0x44e68c3,0x7d1d519,0x44391c1,0x3dbb4bc,0x74e781c,0x717dc85,0x13fbff9,0x4e3c47,0x51f26f8,0x9a26d4,0x13c6214,0x6aaf4bd,0x34c2090,0x7d0b242,0x7752e34,0x5a4552d,0x1a149ea,0x5cb4845,0x246b6ad,0x7a24799,0x6c407a4,0x77ec983,0x16ba77c,0x497ad49,0x2ebe598,0x534231e,0x6c4f9a,0x3e0a073,0x1872622,0x62a6282,0x76f311d,0x7bdf999,0x689eecf,0x295e0df,0x14f3fdf,0x7076a0d,0x2be24ab,0x2da71fe,0x4f80a89,0x251e057,0x322e69a,0x16b2bbf,0x4ff5289,0x3f0e32d,0x16d527a,0x701e1ba,0x20c44cd,0x623e2e2,0x16002e9,0x579a9c7,0x10ce8db,0x6450074,0x455bc64,0x7d311bf,0x4dbfc29,0x59c8d4c,0x7543b60,0x12e5a94,0x3700305,0x5fcdf8,0x717918f,0x4940c85,0x189c0f8,0x9d944b,0x16ddc48,0x634fc61,0x593331f,0x263468f,0x31dc2c9,0x1f84ec6,0x70c419e,0x10d5691,0x2735f36,0x7480514,0x5ede7db,0x423b720,0x6c2692e,0x22904b,0x32b80de,0xbc4c03,0x2155403,0x687464f,0x3b84ebe,0x878c20,0x5f3741d,0x751f169,0x6188f1,0x6ae9086,0x14c446d,0xc057f7,0x3f9e770,0x7b50f01,0x6104f16,0x2579ffd,0x1671bb5,0x25ed079,0x45f06a5,0x8f792a,0x402218c,0x7ab1eec,0xf4c80,0x27fefa4,0x387d544,0x568a258,0x29da24e,0x20ee75b,0x6a74db8,0x44f51b0,0x14f9681,0x3bae8b,0x13420d5,0x27619a7,0x5864241,0xb2f50f,0x48d73de,0x7c2bab,0x49485f,0x46f8c7e,0x71d942a,0x4e7891c,0x62323d1,0x181d65c,0xc4b86f,0x4d0331b,0x7599b74,0x5896207,0x6cc77fa,0x54d4cbf,0x6129685,0x27c4625,0x9a510d,0x2cba43d,0x2ee86f9,0x69c06c3,0x9427e6,0x56e284b,0x2a34e16,0x12689d1,0x1b6aeba,0x7fd22a7,0x547a436,0x1ff185c,0x6351914,0x51c3532,0x286d9f1,0x864b5b,0x80716a,0x72cb23d,0x6679e95,0x534ee49,0x2497172,0x3c32234,0x323e3ec,0x7e6750a,0x3fdbf59,0xdea7bb,0x4ba2cdf,0x27fea89,0x4e69dc8,0x4781409,0x6a0415,0x31aedce,0x2db22c3,0x7c2f2f4,0xd78dcb,0x77b5521,0x472377,0xdf9f67,0x31647d5,0x1920ca,0x2ab9c6b,0x340c89d,0x321e9b0,0x476449e,0x4537447,0x4fd33ab,0x48f3087,0x4962f90,0x5f4a9b,0x5f0fba6,0x55a7b38,0x432f9ea,0x22cd9dc,0x524cdd1,0x3e10242,0x2b75ec3,0x79b098f,0x5bc685d,0xf8e66f,0x68cca72,0xa6c3c4,0x5244bcb,0x4ec557c,0x581e7b,0x462ca63,0x3070dc5,0x25fce06,0x78e740b,0x5fdfd60,0x437f083,0xffe489,0x6c6b517,0x411d983,0x3c9152c,0x41448e9,0x60833c3,0x71cf255,0x499c5d1,0x523caca,0x4e92636,0x13371a6,0x393d9da,0x608e9db,0xd25a16,0x56c2481,0x3e1e7f9,0x16ea093,0x2ebb28a,0x1d134b4,0x70ac086,0x3306cb,0x734053,0x6f31161,0x5cf70e5,0x5b31d29,0xa5fd3,0x2e4c16d,0x21c1e70,0x8ce7e3,0x58965c4,0x115764b,0x7e218d7,0x6481815,0x35f830a,0x6fad851,0x415cc9e,0x4667bad,0x67f23fb,0xcebc6a,0x69f7a10,0x496533,0x7114be2,0x2fa1f7,0x7545eb3,0x5799a9b,0x5b883d5,0x4db0d2b,0x30d0517,0x61a2d48,0x2f35fa3,0x4240c1,0x68e92f6,0x575ccf3,0x4933b25,0x56a20b7,0x55f7d7,0x1b6b755,0x78b329,0x3a746c2,0x7ca2fc5,0x7cb4f6f,0x7e2e2f0,0x79d3f10,0x7c204c1,0xea97ea,0x7fe039b,0x36602f8,0x562d036,0x4a3bcaf,0x717db8b,0x5027292,0x558cfb,0x169127f,0x56a7b81,0x438ed28,0x20bf27b,0x1797db7,0x10441d,0xf700c9,0x109bc1,0x6dfc58e,0x6a2fa19,0x4608c4a,0x5417c51,0x39be70f,0x68da436,0x5e9b14e,0x2ce412e,0xb6f71e,0x2e69e85,0x5c28ee0,0x7ecf45c,0x51d26f0,0x11442ac,0x17be9c6,0x48b5456,0x836963,0x756298e,0x376ae86,0xd43456,0x72a0d97,0x4bf4142,0xcefec6,0x6814369,0x5adf37f,0x55182d9,0x310b174,0x53e22dd,0xb1f8bd,0x2d0efee,0x55ea79c,0x364fb64,0x763976e,0x4a2eebf,0x2cc20ab,0x68d1634,0x2f67fa9,0x190e115,0x6462607,0x1af288f,0x4e4e393,0x271d707,0xb467f5,0x1c61455,0x3d3de48,0x6f81ed3,0xc8c13c,0x4b11854,0x624fe28,0x5b90ec9,0x201edfd,0x5d6f2b6,0x2b87a0a,0x222fcf,0x32607bc,0x6c30b15,0x22b6d7e,0xf8da4,0x74d2eb8,0x6d046e1,0x4d98a6b,0x27fd53,0x12662fd,0x6aa1fd6,0x498444a,0x6cd0adf,0x451a0d4,0x18f0606,0xcf045d,0x195e795,0x3afc84e,0x693d407,0x11aa1c6,0xb01416,0x7dfda83,0x6acb1cd,0x320d61e,0x82c022,0x11d4cbb,0x3acee56,0x5526958,0x34459b5,0x464554b,0x632b495,0x2cbea3,0x3ccf259,0xf643c5,0x6bfa1f,0x1d1d9b0,0x154db08,0x2523afc,0x437c34a,0x5072e17,0x122347d,0x34a3127,0x37b44b,0x6c08534,0x2aa5808,0x3afae59,0x445d921,0x2ab1de6,0x4d96d55,0x5431d,0x523dd2e,0x722f9d5,0x45734bb,0x6bc887f,0x25e1804,0x246af45,0x6768527,0x4585c73,0x64d365f,0x331e48c,0x614144b,0x939809,0x5b41f97,0x6fb4dff,0x3477273,0x1ea6539,0x3f338ec,0x8b6982,0x12ddbb2,0x7c30d5,0x7cd75be,0x55abc82,0xdaa31c,0xd76205,0x22a8473,0x75b80fb,0x679fc3,0x1e17971,0x4d24ffa,0x75c5862,0x557d559,0x74d22c6,0x8ca7ff,0x5991f9c,0x596145b,0x55a814,0x4f14d2a,0xd21cd,0x71a2d4d,0x5cbc7e8,0x2f29f4f,0x6a8e423,0x6811fd8,0x37db3f5,0x1905e43,0x1718e24,0x57df501,0x7aff1cc,0x3b3b3a6,0x18f7a26,0x13c210d,0x45f100b,0x6dc7596,0x6e97f37,0x48d4cc6,0x7f42bb5,0x1f899e9,0xfb9637,0x487f256,0x365863d,0x7597dd3,0xa58a45,0x729f6a4,0x5cb2199,0x17ae74c,0x7909c18,0x2b0b952,0xe0a171,0x693fc73,0x2b57c81,0x29b29b2,0x729b5e3,0x4edc9c,0x634c403,0x247701a,0x6eb82fc,0x2dde47e,0x311d474,0x24a7c70,0x4e015af,0x3ccf141,0x1993500,0x5fc84d5,0x507c2c3,0x2e110e8,0x311ecce,0x3c2471c,0x46b458f,0x16a5ee9,0x13b01df,0x1561ff8,0x38a77ef,0x7c75126,0x1ee8e7c,0x2a01a13,0x6d49243,0x2740959,0x5e3e5b5,0x165085e,0x4bc97de,0x43e9792,0xf454fd,0x455e7d0,0x4e3a904,0x1bb1eb0,0x48cd3d,0x6bead5e,0x71124c1,0x21e1d95,0x773d24e,0x2ed1663,0x6f9f032,0x515f6c8,0x6c67b09,0xb7f77e,0x74728d4,0x426e6ac,0x49a0529,0x35feaaf,0x69f9e7b,0x2869e17,0x5b0bfb5,0x4e7c4ef,0x487b0fe,0x6ee95d7,0x5768ac5,0x6c2e422,0x25bd1c6,0x7f6e275,0x9264a8,0x7eec1b9,0x14ff3b,0x20ea61e,0x3b6f38a,0x17cff30,0x6d28215,0x4af675b,0x3314fa9,0x2d66b59,0xc4e05a,0x3f83dc0,0x6fc0829,0x7d3a801,0x5f31349,0x5c3661b,0x33422b3,0x749d080,0x611ed27,0x4eb127e,0x7059df8,0x1fba41c,0x16a0e2d,0x4d8c23a,0x1c9a55d,0xb8e367,0x4a62a4b,0xf6f13c,0x221bf12,0x8008c8d,0x75e2d09,0x455af8a,0x4d86259,0x4a795b9,0x2829807,0x17db465,0x78cbc07,0x13e818b,0x36269fd,0x4aff55e,0x19a2b7f,0x3d8898a,0x22c8139,0x211b3e6,0x7a4a777,0x7cfa48,0x6c8e467,0x273d68,0x3736667,0x6bb2126,0x306f3ad,0x4bbcfd7,0x42980a6,0x536d6dc,0x1ecd05b,0x24750d6,0x7abe57d,0x7826152,0x280c017,0x29f696,0x972107,0x636de5f,0x4c6270c,0x20ec336,0x7cd3890,0x4f6695b,0x7d812cd,0x7d24295,0x56df8e8,0x32c234c,0x28e09ad,0x614a222,0x62cf3f4,0x320cc34,0x39f9351,0x6045d37,0x18aa271,0x60c4141,0x47379bc,0xb35036,0x5eb8ba7,0x7833692,0x3c19795,0x7558f4,0x4308d8e,0x74a896e,0x444ffec,0x60a9940,0x4f36b02,0x7a6fd03,0x72ed39f,0x5c394a4,0x6428ddc,0x4051209,0x77a7c23,0x25f8654,0x4d3200e,0x30a39d4,0x64905a1,0x3277ccb,0x1c8243,0x74d1181,0x2fa171e,0x294cbd4,0x50daf3c,0x51864c6,0x2db4e5,0x6b2f3a3,0x2ad69d9,0x9ab907,0x4990b7b,0x18e9ae6,0x5b0ebd3,0x7cf100e,0x288d15b,0x2d3038e,0x6e4bfe3,0x8a4d05,0x5765da3,0x411a39d,0x691532,0x32bdc9f,0x6529766,0x7a2da34,0x4441416,0x1b746be,0x298a23,0x60e37c3,0x7169326,0x5a74aab,0x109e47e,0x3e0d746,0x3ae10ca,0x1976153,0x6b1d570,0x44d0848,0x3d2c343,0x3264897,0x64f99df,0x297910d,0x7447561,0x3caafe6,0x71d154c,0x4a9d4e7,0x42baf5a,0x16658f,0x124dfa2,0x1bd6350,0x75e9084,0x795453,0x39e28d4,0x2f22307,0x5321fdc,0x2e85bdf,0x56fed28,0x6bee8d5};
const int32_t iroots[]= {0x7c1ffe1,0x1cbd8f9,0x7a1df83,0x3adfe19,0x431d067,0x76492cb,0x7decffb,0x58fcaa4,0x3970837,0xe306c2,0x29e15f3,0x2933c18,0x37a3999,0x7e6d5d2,0x1a015c3,0x902919,0x1020f5e,0x57dfc2d,0x61e60eb,0x2bf7e38,0x18746a9,0x2dfdb5e,0x754b12a,0xc1aa16,0x4c4fc90,0x112ba75,0x84898a,0x27a0a79,0x173244c,0x4c37729,0x5e8195a,0x3d01886,0x4997e23,0x5266893,0x2e357e,0x615880,0x64ea00a,0x4cca38c,0x4439317,0x3d1252,0x7a63692,0x9a1e6f,0x74c3ce5,0x1a05500,0x21b2fe6,0xfd79af,0xf92690,0x1aaa99b,0x5f38b65,0x2726413,0x3ecb947,0x7aadc4e,0x6f03adb,0x17d2a79,0x41f9010,0x67a7f79,0x42788ef,0x3fbcc7b,0x5d760b2,0x6245a4b,0xece9a7,0xa8b9ee,0x300c624,0x3eac541,0x7c98e9e,0x143d221,0x3f4107c,0x6ed8dde,0x368e5f4,0x4b03de3,0x74e090c,0x7f944c,0x64cfc0f,0x2d1dc41,0x2805254,0x1b9139f,0x777afd9,0x2201d68,0x65404e2,0x52157b1,0x7d53f77,0x7492f3b,0x4311caf,0x71ed08c,0x8de4a4,0x39254e2,0x7757ff5,0x797debb,0x9d643c,0x7fef0bc,0x52c8671,0x6d6c54b,0x42e3a0,0x7e47d76,0x64076e9,0x6f0a9cb,0x314bb76,0x3136ce3,0x5fe2f6d,0x35a5c1,0x4dbd572,0x5fdd0ce,0x36a5236,0x67b5338,0x3d25168,0x7dd8b13,0x8139d1,0x2045439,0x5196fa7,0x6fed9e0,0x2b471de,0x43fc9c4,0x6cde761,0x2ff2e56,0x738804b,0x16c257,0x1aa1e9d,0xd026b6,0x7f0714f,0x5a42908,0x5a1c972,0x12aaced,0x6ea587e,0xc15624,0x1f14097,0x16aa511,0x3868c35,0x206144e,0x3b97384,0x3098b56,0x6fa9363,0x53dd617,0x7e56e7c,0x59ba960,0x7e86257,0x83267,0x3e99622,0x75b4e06,0x2172f17,0x2e6401e,0x7013cc7,0x5849aa6,0x20566d7,0x76b4f63,0x334e402,0x77371d3,0x6fb0e2c,0x1614fe3,0x1db6bc7,0x6148404,0x2d1a143,0x2dfbbac,0x57e66f8,0x79364fb,0x20e2143,0x46ffccf,0x4fcdcff,0x7fe6999,0x4a4cf19,0x597debe,0x29195e,0xc001d2,0x11126b0,0x7179699,0x78e92c0,0x5bd08a6,0xe98670,0x75ae5e,0x7a51118,0x13375ca,0x3d421f3,0x2f7f443,0x173bae6,0x1d1487c,0x1511eaa,0x5149fb5,0x5e7644b,0x3b16db5,0x534dbd4,0x1a4fb75,0x1fc822a,0x4446106,0x2c79d7f,0x330361a,0x14ea101,0x311b92e,0x16195bc,0x20e13ca,0x1471739,0x41e5fb,0x56a23f0,0x1420c43,0x28bb843,0xeb7e4f,0x6f891c3,0xdc4f06,0x795db6e,0x16ccde4,0xfea528,0xb2726a,0x11d5b31,0x11c42f,0x3b068e5,0x726c60f,0x1a64139,0x6340e1d,0x149adc1,0x42c6bb1,0x1478573,0x52e7062,0x57f5516,0x3f888cf,0x3a0db6d,0x22f1b58,0x5f18c91,0x6689baf,0x4ee2fc5,0x6e2d3da,0x137b576,0x62930cb,0x77fe670,0x338160b,0x209bd72,0xcc3fab,0x2b03d42,0x7a65202,0x531bd23,0x1a4af5a,0x7a38a4d,0x606fabd,0x3e4f8fb,0x4dbcc1d,0x730a647,0x49fa9a1,0x7daf97e,0x56d0bd0,0x2edcfcc,0x64257d6,0x2552a12,0x5c8e8a3,0x4610233,0x1149766,0x306a89d,0x5c84415,0x160c82,0x13ee864,0x66b255e,0xe85970,0x770efb4,0x2f8b042,0x7ae0443,0x62222d0,0x2a16143,0x40720dd,0x5165aa3,0x346dd1b,0x7235846,0x40440a8,0x1b8af7,0x4de1c15,0x43eddcd,0x5b88e8f,0x2cd11b8,0x19a616c,0xd54dc4,0x7818e97,0x77bb4a6,0x57b2610,0x2e5cacf,0x1cce6ed,0x602e7a5,0x2ba5bcb,0x4dd5a,0x64b5147,0x6db7630,0x55eb1eb,0x293d7b6,0x76dd81b,0x165f93e,0x5137908,0x5365bc4,0x767aef4,0x585b9dc,0x1ef697c,0x2b4b342,0x1358807,0x2789dfa,0xa8648d,0x331cce6,0x73d4792,0x68029a5,0x1dedc30,0x31a76e5,0xe46bd7,0x3927383,0x7b8b7a2,0x785d456,0x3748c23,0x74f0af2,0x27bbdc0,0x58be65a,0x6cddf2c,0x7c65176,0x6b26980,0x3b2ae51,0x15ab249,0x5f318a6,0x5645db3,0x2995da9,0x47a2abd,0x582105d,0x7f2b381,0x56e115,0x3ffde75,0x77286d7,0x3a2f95c,0x5a32f88,0x69ae44c,0x5aa6004,0x1f1b0eb,0x4cf100,0x4081891,0x741a80a,0x6b5bb94,0x1536f7b,0x7a07710,0xb00e98,0x20e8be4,0x77a73e1,0x449b143,0x17ab9b2,0x5ecabfe,0x745b3fe,0x4d67f23,0x7df6fb6,0x13f96d3,0x3de48e1,0x2141826,0xb9faed,0x58ea0cb,0x6f4a970,0xf5be63,0x609b13b,0x4e43d38,0x59eb972,0x26ecce2,0x1cd03a0,0x69423b9,0x7646bb6,0x6783f09,0x36df37c,0xea6e72,0x7a23209,0x491fcfc,0x6d3a56d,0xadc4a1,0x26572b5,0x32603d8,0x2eee42,0x3ac439d,0x1bcff8d,0x6f51726,0x288563a,0x6a1fd18,0x1de1d1f,0x5f5bb34,0x1001e47,0x694ad87,0x4111cd4,0x302ad78,0x696d442,0x4df1967,0x5b01faa,0x309f578,0x5278e03,0x543db56,0xfa95f4,0x6b2c022,0x56c1f22,0x1781132,0x440668,0x92cee4,0x1d79d7f,0x67ad9df,0x4215f8e,0x795b067,0x2cddce3,0x5161a69,0x36a52b8,0x6965885,0x83367e,0x13df85d,0x5fb868,0x5bb4954,0x236b7bc,0x660b617,0x25daad4,0x8cd1cd,0x314dbf,0x4b5df71,0x1570b44,0x6c59ded,0x767d92d,0x2e2d909,0x7b3c3ba,0x6c24008,0xea237c,0xb387e5,0x4264b45,0x3be6e40,0x302ae8,0x3b3973e,0x438769e,0x320e576,0x1d19005,0x597f6b5,0x74fbe93,0x4667d17,0x6faf18b,0x37fbcae,0x7223abd,0x5d5c57e,0x4769494,0x4f804f7,0x46645f2,0x433f017,0x79d25ba,0x78cc777,0x38eccfc,0x3438319,0x3824dd1,0x3c2c43b,0x49b5ece,0x37b4ad2,0x2552e07,0x13f8a10,0x53af869,0x1ca2b8f,0x7108886,0x65f6618,0x406d8ca,0x30dbb2,0x6db3348,0x79a26ca,0x78e329,0x2f190ce,0x1d78fdf,0x63c2c24,0x53af292,0x4946e9a,0x6027716,0x447a754,0x5752607,0x76bee98,0x6c0d068,0x2004ab1,0x45ed41c,0x170b461,0x4005b51,0x5881e9e,0x3c8b1a8,0x66c50a4,0x183d901,0x67ad700,0x247992d,0x66d7a9b,0x25772ec,0x93c967,0xf47917,0x3622c1,0x76d12e4,0x40bf847,0x2fde9d4,0x6cf5764,0x7c8ef22,0x21e458f,0x3b46bcc,0x1bc2d1c,0x37f3040,0x51a2d39,0x61b46d8,0xbff408,0x5f47142,0x140e102,0x5ba7d24,0x2e627d,0xfa0911,0x3788d52,0x5c1ff05,0x7535763,0x5f1d44a,0x1aa9622,0x4e7d515,0x77201df,0x4deec57,0x7b2c796,0x4d5860c,0x18160f8,0x112c033,0x2957a75,0x5c9fe83,0xf890e4,0x389f378,0x40cc434,0x81954f,0x79aefbf,0x53386da,0x19c3b9b,0x4031d76,0x230756c,0x2498af2,0x2a59155,0x143172c,0x29212d9,0x519a422,0x2cfe025,0x50fdcfa,0x463d72d,0x788abae,0xa36f7d,0x6449cb1,0x6dd205f,0x7eb9a72,0x3d650a7,0x3582b1a,0xe4eab5,0x437501b,0xbd8aa0,0x56a6ef4,0x1b26622,0x4dbb76a,0x42f3cbe,0x3b4f7b9,0x1502a91,0x66a9eae,0x453ef37,0x42128bb,0x6f81b83,0x25ab556,0xeb6cdb,0x1f3c83e,0x7d875de,0x64ab943,0x3bdebeb,0x5f25cd,0x1af689b,0x4d62362,0x798eacf,0x3f05c64,0x28ba25e,0x777b2fc,0x11d401e,0x52efc73,0x5792ea6,0x32eff3,0x251142e,0x673651b,0x368f486,0x76746fa,0x5549628,0x14f0c5e,0x7d44b1c,0x2e99b3b,0x2f450c5,0x56d342d,0x507e8e3,0xb4ee80,0x7e57dbe,0x4da8336,0x1b8fa60,0x4f7c62d,0x32edff3,0x5a279ad,0x8783de,0x3fcedf8,0x1bf7225,0x23e6b5d,0xd32c62,0x5b02fe,0x30e94ff,0x1f766c1,0x3bd0015,0xb77693,0x3d17273,0x78ca70d,0x440686c,0x7ec96f,0x216745a,0x74eafcb,0x38e8645,0x1f5bec0,0x6775d90,0x1fda2ca,0x4626cb0,0x4e133cd,0x1d50c0d,0x1ed5ddf,0x573f654,0x4d5dcb5,0x2940719,0x2fbd6c,0x29ed34,0x30b96a6,0x34c771,0x5f33ccb,0x33bd8f5,0x1cb21a2,0x76adefa,0x7d8096b,0x5813fea,0x7f9eaf,0x561a84,0x5baaf2b,0x6152fa6,0x2cb2925,0x3d87f5b,0x346302a,0x4fb0c54,0x146dedb,0x48e999a,0x7dac299,0x1391b9a,0x78505b9,0x5d588a,0x5f04c1b,0x5d57ec8,0x4297677,0x667d482,0x3520aa3,0x49f9604,0x6c37e76,0x7543fa,0x6844b9c,0x57f67fa,0x35a6a48,0x3299da8,0x3ac5077,0xa3d2f8,0x8037375,0x5e040ef,0x70b0ec5,0x35bd5b6,0x7491c9a,0x6385aa4,0x3293dc7,0x697f1d4,0x6065be5,0xfc6209,0x316ed83,0x1f012da,0xb82f81,0x4cddd4e,0x23e99e6,0x20eecb8,0x2e5800,0x105f7d8,0x409c241,0x73d1fa7,0x52b94a8,0x4d0b058,0x35298a6,0x12f7dec,0x68500d1,0x44b0c77,0x5f359e3,0x7ed00c6,0x133e48,0x76f9b59,0xb1d8c,0x5a62e3b,0x13f1bdf,0x28b753c,0x1136a2a,0x37a4f03,0x31a3b12,0x251404c,0x57b61ea,0x1626186,0x4a21552,0x367fad8,0x3db1955,0xbad72d,0x74a0883,0x13b84f8,0x2ec0939,0x1080fcf,0x514e99e,0x8e2db3,0x5e3e26c,0xf0db40,0x14352a3,0x7b932c4,0x646e151,0x31e56fd,0x3ac1831,0x70dab04,0x3c3686f,0x3456823,0x69cf7a3,0x21e1a4c,0x58df6a8,0x12d6dbe,0x561e5ee,0x6137185,0x3aaedb,0x4778812,0x6abe009,0x6c6fe22,0x697a118,0x396ba72,0x43fb8e5,0x4f01333,0x520ef19,0x2fa3d3e,0x2057b2c,0x668cb01,0x4350ec0,0x321ea52,0x5b78391,0x4f02b8d,0x5241b83,0x1167d05,0x5ba8fe7,0x1cd3bfe,0x7b32365,0xd84a1e,0x566d64f,0x54c8380,0x16e038e,0x7215e90,0x55146af,0x7163e9,0x68718b5,0x236de68,0xd8095d,0x75c75bc,0xa8822e,0x49c79c4,0x37a0dab,0x70669ca,0x6096618,0xdd44c,0x374b33b,0x11880ca,0x1258a6b,0x3a2eff6,0x6c5def4,0x67285db,0x44e4c5b,0x520e35,0x2840b00,0x69071dd,0x671a1be,0x4844c0c,0x180e029,0x1591bde,0x50f60b2,0x2363819,0xe7d2b4,0x7f4de34,0x310b2d7,0x7ac57ed,0x26beba6,0x268e065,0x7755802,0xb4dd3b,0x2aa2aa8,0xa5a79f,0x32fb007,0x6208690,0x79a603e,0xa67f06,0x5d77b8e,0x72a9dfc,0x7275ce5,0x2a7437f,0x348a43,0x785cf2c,0x6d4244f,0x776967f,0x40ec715,0x6179ac8,0x4ba8d8e,0x106b202,0x24de06a,0x76e67f8,0x1edebb6,0x4d01b75,0x1b4c9a2,0x3a9a38e,0x18b7ada,0x5bb50bc,0x5a3e7fd,0x1457782,0x3aacb46,0xdf062c,0x2de22d3,0x7fcbce4,0x32892ac,0x556e21b,0x3bc26e0,0x45251a8,0x557a7f9,0x1417acd,0x7ca4bb6,0x4b7ceda,0x6dfcb84,0x2fad1ea,0x3ca3cb7,0x5afc505,0x6ad24f9,0x6302651,0x79605e2,0x70bbc3c,0x4350da8,0x7d5415e,0x1cf4b6c,0x39daab6,0x4bda64c,0x2af96a9,0x45511ab,0x6e4b346,0x77f3fdf,0x4e129e3,0x1554e34,0x22257e,0x751ebeb,0x6e75e3b,0x16e2bfa,0x45237b3,0x66c186c,0x732fba4,0x672f9fb,0x3b05f2d,0x134f522,0x369bbb7,0x157e02b,0x6db9d04,0x7da02ae,0x3287596,0x131b920,0xb4d149,0x7f2725d,0x5d69283,0x13ef4ec,0x4dbf845,0x7dfd032,0x54985f7,0x22b0d4b,0x6001204,0x248f138,0x1dd01d9,0x350e7ad,0x7393ec5,0x109e12e,0x42e21b9,0x63bebac,0x74d980c,0x59028fa,0x31d1c6e,0x652d772,0x1bbd9fa,0x6711eec,0x50b8058,0x174e9cd,0x535df56,0x35f1142,0x9e6893,0x49d049d,0x2a35865,0x5311013,0x7500744,0x2c3dd24,0x4f14e8d,0x2b07d28,0x2540c82,0x180bc98,0x733013b,0x342bebf,0xd7f26a,0x72dcbab,0x48b517b,0xabd673,0x77e969e,0x376abab,0x686163b,0x6edbd55,0x2e4d911,0x150ba5,0x23f7121,0x51b617c,0x74b08e3,0x533bed3,0x2184eb3,0x1745bcb,0x46618f2,0x2c083b0,0x3a173b7,0x15f05e8,0x1223a73,0x7f16440,0x70aff38,0x7f1bbe4,0x688824a,0x5f60d86,0x3c912d9,0x2978480,0x698ed82,0x7ac7306,0x2ff8d6f,0xea2476,0x35e4352,0x29f2fcb,0x49bfd09,0x3fc66,0x7176817,0x3ffb40,0x64c0f1,0x1f1d11,0x36b092,0x37d03c,0x45ab93f,0x7894cd8,0x64b48ac,0x7ac082a,0x297df4a,0x36ec4dc,0x28c330e,0x1736d0b,0x7bfbf40,0x50ea05e,0x1e7d2b9,0x4f4faea,0x326f2d6,0x2497c2c,0x2886566,0xada14e,0x7d25e0a,0xf0b41f,0x7b89ace,0x16285f1,0x7334397,0x182dc06,0x39b8454,0x3ec3363,0x10727b0,0x4a27cf7,0x1b9e7ec,0x1fe72a,0x6ec89b6,0x2789a3d,0x775181e,0x5e5e191,0x51d3e94,0x7f7a02e,0x24ee2d8,0x2328f1c,0x10eeea0,0x78ebfae,0x7cef936,0xf73f7b,0x630cb4d,0x5164d77,0x6935f6e,0x4201808,0x295db80,0x72fa5eb,0x1f91626,0x46e2627,0x6ce8e5b,0x318d9cb,0x2de3537,0x3683a30,0xe50dac,0x1f9cc3e,0x3edb718,0x438ead5,0x3f0267e,0x13b4aea,0x7021b78,0x3ca0f7e,0x20402a1,0x738bf6,0x5a231fb,0x4faf23c,0x39f359e,0x7a9e186,0x315aa85,0x2ddb436,0x75b3c3d,0x175358f,0x7091992,0x24597a4,0x66f672,0x54aa13e,0x420fdbf,0x2dd3230,0x5d52625,0x3cf0617,0x2a784c9,0x211045b,0x7a2b566,0x36bd071,0x372cf7a,0x304cc56,0x3ae8bba,0x38bbb63,0x4e01651,0x4c13764,0x5566396,0x7e8df37,0x4ebb82c,0x722609a,0x7badc8a,0x86aae0,0x72a7236,0x3f0d0d,0x526dd3e,0x4e71233,0x797fbec,0x389ebf8,0x31b6239,0x5821578,0x347d322};
// TA public key in NTT format
const int32_t H[]={0x377e3ac,0x2360cb0,0x5841181,0x3ef642b,0x4fb0d0,0x17c0de,0x76a2ab5,0x651d1a0,0x25498d,0x41f52e5,0x5c534e2,0x6f5e332,0x6b3c6b6,0x23afb52,0x36b5eb8,0x1714f92,0x5b1e345,0x308f251,0x45277e9,0x7fea756,0x197f90f,0x7f10e43,0xf136e5,0x53a546d,0x42e5ed3,0x3a83ce9,0x1be404f,0x4b423,0x7458a12,0x3990ae0,0x59ea53f,0x7120158,0x53c1e4c,0x2c26ded,0x55b3324,0x6c16736,0x40ed524,0x36e3f9e,0x548fd7d,0x25feb0,0x18b32c0,0x7b98356,0x1d9e22,0x1e791c3,0x4b4f653,0x2b9b5c0,0x13ac4cd,0x1fc4bd7,0x7196c5b,0x6cb7ab2,0x4a04d36,0x57486db,0x7972f4b,0x2a64ed2,0x30d6f31,0x64f0443,0x33352ca,0x4bef8bd,0x315c46a,0x4eb8b62,0x5de0c0b,0x22fdc7a,0x3ae7eae,0x78a3cfa,0x169ec52,0x64e725d,0x15dc340,0x3367ed3,0x1ee1ba7,0x39522fe,0x70a1973,0x655158c,0x5c91545,0x662d3c3,0x622e99e,0x6b42bcf,0x5ca7c85,0x42e93ac,0x325a086,0x408cc43,0x5801e57,0x4e412e9,0x2459d87,0x71a4ca4,0x3f1b0b0,0x7336021,0x48fef71,0x59c8427,0x63a89eb,0x731c8d6,0x460ccfa,0x6b9e8c0,0x36e542e,0x50a2334,0x1762a7f,0x5be94be,0x4ea626a,0x3ec7299,0x614a747,0x2d11f30,0x800f076,0x73486bc,0x26679e8,0x6880939,0x2541798,0x77ff34b,0x310136e,0x7a360f2,0x1b52ac0,0xfb887,0x65d6b54,0x469807d,0x252cb62,0xbff315,0x6fe7a1f,0x4244d2a,0x65d706f,0xc8ab7a,0x128a9c8,0x61e4e65,0xfde5a,0x392acb,0x1613400,0x5906fad,0x6e93932,0x75f599b,0x19424fe,0x5d2d30a,0x4337643,0x6800ec4,0x3eb06f9,0x3497960,0x7798f3e,0x39e1aa7,0x2193267,0x120d716,0x6754886,0x4c762c5,0x5934a21,0x3006633,0x489996f,0xbcddc3,0x325ed6b,0x1872a98,0x5025218,0x3aa692,0xd047cb,0x3abca42,0x286f6fd,0x68d9bee,0x7c3acbf,0x7576a73,0x52a1688,0x64000d,0x146fb7f,0x1b79c87,0x5b58168,0x55c2fd2,0x471a5ad,0x3369dda,0x3070579,0x70e70b7,0xa6b827,0x7dbe0ea,0x61f5222,0x3360d98,0x152c618,0x26a4008,0x41a8735,0x42645a7,0x7f20e6,0x166ce00,0x62298a2,0x2c845c3,0x2be2d6b,0x39baeff,0x631079a,0x6cf03c,0x69ebdb6,0x42baa1,0x32f120,0x2c18dbc,0x5214310,0x3f39556,0x518a26,0x58ee623,0x732d2a5,0x29ac71c,0x6716d00,0x1978ad1,0x1ea0cd9,0x273e4cf,0x4a7a364,0x97183e,0x30bf41c,0x6f84fdf,0xc9094b,0x5da21cf,0x65fb540,0x637a07b,0x9b89bb,0x2efb071,0x73366e2,0x77eccb4,0x3e37d2c,0x13600b5,0x24394a,0x4bb6252,0x5983c53,0x2bb7dd8,0x6307988,0x7165bd8,0x2bbdf23,0x3b1c2e8,0x5f9b60f,0xf31cc7,0x36ab176,0x55ae611,0x51b2830,0x4f6bc12,0xc3cd6c,0x7f01bfe,0x6eacd2,0x1783dfc,0x24917b6,0x4922140,0x25473d7,0x20b5b13,0x13fecc5,0x7a088cb,0x2e25cd7,0x58998c2,0x24e190c,0x443fe75,0x7a8dd11,0x5042d9,0xc65a71,0x4b5afa2,0x409924a,0x3cc3531,0x31a3358,0x72c9b5a,0x74e6a37,0x6aa6040,0x394f548,0x67d4c0d,0x21bb02a,0x74dfbea,0x455d831,0x58fe8f0,0x46b0c09,0x6edba4d,0x74c5063,0x37bf9a6,0x114d925,0x113c16c,0x35ab796,0x6fdd797,0xf80d49,0x3a613cf,0x6e34724,0x442c9ef,0x1301a7,0x7b9c20,0x46a65ce,0x709832b,0x526cf49,0x26f8134,0x5706dba,0x33605aa,0x246556d,0x2c173b1,0x16798c2,0x2f9e079,0x3936798,0x2b4b931,0x3012784,0x72fce5d,0x4708819,0x6e8f495,0x7690898,0x25d2691,0x12d163,0x5f46d2b,0x60d576d,0x5f51064,0x3a18110,0x5217918,0x974971,0x1758994,0x7c4b13d,0x5110b91,0x16c1dce,0x6223ae4,0x3c07fc3,0x2f83045,0x2ce96bd,0x1d50d92,0x61136dd,0x3b677b,0x321c168,0x2d3f3a5,0x12576be,0x365e366,0x33bb933,0x46e9b62,0x5ad0bea,0xe9ac84,0x6b944fd,0x1d302ab,0x602164b,0x5b42a5a,0x15e06b3,0x36e77e1,0x30f7efd,0x4e95aca,0x6d25558,0x4e81718,0x526febc,0x6a23e0c,0x4244242,0x2faf835,0x28a3a7f,0x1020b5e,0x56df169,0x2d714b7,0x1d2ec6c,0x1874d4,0x2b63c87,0x1356ac6,0x2c184d5,0x7240dfd,0x67d8856,0x4be1526,0x299f701,0x2e97da4,0x129357f,0x177d3a5,0xe5e47,0x76ae2c5,0x204cd26,0x3901b87,0x20c1960,0x296f293,0x137e972,0x5190f21,0x4c7bcc3,0x18cfa22,0xca6539,0x7d32bfb,0x6f0f842,0x7f495a8,0x15dae55,0x4648139,0x5682ad0,0x7c5c67c,0x3738cef,0x24d3245,0x1d9a985,0x40dcb42,0x24de229,0x5cc81f5,0x4d57b74,0x4d207a7,0x6c2860c,0x2a87b4e,0x5a44938,0x2e91fa8,0x42d9f49,0x3d95d1f,0x3a99a23,0x2f9a7c7,0x66a97e1,0x1d1d9fb,0x623b30e,0x1f1a5dc,0x852204,0x39843a8,0x6262e02,0x6aa8c16,0x75eaef7,0x71efd55,0x62ab01b,0x7721d13,0x76d859a,0x101f3f6,0x59fb8c1,0x207f290,0x31519b8,0x60f3b54,0x2884d1c,0x2de31a4,0x173afb9,0x4ed680,0x5e2f62f,0x7490c69,0x54ef3d6,0x607c8a3,0x5bb2e42,0x1af69b5,0x23c83a6,0x56447c9,0x7852be8,0x4a3613c,0x110b98e,0x235ae7e,0x31bdb3e,0xec48fd,0x33e0dfa,0x7c778c9,0x64aecdc,0x51b34dd,0x2e5175f,0x7011933,0x49ee13f,0x65cb8f,0x36cbd56,0x5064da7,0x1a80a67,0x1969517,0x6a38c63,0x7c28d6a,0x34bb2a,0x7a876f3,0x342f5e0,0x2fbb12f,0xb25fac,0x3ca6e83,0x15b9cba,0x103b4ff,0x408771e,0x31ee966,0xd7c7de,0x2d0bf76,0x9ab853,0x3a3f9af,0x606595e,0x69d221f,0x6dd45bd,0x33d0c1c,0x23888fb,0x22361ce,0x2e2fadb,0x1a1cc3f,0x7132901,0x2c817fa,0x4157f7c,0x55db333,0x2f0de77,0x38e10fd,0x214f489,0x174c758,0x3da51a5,0x572254a,0x1868348,0x77cc0b9,0x3ce6a12,0x1036ad3,0xd3d696,0x6b11906,0x22735d1,0x7425489,0x7a28d4b,0x4a8a808,0x1a22793,0x6529113,0x139b11f,0x4550de9,0x36be09,0x606ad5d,0x77c98df,0x156058a,0x4d506ca,0x12525aa,0x275e9d5,0x7b92544,0x672b0ff,0x931867,0x678a235,0x185cca6,0x51c77e3,0xb16f85,0x30e02e,0xcc5355,0x58115f,0x148f6e1,0x4262907,0x24b2b45,0x1893364,0x6de5df1,0x74b5ae3,0x7704a8c,0x1dc25a6,0x2bf9703,0x18ceba4,0x78ab580,0x3379bd1,0x588f134,0x15914ca,0x799f482,0x6ab968,0x515cea,0x71d79d1,0x721afda,0x2a39159,0x5e544c0,0x10dd915,0x19b99ec,0x63bb11a,0x15cd90,0x7c9c9e5,0x6b681f5,0x210488d,0x85108e,0x6d92960,0x4c90aa4,0xca81d4,0x75c0bc0,0x77791c,0x17a067b,0x78e440b,0x53a93ee,0x5405009,0x56c1820,0x6a15962,0x39f96cb,0x25d0ff7,0x5949b66,0x78c6d1b,0x6074dfd,0xd9d39e,0x708feac,0x5640323,0x3b17eb0,0x2c8973,0x2c8c4c0,0x5a9a13e,0x6884db7,0x439b45b,0x2106e9a,0xac5c79,0x5dae202,0x1310f16,0x18d049b,0x7f1c7f0,0x5b89ae1,0x52eff13,0x30e3bbe,0x5168608,0x6e7a9f,0x1dc283,0x561d17c,0x7c80555,0x717ce18,0x2758c12,0x33648e0,0x62cff39,0x27d70f5,0x8cdc0e,0x5e8ea65,0x895e62,0x170a599,0x183b830,0x5d7a6ee,0x5fde98c,0x6586b06,0x46856c6,0x801797c,0x60250b7,0x71c319e,0x33c7b1b,0xee0a74,0x4de1f09,0x16dfbcc,0x1f8eb70,0x602aebf,0x66aa4e5,0x1f28478,0x5f3705d,0x1d491fb,0x72f44e6,0x50b1b3,0x18f943c,0x324f3cf,0x3ccc236,0x23b2093,0x8c349a,0xe742c2,0x3c6c5f7,0x2958d29,0x69ac3b7,0x1e5f60a,0x596c48b,0x6aa31f2,0x66e668b,0x45a6166,0x55799e3,0x22e5e06,0x51134fe,0x4c2f853,0x226a6ce,0x1afae06,0x22293a7,0x3f8554,0x6aa7aa4,0x13cd0ab,0x1a95d67,0x6f597ae,0x4d86a24,0x4d86186,0x6c63795,0x51733f0,0x7413b68,0x2bf1065,0x7cef545,0x3885e35,0x5e25e1d,0x476285d,0x7802a69,0x2a3b758,0x4aad59c,0x9f8cc7,0x13abee1,0x10bce32,0x51d1e6e,0x600b6ba,0x683d9ec,0x5da71d0,0x9fdd65,0x513da62,0x5b89037,0x1f04ac9,0x663909,0x49eb4b4,0x6de306e,0x2c608c7,0x637b5ab,0x2b4569f,0x14fc96f,0x3fb247,0x2d0f06f,0x4d395f5,0x6139db3,0x7060a13,0xd23800,0x757718e,0x7bac474,0x485dbcd,0x2f7fc75,0x5470a51,0x22d83b,0x2c0e18c,0x1a38f32,0x319c112,0x315855f,0x5c1f68f,0x5c7d3ef,0x426d659,0x4c546ec,0x5650a59,0x7fcc7dc,0x5e85103,0xa5ff03,0x768adaa,0x3d725b0,0x5f2c4c5,0x326fedc,0xf862cd,0x3f7d1e3,0x2419447,0x78a5cba,0x5156c17,0x5b3100b,0x5bd5db3,0x57734e5,0x306c5b0,0x431a133,0x6710fda,0x5fb4bde,0x18a7d45,0x20e993e,0x418ff53,0x7c7ac7,0x2f67806,0x3d7aef8,0x6fcd3c5,0x2e57f8d,0x61835b9,0x1b79247,0x1a764e5,0x393e5dc,0x3c5095d,0x4df1e3d,0x16ed9e2,0x23ce993,0x4b8c002,0x56f37c7,0xb78b4e,0x772a665,0x4e174a3,0xe9d697,0x341d634,0x671c049,0x30070dc,0x6b661e6,0x4d962a3,0x5b6c05d,0x418723a,0x3ecca9f,0x4e75db9,0x1b84a70,0x192af1a,0x6e64168,0x6b20c83,0x7c4a4b,0x47d18b5,0x5ceb492,0x38cca1f,0x36fb59b,0x5f6f4d7,0x218d94a,0x429c411,0x3e20f8b,0xa2f49f,0x15be4e2,0x69a75b4,0x335cbd1,0x622e90b,0x58021b7,0x45cd581,0x2ecff8e,0x30dbf67,0x2b63d19,0x4e5d7d1,0xaa1122,0x4243cdf,0x4dbb9c,0x390acf9,0xdf1f53,0x78c38c0,0x253ebec,0x34ad12d,0x40ed99e,0x413f7ed,0x293108b,0x7233723,0x7571447,0x3f98a72,0x68cad3a,0xab5195,0x10af3f4,0x5d5abbb,0x677b7d0,0xaa5970,0x507f4e9,0x1529cde,0x4bd461d,0x564541a,0xa92a3f,0x1221af,0x33e8927,0x36abcda,0x15f434d,0x4e091ad,0x3d0dcab,0x6056a3f,0x22cb1ad,0x349f4c7,0x4703e5f,0xb53ee1,0x36f3b03,0x5695df,0x2e07e6d,0x7a5e49c,0x1dca3ae,0x314d93,0x2d93c87,0x187d956,0x7f49488,0x62b143f,0xe30574,0x19f61b9,0x40e298b,0x77801bd,0x456108e,0x7f7ace4,0x200b80b,0x3d8e631,0x4218d7a,0x10312bc,0x54462b,0x2466b11,0x5c38b9,0x7ab99de,0x7b8c192,0x5b5b75b,0x757bd87,0x5be9f20,0x887b68,0x47a624c,0x23f2c2f,0x2693e64,0x7a0e484,0x3635e7f,0x259d8d2,0x7c7dd8a,0x59abde1,0x3b4b658,0x605ef55,0x298b136,0x57655ab,0x8c5e54,0x2c4ce91,0x5820d2e,0x16911c8,0x38c421a,0x604a251,0x51c06e5,0x3c70a52,0x56a4ffd,0x605d5dd,0x2259b23,0x6a1e0d3,0x6384c16,0x2523d50,0x7f7374e,0x1992354,0x25a854b,0x3d33eb5,0x502b7bc,0x1a8a059,0x455b4ec,0xa4e7e5,0x4258fd7,0x6468d44,0x1845bef,0x52f9f4c,0x6e4e591,0x3681eea,0x711278c,0x255f6fb,0x77e6067,0x2625a0c,0x976464,0x69bd825,0x348c924,0x1eaee70,0x245a55f,0x4bb4e7d,0x7fb363f,0x56689fc,0x3155ef0,0xfdedbc,0x6ba113f,0x69aa598,0x3aa95c6,0x20475ae,0x204b624,0xc1cd31,0x5552a6,0x2e28e54,0x32ed92d,0x4c42445,0x2780720,0x7ec4fb3,0x62a791d,0xfca712,0x4fa24a2,0x4c1acb2,0x3a9b11a,0x3aaf977,0x2161312,0xb45b8b,0x5087b66,0x2ad83f4,0x2dc9633,0x3b1da6e,0x57e5881,0x2741763,0x63cd22,0x215e9b4,0x5614da5,0x217134b,0x66d5cc8,0x4a48a8e,0x664a46d,0x7fb33ca,0x2b4a5ce,0x646d5da,0x26d8854,0x274bde1,0x28668a6,0x6ac9b6d,0x17b17af,0x2a9c5f0,0x11d9aac,0x4e0908f,0x4e5ba9f,0x45c6a32,0x67cbfde,0x4fddb5a,0x7c0ab08,0x1f5c2f8,0x320b5cb,0x3b1fc26,0x667aa46,0x129e8b2,0x1d098e9,0x29635a2,0x78ab019,0x6b62e6f,0x390cb0b,0x4858319,0x3129817,0x3ec0f33,0x1a79dc2,0x1b32f49,0x58cb4cd,0x30ccc0,0x5ef2398,0x5f282b0,0x4804dfc,0x3156aaf,0x5fef5b5,0x6cd995f,0x7c2d048,0x5d967cc,0x2bfd61c,0x7496c44,0x96d5f6,0x2f2ce2,0x6ef6f06,0x1704980,0x466a39,0x210aef4,0x7242fde,0x6bcf42d,0x2584d1b,0x708da42,0x195f6b,0x6a6b70f,0x43fea69,0x3043fc,0x3b5c396,0x29d78df,0x29f5748,0x31ca59a,0x46f93c,0x703582f,0x115bf,0x43fac3,0x5029494,0x64e518a,0x5267f1e,0x6f34a89,0x1b4c416,0x15e4630,0x2d7eae7,0x55cd171,0x5fab087,0x11cc383,0x1eb2fbc,0x43e682d,0x430c7d9,0x60fa28,0x413ad72,0x4b56a22,0x6fbc498,0x1f8858a,0x238a96b,0x4869439,0x6f334e7,0x7c9737b,0x7634fdd,0x1dcb9f7,0x5be249a,0x5716fec,0x16cc3fb,0x291eb70,0x2c06aac,0x493f3b,0x4aba690,0x433c2d8,0x50a029d,0x376baa9,0x792ac7a,0x86f7a1,0x21ffc32,0x634fcc5,0x2ac6037,0x669a60a,0x3f6ae71,0xe3a783,0x70b68d5,0x4e415ce,0x15bdfe9,0x5211065,0x419f9a8,0xae2fed,0x57f38eb,0x4548482,0x1ac2eb6,0x76b3309,0x52c34a4,0x444e63a,0x18bd3f5,0x356572f,0x6d6fa48,0x3c1e8d7,0x4bae0e9,0x63bbdbd,0x1866492,0x5bfd368,0x3b9739a,0x24c216,0xf50471,0xd94777,0x5e2a3c7,0x767072b,0x36a5764,0x78888ac,0x5c6b3d5,0x38200b9,0x658ed81};
//const int32_t H[]={52424332,86419331,100281829,26092113,31425049,44501326,22753073,25911274,32399324,52275749,82654901,112957555,7062995,72377240,59635533,2947678,23443436,11737345,24467451,83146335,60806975,83310820,52671905,50859759,46747981,123697787,42273843,53140943,132744737,23193929,55161079,88883569,30185251,15426898,10637871,6011655,47924241,64955761,97600115,94237518,123408389,65294538,91425157,39535266,67296739,35846403,114135997,17015834,84492896,118318790,123429403,97254014,119976388,119441899,69987419,22357274,13836478,99715640,8864885,97805755,989907,65769383,55337542,87376917,19609637,10589162,67727916,85356123,18263070,59254521,126168209,51233539,99698,48958079,97936146,84678921,34269358,122328672,97259374,18008647,48770962,116473697,131067647,120796592,34695112,132070906,85630497,94466376,44421174,94745700,104683424,85985627,70456618,82488252,6609853,118120182,9887156,95128290,74287744,65972735,116093844,90397373,105781092,81267675,47824996,17182203,92192736,73224256,14172570,26817363,101766600,57880921,119252825,29519272,57851033,100629940,91247239,110316721,127118676,47454805,15198736,93588873,91861761,116023232,119093487,75999855,45406328,2833127,98969504,116439286,121520408,127305365,134243779,101459576,86403802,27611155,133305973,89651114,1125832,76906685,69801243,120940569,128028546,91933707,77070197,34080494,5046436,101866359,96966064,49690507,128208599,105888911,131630254,23330239,51623014,6346113,129792069,42209429,37798608,124278266,43189912,38352552,93519575,5389657,39702635,97884097,110700562,54705611,116229619,62434923,124433437,105517671,100752396,97362328,126455555,21159148,5542264,48413029,22966322,13228484,133947423,39801261,124287483,36305722,123431838,101012364,129307403,125152359,131262913,64841473,117102988,54682368,110333297,117596464,90409186,48021946,58770261,28300887,74521533,115537872,2066913,72679842,92648376,94779373,50019904,34622343,93422624,113273797,95111397,88118762,60696715,81203606,77432432,111020166,73829036,108735877,73877602,71124764,81179850,118258267,101357992,30006004,90991921,36918520,111573417,65290828,25141260,74246924,39429006,5698526,127752863,119673924,43428974,26155101,80755282,133006106,37786815,19242105,95709873,13115771,67096487,18950767,14136188,16540678,72841015,132445350,74727888,34978150,54966701,75568253,133042029,87356538,14160641,115289370,50721712,60887488,114874297,40189801,118783177,79033409,25628073,86202718,123220958,78315831,129908154,3000567,122075976,51019479,14344667,96536064,20975064,125270612,7095488,2095571,118366518,88696041,49349421,102916376,77879043,90959260,49942433,428027,125026597,73734673,41470068,75050280,49152345,53421135,74573404,79797348,15822022,84838620,126135335,108604222,40269793,64323769,116591979,39143511,66043329,123308186,92142975,115991222,122992385,64152735,41516562,16472280,81250609,816025,105588493,75511207,51540932,101092200,58959708,103649482,25408188,2196171,46308717,85855626,43544673,21152673,31883599,29269620,122563584,133332028,17063666,60948372,14016273,14689030,25586454,129464115,50558555,12797097,48094136,110525720,46505184,66728736,86882082,55570781,81922957,122754743,100267365,51195568,9130045,30394901,68898169,11293130,30906247,11796641,30009770,40474754,124723788,15605488,95481047,112150212,44538708,30037242,68082669,37442145,86901110,117611103,88652182,10189372,107115246,101852173,18499596,18646227,40456333,109112707,2499886,84041509,128557219,97339579,54298690,69606243,64038161,35498763,120149516,106907488,90247483,55278888,83634890,26220477,133429657,134291341,67962165,102611987,78209219,123116708,56797777,38254315,99160685,40801077,18206523,90403438,96884501,89939923,90704566,21910498,96863340,74310984,70006448,59618015,72462291,25892069,48792519,39009680,112270430,98246423,14288031,112644070,57610566,19936956,117113146,4113978,95352569,65843878,71076167,60117679,104368912,31431216,128325629,67731501,86396140,72904827,2526590,24280599,71606365,115882957,41331204,131738828,13048050,26951535,42473681,133533473,132347619,112237258,100301245,45357069,82615782,55635866,26347114,106800099,26417572,30257513,24567678,5135738,89760357,35044991,14825144,51876073,133438263,112794022,66906734,33613612,36882667,131739622,69467978,76035891,46374841,69947815,65745578,60802087,107791076,27694285,103134164,28845134,56374995,74509691,100947666,54737872,54323629,104825279,49556397,61871432,59433417,92479810,24987343,44974886,78049016,74651793,131310946,123076389,23827503,32780498,122814008,79480358,40114679,108645752,87253173,9404390,59366696,103340339,18019654,58427436,123411247,122767531,131652653,47809513,11144541,5752843,46843099,102556976,75448535,59479983,480938,72060011,53262583,47569127,44016601,99737548,93882,90568115,125891252,100707413,129054689,75033734,56539032,81405087,94330069,82153157,67532499,9491526,91445122,98746764,92748435,11353150,108185221,95930896,86017813,93240952,61593524,42085038,16326710,91788414,85454637,29872098,99011028,20484059,83394964,69324195,99411734,105075731,115515854,13107968,3151274,116415188,53388904,27922677,90743194,50739983,90526394,40100406,24557502,122469465,9448796,74346179,122853371,96645823,20797293,21796784,17831658,100620993,25724587,44474440,8978677,13041919,81777314,48999282,55225918,53423365,32435528,127865706,6035767,73795793,34329857,43814229,129737792,112993171,82456892,100149457,101046923,9289912,842669,48983587,13059687,52470541,107864607,84227225,93233687,100768545,35983862,870451,56516996,66492244,42498661,22827895,132301563,98181621,127415837,130962310,91690763,39579876,102838246,73002957,27520870,79902536,109099537,70100599,67404515,85171687,20839391,115692911,101263743,48151238,133222895,90560286,23163955,76381570,85319617,63920745,57533283,68552278,102196222,45415213,53857986,36768339,60276613,42065347,125247831,76921630,118795162,5625373,3957099,21966915,16302433,78977029,83766933,37129994,17584516,79728873,70427663,70318518,116880832,111313395,94814779,29607742,125560375,72161564,66793202,120260029,127389909,10856241,111280397,103232081,108534252,45177642,109019188,134030253,22175887,63692449,4583502,112333582,33559936,15382241,68806714,110237657,59022733,10049406,117621209,20779886,96265824,58020339,91107100,18143953,129938028,120462121,23174953,1853276,41683620,71851681,121856823,23228953,97023774,42359166,109928096,50358377,27446342,86838794,96642231,66162861,87324702,10930841,121426415,110874157,84267068,55521942,89330885,79477413,104738166,41448239,9766281,5536060,65502203,18636018,40694365,106741558,63866525,34428645,48266013,119154354,87977344,111527653,68282956,132818766,113079857,91591643,39605275,26903585,93499204,68370597,43074923,21116811,47554947,100290988,13870353,67740156,36807943,117425171,113689190,114013167,9937281,34877307,85405469,131081591,66007357,49059664,98025400,8767865,14576411,103236582,99445632,110099846,71281841,77048977,126786994,58575748,26596444,89739571,20955683,132876433,118667531,55147207,126801934,30893304,51321294,65044602,5095993,50913997,1406190,115366977,24235264,13092365,51233323,93031369,129137885,37818994,72279792,92816397,41378017,37364616,16238111,133460582,110347273,46407959,35479797,64835662,61359683,94233975,98957066,39355213,67191078,116498323,33078316,91548094,106687690,133815897,53234284,67269353,35150304,103754008,85412263,78524363,21045548,96386411,81989943,80050053,82811384,97906219,14005136,113759288,122132932,17473929,92158016,74354590,85904482,55482271,118792296,67893009,35983939,115208180,84319300,8243647,3502033,134105132,131316195,6765964,129838929,18525476,94367510,127521896,114149960,53215231,107103561,32255750,127880023,113386704,33825514,34011551,46595177,84069299,113510736,55747635,13819979,64645821,39384625,16222866,32371103,119221772,99078413,111369857,97914167,36588680,7455259,3702310,61940999,44387690,80253318,56683185,79371780,99339643,110962059,27852371,14540752,84924345,44302826,92089672,29492836,92093272,33269678,120013054,41046690,104201099,28993849,59305427,75835453,100200239,65646558,126623243,3520446,28324976,105534807,129508010,123353332,105880886,127733718,133979673,32160414,129291675,40933549,70296420,19048568,76255625,87293490,72641469,84016402,17848394,52294772,50389475,102702919,27821913,67439374,102533264,98482214,85705482,80113799,63600325,16279678,24898624,74353543,124272522,122242063,4028236,111188658,112359413,96597406,17966994,12783736,86405629,90175003,120958474,65608160,7444914,84236262,123690589,7546562,64583839,104967000,24321391,32261932,56983422,48997040,105859075,69691436,88623611,48312043,105486076,71322824,5799394,122765063,103791846,34983369,69364859,34664304,58895391,86120655,93269113,79150599,44867189,13453528,12029236,50455252,60398380,103790686,99086202,120580468,99994872,44394436,5726310,40284169,38535660,99370987,39951542,65839277,119647299,48073185,34637029,17412488,103910610,11569532,91895875,9599888,50820116,118427843,43949183,42999693,117697835,42914867,83367243,41310186,71618340,117707086,18664027,121014994,41796657,25957978,64076656,35553428,30792208,74815321,41034239,460930,94049175,115342314,100500760,112292800,8626756,50883476,54784229,9666235,88038534,93654719,113248418,42712121,84292206,101330205,105685153,78431032,32876904,67004528,10022085,54387564,104851782,103709360,27848793,46759222,29489160,81116087,9317969,100822045,22376412,83562083,110182728,39320209,61871848,60538388,102540813,56651003,129293924,531836,92131342,33698785,61250227,108880159,19767189};
// random 128 bytes
const byte rkey[]={103,198,105,115,81,255,74,236,41,205,186,171,242,251,227,70,124,194,84,248,27,232,231,141,118,90,46,99,51,159,201,154,102,50,13,183,49,88,163,90,37,93,5,23,88,233,94,212,171,178,205,198,155,180,84,17,14,130,116,65,33,61,220,135,112,233,62,161,65,225,252,103,62,1,126,151,234,220,107,150,143,56,92,42,236,176,59,251,50,175,60,84,236,24,219,92,2,26,254,67,251,250,170,58,251,41,209,230,5,60,124,148,117,216,190,97,137,249,92,187,168,153,15,149,177,235,241,179};
/* Montgomery stuff */
static int32_t redc(uint64_t T)
{
uint32_t m=(uint32_t)T*(uint32_t)ND;
return ((uint64_t)m*PRIME+T)>>32;
}
static int32_t nres(uint32_t x)
{
return redc((uint64_t)x*R2MODP);
}
static int32_t modmul(uint32_t a,uint32_t b)
{
return redc((uint64_t)a*b);
}
/* NTT code */
/* Cooley-Tukey NTT */
static void ntt(int32_t *b)
{
int m,i,j,k,t=DEGREE/2;
int32_t S,U,V,q=PRIME;
for (j=0;j<DEGREE;j++)
b[j]=nres(b[j]);
m=1;
while (m<DEGREE)
{
k=0;
for (i=0;i<m;i++)
{
S=roots[m+i];
for (j=k;j<k+t;j++)
{
U=b[j];
V=modmul(b[j+t],S);
b[j]=U+V;
b[j+t]=U+2*q-V;
}
k+=2*t;
}
t/=2;
m*=2;
}
}
/* Gentleman-Sande INTT */
static void intt(int32_t *b)
{
int m,i,j,k,n,t=1;
int32_t S,U,V,W,q=PRIME;
int lim;
m=DEGREE/2;
n=LGN;
while (m>=LIM)
{
n--;
k=0;
for (i=0;i<m;i++)
{
S=iroots[m+i];
for (j=k;j<k+t;j++)
{
U=b[j];
V=b[j+t];
b[j]=U+V;
W=U+DLQ-V;
b[j+t]=modmul(W,S);
}
k+=2*t;
}
t*=2;
m/=2;
}
while (m>1)
{
lim=LIM>>n;
n--;
k=0;
for (i=0;i<m;i++)
{
S=iroots[m+i];
for (j=k;j<k+lim;j++)
{
U=modmul(b[j],ONE);
V=modmul(b[j+t],ONE);
b[j]=U+V;
W=U+DLQ-V;
b[j+t]=modmul(W,S);
}
for (j=k+lim;j<k+t;j++)
{
U=b[j];
V=b[j+t];
b[j]=U+V;
W=U+DLQ-V;
b[j+t]=modmul(W,S);
}
k+=2*t;
}
t*=2;
m/=2;
}
t=DEGREE/2;
for (j=0;j<t;j++)
{
if (j<LIM/2)
{ // need to knock back excesses. Never used if L=1.
U=modmul(b[j],ONE);
V=modmul(b[j+t],ONE);
}
else
{
U=b[j];
V=b[j+t];
}
W=U+DLQ-V;
b[j+t]=modmul(W,invpr);
b[j]=modmul(U+V,inv);
}
for (j=0;j<DEGREE;j++)
{
b[j]=redc((uint64_t)b[j]);
b[j]=b[j]-q;
b[j]+=(b[j]>>31)&q;
}
}
// polynomial functions
/* reduces inputs < 2q */
static void poly_soft_reduce(int32_t *poly)
{
int i;
int32_t e;
for (i=0;i<DEGREE;i++)
{
e=poly[i]-PRIME;
poly[i]=(e+((e>>31)&PRIME)); //**
}
}
/* fully reduces modulo q */
static void poly_hard_reduce(int32_t *poly)
{
int i;
int32_t e;
for (i=0;i<DEGREE;i++)
{
e=modmul(poly[i],ONE);
e=e-PRIME;
poly[i]=e+((e>>31)&PRIME);
}
}
// multiply two polynomials in frequency domain
static void poly_mul(int32_t *p1,int32_t *p2,int32_t *p3)
{
int i;
for (i=0;i<DEGREE;i++)
p1[i]=modmul(p2[i],p3[i]);
poly_hard_reduce(p1);
}
static void poly_add(int32_t *p1,int32_t *p2,int32_t *p3)
{
int i;
for (i=0;i<DEGREE;i++)
p1[i]=(p2[i]+p3[i]); //**
}
static void poly_sub(int32_t *p1,int32_t *p2,int32_t *p3)
{
int i;
for (i=0;i<DEGREE;i++)
p1[i]=(p2[i]+PRIME-p3[i]); //**
}
// shorten, but round to VBITS
static void poly_shorten(int32_t *p)
{
int i;
for (i=0;i<DEGREE;i++) {
p[i]/=(1<<(UBITS-VBITS-1));
if ((p[i]&1) == 1) {
p[i]>>=1;
p[i]+=1;
} else {
p[i]>>=1;
}
}
}
static void poly_lengthen(int32_t *p)
{
int i;
for (i=0;i<DEGREE;i++)
p[i]*=(1<<(UBITS-VBITS));
}
static void hid(char *ID,int32_t *id)
{ // hash identity to polynomial
sha3 SHA3;
char hash[4*DEGREE];
SHA3_init(&SHA3,SHAKE128);
int k,m,i=0;
while (ID[i]!=0)
SHA3_process(&SHA3,ID[i++]);
SHA3_shake(&SHA3,hash,4*DEGREE);
for (i=m=0;i<DEGREE;i++)
{
byte n=(byte)hash[m++];
uint32_t s=(uint32_t)n;
for (k=1;k<4;k++) {s<<=8; n=(byte)hash[m++]; s+=(uint32_t)n;}
s%=PRIME;
id[i]=(int32_t)s;
//if (id[i]>(PRIME/2)) id[i]-=PRIME;
}
}
// get n-th bit from byte array
static int getbit(byte b[],int n)
{
int wd=n/8;
int bt=n%8;
return (b[wd]>>bt)&1;
}
// centered binomial distribution
static void CBD(byte bts[],int32_t *f)
{
int a,b;
for (int i=0;i<DEGREE;i++)
{
a=getbit(bts,2*i);
b=getbit(bts,2*i+1);
f[i]=(PRIME+a-b)%PRIME;
}
}
// hash internal key of length DEGREE/8 into external key of length 32
static void hdk(byte *ikey,byte *key) {
sha3 SHA3;
SHA3_init(&SHA3,SHA3_HASH256);
for (int i=0;i<DEGREE/8;i++) SHA3_process(&SHA3,ikey[i]);
SHA3_hash(&SHA3,(char *)key);
}
static void expand(byte *ikey,int32_t *key) {
int i,k,m;
byte next=0;
for (m=k=i=0;i<DEGREE;i++)
{ // expand into polynomial
if (m==0)
next=ikey[k++];
key[i]=(next&1)*(PRIME/2);
next>>=1; m++; m&=7;
}
}
static void shrink(int32_t *key,byte *ikey)
{
int i,k,m;
byte next=0;
for (m=k=i=0;i<DEGREE;i++)
{ // shrink into byte array
next+=((key[i]/(PRIME/2))&1)<<m; m++;
if (m==8) {
m=0;
ikey[k]=next; k++;
next=0;
}
}
}
// array t has ab active bits per word
// extract bytes from array of words
static byte nextbyte32(int ab,int32_t *t,int &ptr, int &bts)
{
int32_t r,w;
int left=ab-bts; // number of bits left in this word
int i=0;
w=t[ptr];
r=w>>bts;
while (left<8)
{
i++;
w=t[ptr+i];
r|=w<<left;
left+=ab;
}
bts+=8;
while (bts>=ab)
{
bts-=ab;
ptr++;
}
return (byte)r&0xff;
}
// extract ab bits into word from dense byte stream
static int32_t nextword(const int ab,byte t[],int &ptr, int &bts)
{
int32_t r=t[ptr]>>bts;
int32_t mask=(1<<ab)-1;
int32_t w;
int i=0;
int gotbits=8-bts; // bits left in current byte
while (gotbits<ab)
{
i++;
w=(int32_t)t[ptr+i];
r|=w<<gotbits;
gotbits+=8;
}
bts+=ab;
while (bts>=8)
{
bts-=8;
ptr++;
}
w=r&mask;
return w;
}
// pack ciphertext
static int pack_ct(byte ct[],int32_t *u,int32_t *v)
{
int ptr,bts,i,n=0;
ptr=bts=0;
for (i=0;i<ULEN;i++)
ct[n++]=nextbyte32(UBITS,u,ptr,bts);
ptr=bts=0;
for (i=0;i<VLEN;i++)
ct[n++]=nextbyte32(VBITS,v,ptr,bts);
return n;
}
// pack ciphertext and check its the same
static int chk_pack_ct(byte ct[],int32_t *u,int32_t *v)
{
int ptr,bts,i,n=0;
byte m,diff=0;
ptr=bts=0;
for (i=0;i<ULEN;i++) {
m=nextbyte32(UBITS,u,ptr,bts);
diff|=(m^ct[n++]);
}
ptr=bts=0;
for (i=0;i<VLEN;i++) {
m=nextbyte32(VBITS,v,ptr,bts);
diff|=(m^ct[n++]);
}
return diff;
}
// unpack ciphertext
static void unpack_ct(int32_t *u,int32_t *v,byte pk[])
{
int ptr,bts,i;
ptr=bts=0;
for (i=0;i<DEGREE;i++ )
u[i]=nextword(UBITS,pk,ptr,bts);
for (i=0;i<DEGREE;i++ )
v[i]=nextword(VBITS,pk,ptr,bts);
}
// ID is identity, ikey is input session key, ud/vt is ciphertext
static void cpa_base_encrypt(char *ID,byte *ikey,int32_t *ud,int32_t *vd)
{
int i,j;
int32_t rd[DEGREE],e[DEGREE];
byte sigma[32];
byte buff[256];
sha3 sh;
hdk(ikey,sigma); // Use ikey as seed
SHA3_init(&sh,SHAKE256);
for (j=0;j<32;j++)
SHA3_process(&sh,sigma[j]);
SHA3_process(&sh,0);
SHA3_shake(&sh,(char *)buff,256);
CBD(buff,rd);
for (i=0;i<DEGREE;i++)
e[i]=H[i]; // already in ntt format
ntt(rd);
poly_mul(ud,e,rd);
intt(ud);
SHA3_init(&sh,SHAKE256);
for (j=0;j<32;j++)
SHA3_process(&sh,sigma[j]);
SHA3_process(&sh,1);
SHA3_shake(&sh,(char *)buff,256);
CBD(buff,e);
poly_add(ud,ud,e);
poly_hard_reduce(ud);
// v=rt+e2+K
hid(ID,e);
ntt(e);
poly_mul(vd,e,rd);
intt(vd);
SHA3_init(&sh,SHAKE256);
for (j=0;j<32;j++)
SHA3_process(&sh,sigma[j]);
SHA3_process(&sh,2);
SHA3_shake(&sh,(char *)buff,256);
CBD(buff,e);
poly_add(vd,vd,e);
poly_soft_reduce(vd);
expand(ikey,e); // expand to polynomial - re-use e
poly_add(vd,vd,e);
poly_hard_reduce(vd);
poly_shorten(vd);
// pack_ct(ct,ud,vd);
}
// ID is identity, ikey is input session key, ct is ciphertext
static void cpa_encrypt(char *ID,byte *ikey,byte *ct)
{
int32_t ud[DEGREE],vd[DEGREE];
cpa_base_encrypt(ID,ikey,ud,vd);
pack_ct(ct,ud,vd);
}
// ID is identity, ikey is output session key, ct is ciphertext
// This time checking that (ud,vd) does in fact compress to ct
static byte cpa_check_encrypt(char *ID,byte *ikey,byte *ct)
{
int32_t ud[DEGREE],vd[DEGREE];
cpa_base_encrypt(ID,ikey,ud,vd);
byte d=chk_pack_ct(ct,ud,vd);
if (d==0)
return 0;
else
return 0xff;
}
static void cpa_decrypt(const int16_t *csk,byte *ct,byte *ikey) {
int i;
int32_t sk[DEGREE];
int32_t u[DEGREE],v[DEGREE];
//byte ikey[DEGREE/8];
unpack_ct(u,v,ct);
for (int i=0;i<DEGREE;i++) {
sk[i]=(int32_t)csk[i];
if (sk[i]<0) sk[i]+=PRIME;
}
poly_lengthen(v);
ntt(sk);
ntt(u);
poly_mul(u,u,sk);
intt(u);
poly_sub(v,v,u);
poly_hard_reduce(v);
for (i=0;i<DEGREE;i++)
{
if (v[i]>(PRIME/4) && v[i]<((3*PRIME)/4)) v[i]=PRIME/2;
else v[i]=0;;
}
shrink(v,ikey);
}
// encapsulate 32-byte key inside ciphertext ct
void PQIBE_CCA_ENCRYPT(char *ID,octet *R32,octet *KEY,octet *CT)
{
int i;
byte ikey[DEGREE/8],ss[32];
sha3 sh;
SHA3_init(&sh,SHAKE256);
for (i=0;i<R32->len;i++)
SHA3_process(&sh,R32->val[i]);
SHA3_shake(&sh,(char *)ikey,128);
hdk(ikey,ss);
cpa_encrypt(ID,ikey,(byte *)CT->val);
for (i=0;i<32;i++)
CT->val[i+ULEN+VLEN]=(char)ss[i];
CT->len=ULEN+VLEN+32;
SHA3_init(&sh,SHA3_HASH256);
for (i=0;i<CT->len;i++)
SHA3_process(&sh,(unsigned char)CT->val[i]);
for (i=0;i<DEGREE/8;i++)
SHA3_process(&sh,ikey[i]);
SHA3_hash(&sh,KEY->val);
KEY->len=32;
}
// decapsulate 32-byte key inside ciphertext ct
void PQIBE_CCA_DECRYPT(char *ID,const int16_t *csk,octet *CT,octet *KEY) {
int i;
byte ikey[DEGREE/8];
sha3 sh;
cpa_decrypt(csk,(byte *)CT->val,ikey);
byte mask=cpa_check_encrypt(ID,ikey,(byte *)CT->val); // make sure to generate the same ciphertext
for (i=0;i<DEGREE/8;i++)
ikey[i]^=(ikey[i]^rkey[i])&mask; // if not substitute some nonsense
SHA3_init(&sh,SHA3_HASH256);
for (i=0;i<CT->len;i++)
SHA3_process(&sh,(unsigned char)CT->val[i]);
for (i=0;i<DEGREE/8;i++)
SHA3_process(&sh,ikey[i]);
SHA3_hash(&sh,KEY->val);
KEY->len=32;
}
/*
int main() {
int i,m,k;
byte ikey[DEGREE/8],ikey2[DEGREE/8];
sha3 SHA3;
byte ct[4000];
byte key[32];
byte key2[32];
byte r32[32];
//for (i=0;i<128;i++)
// printf("%d,",rand()%256);
//printf("\n");
for (m=0;m<100;m++)
{
for (i=0;i<32;i++) // create byte array with DEGREE bits for polynomial
r32[i]=rand()%256;
// for (i=0;i<DEGREE/8;i++) // create byte array with DEGREE bits for polynomial
// ikey[i]=rand()%256;
// cpa_encrypt(ID,ikey,ct);
// cout << "session key= ";
// for (i=0;i<32;i++) {
// cout << (int)ikey[i] << ",";
// }
// cout << endl;
// cpa_decrypt(csk,ct,ikey2);
// cout << "session key= ";
// for (i=0;i<32;i++) {
// cout << (int)ikey2[i] << ",";
// }
// cout << endl;
core::IBE_CCA_encrypt(ID,r32,key,ct);
printf("EK= ");
for (i=0;i<32;i++)
printf("%d,",key[i]);
printf("\n");
core::IBE_CCA_decrypt(ID,csk,ct,key2);
printf("DK= ");
for (i=0;i<32;i++)
printf("%d,",key2[i]);
printf("\n");
for (i=0;i<32;i++)
{
if (key[i]!=key2[i]) {printf("SCREAM\n"); exit(0);}
}
}
return 0;
}
*/