package org.bouncycastle.pqc.crypto.qtesla;

import org.bouncycastle.util.Arrays;

class Sample
{

    static final double[][] EXPONENTIAL_DISTRIBUTION_I = {
        /* [3][32] */
        {
            1.0000000000000000000000000000000000000000, 0.9990496327075997720621566739241504871513,
            0.9981001686131900082646604498429491608001, 0.9971516068584008799087793737854343387385,
            0.9962039465856783249057599531380206128030, 0.9952571869382832724989228009014122394200,
            0.9943113270602908687225570427678069689363, 0.9933663660965897025969132575731249565771,
            0.9924223031928810330585953871541593536283, 0.9914791374956780166256527164832613053574,
            0.9905368681523049357966736891640434381216, 0.9895954943108964281831839869512129866330,
            0.9886550151203967163746519649066284074237, 0.9877154297305588385354051961226109899227,
            0.9867767372919438797327625416330343864518, 0.9858389369559202039956868221933583419625,
            0.9849020278746626871032638290431658501235, 0.9839660092011519501023140705695025630520,
            0.9830308800891735935534443109670000387768, 0.9820966396933174325048466155419862577528,
            0.9811632871689767321931532752331431453491, 0.9802308216723474444706566402213564033800,
            0.9792992423604274449582035491768120172661, 0.9783685483910157709230746967427200384407,
            0.9774387389227118598811599372828827520575, 0.9765098131149147889227411777252636721429,
            0.9755817701278225147611951665163479411869, 0.9746546091224311145039291392620050672727,
            0.9737283292605340271448629345703623656609, 0.9728029297047212957777718459314622781631,
            0.9718784096183788105298051271677986565965, 0.9709547681656875522144957200697952895280
        },

        {
            1.0000000000000000000000000000000000000000, 0.9700320045116228367035774232914930379400,
            0.9409620897768370674212298508058219852849, 0.9127633421156708668942503744059309052528,
            0.8854096543971923811501043960464255901147, 0.8588757018688517364879932717859212289637,
            0.8331369187101692180902460141030849026557, 0.8081694752890624155161689578277768341910,
            0.7839502560997556536888618983783791053116, 0.7604568383618460545183896873859249753543,
            0.7376674712607126902372883387750345338472, 0.7155610558100490615694685434237323547987,
            0.6941171253178751117406951384261687867164, 0.6733158264379437043232142381368341940533,
            0.6531379007889984662634253213819854052726, 0.6335646671248656289427239706049936967143,
            0.6145780040388724765036124496076447154217, 0.5961603331865797040852326968966728810261,
            0.5782946030112948570545930362131434268247, 0.5609642729572995100665682618108293115511,
            0.5441532981561743827978648643747061873131, 0.5278461145720445955231454653404664082188,
            0.5120276245919921478529972155927751107378, 0.4966831830482948512984566287866591847562,
            0.4817985836595507424420546966358580262381, 0.4673600458781348185224193866260805625424,
            0.4533542021318111302275642196084653301628, 0.4397680854476881857303133336231578259611,
            0.4265891174470596033395475021945475958821, 0.4138050967000153253100465421861800587782,
            0.4014041874290417902572763743098032661210, 0.3893749085511525646401543103372782315254
        },

        {
            1.0000000000000000000000000000000000000000000, 0.3777061230484043540417651455683576466650000,
            0.1426619153882563708052119679085105421822000, 0.0538842789679578114076165050703859298545800,
            0.0203524221022460198907862721163275696205800, 0.0076872344468839996101743286763347159496400,
            0.0029035155198967005412614828182250511400990, 0.0010966755902310549151227158892825815595730,
            0.0004142210854279922997296008273437255752956, 0.0001564538402619088712753422615493598849163,
            5.909357344135995142394679824207999201121E-5, 2.232000452161222135025591154935960584027E-5,
            8.430402374281007236700902260035220289887E-6, 3.184214596527742337148476455363347356131E-6,
            1.202697350208632670782595114365065060885E-6, 4.542661533478916755570208360842380811059E-7,
            1.715791076131440947144583312662638239090E-7, 6.480647953266561572601959656715022445021E-8,
            2.447780413269889735078224512008720987199E-8, 9.245416499699910342143072277116651273927E-9,
            3.492050422069402212293514861017928736701E-9, 1.318968826409377991494549187659977485249E-9,
            4.981826018447900060525041555590742055479E-10, 1.881666191129624879723808164319051826703E-10,
            7.107168419228284402686789774896404982106E-11, 2.684421029478771850078976357840397379201E-11,
            1.013922259674033292202917547107956246173E-11, 3.829646457739566105989785588606755995719E-12,
            1.446480916198866420590826731657500079699E-12, 5.463446989209777070985952848270039796153E-13,
            2.063577380774902353530525926195322827410E-13, 7.794258121028692337871970872695782456164E-14
        }

    };

