MastersThesis/TIIGER_TLS/PQ_TIIGER_TLS/lib/ibe/tls_pqibe.cpp

642 lines
52 KiB
C++
Raw Normal View History

2024-04-15 09:53:30 +00:00
//
// 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,0x7543b6
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,
// 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,0x2e
//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
// 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;
}
*/