    static final double[][] EXPONENTIAL_DISTRIBUTION_III_SIZE = {
        /* [3][32] */
        {
            1.0000000000000000000000000000000000000000, 0.9914791374956780166256527164832613053571,
            0.9830308800891735935534443109670000387763, 0.9746546091224311145039291392620050672719,
            0.9663497112088951922951613058690022829314, 0.9581155781885929401990530331782558043141,
            0.9499516070835989810875119461809064028436, 0.9418572000538799331122753584612083652659,
            0.9338317643535151384510743106138183393464, 0.9258747122872904292046909607697858626681,
            0.9179854611676617518466375609653990674902, 0.9101634332720854987115840832838713554612,
            0.9024080558007124218622779514513692802555, 0.8947187608344420312994997523024746481561,
            0.8870949852933344058775329566907233056474, 0.8795361708953763714606266672461444022383,
            0.8720417641155990268059148554652540437481, 0.8646112161455436233871237462566364157436,
            0.8572439828530728308830350554160731167048, 0.8499395247425244453469447315612369857573,
            0.8426973069152046221501168284377584096225, 0.8355167990302177406553164840946716839800,
            0.8283974752656300322277354108287439566785, 0.8213388142799641276318029906853001579399,
            0.8143402991740217040952958306017837324709, 0.8074014174530314363485930132316684297705,
            0.8005216609891194797686327175999898485396, 0.7937005259840997373758528196362056425534,
            0.7869375129325811858498730937766509221324, 0.7802321265853895589476145632070372895529,
            0.7735838759133007097276526159890746982448, 0.7669922740710829958085504579386416555178
        },

        {
            1.0000000000000000000000000000000000000000000, 0.7604568383618460545183896873859249753475000,
            0.5782946030112948570545930362131434268144000, 0.4397680854476881857303133336231578259493000,
            0.3344246478719911187527828322027724928608000, 0.2543155103910080342970055083858543302085000,
            0.1933959689783251774319131539973439846964000, 0.1470692871211828233002294902623869285186000,
            0.1118398451043052539124374690378746581867000, 0.0850493750108985602659800234578596968909400,
            0.0646763788254389154655681775607238774758000, 0.0491835945582863241156170683610789877042500,
            0.0374020008170653143735533498156831735514100, 0.0284426072897526718347370026026486693779300,
            0.0216293752143329118535087528015400204365400, 0.0164482062912336825104561988130156459132400,
            0.0125081509529549918713848862125144537439400, 0.0095119089274368649464762531606995319241100,
            0.0072333961897444564781616481310238106761860, 0.0055006855970716932734388078251246759697760,
            0.0041830339779716833064716700383503988117580, 0.0031810167936485222816222493382931725715270,
            0.0024190259736738921137934575940109408536480, 0.0018395648438552342443599128094977711325760,
            0.0013989096651197544439950127319659303796870, 0.0010638104210907972987681203969116907947710,
            0.0008089819094390918283473978621390203944673, 0.0006151958251439810374839895543363501050953,
            0.0004678298721623988965815688638575721914033, 0.0003557644254758444808169155363704398225966,
            0.0002705434901989792929582192527080744710506, 0.0002057366471960948784546183663182928059645
        },

        {
            1.000000000000000000000000000000000000000, 0.0001564538402619088712753422615493598848717,
            2.447780413269889735078224512008720985804E-8, 3.829646457739566105989785588606755992447E-12,
            5.991628951587712183461314435723455239107E-16, 9.374133589003324437283071562544462897124E-20,
            1.466619199127720628458909574032394007656E-23, 2.294582059053771218038974267927533833163E-27,
            3.589961749350406706790987553377863179812E-31, 5.616633020792314645332222710264644857908E-35,
            8.787438054448034835939954112296077697602E-39, 1.374828429682032112779050229478845154715E-42,
            2.150971875250036652628677686695580621313E-46, 3.365278101782278104362461212648493483965E-50,
            5.265106825731444425408506379787751403098E-54, 8.237461822748734749731771711361450782154E-58,
            1.288782536179903234906819256928735424052E-61, 2.016349770478283712998453222332343703812E-65,
            3.154656649025460159903286438614052035760E-69, 4.935581474477980619913950088312373997931E-73,
            7.721906756076146364991353446502442654680E-77, 1.208121966132492313782281967679468463452E-80,
            1.890153211061962317744312705074835436919E-84, 2.957217285540223765931001823632869648146E-88,
            4.626680008116659240109379372702265238809E-92, 7.238618549328510447646200176448777448608E-96,
            1.132509670233533294861752560334068442100E-99, 1.771854870417843101882482426208692422294E-103,
            2.772134988636384669818807165401424398102E-107, 4.337111646965654912069237407317707678694E-111,
            6.785577728124290751600099215097500773985E-115, 1.061629693960724289088455922591023103484E-118
        }

    };

    static final double[][] EXPONENTIAL_DISTRIBUTION_III_SPEED = {
        /* [3][32] */
        {
            1.0000000000000000000000000000000000000000, 0.9951980443443537316500388424172839303752,
            0.9904191474668262564830185894967173613892, 0.9856631986401875746675941557587114196642,
            0.9809300876689149347041557365309129923940, 0.9762197048866395987965541168345276706016,
            0.9715319411536058687432894158212596709598, 0.9668666878541423134736924881553750396380,
            0.9622238368941451396373408016639000521875, 0.9576032806985736469363056351479270970296,
            0.9530049122089577101698314104664824876542, 0.9484286248809172302397073765744987564880,
            0.9438743126816934966419131566675496907225, 0.9393418700876924042461092785035073150884,
            0.9348311920820394674392081270253399758265, 0.9303421741521465749826061515830447550861,
            0.9258747122872904292046909607697858626672, 0.9214287029762026134209634491584644007645,
            0.9170040432046712317435415947941667461407, 0.9126006304531540657099452867877830194818,
            0.9082183626944031924279067014123113094560, 0.9038571383911010091985145255388756529519,
            0.8995168564935076098442888811876009946339, 0.8951974164371194582318032579854959087286,
            0.8908987181403393047402262055905414183192, 0.8866206620021572916876550405654798379036,
            0.8823631488998431939863624175501337704454, 0.8781260801866497415560803096876886684788,
            0.8739093576895269702812107160640808580937, 0.8697128837068475485533842136704059167642,
            0.8655365610061430266950922187780245940470, 0.8613802928218509568132024098758678171240
        },

        {
            1.000000000000000000000000000000000000000000, 0.857243982853072830883035055416073116703300,
            0.734867246137799425692104349091725698937400, 0.629960524947436582383605303639195946052600,
            0.540029869446153084936465415644391919699900, 0.462937356143645214602345480384983067321600,
            0.396850262992049868687926409818180089809000, 0.340197500043594241063920093831306311583500,
            0.291632259894029145223423158665267961335500, 0.250000000000000000000000000000097352251700,
            0.214310995713268207720758763854101733807800, 0.183716811534449856423026087273002965715400,
            0.157490131236859145595901325909860314588700, 0.135007467361538271234116353911150553048700,
            0.115734339035911303650586370096290834824400, 0.099212565748012467171981602454583656718920,
            0.085049375010898560265980023457859696888520, 0.072908064973507286305855789666345381391030,
            0.062500000000000000000000000000048676125830, 0.053577748928317051930189690963546297109930,
            0.045929202883612464105756521818268626674130, 0.039372532809214786398975331477480410666060,
            0.033751866840384567808529088477800781543110, 0.028933584758977825912646592524083975704600,
            0.024803141437003116792995400613655572746400, 0.021262343752724640066495005864473203970290,
            0.018227016243376821576463947416593443112050, 0.015625000000000000000000000000018253547190,
            0.013394437232079262982547422740891790191980, 0.011482300720903116026439130454571627979850,
            0.009843133202303696599743832869373935671238, 0.008437966710096141952132272119453481206014
        },

        {
            1.000000000000000000000000000000000000000, 0.007233396189744456478161648131023810675775,
            5.232202043780962102557587008169005410143E-5, 3.784659032745836912993682954976324658164E-7,
            2.737593822694567686662466634421542264066E-9, 1.980210072614684707158711353745069372717E-11,
            1.432364399414465384287735340977513952565E-13, 1.036085918905020069841154248521752033776E-15,
            7.494419938055456100418425186702743722723E-18, 5.421010862427522170037264004417260251684E-20,
            3.921231931684654880817938739668273317360E-22, 2.836382411375207747860568187463889509638E-24,
            2.051667772709962123314993704273413823620E-26, 1.484052584974173558955043468582713624191E-28,
            1.073474031353259824558654154333806911547E-30, 7.764862968180290824468612020607860317513E-33,
            5.616633020792314645332222710264644852793E-35, 4.062733189179202535382045195211707654781E-37,
            2.938735877055718769921841343128853888538E-39, 2.125704089576016965228859756656407540404E-41,
            1.537605986206336992222535387300608525931E-43, 1.112211328195318530448364746285024038827E-45,
            8.045065183558638234146057828832053516826E-48, 5.819314384499884015403474144560288801662E-50,
            4.209340649576656799996170991423257963815E-52, 3.044782861598424467581974062513986546956E-54,
            2.202412074968526631812431321732133496007E-56, 1.593091911132452277028880397827266782094E-58,
            1.152346495989819456843455045622426762614E-60, 8.335378753358135655955994470664225877261E-63,
            6.029309691461763611680553229574282672923E-65, 4.361238574900884540660050746922306538111E-67,
        }

    };

    static final double[][] EXPONENTIAL_DISTRIBUTION_P = {
        /* [3][32] */
        {
            1.0000000000000000000000000000000000000000, 0.9930924954370359015332102168880765048173,
            0.9862327044933591729073804985266878802443, 0.9794202975869268710835182321094224250961,
            0.9726549474122855185227020947295413763023, 0.9659363289248455510651443129204733029988,
            0.9592641193252643901322834293949397264660, 0.9526379980439373889289005948680289570903,
            0.9460576467255959075051119972754354254470, 0.9395227492140117766851490088262829075331,
            0.9330329915368074159813432661499603336007, 0.9265880618903708756879317851202732375877,
            0.9201876506248750783904312382017973974891, 0.9138314502294005401326428921359892449876,
            0.9075191553171608564550809482180658363403, 0.9012504626108302434560060155923701020040,
            0.8950250709279724289295293992056807493013, 0.8888426811665701935046683790031660959701,
            0.8827029962906548665450116490541232503509, 0.8766057213160350863710299119436526437378,
            0.8705505632961241391362700174797799990040, 0.8645372313078651954249311342751209858410,
            0.8585654364377537683418658040230197384022, 0.8526348917679567215371033354114150564474,
            0.8467453123625271602457822707284519309456, 0.8408964152537145430311254762332558266219,
            0.8350879194283693564930171007187976000468, 0.8293195458144416997480650199452263126561,
            0.8235910172675731299989737240342361894393, 0.8179020585577811249918276889374069238047,
            0.8122523963562355226097093827753290960475, 0.8066417592221263022701629871861700330324
        },

        {
            1.000000000000000000000000000000000000000000, 0.801069877589622077182576980035615205902700,
            0.641712948781452099037917089781420222618900, 0.514056913328033254673172479396413573907600,
            0.411795508633786564999486862017198273163900, 0.329876977693223564843500492807512798916800,
            0.264254510140345093624873553521627364440900, 0.211686328090631790061445567682195415303500,
            0.169575540930958985396762834141244920349500, 0.135841857815757262606900740466230788178000,
            0.108818820412015517392033752185036062422000, 0.087171479146900338767218235365499637556050,
            0.069830446129513747913186914700207350540810, 0.055939066932998276808095587450398613186620,
            0.044811101500494605684562734558780780465070, 0.035896823593657343962457092086843785683310,
            0.028755864082027346199700976193834163154190, 0.023035456520173456442055699495851578765410,
            0.018453010334836412492976026695119689178670, 0.014782150730087436054767374957445947431420,
            0.011841535675862485018337967197721359270050, 0.009485897534336303604787967133085469399049,
            0.007598866776658480613458610115084898737984, 0.006087223278597655149117219956228990612855,
            0.004876291206646921576592633968279399063782, 0.003906250000000000000000000000006084516053,
            0.003129179209334461238994441328268996020587, 0.002506691206177547261866863631962577257343,
            0.002008034817687629901067079997645368310618, 0.001608576205600728769529245554757186330929,
            0.001288581944114154550169923800031354012535, 0.001032244180235723021972162318445464753156
        },

        {
            1.000000000000000000000000000000000000000, 0.0008268997191040304299275217487598638498908,
            6.837631454543244275598561791827450446268E-7, 5.654035529098691704742888887601969318770E-10,
            4.675320390815916240837145591289455678271E-13, 3.866021117887026910581260785663924052584E-16,
            3.196811776431032265107748321378670183434E-19, 2.643442759959277106397015416454182808165E-22,
            2.185862075677909177530183421677021601630E-25, 1.807488736378216004902267757945329990433E-28,
            1.494611928394845722509566662381681852231E-31, 1.235894183759231170477230799378805483584E-34,
            1.021960553392813221805059629881904702629E-37, 8.450588945359167454685108853553438401193E-41,
            6.987789625181120323479538530531788834637E-44, 5.778201278220326478541087516212630539830E-47,
            4.777993013886937548374901071454718579294E-50, 3.950921081064128423947108109095179681258E-53,
            3.267015532134120033414586853048549151733E-56, 2.701494225830208356330596231491229575841E-59,
            2.233864816500159437321055999997722887780E-62, 1.847182189280358319436455385107649366142E-65,
            1.527434433449896263866613728025637317872E-68, 1.263035103969543081968346060350962609985E-71,
            1.044403372690945043917523022329044283453E-74, 8.636168555094444625386351863230863826745E-78,
            7.141245352342656606906053992842560076147E-81, 5.905093775905105564186232605424573035226E-84,
            4.882920384578890205960673105845289217904E-87, 4.037685494415628551550334502904113261957E-90,
            3.338761001162701476381524668052565130775E-93, 2.760820534016929266476966660680800456743E-96
        }

    };

    static final long[][] CUMULATIVE_DISTRIBUTION_TABLE_I = {
        /* [12][2] */
        {0x0200000000000000L, 0x0000000000000000L}, {0x0300000000000000L, 0x0000000000000000L},
        {0x0320000000000000L, 0x0000000000000000L}, {0x0321000000000000L, 0x0000000000000000L},
        {0x0321020000000000L, 0x0000000000000000L}, {0x0321020100000000L, 0x0000000000000000L},
        {0x0321020100200000L, 0x0000000000000000L}, {0x0321020100200100L, 0x0000000000000000L},
        {0x0321020100200100L, 0x0200000000000000L}, {0x0321020100200100L, 0x0200010000000000L},
        {0x0321020100200100L, 0x0200010000200000L}, {0x0321020100200100L, 0x0200010000200001L},

    };

    static final long[][] CUMULATIVE_DISTRIBUTION_TABLE_III = {
        /* [14][3] */
        {0x0000020000000000L, 0x0000000000000000L, 0x0000000000000000L},
        {0x0000030000000000L, 0x0000000000000000L, 0x0000000000000000L},
        {0x0000032000000000L, 0x0000000000000000L, 0x0000000000000000L},
        {0x0000032100000000L, 0x0000000000000000L, 0x0000000000000000L},
        {0x0000032102000000L, 0x0000000000000000L, 0x0000000000000000L},
        {0x0000032102010000L, 0x0000000000000000L, 0x0000000000000000L},
        {0x0000032102010020L, 0x0000000000000000L, 0x0000000000000000L},
        {0x0000032102010020L, 0x0100000000000000L, 0x0000000000000000L},
        {0x0000032102010020L, 0x0100020000000000L, 0x0000000000000000L},
        {0x0000032102010020L, 0x0100020001000000L, 0x0000000000000000L},
        {0x0000032102010020L, 0x0100020001000020L, 0x0000000000000000L},
        {0x0000032102010020L, 0x0100020001000020L, 0x0001000000000000L},
        {0x0000032102010020L, 0x0100020001000020L, 0x0001000002000000L},
        {0x0000032102010020L, 0x0100020001000020L, 0x0001000002000001L}

    };

    private static long modulus7(long number)
    {

        long temporary = number;

        for (int i = 0; i < 2; i++)
        {

            temporary = (temporary & 7) + (temporary >> 3);

        }

        return ((temporary - 7) >> 3) & temporary;

    }

    
Description: Samples Polynomial Y, Such That Each Coefficient is in the Range [-B, B], for Heuristic qTESLA Security Category-1 and Security Category-3 (Option for Size or Speed)
Params:
  • Y – Polynomial Y
  • seed – Kappa-Bit Seed
  • seedOffset – Starting Point of the Kappa-Bit Seed
  • nonce – Domain Separator for Error Polynomial and Secret Polynomial
  • n – Polynomial Degree
  • q – Modulus
  • b – Determines the Interval the Randomness is Chosen in During Signing
  • bBit – b = 2 ^ bBit - 1
Returns:none
/****************************************************************************************************************** * Description: Samples Polynomial Y, Such That Each Coefficient is in the Range [-B, B], for Heuristic qTESLA * Security Category-1 and Security Category-3 (Option for Size or Speed) * * @param Y Polynomial Y * @param seed Kappa-Bit Seed * @param seedOffset Starting Point of the Kappa-Bit Seed * @param nonce Domain Separator for Error Polynomial and Secret Polynomial * @param n Polynomial Degree * @param q Modulus * @param b Determines the Interval the Randomness is Chosen in During Signing * @param bBit b = 2 ^ bBit - 1 * * @return none ******************************************************************************************************************/
public static void sampleY(int[] Y, final byte[] seed, int seedOffset, int nonce, int n, int q, int b, int bBit) { int i = 0; int position = 0; int numberOfByte = (bBit + 1 + 7) / 8; int numberOfBlock = n; byte[] buffer = new byte[n * numberOfByte]; int[] y = new int[4]; short dualModeSampler = (short)(nonce << 8); if (q == Parameter.Q_I) { HashUtils.customizableSecureHashAlgorithmKECCAK128Simple( buffer, 0, n * numberOfByte, dualModeSampler++, seed, seedOffset, Polynomial.RANDOM ); } if (q == Parameter.Q_III_SIZE || q == Parameter.Q_III_SPEED) { HashUtils.customizableSecureHashAlgorithmKECCAK256Simple( buffer, 0, n * numberOfByte, dualModeSampler++, seed, seedOffset, Polynomial.RANDOM ); } while (i < n) { if (position > numberOfBlock * numberOfByte * 4) { if (q == Parameter.Q_I) { numberOfBlock = HashUtils.SECURE_HASH_ALGORITHM_KECCAK_128_RATE / ((bBit + 1 + 7) / 8); HashUtils.customizableSecureHashAlgorithmKECCAK128Simple( buffer, 0, HashUtils.SECURE_HASH_ALGORITHM_KECCAK_128_RATE, dualModeSampler++, seed, seedOffset, Polynomial.RANDOM ); } if (q == Parameter.Q_III_SIZE || q == Parameter.Q_III_SPEED) { numberOfBlock = HashUtils.SECURE_HASH_ALGORITHM_KECCAK_256_RATE / ((bBit + 1 + 7) / 8); HashUtils.customizableSecureHashAlgorithmKECCAK256Simple( buffer, 0, HashUtils.SECURE_HASH_ALGORITHM_KECCAK_256_RATE, dualModeSampler++, seed, seedOffset, Polynomial.RANDOM ); } position = 0; } y[0] = (CommonFunction.load32(buffer, position) & ((1 << (bBit + 1)) - 1)) - b; y[1] = (CommonFunction.load32(buffer, position + numberOfByte) & ((1 << (bBit + 1)) - 1)) - b; y[2] = (CommonFunction.load32(buffer, position + numberOfByte * 2) & ((1 << (bBit + 1)) - 1)) - b; y[3] = (CommonFunction.load32(buffer, position + numberOfByte * 3) & ((1 << (bBit + 1)) - 1)) - b; if (i < n && y[0] != (1 << bBit)) { Y[i++] = y[0]; } if (i < n && y[1] != (1 << bBit)) { Y[i++] = y[1]; } if (i < n && y[2] != (1 << bBit)) { Y[i++] = y[2]; } if (i < n && y[3] != (1 << bBit)) { Y[i++] = y[3]; } position += numberOfByte * 4; } }
Description: Samples Polynomial Y, Such That Each Coefficient is in the Range [-B, B], for Provably-Secure qTESLA Security Category-1 and Security Category-3
Params:
  • Y – Polynomial Y
  • seed – Kappa-Bit Seed
  • seedOffset – Starting Point of the Kappa-Bit Seed
  • nonce – Domain Separator for Error Polynomial and Secret Polynomial
  • n – Polynomial Degree
  • q – Modulus
  • b – Determines the Interval the Randomness is Chosen in During Signing
  • bBit – b = 2 ^ bBit - 1
Returns:none
/******************************************************************************************************************* * Description: Samples Polynomial Y, Such That Each Coefficient is in the Range [-B, B], for Provably-Secure qTESLA * Security Category-1 and Security Category-3 * * @param Y Polynomial Y * @param seed Kappa-Bit Seed * @param seedOffset Starting Point of the Kappa-Bit Seed * @param nonce Domain Separator for Error Polynomial and Secret Polynomial * @param n Polynomial Degree * @param q Modulus * @param b Determines the Interval the Randomness is Chosen in During Signing * @param bBit b = 2 ^ bBit - 1 * * @return none *******************************************************************************************************************/
public static void sampleY(long[] Y, final byte[] seed, int seedOffset, int nonce, int n, int q, int b, int bBit) { int i = 0; int position = 0; int numberOfByte = (bBit + 1 + 7) / 8; int numberOfBlock = n; byte[] buffer = new byte[n * numberOfByte]; short dualModeSampler = (short)(nonce << 8); if (q == Parameter.Q_I_P) { HashUtils.customizableSecureHashAlgorithmKECCAK128Simple( buffer, 0, n * numberOfByte, dualModeSampler++, seed, seedOffset, Polynomial.RANDOM ); } if (q == Parameter.Q_III_P) { HashUtils.customizableSecureHashAlgorithmKECCAK256Simple( buffer, 0, n * numberOfByte, dualModeSampler++, seed, seedOffset, Polynomial.RANDOM ); } while (i < n) { if (position > numberOfBlock * numberOfByte) { if (q == Parameter.Q_I_P) { numberOfBlock = HashUtils.SECURE_HASH_ALGORITHM_KECCAK_128_RATE / ((bBit + 1 + 7) / 8); HashUtils.customizableSecureHashAlgorithmKECCAK128Simple( buffer, 0, HashUtils.SECURE_HASH_ALGORITHM_KECCAK_128_RATE, dualModeSampler++, seed, seedOffset, Polynomial.RANDOM ); } if (q == Parameter.Q_III_P) { numberOfBlock = HashUtils.SECURE_HASH_ALGORITHM_KECCAK_256_RATE / ((bBit + 1 + 7) / 8); HashUtils.customizableSecureHashAlgorithmKECCAK256Simple( buffer, 0, HashUtils.SECURE_HASH_ALGORITHM_KECCAK_256_RATE, dualModeSampler++, seed, seedOffset, Polynomial.RANDOM ); } position = 0; } Y[i] = (CommonFunction.load32(buffer, position) & ((1 << (bBit + 1)) - 1)) - b; if (Y[i] != (1 << bBit)) { i++; } position += numberOfByte; } }
Description: Samples A Bit from Bernoulli with Restriction of 20-Bit Exponent
/***************************************************************************************************************** * Description: Samples A Bit from Bernoulli with Restriction of 20-Bit Exponent *****************************************************************************************************************/
private static int bernoulli(long result, long fractionOfExponent, double[][] exponentialDistribution) { /* * * Computes the Actual Bernoulli Parameter = exp (-t / f) * Yields A Fraction of 2^62, to Keep Only 62 Bits of Precision in This Implementation * */ double bernoulliParameter = 4611686018427387904.0; for (long i = 0, j = fractionOfExponent; i < 3; i++, j >>= 5) { bernoulliParameter *= exponentialDistribution[(int)i][(int)(j & 31)]; } /* Sample from Bernoulli of bernoulliParameter */ return (int)(((result & 0x3FFFFFFFFFFFFFFFL) - round(bernoulliParameter)) >>> 63); }
Description: Gaussian Sampler for Heuristic qTESLA Security Category-1
Params:
  • data – Data to be Sampled
  • dataOffset – Starting Point of the Data to be Sampled
  • seed – Kappa-Bit Seed
  • seedOffset – Starting Point of the Kappa-Bit Seed
  • nonce – Domain Separator for Error Polynomial and Secret Polynomial
Returns:none
/********************************************************************************************************************** * Description: Gaussian Sampler for Heuristic qTESLA Security Category-1 * * @param data Data to be Sampled * @param dataOffset Starting Point of the Data to be Sampled * @param seed Kappa-Bit Seed * @param seedOffset Starting Point of the Kappa-Bit Seed * @param nonce Domain Separator for Error Polynomial and Secret Polynomial * * @return none **********************************************************************************************************************/
public static void polynomialGaussSamplerI(int[] data, int dataOffset, final byte[] seed, int seedOffset, int nonce) { byte[] seedExpander = new byte[Parameter.N_I * Const.LONG_SIZE / Const.INT_SIZE]; short domainSeparator = (short)(nonce << 8); int index; int j = 0; long k; long sign; long r; long s; long randomBit; long bitRemained; long y; long z; long buffer; HashUtils.customizableSecureHashAlgorithmKECCAK128Simple( seedExpander, 0, Parameter.N_I * Const.LONG_SIZE / Const.INT_SIZE, domainSeparator++, seed, seedOffset, Polynomial.RANDOM ); for (index = 0; index < Parameter.N_I; index++) { if (j + 46 > Parameter.N_I) { HashUtils.customizableSecureHashAlgorithmKECCAK128Simple( seedExpander, 0, Parameter.N_I * Const.LONG_SIZE / Const.INT_SIZE, domainSeparator++, seed, seedOffset, Polynomial.RANDOM ); j = 0; } do { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; do { /* Sample x from D^+_{\SIGMA_2} and y from U ({0, ..., k - 1}) */ do { r = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); s = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); if (bitRemained <= 64 - 6) { randomBit = (randomBit << 6) ^ ((r >>> 58) & 63L); bitRemained += 6; } r &= 0x03FFFFFFFFFFFFFFL; /* * Checks If r Exceeds A Maximum Value * Variation is Random ad Does not Depend on Private Data */ } while (r > 0x0321020100200100L); y = 0; for (int i = 0; i < 12; i++) { long c = s - CUMULATIVE_DISTRIBUTION_TABLE_I[i][1]; long b = (((c & CUMULATIVE_DISTRIBUTION_TABLE_I[i][1]) & 1) + (CUMULATIVE_DISTRIBUTION_TABLE_I[i][1] >> 1) + (c >>> 1)) >>> 63; c = r - (CUMULATIVE_DISTRIBUTION_TABLE_I[i][0] + b); y += ~(c >>> 63) & 1L; } /* The Next Sampler Works Exclusively for xi <= 28 */ do { do { if (bitRemained < 6) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } z = randomBit & 63L; randomBit >>= 6; bitRemained -= 6; } while (z == 63); if (bitRemained < 2) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } z = (modulus7(z) << 2) + (randomBit & 3L); randomBit >>= 2; bitRemained -= 2; /* * Making Sure Random z Does not Exceed A Certain Limit * No Private Data is Leaked * It Varies Uniformly */ } while (z >= Parameter.XI_I); /* Sample A Bit from Bernoulli_{exp (- y * (y + 2 * k * x) / (2 * k^2 * SIGMA_2^2))} */ k = (long)(Parameter.XI_I * y + z); buffer = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); } while (bernoulli(buffer, z * ((k << 1) - z), EXPONENTIAL_DISTRIBUTION_I) == 0); /* Put Last Random Bits into Sign Bit */ randomBit <<= (int)(64 - bitRemained); if (bitRemained == 0) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } sign = randomBit >> 63; randomBit <<= 1; bitRemained--; } while ((k | (sign & 1L)) == 0); if (bitRemained == 0) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } sign = randomBit >> 63; randomBit <<= 1; bitRemained--; k = ((k << 1) & sign) - k; data[dataOffset + index] = (int)((k << 48) >> 48); } }
Description: Gaussian Sampler for Provably-Secure qTESLA Security Category-1
Params:
  • data – Data to be Sampled
  • dataOffset – Starting Point of the Data to be Sampled
  • seed – Kappa-Bit Seed
  • seedOffset – Starting Point of the Kappa-Bit Seed
  • nonce – Domain Separator for Error Polynomial and Secret Polynomial
Returns:none
/********************************************************************************************************************** * Description: Gaussian Sampler for Provably-Secure qTESLA Security Category-1 * * @param data Data to be Sampled * @param dataOffset Starting Point of the Data to be Sampled * @param seed Kappa-Bit Seed * @param seedOffset Starting Point of the Kappa-Bit Seed * @param nonce Domain Separator for Error Polynomial and Secret Polynomial * * @return none **********************************************************************************************************************/
public static void polynomialGaussSamplerIP(long[] data, int dataOffset, final byte[] seed, int seedOffset, int nonce) { byte[] seedExpander = new byte[Parameter.N_I_P * Const.LONG_SIZE / Const.INT_SIZE]; short domainSeparator = (short)(nonce << 8); int index; int j = 0; long k; long sign; long r; long s; long randomBit; long bitRemained; long y; long z; long buffer; HashUtils.customizableSecureHashAlgorithmKECCAK128Simple( seedExpander, 0, Parameter.N_I_P * Const.LONG_SIZE / Const.INT_SIZE, domainSeparator++, seed, seedOffset, Polynomial.RANDOM ); for (index = 0; index < Parameter.N_I_P; index++) { if (j + 46 > Parameter.N_I_P) { HashUtils.customizableSecureHashAlgorithmKECCAK128Simple( seedExpander, 0, Parameter.N_I_P * Const.LONG_SIZE / Const.INT_SIZE, domainSeparator++, seed, seedOffset, Polynomial.RANDOM ); j = 0; } do { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; do { /* Sample x from D^+_{\SIGMA_2} and y from U ({0, ..., k - 1}) */ do { r = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); s = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); if (bitRemained <= 64 - 6) { randomBit = (randomBit << 6) ^ ((r >>> 58) & 63L); bitRemained += 6; } r &= 0x03FFFFFFFFFFFFFFL; /* * Checks If r Exceeds A Maximum Value * Variation is Random ad Does not Depend on Private Data */ } while (r > 0x0321020100200100L); y = 0; for (int i = 0; i < 12; i++) { long c = s - CUMULATIVE_DISTRIBUTION_TABLE_I[i][1]; long b = (((c & CUMULATIVE_DISTRIBUTION_TABLE_I[i][1]) & 1) + (CUMULATIVE_DISTRIBUTION_TABLE_I[i][1] >> 1) + (c >>> 1)) >>> 63; c = r - (CUMULATIVE_DISTRIBUTION_TABLE_I[i][0] + b); y += ~(c >>> 63) & 1L; } /* The Next Sampler Works Exclusively for xi <= 28 */ do { do { if (bitRemained < 6) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } z = randomBit & 63L; randomBit >>= 6; bitRemained -= 6; } while (z == 63); if (bitRemained < 2) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } z = (modulus7(z) << 2) + (randomBit & 3L); randomBit >>= 2; bitRemained -= 2; /* * Making Sure Random z Does not Exceed A Certain Limit * No Private Data is Leaked * It Varies Uniformly */ } while (z >= Parameter.XI_I_P); /* Sample A Bit from Bernoulli_{exp (- y * (y + 2 * k * x) / (2 * k^2 * SIGMA_2^2))} */ k = (long)(Parameter.XI_I_P * y + z); buffer = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); } while (bernoulli(buffer, z * ((k << 1) - z), EXPONENTIAL_DISTRIBUTION_P) == 0); /* Put Last Random Bits into Sign Bit */ randomBit <<= (int)(64 - bitRemained); if (bitRemained == 0) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } sign = randomBit >> 63; randomBit <<= 1; bitRemained--; } while ((k | (sign & 1L)) == 0); if (bitRemained == 0) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } sign = randomBit >> 63; randomBit <<= 1; bitRemained--; k = ((k << 1) & sign) - k; data[dataOffset + index] = (k << 48) >> 48; } }
Description: Gaussian Sampler for Heuristic qTESLA Security Category-3 (Option for Size or Speed)
Params:
  • data – Data to be Sampled
  • dataOffset – Starting Point of the Data to be Sampled
  • seed – Kappa-Bit Seed
  • seedOffset – Starting Point of the Kappa-Bit Seed
  • nonce – Domain Separator for Error Polynomial and Secret Polynomial
  • n – Polynomial Degree
  • xi –
  • exponentialDistribution – Exponential Distribution Table
Returns:none
/******************************************************************************************************************************************************************************* * Description: Gaussian Sampler for Heuristic qTESLA Security Category-3 (Option for Size or Speed) * * @param data Data to be Sampled * @param dataOffset Starting Point of the Data to be Sampled * @param seed Kappa-Bit Seed * @param seedOffset Starting Point of the Kappa-Bit Seed * @param nonce Domain Separator for Error Polynomial and Secret Polynomial * @param n Polynomial Degree * @param xi * @param exponentialDistribution Exponential Distribution Table * * @return none *******************************************************************************************************************************************************************************/
public static void polynomialGaussSamplerIII(int[] data, int dataOffset, final byte[] seed, int seedOffset, int nonce, int n, double xi, double[][] exponentialDistribution) { byte[] seedExpander = new byte[n * Const.LONG_SIZE / Const.INT_SIZE]; short domainSeparator = (short)(nonce << 8); int index; int j = 0; long k; long sign; long r; long s; long t; long randomBit; long bitRemained; long y; long z; HashUtils.customizableSecureHashAlgorithmKECCAK256Simple( seedExpander, 0, n * Const.LONG_SIZE / Const.INT_SIZE, domainSeparator++, seed, seedOffset, Polynomial.RANDOM ); for (index = 0; index < n; index++) { if (j + 46 > n) { HashUtils.customizableSecureHashAlgorithmKECCAK256Simple( seedExpander, 0, n * Const.LONG_SIZE / Const.INT_SIZE, domainSeparator++, seed, seedOffset, Polynomial.RANDOM ); j = 0; } do { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; do { /* Sample x from D^+_{\SIGMA_2} and y from U ({0, ..., k - 1}) */ do { r = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); s = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); t = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); if (bitRemained <= 64 - 6) { randomBit = (randomBit << 6) ^ ((r >>> 58) & 63L); bitRemained += 6; } r &= 0x000003FFFFFFFFFFL; /* * Checks If r Exceeds A Maximum Value * Variation is Random ad Does not Depend on Private Data */ } while (r > 0x0000032102010020L); y = 0; for (int i = 0; i < 14; i++) { long c = t - CUMULATIVE_DISTRIBUTION_TABLE_III[i][2]; long b = ((c & CUMULATIVE_DISTRIBUTION_TABLE_III[i][2] & 1L) + (CUMULATIVE_DISTRIBUTION_TABLE_III[i][2] >> 1) + (c >>> 1)) >> 63; /* Least significant Bits of All CUMULATIVE_DISTRIBUTION_TABLE[i][1] are Zero: Overflow Cannot Occur at This Point */ c = s - (CUMULATIVE_DISTRIBUTION_TABLE_III[i][1] + b); b = (((c & b) & 1L) + (CUMULATIVE_DISTRIBUTION_TABLE_III[i][1] >> 1) + (c >>> 1)) >> 63; /* Least significant Bits of All CUMULATIVE_DISTRIBUTION_TABLE[i][0] are Zero: Overflow Cannot Occur at This Point */ c = r - (CUMULATIVE_DISTRIBUTION_TABLE_III[i][0] + b); y += ~(c >>> 63) & 1L; } /* The Next Sampler Works Exclusively for xi <= 28 */ do { do { if (bitRemained < 6) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } z = randomBit & 63L; randomBit >>= 6; bitRemained -= 6; } while (z == 63L); if (bitRemained < 2) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } z = (modulus7(z) << 2) + (randomBit & 3L); randomBit >>= 2; bitRemained -= 2; /* * Making Sure Random z Does not Exceed A Certain Limit * No Private Data is Leaked * It Varies Uniformly */ } while (z >= xi); /* Sample A Bit from Bernoulli_{exp (- y * (y + 2 * k * x) / (2 * k^2 * SIGMA_2^2))} */ k = (long)(xi * y + z); } while (bernoulli(CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE), z * ((k << 1) - z), exponentialDistribution) == 0); /* Put Last Random Bits into Sign Bit */ randomBit <<= (int)(64 - bitRemained); if (bitRemained == 0L) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } sign = randomBit >> 63; randomBit <<= 1; bitRemained--; } while ((k | (sign & 1L)) == 0); if (bitRemained == 0) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } sign = randomBit >> 63; randomBit <<= 1; bitRemained--; k = ((k << 1) & sign) - k; data[dataOffset + index] = (int)((k << 48) >> 48); } }
Description: Gaussian Sampler for Provably-Secure qTESLA Security Category-3
Params:
  • data – Data to be Sampled
  • dataOffset – Starting Point of the Data to be Sampled
  • seed – Kappa-Bit Seed
  • seedOffset – Starting Point of the Kappa-Bit Seed
  • nonce – Domain Separator for Error Polynomial and Secret Polynomial
Returns:none
/************************************************************************************************************************** * Description: Gaussian Sampler for Provably-Secure qTESLA Security Category-3 * * @param data Data to be Sampled * @param dataOffset Starting Point of the Data to be Sampled * @param seed Kappa-Bit Seed * @param seedOffset Starting Point of the Kappa-Bit Seed * @param nonce Domain Separator for Error Polynomial and Secret Polynomial * * @return none **************************************************************************************************************************/
public static void polynomialGaussSamplerIIIP(long[] data, int dataOffset, final byte[] seed, int seedOffset, int nonce) { byte[] seedExpander = new byte[Parameter.N_III_P * Const.LONG_SIZE / Const.INT_SIZE]; short domainSeparator = (short)(nonce << 8); int index; int j = 0; long k; long sign; long r; long s; long t; long randomBit; long bitRemained; long y; long z; HashUtils.customizableSecureHashAlgorithmKECCAK256Simple( seedExpander, 0, Parameter.N_III_P * Const.LONG_SIZE / Const.INT_SIZE, domainSeparator++, seed, seedOffset, Polynomial.RANDOM ); for (index = 0; index < Parameter.N_III_P; index++) { if (j + 46 > Parameter.N_III_P) { HashUtils.customizableSecureHashAlgorithmKECCAK256Simple( seedExpander, 0, Parameter.N_III_P * Const.LONG_SIZE / Const.INT_SIZE, domainSeparator++, seed, seedOffset, Polynomial.RANDOM ); j = 0; } do { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; do { /* Sample x from D^+_{\SIGMA_2} and y from U ({0, ..., k - 1}) */ do { r = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); s = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); t = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); if (bitRemained <= 64 - 6) { randomBit = (randomBit << 6) ^ ((r >>> 58) & 63L); bitRemained += 6; } r &= 0x000003FFFFFFFFFFL; /* * Checks If r Exceeds A Maximum Value * Variation is Random ad Does not Depend on Private Data */ } while (r > 0x0000032102010020L); y = 0; for (int i = 0; i < 14; i++) { long c = t - CUMULATIVE_DISTRIBUTION_TABLE_III[i][2]; long b = ((c & CUMULATIVE_DISTRIBUTION_TABLE_III[i][2] & 1L) + (CUMULATIVE_DISTRIBUTION_TABLE_III[i][2] >> 1) + (c >>> 1)) >> 63; /* Least significant Bits of All CUMULATIVE_DISTRIBUTION_TABLE[i][1] are Zero: Overflow Cannot Occur at This Point */ c = s - (CUMULATIVE_DISTRIBUTION_TABLE_III[i][1] + b); b = (((c & b) & 1L) + (CUMULATIVE_DISTRIBUTION_TABLE_III[i][1] >> 1) + (c >>> 1)) >> 63; /* Least significant Bits of All CUMULATIVE_DISTRIBUTION_TABLE[i][0] are Zero: Overflow Cannot Occur at This Point */ c = r - (CUMULATIVE_DISTRIBUTION_TABLE_III[i][0] + b); y += ~(c >>> 63) & 1L; } /* The Next Sampler Works Exclusively for xi <= 28 */ do { do { if (bitRemained < 6) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } z = randomBit & 63L; randomBit >>= 6; bitRemained -= 6; } while (z == 63L); if (bitRemained < 2) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } z = (modulus7(z) << 2) + (randomBit & 3L); randomBit >>= 2; bitRemained -= 2; /* * Making Sure Random z Does not Exceed A Certain Limit * No Private Data is Leaked * It Varies Uniformly */ } while (z >= Parameter.XI_III_P); /* Sample A Bit from Bernoulli_{exp (- y * (y + 2 * k * x) / (2 * k^2 * SIGMA_2^2))} */ k = (long)(Parameter.XI_III_P * y + z); } while (bernoulli(CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE), z * ((k << 1) - z), EXPONENTIAL_DISTRIBUTION_P) == 0); /* Put Last Random Bits into Sign Bit */ randomBit <<= (int)(64 - bitRemained); if (bitRemained == 0L) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } sign = randomBit >> 63; randomBit <<= 1; bitRemained--; } while ((k | (sign & 1L)) == 0); if (bitRemained == 0) { randomBit = CommonFunction.load64(seedExpander, (j++) * Const.LONG_SIZE / Const.INT_SIZE); bitRemained = 64; } sign = randomBit >> 63; randomBit <<= 1; bitRemained--; k = ((k << 1) & sign) - k; data[dataOffset + index] = (k << 48) >> 48; } }
Description: Encoding of C' by Mapping the Output of the Hash Function H to An N-Element Vector with Entries {-1, 0, 1}
Params:
  • positionList – {0, ..., n - 1} ^ h
  • signList – {-1, +1} ^ h
  • output – Result of the Hash Function H
  • outputOffset – Starting Point of the Result of the Hash Function H
  • n – Polynomial Degree
  • h – Number of Non-Zero Entries of Output Elements of Encryption
Returns:none
/************************************************************************************************************************* * Description: Encoding of C' by Mapping the Output of the Hash Function H to An N-Element Vector with Entries {-1, 0, 1} * * @param positionList {0, ..., n - 1} ^ h * @param signList {-1, +1} ^ h * @param output Result of the Hash Function H * @param outputOffset Starting Point of the Result of the Hash Function H * @param n Polynomial Degree * @param h Number of Non-Zero Entries of Output Elements of Encryption * * @return none *************************************************************************************************************************/
public static void encodeC(int[] positionList, short[] signList, byte[] output, int outputOffset, int n, int h) { int count = 0; int position; short domainSeparator = 0; short[] C = new short[n]; byte[] randomness = new byte[HashUtils.SECURE_HASH_ALGORITHM_KECCAK_128_RATE]; /* Use the Hash Value as Key to Generate Some Randomness */ HashUtils.customizableSecureHashAlgorithmKECCAK128Simple( randomness, 0, HashUtils.SECURE_HASH_ALGORITHM_KECCAK_128_RATE, domainSeparator++, output, outputOffset, Polynomial.RANDOM ); /* Use Rejection Sampling to Determine Positions to be Set in the New Vector */ Arrays.fill(C, (short)0); /* Sample A Unique Position k times. * Use Two Bytes */ for (int i = 0; i < h; ) { if (count > HashUtils.SECURE_HASH_ALGORITHM_KECCAK_128_RATE - 3) { HashUtils.customizableSecureHashAlgorithmKECCAK128Simple( randomness, 0, HashUtils.SECURE_HASH_ALGORITHM_KECCAK_128_RATE, domainSeparator++, output, outputOffset, Polynomial.RANDOM ); count = 0; } position = (randomness[count] << 8) | (randomness[count + 1] & 0xFF); position &= (n - 1); /* Position is between [0, n - 1] and Has not Been Set Yet * Determine Signature */ if (C[position] == 0) { if ((randomness[count + 2] & 1) == 1) { C[position] = -1; } else { C[position] = 1; } positionList[i] = position; signList[i] = C[position]; i++; } count += 3; } } private static long round(double v) { if (v < 0) { return (long)(v - 0.5); } else { return (long)(v + 0.5); } } }