ClpBigInteger.pas 108 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043
  1. { *********************************************************************************** }
  2. { * CryptoLib Library * }
  3. { * Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe * }
  4. { * Github Repository <https://github.com/Xor-el> * }
  5. { * Distributed under the MIT software license, see the accompanying file LICENSE * }
  6. { * or visit http://www.opensource.org/licenses/mit-license.php. * }
  7. { * Acknowledgements: * }
  8. { * * }
  9. { * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * }
  10. { * development of this library * }
  11. { * ******************************************************************************* * }
  12. (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
  13. unit ClpBigInteger;
  14. {$I ..\Include\CryptoLib.inc}
  15. interface
  16. uses
  17. Classes,
  18. Math,
  19. SysUtils,
  20. StrUtils,
  21. Generics.Collections,
  22. ClpNumberStyles,
  23. ClpISecureRandom,
  24. ClpIRandom,
  25. ClpCryptoLibTypes;
  26. resourcestring
  27. SDivisionByZero = 'Division by Zero Error';
  28. SModulusPositive = 'Modulus must be Positive';
  29. SNotRelativelyPrime = 'Numbers not Relatively Prime.';
  30. SNegativeValue = 'Cannot be Called on Value < 0';
  31. SNegativeExponent = 'Negative Exponent';
  32. SResultTooLarge = 'Result too Large';
  33. SNegativeBitPosition = 'Bit Position must not be Negative';
  34. SInvalidBitAddress = 'Bit Address less than Zero';
  35. SZeroLengthBigInteger = 'Zero length BigInteger';
  36. SInvalidSign = 'Invalid Sign Value';
  37. SNegativeSizeInBits = 'sizeInBits must be non-negative';
  38. SInvalidBitLength = 'bitLength < 2';
  39. SInvalidBase = 'Only bases 2, 8, 10, or 16 allowed';
  40. SBadCharacterRadix8 = 'Bad Character in radix 8 string: %s';
  41. SBadCharacterRadix2 = 'Bad Character in radix 2 string: %s';
  42. SUnSupportedBase = 'Only bases 2, 8, 10, 16 are allowed';
  43. type
  44. TBigInteger = record
  45. strict private
  46. const
  47. IMASK = Int64($FFFFFFFF);
  48. UIMASK = UInt64($FFFFFFFF);
  49. BitLengthTable: array [0 .. 255] of Byte = (0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4,
  50. 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
  51. 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  52. 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  53. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  54. 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
  55. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  56. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  57. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  58. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  59. 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8);
  60. /// <summary>
  61. /// These are the threshold bit-lengths (of an exponent) where we
  62. /// increase the window size. <br />They are calculated according to the
  63. /// expected savings in multiplications. <br />Some squares will also be
  64. /// saved on average, but we offset these against the extra storage
  65. /// costs. <br />
  66. /// </summary>
  67. ExpWindowThresholds: array [0 .. 7] of Int32 = (7, 25, 81, 241, 673, 1793,
  68. 4609, Int32($7FFFFFFF));
  69. // TODO Parse radix-2 64 bits at a time and radix-8 63 bits at a time
  70. chunk2 = Int32(1);
  71. chunk8 = Int32(1);
  72. chunk10 = Int32(19);
  73. chunk16 = Int32(16);
  74. BitsPerByte = Int32(8);
  75. BitsPerInt = Int32(32);
  76. BytesPerInt = Int32(4);
  77. var
  78. // array of ints with [0] being the most significant
  79. Fmagnitude: TCryptoLibInt32Array;
  80. Fsign: Int32; // -1 means -ve; +1 means +ve; 0 means 0;
  81. FnBits: Int32; // cache BitCount() value
  82. FnBitLength: Int32; // cache BitLength() value
  83. // -m^(-1) mod b, b = 2^32 (see Montgomery mult.), 0 when uninitialised
  84. FmQuote: Int32;
  85. FIsInitialized: Boolean;
  86. class var
  87. FZero, FOne, FTwo, FThree, FFour, FTen: TBigInteger;
  88. // Each list has a product < 2^31
  89. FprimeLists: TCryptoLibMatrixInt32Array;
  90. FprimeProducts, FZeroMagnitude: TCryptoLibInt32Array;
  91. FZeroEncoding: TCryptoLibByteArray;
  92. FSMALL_CONSTANTS: TCryptoLibGenericArray<TBigInteger>;
  93. Fradix2, Fradix2E, Fradix8, Fradix8E, Fradix10, Fradix10E, Fradix16,
  94. Fradix16E: TBigInteger;
  95. FRandomSource: ISecureRandom;
  96. function GetBitLength: Int32; inline;
  97. function GetBitCount: Int32; inline;
  98. function GetInt32Value: Int32; inline;
  99. function GetInt64Value: Int64; inline;
  100. function GetIsInitialized: Boolean; inline;
  101. function GetSignValue: Int32; inline;
  102. function AddToMagnitude(magToAdd: TCryptoLibInt32Array): TBigInteger;
  103. function QuickPow2Check(): Boolean; inline;
  104. /// <summary>
  105. /// return z = x / y - done in place (z value preserved, x contains the *
  106. /// remainder)
  107. /// </summary>
  108. function Divide(x, y: TCryptoLibInt32Array): TCryptoLibInt32Array; overload;
  109. function IsEqualMagnitude(const x: TBigInteger): Boolean;
  110. function CheckProbablePrime(certainty: Int32; const random: IRandom;
  111. randomlySelected: Boolean): Boolean;
  112. function ModInversePow2(const m: TBigInteger): TBigInteger;
  113. /// <summary>
  114. /// Calculate mQuote = -m^(-1) mod b with b = 2^32 (32 = word size)
  115. /// </summary>
  116. function GetMQuote(): Int32; inline;
  117. function Remainder(m: Int32): Int32; overload; inline;
  118. /// <summary>
  119. /// return x = x mod y - done in place (y value preserved)
  120. /// </summary>
  121. function Remainder(x, y: TCryptoLibInt32Array)
  122. : TCryptoLibInt32Array; overload;
  123. function LastNBits(n: Int32): TCryptoLibInt32Array; inline;
  124. function DivideWords(w: Int32): TBigInteger; inline;
  125. function RemainderWords(w: Int32): TBigInteger; inline;
  126. function ToByteArray(unsigned: Boolean): TCryptoLibByteArray; overload;
  127. function FlipExistingBit(n: Int32): TBigInteger; inline;
  128. function GetLowestSetBitMaskFirst(firstWordMask: Int32): Int32;
  129. procedure ParseString(const str: String; radix: Int32);
  130. procedure ParseBytes(bytes: TCryptoLibByteArray; offset, length: Int32);
  131. procedure ParseBytesWithSign(sign: Int32; bytes: TCryptoLibByteArray;
  132. offset, length: Int32);
  133. class function GetZero: TBigInteger; static; inline;
  134. class function GetOne: TBigInteger; static; inline;
  135. class function GetTwo: TBigInteger; static; inline;
  136. class function GetThree: TBigInteger; static; inline;
  137. class function GetFour: TBigInteger; static; inline;
  138. class function GetTen: TBigInteger; static; inline;
  139. class function GetprimeLists: TCryptoLibMatrixInt32Array; static; inline;
  140. class function GetprimeProducts: TCryptoLibInt32Array; static; inline;
  141. class function GetRandomSource: ISecureRandom; static; inline;
  142. class function GetByteLength(nBits: Int32): Int32; static; inline;
  143. class function MakeMagnitude(bytes: TCryptoLibByteArray;
  144. offset, length: Int32): TCryptoLibInt32Array; static;
  145. /// <summary>
  146. /// a = a + b - b preserved.
  147. /// </summary>
  148. class function AddMagnitudes(a, b: TCryptoLibInt32Array)
  149. : TCryptoLibInt32Array; static; inline;
  150. class function CalcBitLength(sign, indx: Int32; mag: TCryptoLibInt32Array)
  151. : Int32; static;
  152. /// <summary>
  153. /// unsigned comparison on two arrays - note the arrays may start with
  154. /// leading zeros.
  155. /// </summary>
  156. class function CompareTo(xIndx: Int32; x: TCryptoLibInt32Array;
  157. yIndx: Int32; y: TCryptoLibInt32Array): Int32; overload; static;
  158. class function CompareNoLeadingZeroes(xIndx: Int32; x: TCryptoLibInt32Array;
  159. yIndx: Int32; y: TCryptoLibInt32Array): Int32; static;
  160. class function ModInverse32(d: Int32): Int32; static; inline;
  161. class function ModInverse64(d: Int64): Int64; static; inline;
  162. /// <summary>
  163. /// Calculate the numbers u1, u2, and u3 such that: <br />u1 * a + u2 * b
  164. /// = u3 <br />where u3 is the greatest common divider of a and b. <br />
  165. /// a and b using the extended Euclid algorithm (refer p. 323 of The Art
  166. /// of Computer Programming vol 2, 2nd ed). <br />This also seems to have
  167. /// the side effect of calculating some form of multiplicative inverse.
  168. /// </summary>
  169. /// <param name="a">
  170. /// First number to calculate gcd for
  171. /// </param>
  172. /// <param name="b">
  173. /// Second number to calculate gcd for
  174. /// </param>
  175. /// <param name="u1Out">
  176. /// the return object for the u1 value
  177. /// </param>
  178. /// <returns>
  179. /// The greatest common divisor of a and b
  180. /// </returns>
  181. class function ExtEuclid(const a, b: TBigInteger; out u1Out: TBigInteger)
  182. : TBigInteger; static; inline;
  183. class function ModPowBarrett(const b, e, m: TBigInteger)
  184. : TBigInteger; static;
  185. class function ReduceBarrett(x: TBigInteger; const m, mr, yu: TBigInteger)
  186. : TBigInteger; static;
  187. class function ModPowMonty(b: TBigInteger; const e, m: TBigInteger;
  188. convert: Boolean): TBigInteger; static;
  189. class function GetWindowList(mag: TCryptoLibInt32Array; extraBits: Int32)
  190. : TCryptoLibInt32Array; static;
  191. class function CreateWindowEntry(mult, zeroes: Int32): Int32;
  192. static; inline;
  193. /// <returns>
  194. /// w with w = x * x - w is assumed to have enough space.
  195. /// </returns>
  196. class function Square(w, x: TCryptoLibInt32Array): TCryptoLibInt32Array;
  197. overload; static;
  198. /// <returns>
  199. /// x with x = y * z - x is assumed to have enough space.
  200. /// </returns>
  201. class function Multiply(x, y, z: TCryptoLibInt32Array)
  202. : TCryptoLibInt32Array; overload; static;
  203. // mDash = -m^(-1) mod b
  204. class procedure MontgomeryReduce(x, m: TCryptoLibInt32Array;
  205. mDash: UInt32); static;
  206. // mDash = -m^(-1) mod b
  207. /// <summary>
  208. /// Montgomery multiplication: a = x * y * R^(-1) mod m <br />Based
  209. /// algorithm 14.36 of Handbook of Applied Cryptography. <br />&lt;li&gt;
  210. /// m, x, y should have length n &lt;/li&gt; <br />&lt;li&gt; a should
  211. /// have length (n + 1) &lt;/li&gt; <br />&lt;li&gt; b = 2^32, R = b^n
  212. /// &lt;/li&gt; <br />&lt;br/&gt; <br />The result is put in x <br />
  213. /// &lt;br/&gt; <br />NOTE: the indices of x, y, m, a different in HAC
  214. /// and in Java <br />
  215. /// </summary>
  216. class procedure MultiplyMonty(a, x, y, m: TCryptoLibInt32Array;
  217. mDash: UInt32; smallMontyModulus: Boolean); static;
  218. // mDash = -m^(-1) mod b
  219. class procedure SquareMonty(a, x, m: TCryptoLibInt32Array; mDash: UInt32;
  220. smallMontyModulus: Boolean); static;
  221. class function MultiplyMontyNIsOne(x, y, m, mDash: UInt32): UInt32;
  222. static; inline;
  223. /// <summary>
  224. /// do a left shift - this returns a new array.
  225. /// </summary>
  226. class function ShiftLeft(mag: TCryptoLibInt32Array; n: Int32)
  227. : TCryptoLibInt32Array; overload; static;
  228. /// <summary>
  229. /// do a right shift - this does it in place.
  230. /// </summary>
  231. class procedure ShiftRightInPlace(start: Int32; mag: TCryptoLibInt32Array;
  232. n: Int32); static;
  233. /// <summary>
  234. /// do a right shift by one - this does it in place.
  235. /// </summary>
  236. class procedure ShiftRightOneInPlace(start: Int32;
  237. mag: TCryptoLibInt32Array); static;
  238. /// <summary>
  239. /// returns x = x - y - we assume x is &gt;= y
  240. /// </summary>
  241. class function Subtract(xStart: Int32; x: TCryptoLibInt32Array;
  242. yStart: Int32; y: TCryptoLibInt32Array): TCryptoLibInt32Array;
  243. overload; static;
  244. class function doSubBigLil(bigMag, lilMag: TCryptoLibInt32Array)
  245. : TCryptoLibInt32Array; static; inline;
  246. class procedure AppendZeroExtendedString(var sl: TStringList;
  247. const s: String; minLength: Int32); static; inline;
  248. class procedure ToString(sl: TStringList; radix: Int32;
  249. moduli: TList<TBigInteger>; scale: Int32; const pos: TBigInteger);
  250. overload; static;
  251. class function CreateUValueOf(value: UInt64): TBigInteger; static;
  252. class function CreateValueOf(value: Int64): TBigInteger; static;
  253. class function IntToBin(input: Int32): string; static;
  254. class function IntToOctal(input: Int32): string; static;
  255. constructor Create(signum: Int32; mag: TCryptoLibInt32Array;
  256. checkMag: Boolean); overload;
  257. class constructor BigInteger();
  258. public
  259. property BitLength: Int32 read GetBitLength;
  260. property BitCount: Int32 read GetBitCount;
  261. property IsInitialized: Boolean read GetIsInitialized;
  262. property Int32Value: Int32 read GetInt32Value;
  263. property Int64Value: Int64 read GetInt64Value;
  264. property SignValue: Int32 read GetSignValue;
  265. class property Zero: TBigInteger read GetZero;
  266. class property One: TBigInteger read GetOne;
  267. class property Two: TBigInteger read GetTwo;
  268. class property Three: TBigInteger read GetThree;
  269. class property Four: TBigInteger read GetFour;
  270. class property Ten: TBigInteger read GetTen;
  271. class property primeLists: TCryptoLibMatrixInt32Array read GetprimeLists;
  272. class property primeProducts: TCryptoLibInt32Array read GetprimeProducts;
  273. class property RandomSource: ISecureRandom read GetRandomSource;
  274. constructor Create(const value: String); overload;
  275. constructor Create(const str: String; radix: Int32); overload;
  276. constructor Create(bytes: TCryptoLibByteArray); overload;
  277. constructor Create(bytes: TCryptoLibByteArray;
  278. offset, length: Int32); overload;
  279. constructor Create(sign: Int32; bytes: TCryptoLibByteArray); overload;
  280. constructor Create(sign: Int32; bytes: TCryptoLibByteArray;
  281. offset, length: Int32); overload;
  282. constructor Create(sizeInBits: Int32; const random: IRandom); overload;
  283. constructor Create(BitLength, certainty: Int32;
  284. const random: IRandom); overload;
  285. function Abs(): TBigInteger;
  286. function Add(const value: TBigInteger): TBigInteger;
  287. function Subtract(const n: TBigInteger): TBigInteger; overload;
  288. function &And(const value: TBigInteger): TBigInteger;
  289. function &Not(): TBigInteger;
  290. function AndNot(const val: TBigInteger): TBigInteger;
  291. function &Or(const value: TBigInteger): TBigInteger;
  292. function &Xor(const value: TBigInteger): TBigInteger;
  293. function CompareTo(const value: TBigInteger): Int32; overload;
  294. function Divide(const val: TBigInteger): TBigInteger; overload;
  295. function DivideAndRemainder(const val: TBigInteger)
  296. : TCryptoLibGenericArray<TBigInteger>;
  297. function Gcd(const value: TBigInteger): TBigInteger;
  298. function Inc(): TBigInteger;
  299. function RabinMillerTest(certainty: Int32; const random: IRandom)
  300. : Boolean; overload;
  301. function RabinMillerTest(certainty: Int32; const random: IRandom;
  302. randomlySelected: Boolean): Boolean; overload;
  303. /// <summary>
  304. /// return whether or not a BigInteger is probably prime with a
  305. /// probability of 1 - (1/2)**certainty. <br />&lt;p&gt;From Knuth Vol 2,
  306. /// pg 395.&lt;/p&gt;
  307. /// </summary>
  308. function IsProbablePrime(certainty: Int32): Boolean; overload;
  309. function IsProbablePrime(certainty: Int32; randomlySelected: Boolean)
  310. : Boolean; overload;
  311. function Max(const value: TBigInteger): TBigInteger;
  312. function Min(const value: TBigInteger): TBigInteger;
  313. function &Mod(const m: TBigInteger): TBigInteger;
  314. function ModInverse(const m: TBigInteger): TBigInteger;
  315. function ModPow(e: TBigInteger; const m: TBigInteger): TBigInteger;
  316. function Multiply(const val: TBigInteger): TBigInteger; overload;
  317. function Square(): TBigInteger; overload;
  318. function Negate(): TBigInteger;
  319. function NextProbablePrime(): TBigInteger;
  320. function Pow(exp: Int32): TBigInteger;
  321. function Remainder(const n: TBigInteger): TBigInteger; overload;
  322. function ShiftLeft(n: Int32): TBigInteger; overload;
  323. function ShiftRight(n: Int32): TBigInteger;
  324. function ToByteArray(): TCryptoLibByteArray; overload;
  325. function ToByteArrayUnsigned(): TCryptoLibByteArray;
  326. function TestBit(n: Int32): Boolean;
  327. function SetBit(n: Int32): TBigInteger;
  328. function ClearBit(n: Int32): TBigInteger;
  329. function FlipBit(n: Int32): TBigInteger;
  330. function GetLowestSetBit(): Int32;
  331. function ToString(): String; overload;
  332. function ToString(radix: Int32): String; overload;
  333. function Equals(const other: TBigInteger): Boolean; inline;
  334. function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
  335. inline;
  336. {$ENDIF DELPHI}
  337. class function BitCnt(i: Int32): Int32; static;
  338. /// <summary>
  339. /// BitLen(value) is the number of bits in value.
  340. /// </summary>
  341. class function BitLen(w: Int32): Int32; static;
  342. class function ProbablePrime(BitLength: Int32; const random: IRandom)
  343. : TBigInteger; static;
  344. class function ValueOf(value: Int64): TBigInteger; static;
  345. class function Arbitrary(sizeInBits: Int32): TBigInteger; static;
  346. class function Jacobi(const a, b: TBigInteger): Int32; static;
  347. class procedure Boot(); static;
  348. end;
  349. implementation
  350. uses
  351. ClpSecureRandom; // included here to avoid circular dependency :)
  352. { TBigInteger }
  353. class function TBigInteger.BitLen(w: Int32): Int32;
  354. var
  355. v, t: UInt32;
  356. begin
  357. v := UInt32(w);
  358. t := v shr 24;
  359. if (t <> 0) then
  360. begin
  361. Result := 24 + BitLengthTable[t];
  362. Exit;
  363. end;
  364. t := v shr 16;
  365. if (t <> 0) then
  366. begin
  367. Result := 16 + BitLengthTable[t];
  368. Exit;
  369. end;
  370. t := v shr 8;
  371. if (t <> 0) then
  372. begin
  373. Result := 8 + BitLengthTable[t];
  374. Exit;
  375. end;
  376. Result := BitLengthTable[v];
  377. end;
  378. class function TBigInteger.CalcBitLength(sign, indx: Int32;
  379. mag: TCryptoLibInt32Array): Int32;
  380. var
  381. BitLength, firstMag: Int32;
  382. begin
  383. while True do
  384. begin
  385. if (indx >= System.length(mag)) then
  386. begin
  387. Result := 0;
  388. Exit;
  389. end;
  390. if (mag[indx] <> 0) then
  391. begin
  392. break;
  393. end;
  394. System.Inc(indx);
  395. end;
  396. // bit length for everything after the first int
  397. BitLength := 32 * ((System.length(mag) - indx) - 1);
  398. // and determine bitlength of first int
  399. firstMag := mag[indx];
  400. BitLength := BitLength + BitLen(firstMag);
  401. // Check for negative powers of two
  402. if ((sign < 0) and ((firstMag and Int32(-firstMag)) = firstMag)) then
  403. begin
  404. repeat
  405. System.Inc(indx);
  406. if (indx >= System.length(mag)) then
  407. begin
  408. System.Dec(BitLength);
  409. break;
  410. end;
  411. until (not(mag[indx] = 0));
  412. end;
  413. Result := BitLength;
  414. end;
  415. class function TBigInteger.GetZero: TBigInteger;
  416. begin
  417. Result := FZero;
  418. end;
  419. class function TBigInteger.GetOne: TBigInteger;
  420. begin
  421. Result := FOne;
  422. end;
  423. class function TBigInteger.GetTwo: TBigInteger;
  424. begin
  425. Result := FTwo;
  426. end;
  427. class function TBigInteger.GetThree: TBigInteger;
  428. begin
  429. Result := FThree;
  430. end;
  431. class function TBigInteger.GetFour: TBigInteger;
  432. begin
  433. Result := FFour;
  434. end;
  435. class function TBigInteger.GetTen: TBigInteger;
  436. begin
  437. Result := FTen;
  438. end;
  439. class function TBigInteger.GetprimeLists: TCryptoLibMatrixInt32Array;
  440. begin
  441. Result := FprimeLists;
  442. end;
  443. class function TBigInteger.GetprimeProducts: TCryptoLibInt32Array;
  444. begin
  445. Result := FprimeProducts;
  446. end;
  447. class function TBigInteger.GetRandomSource: ISecureRandom;
  448. begin
  449. Result := FRandomSource;
  450. end;
  451. function TBigInteger.GetSignValue: Int32;
  452. begin
  453. Result := Fsign;
  454. end;
  455. function TBigInteger.GetBitLength: Int32;
  456. begin
  457. if (FnBitLength = -1) then
  458. begin
  459. if Fsign = 0 then
  460. begin
  461. FnBitLength := 0;
  462. end
  463. else
  464. begin
  465. FnBitLength := CalcBitLength(Fsign, 0, Fmagnitude);
  466. end;
  467. end;
  468. Result := FnBitLength;
  469. end;
  470. function TBigInteger.GetInt32Value: Int32;
  471. var
  472. n, v: Int32;
  473. begin
  474. if (Fsign = 0) then
  475. begin
  476. Result := 0;
  477. Exit;
  478. end;
  479. n := System.length(Fmagnitude);
  480. v := Fmagnitude[n - 1];
  481. if Fsign < 0 then
  482. begin
  483. Result := -v;
  484. end
  485. else
  486. begin
  487. Result := v;
  488. end;
  489. end;
  490. function TBigInteger.GetInt64Value: Int64;
  491. var
  492. n: Int32;
  493. v: Int64;
  494. begin
  495. if (Fsign = 0) then
  496. begin
  497. Result := 0;
  498. Exit;
  499. end;
  500. n := System.length(Fmagnitude);
  501. v := Fmagnitude[n - 1] and IMASK;
  502. if (n > 1) then
  503. begin
  504. v := v or ((Fmagnitude[n - 2] and IMASK) shl 32);
  505. end;
  506. if Fsign < 0 then
  507. begin
  508. Result := -v;
  509. Exit;
  510. end
  511. else
  512. begin
  513. Result := v;
  514. Exit;
  515. end;
  516. end;
  517. function TBigInteger.GetIsInitialized: Boolean;
  518. begin
  519. Result := FIsInitialized;
  520. end;
  521. class function TBigInteger.BitCnt(i: Int32): Int32;
  522. var
  523. u: UInt32;
  524. begin
  525. u := UInt32(i);
  526. {$IFDEF FPC}
  527. Result := Int32(PopCnt(u));
  528. {$ELSE}
  529. u := u - ((u shr 1) and $55555555);
  530. u := (u and $33333333) + ((u shr 2) and $33333333);
  531. u := (u + (u shr 4)) and $0F0F0F0F;
  532. u := u + (u shr 8);
  533. u := u + (u shr 16);
  534. u := u and $3F;
  535. Result := Int32(u);
  536. {$ENDIF FPC}
  537. end;
  538. class function TBigInteger.CreateWindowEntry(mult, zeroes: Int32): Int32;
  539. begin
  540. while ((mult and 1) = 0) do
  541. begin
  542. mult := mult shr 1;
  543. System.Inc(zeroes);
  544. end;
  545. Result := mult or (zeroes shl 8);
  546. end;
  547. class function TBigInteger.GetByteLength(nBits: Int32): Int32;
  548. begin
  549. Result := (nBits + BitsPerByte - 1) div BitsPerByte;
  550. end;
  551. function TBigInteger.LastNBits(n: Int32): TCryptoLibInt32Array;
  552. var
  553. numWords, excessBits: Int32;
  554. begin
  555. if (n < 1) then
  556. begin
  557. Result := FZeroMagnitude;
  558. Exit;
  559. end;
  560. numWords := (n + BitsPerInt - 1) div BitsPerInt;
  561. numWords := Math.Min(numWords, System.length(Fmagnitude));
  562. System.SetLength(Result, numWords);
  563. System.Move(Fmagnitude[System.length(Fmagnitude) - numWords], Result[0],
  564. numWords * System.SizeOf(Int32));
  565. excessBits := (numWords shl 5) - n;
  566. if (excessBits > 0) then
  567. begin
  568. Result[0] := Result[0] and (Int32(System.High(UInt32) shr excessBits));
  569. end;
  570. end;
  571. function TBigInteger.CompareTo(const value: TBigInteger): Int32;
  572. begin
  573. if Fsign < value.Fsign then
  574. begin
  575. Result := -1;
  576. end
  577. else
  578. begin
  579. if Fsign > value.Fsign then
  580. begin
  581. Result := 1;
  582. end
  583. else
  584. begin
  585. if Fsign = 0 then
  586. begin
  587. Result := 0
  588. end
  589. else
  590. begin
  591. Result := Fsign * CompareNoLeadingZeroes(0, Fmagnitude, 0,
  592. value.Fmagnitude);
  593. end;
  594. end;
  595. end;
  596. end;
  597. class function TBigInteger.CreateValueOf(value: Int64): TBigInteger;
  598. begin
  599. if (value < 0) then
  600. begin
  601. if (value = System.Low(Int64)) then
  602. begin
  603. Result := CreateValueOf(not value).&Not();
  604. Exit;
  605. end;
  606. Result := CreateValueOf(-value).Negate();
  607. Exit;
  608. end;
  609. Result := CreateUValueOf(UInt64(value));
  610. end;
  611. class function TBigInteger.CreateUValueOf(value: UInt64): TBigInteger;
  612. var
  613. msw, lsw: Int32;
  614. begin
  615. msw := Int32(value shr 32);
  616. lsw := Int32(value);
  617. if (msw <> 0) then
  618. begin
  619. Result := TBigInteger.Create(1, TCryptoLibInt32Array.Create(msw,
  620. lsw), false);
  621. Exit;
  622. end;
  623. if (lsw <> 0) then
  624. begin
  625. Result := TBigInteger.Create(1, TCryptoLibInt32Array.Create(lsw), false);
  626. // Check for a power of two
  627. if ((lsw and -lsw) = lsw) then
  628. begin
  629. Result.FnBits := 1;
  630. end;
  631. Exit;
  632. end;
  633. Result := Zero;
  634. end;
  635. class function TBigInteger.ValueOf(value: Int64): TBigInteger;
  636. begin
  637. if ((value >= 0) and (value < System.length(FSMALL_CONSTANTS))) then
  638. begin
  639. Result := FSMALL_CONSTANTS[value];
  640. Exit;
  641. end;
  642. Result := CreateValueOf(value);
  643. end;
  644. class procedure TBigInteger.Boot;
  645. var
  646. i: UInt32;
  647. primeList: TCryptoLibInt32Array;
  648. product, j: Int32;
  649. begin
  650. System.SetLength(FZeroEncoding, 0);
  651. System.SetLength(FZeroMagnitude, 0);
  652. FprimeLists := TCryptoLibMatrixInt32Array.Create
  653. (TCryptoLibInt32Array.Create(3, 5, 7, 11, 13, 17, 19, 23),
  654. TCryptoLibInt32Array.Create(29, 31, 37, 41, 43),
  655. TCryptoLibInt32Array.Create(47, 53, 59, 61, 67),
  656. TCryptoLibInt32Array.Create(71, 73, 79, 83), TCryptoLibInt32Array.Create(89,
  657. 97, 101, 103),
  658. TCryptoLibInt32Array.Create(107, 109, 113, 127),
  659. TCryptoLibInt32Array.Create(131, 137, 139, 149),
  660. TCryptoLibInt32Array.Create(151, 157, 163, 167),
  661. TCryptoLibInt32Array.Create(173, 179, 181, 191),
  662. TCryptoLibInt32Array.Create(193, 197, 199, 211),
  663. TCryptoLibInt32Array.Create(223, 227, 229), TCryptoLibInt32Array.Create(233,
  664. 239, 241), TCryptoLibInt32Array.Create(251, 257, 263),
  665. TCryptoLibInt32Array.Create(269, 271, 277), TCryptoLibInt32Array.Create(281,
  666. 283, 293),
  667. TCryptoLibInt32Array.Create(307, 311, 313), TCryptoLibInt32Array.Create(317,
  668. 331, 337), TCryptoLibInt32Array.Create(347, 349, 353),
  669. TCryptoLibInt32Array.Create(359, 367, 373), TCryptoLibInt32Array.Create(379,
  670. 383, 389),
  671. TCryptoLibInt32Array.Create(397, 401, 409), TCryptoLibInt32Array.Create(419,
  672. 421, 431), TCryptoLibInt32Array.Create(433, 439, 443),
  673. TCryptoLibInt32Array.Create(449, 457, 461), TCryptoLibInt32Array.Create(463,
  674. 467, 479),
  675. TCryptoLibInt32Array.Create(487, 491, 499), TCryptoLibInt32Array.Create(503,
  676. 509, 521), TCryptoLibInt32Array.Create(523, 541, 547),
  677. TCryptoLibInt32Array.Create(557, 563, 569), TCryptoLibInt32Array.Create(571,
  678. 577, 587),
  679. TCryptoLibInt32Array.Create(593, 599, 601), TCryptoLibInt32Array.Create(607,
  680. 613, 617), TCryptoLibInt32Array.Create(619, 631, 641),
  681. TCryptoLibInt32Array.Create(643, 647, 653), TCryptoLibInt32Array.Create(659,
  682. 661, 673),
  683. TCryptoLibInt32Array.Create(677, 683, 691), TCryptoLibInt32Array.Create(701,
  684. 709, 719), TCryptoLibInt32Array.Create(727, 733, 739),
  685. TCryptoLibInt32Array.Create(743, 751, 757), TCryptoLibInt32Array.Create(761,
  686. 769, 773),
  687. TCryptoLibInt32Array.Create(787, 797, 809), TCryptoLibInt32Array.Create(811,
  688. 821, 823), TCryptoLibInt32Array.Create(827, 829, 839),
  689. TCryptoLibInt32Array.Create(853, 857, 859), TCryptoLibInt32Array.Create(863,
  690. 877, 881),
  691. TCryptoLibInt32Array.Create(883, 887, 907), TCryptoLibInt32Array.Create(911,
  692. 919, 929), TCryptoLibInt32Array.Create(937, 941, 947),
  693. TCryptoLibInt32Array.Create(953, 967, 971), TCryptoLibInt32Array.Create(977,
  694. 983, 991),
  695. TCryptoLibInt32Array.Create(997, 1009, 1013),
  696. TCryptoLibInt32Array.Create(1019, 1021, 1031),
  697. TCryptoLibInt32Array.Create(1033, 1039, 1049),
  698. TCryptoLibInt32Array.Create(1051, 1061, 1063),
  699. TCryptoLibInt32Array.Create(1069, 1087, 1091),
  700. TCryptoLibInt32Array.Create(1093, 1097, 1103),
  701. TCryptoLibInt32Array.Create(1109, 1117, 1123),
  702. TCryptoLibInt32Array.Create(1129, 1151, 1153),
  703. TCryptoLibInt32Array.Create(1163, 1171, 1181),
  704. TCryptoLibInt32Array.Create(1187, 1193, 1201),
  705. TCryptoLibInt32Array.Create(1213, 1217, 1223),
  706. TCryptoLibInt32Array.Create(1229, 1231, 1237),
  707. TCryptoLibInt32Array.Create(1249, 1259, 1277),
  708. TCryptoLibInt32Array.Create(1279, 1283, 1289));
  709. //TSecureRandom.Boot;
  710. FRandomSource := TSecureRandom.Create();
  711. FZero := TBigInteger.Create(0, FZeroMagnitude, false);
  712. FZero.FnBits := 0;
  713. FZero.FnBitLength := 0;
  714. System.SetLength(FSMALL_CONSTANTS, 17);
  715. FSMALL_CONSTANTS[0] := FZero;
  716. i := 1;
  717. while i < UInt32(System.length(FSMALL_CONSTANTS)) do
  718. begin
  719. FSMALL_CONSTANTS[i] := CreateUValueOf(i);
  720. System.Inc(i);
  721. end;
  722. FOne := FSMALL_CONSTANTS[1];
  723. FTwo := FSMALL_CONSTANTS[2];
  724. FThree := FSMALL_CONSTANTS[3];
  725. FFour := FSMALL_CONSTANTS[4];
  726. FTen := FSMALL_CONSTANTS[10];
  727. Fradix2 := ValueOf(2);
  728. Fradix2E := Fradix2.Pow(chunk2);
  729. Fradix8 := ValueOf(8);
  730. Fradix8E := Fradix8.Pow(chunk8);
  731. Fradix10 := ValueOf(10);
  732. Fradix10E := Fradix10.Pow(chunk10);
  733. Fradix16 := ValueOf(16);
  734. Fradix16E := Fradix16.Pow(chunk16);
  735. System.SetLength(FprimeProducts, System.length(primeLists));
  736. for i := 0 to System.Pred(System.length(primeLists)) do
  737. begin
  738. primeList := primeLists[i];
  739. product := primeList[0];
  740. for j := 1 to System.Pred(System.length(primeList)) do
  741. begin
  742. product := product * primeList[j];
  743. end;
  744. FprimeProducts[i] := product;
  745. end;
  746. end;
  747. function TBigInteger.QuickPow2Check: Boolean;
  748. begin
  749. Result := (Fsign > 0) and (FnBits = 1);
  750. end;
  751. function TBigInteger.Negate: TBigInteger;
  752. begin
  753. if (Fsign = 0) then
  754. begin
  755. Result := Self;
  756. Exit;
  757. end;
  758. Result := TBigInteger.Create(-Fsign, Fmagnitude, false);
  759. end;
  760. class function TBigInteger.doSubBigLil(bigMag, lilMag: TCryptoLibInt32Array)
  761. : TCryptoLibInt32Array;
  762. var
  763. res: TCryptoLibInt32Array;
  764. begin
  765. res := System.Copy(bigMag);
  766. Result := Subtract(0, res, 0, lilMag);
  767. end;
  768. function TBigInteger.Inc: TBigInteger;
  769. begin
  770. if (Fsign = 0) then
  771. begin
  772. Result := One;
  773. Exit;
  774. end;
  775. if (Fsign < 0) then
  776. begin
  777. Result := TBigInteger.Create(-1, doSubBigLil(Fmagnitude,
  778. One.Fmagnitude), True);
  779. Exit;
  780. end;
  781. Result := AddToMagnitude(One.Fmagnitude);
  782. end;
  783. class function TBigInteger.IntToBin(input: Int32): string;
  784. var
  785. bits: TCryptoLibCharArray;
  786. i: Int32;
  787. begin
  788. Result := '';
  789. System.SetLength(bits, System.SizeOf(Int32) * 8);
  790. i := 0;
  791. while (input <> 0) do
  792. begin
  793. if (input and 1) = 1 then
  794. begin
  795. bits[i] := '1'
  796. end
  797. else
  798. begin
  799. bits[i] := '0';
  800. end;
  801. System.Inc(i);
  802. input := input shr 1;
  803. end;
  804. System.SetString(Result, PChar(@bits[0]), i);
  805. Result := ReverseString(Result);
  806. end;
  807. class function TBigInteger.IntToOctal(input: Int32): string;
  808. var
  809. bits: TCryptoLibCharArray;
  810. i: Int32;
  811. begin
  812. Result := '';
  813. System.SetLength(bits, System.SizeOf(Int32) * 8);
  814. i := 0;
  815. while (input <> 0) do
  816. begin
  817. case (input and 7) of
  818. 0:
  819. bits[i] := '0';
  820. 1:
  821. bits[i] := '1';
  822. 2:
  823. bits[i] := '2';
  824. 3:
  825. bits[i] := '3';
  826. 4:
  827. bits[i] := '4';
  828. 5:
  829. bits[i] := '5';
  830. 6:
  831. bits[i] := '6';
  832. 7:
  833. bits[i] := '7';
  834. end;
  835. System.Inc(i);
  836. input := input shr 3;
  837. end;
  838. System.SetString(Result, PChar(@bits[0]), i);
  839. Result := ReverseString(Result);
  840. end;
  841. function TBigInteger.&Not: TBigInteger;
  842. begin
  843. Result := Inc().Negate();
  844. end;
  845. function TBigInteger.TestBit(n: Int32): Boolean;
  846. var
  847. wordNum, word: Int32;
  848. begin
  849. if (n < 0) then
  850. begin
  851. raise EArithmeticCryptoLibException.CreateRes(@SNegativeBitPosition);
  852. end;
  853. if (Fsign < 0) then
  854. begin
  855. Result := (not &Not().TestBit(n));
  856. Exit;
  857. end;
  858. wordNum := n div 32;
  859. if (wordNum >= System.length(Fmagnitude)) then
  860. begin
  861. Result := false;
  862. Exit;
  863. end;
  864. word := Fmagnitude[System.length(Fmagnitude) - 1 - wordNum];
  865. Result := ((word shr (n and 31)) and 1) > 0;
  866. end;
  867. function TBigInteger.Abs: TBigInteger;
  868. begin
  869. if Fsign >= 0 then
  870. begin
  871. Result := Self;
  872. end
  873. else
  874. begin
  875. Result := Negate();
  876. end;
  877. end;
  878. function TBigInteger.Square: TBigInteger;
  879. var
  880. resLength: Int32;
  881. res: TCryptoLibInt32Array;
  882. begin
  883. if (Fsign = 0) then
  884. begin
  885. Result := Zero;
  886. Exit;
  887. end;
  888. if (QuickPow2Check()) then
  889. begin
  890. Result := ShiftLeft(Abs().BitLength - 1);
  891. Exit;
  892. end;
  893. resLength := System.length(Fmagnitude) shl 1;
  894. if (UInt32(Fmagnitude[0]) shr 16 = 0) then
  895. begin
  896. System.Dec(resLength);
  897. end;
  898. System.SetLength(res, resLength);
  899. Square(res, Fmagnitude);
  900. Result := TBigInteger.Create(1, res, false);
  901. end;
  902. function TBigInteger.Add(const value: TBigInteger): TBigInteger;
  903. begin
  904. if (Fsign = 0) then
  905. begin
  906. Result := value;
  907. Exit;
  908. end;
  909. if (Fsign <> value.Fsign) then
  910. begin
  911. if (value.Fsign = 0) then
  912. begin
  913. Result := Self;
  914. Exit;
  915. end;
  916. if (value.Fsign < 0) then
  917. begin
  918. Result := Subtract(value.Negate());
  919. Exit;
  920. end;
  921. Result := value.Subtract(Negate());
  922. Exit;
  923. end;
  924. Result := AddToMagnitude(value.Fmagnitude);
  925. end;
  926. class function TBigInteger.AddMagnitudes(a, b: TCryptoLibInt32Array)
  927. : TCryptoLibInt32Array;
  928. var
  929. tI, vI: Int32;
  930. m: Int64;
  931. begin
  932. tI := System.length(a) - 1;
  933. vI := System.length(b) - 1;
  934. m := 0;
  935. while (vI >= 0) do
  936. begin
  937. m := m + (Int64(UInt32(a[tI])) + Int64(UInt32(b[vI])));
  938. System.Dec(vI);
  939. a[tI] := Int32(m);
  940. System.Dec(tI);
  941. m := Int64(UInt64(m shr 32));
  942. end;
  943. if (m <> 0) then
  944. begin
  945. while (tI >= 0) do
  946. begin
  947. a[tI] := a[tI] + 1;
  948. if (a[tI] <> 0) then
  949. begin
  950. break;
  951. end;
  952. System.Dec(tI);
  953. end;
  954. end;
  955. Result := a;
  956. end;
  957. function TBigInteger.AddToMagnitude(magToAdd: TCryptoLibInt32Array)
  958. : TBigInteger;
  959. var
  960. big, small, bigCopy: TCryptoLibInt32Array;
  961. limit: UInt32;
  962. possibleOverflow: Boolean;
  963. begin
  964. if (System.length(Fmagnitude) < System.length(magToAdd)) then
  965. begin
  966. big := magToAdd;
  967. small := Fmagnitude;
  968. end
  969. else
  970. begin
  971. big := Fmagnitude;
  972. small := magToAdd;
  973. end;
  974. // Conservatively avoid over-allocation when no overflow possible
  975. limit := System.High(UInt32);
  976. if (System.length(big) = System.length(small)) then
  977. begin
  978. limit := limit - UInt32(small[0]);
  979. end;
  980. possibleOverflow := UInt32(big[0]) >= limit;
  981. if (possibleOverflow) then
  982. begin
  983. System.SetLength(bigCopy, System.length(big) + 1);
  984. System.Move(big[0], bigCopy[1], System.length(big) * System.SizeOf(Int32));
  985. end
  986. else
  987. begin
  988. bigCopy := System.Copy(big);
  989. end;
  990. bigCopy := AddMagnitudes(bigCopy, small);
  991. Result := TBigInteger.Create(Fsign, bigCopy, possibleOverflow);
  992. end;
  993. function TBigInteger.&And(const value: TBigInteger): TBigInteger;
  994. var
  995. aMag, bMag, resultMag: TCryptoLibInt32Array;
  996. resultNeg: Boolean;
  997. resultLength, aStart, bStart, i, aWord, bWord: Int32;
  998. begin
  999. if ((Fsign = 0) or (value.Fsign = 0)) then
  1000. begin
  1001. Result := Zero;
  1002. Exit;
  1003. end;
  1004. if Fsign > 0 then
  1005. begin
  1006. aMag := Fmagnitude;
  1007. end
  1008. else
  1009. begin
  1010. aMag := Add(One).Fmagnitude;
  1011. end;
  1012. if value.Fsign > 0 then
  1013. begin
  1014. bMag := value.Fmagnitude;
  1015. end
  1016. else
  1017. begin
  1018. bMag := value.Add(One).Fmagnitude;
  1019. end;
  1020. resultNeg := (Fsign < 0) and (value.Fsign < 0);
  1021. resultLength := Math.Max(System.length(aMag), System.length(bMag));
  1022. System.SetLength(resultMag, resultLength);
  1023. aStart := System.length(resultMag) - System.length(aMag);
  1024. bStart := System.length(resultMag) - System.length(bMag);
  1025. for i := 0 to System.Pred(System.length(resultMag)) do
  1026. begin
  1027. if i >= aStart then
  1028. begin
  1029. aWord := aMag[i - aStart];
  1030. end
  1031. else
  1032. begin
  1033. aWord := 0;
  1034. end;
  1035. if i >= bStart then
  1036. begin
  1037. bWord := bMag[i - bStart];
  1038. end
  1039. else
  1040. begin
  1041. bWord := 0;
  1042. end;
  1043. if (Fsign < 0) then
  1044. begin
  1045. aWord := not aWord;
  1046. end;
  1047. if (value.Fsign < 0) then
  1048. begin
  1049. bWord := not bWord;
  1050. end;
  1051. resultMag[i] := aWord and bWord;
  1052. if (resultNeg) then
  1053. begin
  1054. resultMag[i] := not resultMag[i];
  1055. end;
  1056. end;
  1057. Result := TBigInteger.Create(1, resultMag, True);
  1058. // TODO Optimise this case
  1059. if (resultNeg) then
  1060. begin
  1061. Result := Result.&Not();
  1062. end;
  1063. end;
  1064. function TBigInteger.AndNot(const val: TBigInteger): TBigInteger;
  1065. begin
  1066. Result := &And(val.&Not());
  1067. end;
  1068. class procedure TBigInteger.AppendZeroExtendedString(var sl: TStringList;
  1069. const s: String; minLength: Int32);
  1070. var
  1071. len: Int32;
  1072. begin
  1073. len := System.length(s);
  1074. while len < minLength do
  1075. begin
  1076. sl.Add('0');
  1077. System.Inc(len);
  1078. end;
  1079. sl.Add(s);
  1080. end;
  1081. class procedure TBigInteger.ToString(sl: TStringList; radix: Int32;
  1082. moduli: TList<TBigInteger>; scale: Int32; const pos: TBigInteger);
  1083. var
  1084. s: String;
  1085. qr: TCryptoLibGenericArray<TBigInteger>;
  1086. begin
  1087. if (pos.BitLength < 64) then
  1088. begin
  1089. s := IntToStr(pos.Int64Value);
  1090. if ((sl.Count > 1) or ((sl.Count = 1) and (sl[0] <> '-'))) then
  1091. begin
  1092. AppendZeroExtendedString(sl, s, 1 shl scale);
  1093. end
  1094. else if (pos.SignValue <> 0) then
  1095. begin
  1096. sl.Append(s);
  1097. end;
  1098. Exit;
  1099. end;
  1100. System.Dec(scale);
  1101. qr := pos.DivideAndRemainder(moduli[scale]);
  1102. ToString(sl, radix, moduli, scale, qr[0]);
  1103. ToString(sl, radix, moduli, scale, qr[1]);
  1104. end;
  1105. class function TBigInteger.Arbitrary(sizeInBits: Int32): TBigInteger;
  1106. begin
  1107. Result := TBigInteger.Create(sizeInBits, RandomSource);
  1108. end;
  1109. function TBigInteger.Remainder(m: Int32): Int32;
  1110. var
  1111. acc, posVal: Int64;
  1112. &pos: Int32;
  1113. begin
  1114. {$IFDEF DEBUG}
  1115. System.Assert(m > 0);
  1116. {$ENDIF DEBUG}
  1117. acc := 0;
  1118. for pos := 0 to System.Pred(System.length(Fmagnitude)) do
  1119. begin
  1120. posVal := UInt32(Fmagnitude[pos]);
  1121. acc := ((acc shl 32) or posVal) mod m;
  1122. end;
  1123. Result := Int32(acc);
  1124. end;
  1125. function TBigInteger.Remainder(const n: TBigInteger): TBigInteger;
  1126. var
  1127. val, rem: Int32;
  1128. tempRes: TCryptoLibInt32Array;
  1129. begin
  1130. if (n.Fsign = 0) then
  1131. begin
  1132. raise EArithmeticCryptoLibException.CreateRes(@SDivisionByZero);
  1133. end;
  1134. if (Fsign = 0) then
  1135. begin
  1136. Result := Zero;
  1137. Exit;
  1138. end;
  1139. // For small values, use fast remainder method
  1140. if (System.length(n.Fmagnitude) = 1) then
  1141. begin
  1142. val := n.Fmagnitude[0];
  1143. if (val > 0) then
  1144. begin
  1145. if (val = 1) then
  1146. begin
  1147. Result := Zero;
  1148. Exit;
  1149. end;
  1150. // TODO Make this func work on uint, and handle val == 1?
  1151. rem := Remainder(val);
  1152. if rem = 0 then
  1153. begin
  1154. Result := Zero;
  1155. Exit;
  1156. end
  1157. else
  1158. begin
  1159. Result := TBigInteger.Create(Fsign,
  1160. TCryptoLibInt32Array.Create(rem), false);
  1161. Exit;
  1162. end;
  1163. end;
  1164. end;
  1165. if (CompareNoLeadingZeroes(0, Fmagnitude, 0, n.Fmagnitude) < 0) then
  1166. begin
  1167. Result := Self;
  1168. Exit;
  1169. end;
  1170. if (n.QuickPow2Check()) then // n is power of two
  1171. begin
  1172. // TODO Move before small values branch above?
  1173. tempRes := LastNBits(n.Abs().BitLength - 1);
  1174. end
  1175. else
  1176. begin
  1177. tempRes := System.Copy(Fmagnitude);
  1178. tempRes := Remainder(tempRes, n.Fmagnitude);
  1179. end;
  1180. Result := TBigInteger.Create(Fsign, tempRes, True);
  1181. end;
  1182. function TBigInteger.&Mod(const m: TBigInteger): TBigInteger;
  1183. var
  1184. biggie: TBigInteger;
  1185. begin
  1186. if (m.Fsign < 1) then
  1187. begin
  1188. raise EArithmeticCryptoLibException.CreateRes(@SModulusPositive);
  1189. end;
  1190. biggie := Remainder(m);
  1191. if biggie.Fsign >= 0 then
  1192. begin
  1193. Result := biggie;
  1194. end
  1195. else
  1196. begin
  1197. Result := biggie.Add(m);
  1198. end;
  1199. end;
  1200. function TBigInteger.&Or(const value: TBigInteger): TBigInteger;
  1201. var
  1202. aMag, bMag, resultMag: TCryptoLibInt32Array;
  1203. resultNeg: Boolean;
  1204. resultLength, aStart, bStart, i, aWord, bWord: Int32;
  1205. begin
  1206. if (Fsign = 0) then
  1207. begin
  1208. Result := value;
  1209. Exit;
  1210. end;
  1211. if (value.Fsign = 0) then
  1212. begin
  1213. Result := Self;
  1214. Exit;
  1215. end;
  1216. if Fsign > 0 then
  1217. begin
  1218. aMag := Fmagnitude;
  1219. end
  1220. else
  1221. begin
  1222. aMag := Add(One).Fmagnitude;
  1223. end;
  1224. if value.Fsign > 0 then
  1225. begin
  1226. bMag := value.Fmagnitude;
  1227. end
  1228. else
  1229. begin
  1230. bMag := value.Add(One).Fmagnitude;
  1231. end;
  1232. resultNeg := (Fsign < 0) or (value.Fsign < 0);
  1233. resultLength := Math.Max(System.length(aMag), System.length(bMag));
  1234. System.SetLength(resultMag, resultLength);
  1235. aStart := System.length(resultMag) - System.length(aMag);
  1236. bStart := System.length(resultMag) - System.length(bMag);
  1237. for i := 0 to System.Pred(System.length(resultMag)) do
  1238. begin
  1239. if i >= aStart then
  1240. begin
  1241. aWord := aMag[i - aStart];
  1242. end
  1243. else
  1244. begin
  1245. aWord := 0;
  1246. end;
  1247. if i >= bStart then
  1248. begin
  1249. bWord := bMag[i - bStart];
  1250. end
  1251. else
  1252. begin
  1253. bWord := 0;
  1254. end;
  1255. if (Fsign < 0) then
  1256. begin
  1257. aWord := not aWord;
  1258. end;
  1259. if (value.Fsign < 0) then
  1260. begin
  1261. bWord := not bWord;
  1262. end;
  1263. resultMag[i] := aWord or bWord;
  1264. if (resultNeg) then
  1265. begin
  1266. resultMag[i] := not resultMag[i];
  1267. end;
  1268. end;
  1269. Result := TBigInteger.Create(1, resultMag, True);
  1270. // TODO Optimise this case
  1271. if (resultNeg) then
  1272. begin
  1273. Result := Result.&Not();
  1274. end;
  1275. end;
  1276. function TBigInteger.&Xor(const value: TBigInteger): TBigInteger;
  1277. var
  1278. aMag, bMag, resultMag: TCryptoLibInt32Array;
  1279. resultNeg: Boolean;
  1280. resultLength, aStart, bStart, i, aWord, bWord: Int32;
  1281. begin
  1282. if (Fsign = 0) then
  1283. begin
  1284. Result := value;
  1285. Exit;
  1286. end;
  1287. if (value.Fsign = 0) then
  1288. begin
  1289. Result := Self;
  1290. Exit;
  1291. end;
  1292. if Fsign > 0 then
  1293. begin
  1294. aMag := Fmagnitude;
  1295. end
  1296. else
  1297. begin
  1298. aMag := Add(One).Fmagnitude;
  1299. end;
  1300. if value.Fsign > 0 then
  1301. begin
  1302. bMag := value.Fmagnitude;
  1303. end
  1304. else
  1305. begin
  1306. bMag := value.Add(One).Fmagnitude;
  1307. end;
  1308. // TODO Can just replace with sign != value.sign?
  1309. resultNeg := ((Fsign < 0) and (value.Fsign >= 0)) or
  1310. ((Fsign >= 0) and (value.Fsign < 0));
  1311. resultLength := Math.Max(System.length(aMag), System.length(bMag));
  1312. System.SetLength(resultMag, resultLength);
  1313. aStart := System.length(resultMag) - System.length(aMag);
  1314. bStart := System.length(resultMag) - System.length(bMag);
  1315. for i := 0 to System.Pred(System.length(resultMag)) do
  1316. begin
  1317. if i >= aStart then
  1318. begin
  1319. aWord := aMag[i - aStart];
  1320. end
  1321. else
  1322. begin
  1323. aWord := 0;
  1324. end;
  1325. if i >= bStart then
  1326. begin
  1327. bWord := bMag[i - bStart];
  1328. end
  1329. else
  1330. begin
  1331. bWord := 0;
  1332. end;
  1333. if (Fsign < 0) then
  1334. begin
  1335. aWord := not aWord;
  1336. end;
  1337. if (value.Fsign < 0) then
  1338. begin
  1339. bWord := not bWord;
  1340. end;
  1341. resultMag[i] := aWord xor bWord;
  1342. if (resultNeg) then
  1343. begin
  1344. resultMag[i] := not resultMag[i];
  1345. end;
  1346. end;
  1347. Result := TBigInteger.Create(1, resultMag, True);
  1348. // TODO Optimise this case
  1349. if (resultNeg) then
  1350. begin
  1351. Result := Result.&Not();
  1352. end;
  1353. end;
  1354. class constructor TBigInteger.BigInteger;
  1355. begin
  1356. TBigInteger.Boot;
  1357. end;
  1358. constructor TBigInteger.Create(const value: String);
  1359. begin
  1360. ParseString(value, 10);
  1361. end;
  1362. constructor TBigInteger.Create(const str: String; radix: Int32);
  1363. begin
  1364. ParseString(str, radix);
  1365. end;
  1366. constructor TBigInteger.Create(bytes: TCryptoLibByteArray);
  1367. begin
  1368. ParseBytes(bytes, 0, System.length(bytes));
  1369. end;
  1370. constructor TBigInteger.Create(sign: Int32; bytes: TCryptoLibByteArray);
  1371. begin
  1372. ParseBytesWithSign(sign, bytes, 0, System.length(bytes));
  1373. end;
  1374. constructor TBigInteger.Create(bytes: TCryptoLibByteArray;
  1375. offset, length: Int32);
  1376. begin
  1377. ParseBytes(bytes, offset, length);
  1378. end;
  1379. constructor TBigInteger.Create(sign: Int32; bytes: TCryptoLibByteArray;
  1380. offset, length: Int32);
  1381. begin
  1382. ParseBytesWithSign(sign, bytes, offset, length);
  1383. end;
  1384. constructor TBigInteger.Create(BitLength, certainty: Int32;
  1385. const random: IRandom);
  1386. var
  1387. nBytes, xBits, j: Int32;
  1388. mask, lead: Byte;
  1389. b: TCryptoLibByteArray;
  1390. begin
  1391. if (BitLength < 2) then
  1392. begin
  1393. raise EArithmeticCryptoLibException.CreateRes(@SInvalidBitLength);
  1394. end;
  1395. Fsign := 1;
  1396. FnBits := -1;
  1397. FnBitLength := BitLength;
  1398. FmQuote := 0;
  1399. FIsInitialized := True;
  1400. if (BitLength = 2) then
  1401. begin
  1402. if (random.Next(2) = 0) then
  1403. begin
  1404. Fmagnitude := Two.Fmagnitude
  1405. end
  1406. else
  1407. begin
  1408. Fmagnitude := Three.Fmagnitude
  1409. end;
  1410. Exit;
  1411. end;
  1412. nBytes := GetByteLength(BitLength);
  1413. System.SetLength(b, nBytes);
  1414. xBits := (BitsPerByte * nBytes) - BitLength;
  1415. mask := Byte(UInt32(255) shr xBits);
  1416. lead := Byte(1 shl (7 - xBits));
  1417. while True do
  1418. begin
  1419. random.NextBytes(b);
  1420. // strip off any excess bits in the MSB
  1421. b[0] := b[0] and mask;
  1422. // ensure the leading bit is 1 (to meet the strength requirement)
  1423. b[0] := b[0] or lead;
  1424. // ensure the trailing bit is 1 (i.e. must be odd)
  1425. b[nBytes - 1] := b[nBytes - 1] or 1;
  1426. Fmagnitude := MakeMagnitude(b, 0, System.length(b));
  1427. FnBits := -1;
  1428. FmQuote := 0;
  1429. if (certainty < 1) then
  1430. begin
  1431. break;
  1432. end;
  1433. if (CheckProbablePrime(certainty, random, True)) then
  1434. begin
  1435. break;
  1436. end;
  1437. j := 1;
  1438. while j < (System.length(Fmagnitude) - 1) do
  1439. begin
  1440. Fmagnitude[j] := Fmagnitude[j] xor random.Next();
  1441. if (CheckProbablePrime(certainty, random, True)) then
  1442. begin
  1443. Exit;
  1444. end;
  1445. System.Inc(j);
  1446. end;
  1447. end;
  1448. end;
  1449. constructor TBigInteger.Create(sizeInBits: Int32; const random: IRandom);
  1450. var
  1451. nBytes, xBits: Int32;
  1452. b: TCryptoLibByteArray;
  1453. begin
  1454. if (sizeInBits < 0) then
  1455. begin
  1456. raise EArgumentCryptoLibException.CreateRes(@SNegativeSizeInBits);
  1457. end;
  1458. Fsign := -1;
  1459. FnBits := -1;
  1460. FnBitLength := -1;
  1461. FmQuote := 0;
  1462. FIsInitialized := True;
  1463. if (sizeInBits = 0) then
  1464. begin
  1465. Fsign := 0;
  1466. Fmagnitude := FZeroMagnitude;
  1467. Exit;
  1468. end;
  1469. nBytes := GetByteLength(sizeInBits);
  1470. System.SetLength(b, nBytes);
  1471. random.NextBytes(b);
  1472. // strip off any excess bits in the MSB
  1473. xBits := (BitsPerByte * nBytes) - sizeInBits;
  1474. b[0] := b[0] and Byte(UInt32(255) shr xBits);
  1475. Fmagnitude := MakeMagnitude(b, 0, System.length(b));
  1476. if System.length(Fmagnitude) < 1 then
  1477. begin
  1478. Fsign := 0;
  1479. end
  1480. else
  1481. begin
  1482. Fsign := 1;
  1483. end;
  1484. end;
  1485. constructor TBigInteger.Create(signum: Int32; mag: TCryptoLibInt32Array;
  1486. checkMag: Boolean);
  1487. var
  1488. i: Int32;
  1489. begin
  1490. Fsign := -1;
  1491. FnBits := -1;
  1492. FnBitLength := -1;
  1493. FmQuote := 0;
  1494. FIsInitialized := True;
  1495. if (checkMag) then
  1496. begin
  1497. i := 0;
  1498. while ((i < System.length(mag)) and (mag[i] = 0)) do
  1499. begin
  1500. System.Inc(i);
  1501. end;
  1502. if (i = System.length(mag)) then
  1503. begin
  1504. Fsign := 0;
  1505. Fmagnitude := FZeroMagnitude;
  1506. end
  1507. else
  1508. begin
  1509. Fsign := signum;
  1510. if (i = 0) then
  1511. begin
  1512. Fmagnitude := mag;
  1513. end
  1514. else
  1515. begin
  1516. // strip leading 0 words
  1517. System.SetLength(Fmagnitude, System.length(mag) - i);
  1518. System.Move(mag[i], Fmagnitude[0], System.length(Fmagnitude) *
  1519. System.SizeOf(Int32));
  1520. end
  1521. end;
  1522. end
  1523. else
  1524. begin
  1525. Fsign := signum;
  1526. Fmagnitude := mag;
  1527. end;
  1528. end;
  1529. function TBigInteger.Equals(const other: TBigInteger): Boolean;
  1530. begin
  1531. Result := (Fsign = other.Fsign) and IsEqualMagnitude(other);
  1532. end;
  1533. class function TBigInteger.ExtEuclid(const a, b: TBigInteger;
  1534. out u1Out: TBigInteger): TBigInteger;
  1535. var
  1536. u1, v1, u3, v3, oldU1: TBigInteger;
  1537. q: TCryptoLibGenericArray<TBigInteger>;
  1538. begin
  1539. u1 := One;
  1540. v1 := Zero;
  1541. u3 := a;
  1542. v3 := b;
  1543. if (v3.Fsign > 0) then
  1544. begin
  1545. while True do
  1546. begin
  1547. q := u3.DivideAndRemainder(v3);
  1548. u3 := v3;
  1549. v3 := q[1];
  1550. oldU1 := u1;
  1551. u1 := v1;
  1552. if (v3.Fsign <= 0) then
  1553. begin
  1554. break;
  1555. end;
  1556. v1 := oldU1.Subtract(v1.Multiply(q[0]));
  1557. end;
  1558. end;
  1559. u1Out := u1;
  1560. Result := u3;
  1561. end;
  1562. function TBigInteger.FlipExistingBit(n: Int32): TBigInteger;
  1563. var
  1564. mag: TCryptoLibInt32Array;
  1565. begin
  1566. {$IFDEF DEBUG}
  1567. System.Assert(Fsign > 0);
  1568. System.Assert(n >= 0);
  1569. System.Assert(n < BitLength - 1);
  1570. {$ENDIF DEBUG}
  1571. mag := System.Copy(Fmagnitude);
  1572. mag[System.length(mag) - 1 - (n shr 5)] :=
  1573. mag[System.length(mag) - 1 - (n shr 5)] xor (1 shl (n and 31));
  1574. // Flip bit
  1575. // mag[mag.Length - 1 - (n / 32)] ^= (1 << (n % 32));
  1576. Result := TBigInteger.Create(Fsign, mag, false);
  1577. end;
  1578. function TBigInteger.FlipBit(n: Int32): TBigInteger;
  1579. begin
  1580. if (n < 0) then
  1581. begin
  1582. raise EArithmeticCryptoLibException.CreateRes(@SInvalidBitAddress);
  1583. end;
  1584. // TODO Handle negative values and zero
  1585. if ((Fsign > 0) and (n < (BitLength - 1))) then
  1586. begin
  1587. Result := FlipExistingBit(n);
  1588. Exit;
  1589. end;
  1590. Result := &Xor(One.ShiftLeft(n));
  1591. end;
  1592. function TBigInteger.Gcd(const value: TBigInteger): TBigInteger;
  1593. var
  1594. r, u, v: TBigInteger;
  1595. begin
  1596. if (value.Fsign = 0) then
  1597. begin
  1598. Result := Abs();
  1599. Exit;
  1600. end;
  1601. if (Fsign = 0) then
  1602. begin
  1603. Result := value.Abs();
  1604. Exit;
  1605. end;
  1606. u := Self;
  1607. v := value;
  1608. while (v.Fsign <> 0) do
  1609. begin
  1610. r := u.&Mod(v);
  1611. u := v;
  1612. v := r;
  1613. end;
  1614. Result := u;
  1615. end;
  1616. function TBigInteger.GetBitCount: Int32;
  1617. var
  1618. sum, i: Int32;
  1619. begin
  1620. if (FnBits = -1) then
  1621. begin
  1622. if (Fsign < 0) then
  1623. begin
  1624. // TODO Optimise this case
  1625. FnBits := &Not().BitCount;
  1626. end
  1627. else
  1628. begin
  1629. sum := 0;
  1630. for i := 0 to System.Pred(System.length(Fmagnitude)) do
  1631. begin
  1632. sum := sum + BitCnt(Fmagnitude[i]);
  1633. end;
  1634. FnBits := sum;
  1635. end;
  1636. end;
  1637. Result := FnBits;
  1638. end;
  1639. function TBigInteger.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
  1640. {$ENDIF DELPHI}
  1641. var
  1642. hc: Int32;
  1643. begin
  1644. hc := System.length(Fmagnitude);
  1645. if (System.length(Fmagnitude) > 0) then
  1646. begin
  1647. hc := hc xor Fmagnitude[0];
  1648. if (System.length(Fmagnitude) > 1) then
  1649. begin
  1650. hc := hc xor Fmagnitude[System.length(Fmagnitude) - 1];
  1651. end;
  1652. end;
  1653. if Fsign < 0 then
  1654. begin
  1655. Result := not hc;
  1656. end
  1657. else
  1658. begin
  1659. Result := hc;
  1660. end;
  1661. end;
  1662. function TBigInteger.GetLowestSetBit: Int32;
  1663. begin
  1664. if (Fsign = 0) then
  1665. begin
  1666. Result := -1;
  1667. Exit;
  1668. end;
  1669. Result := GetLowestSetBitMaskFirst(-1);
  1670. end;
  1671. function TBigInteger.GetLowestSetBitMaskFirst(firstWordMask: Int32): Int32;
  1672. var
  1673. w, offset: Int32;
  1674. word: UInt32;
  1675. begin
  1676. w := System.length(Fmagnitude);
  1677. offset := 0;
  1678. System.Dec(w);
  1679. word := UInt32(Fmagnitude[w] and firstWordMask);
  1680. {$IFDEF DEBUG}
  1681. System.Assert(Fmagnitude[0] <> 0);
  1682. {$ENDIF DEBUG}
  1683. while (word = 0) do
  1684. begin
  1685. System.Dec(w);
  1686. word := UInt32(Fmagnitude[w]);
  1687. offset := offset + 32;
  1688. end;
  1689. while ((word and $FF) = 0) do
  1690. begin
  1691. word := word shr 8;
  1692. offset := offset + 8;
  1693. end;
  1694. while ((word and 1) = 0) do
  1695. begin
  1696. word := word shr 1;
  1697. System.Inc(offset);
  1698. end;
  1699. Result := offset;
  1700. end;
  1701. class function TBigInteger.ModInverse32(d: Int32): Int32;
  1702. var
  1703. x: Int32;
  1704. begin
  1705. // Newton's method with initial estimate "correct to 4 bits"
  1706. {$IFDEF DEBUG}
  1707. System.Assert((d and 1) <> 0);
  1708. {$ENDIF DEBUG}
  1709. x := d + (((d + 1) and 4) shl 1); // d.x == 1 mod 2**4
  1710. {$IFDEF DEBUG}
  1711. System.Assert(((d * x) and 15) = 1);
  1712. {$ENDIF DEBUG}
  1713. x := x * (2 - (d * x)); // d.x == 1 mod 2**8
  1714. x := x * (2 - (d * x)); // d.x == 1 mod 2**16
  1715. x := x * (2 - (d * x)); // d.x == 1 mod 2**32
  1716. {$IFDEF DEBUG}
  1717. System.Assert(d * x = 1);
  1718. {$ENDIF DEBUG}
  1719. Result := x;
  1720. end;
  1721. function TBigInteger.GetMQuote: Int32;
  1722. var
  1723. d: Int32;
  1724. begin
  1725. if (FmQuote <> 0) then
  1726. begin
  1727. Result := FmQuote; // already calculated
  1728. Exit;
  1729. end;
  1730. {$IFDEF DEBUG}
  1731. System.Assert(Fsign > 0);
  1732. {$ENDIF DEBUG}
  1733. d := Int32(Fmagnitude[System.length(Fmagnitude) - 1]);
  1734. d := -d;
  1735. {$IFDEF DEBUG}
  1736. System.Assert((d and 1) <> 0);
  1737. {$ENDIF DEBUG}
  1738. FmQuote := ModInverse32(d);
  1739. Result := FmQuote;
  1740. end;
  1741. function TBigInteger.IsEqualMagnitude(const x: TBigInteger): Boolean;
  1742. var
  1743. i: Integer;
  1744. xMag: TCryptoLibInt32Array;
  1745. begin
  1746. xMag := x.Fmagnitude;
  1747. if (System.length(Fmagnitude) <> System.length(xMag)) then
  1748. begin
  1749. Result := false;
  1750. Exit;
  1751. end;
  1752. for i := 0 to System.Pred(System.length(Fmagnitude)) do
  1753. begin
  1754. if (Fmagnitude[i] <> xMag[i]) then
  1755. begin
  1756. Result := false;
  1757. Exit;
  1758. end;
  1759. end;
  1760. Result := True;
  1761. end;
  1762. function TBigInteger.IsProbablePrime(certainty: Int32;
  1763. randomlySelected: Boolean): Boolean;
  1764. var
  1765. n: TBigInteger;
  1766. begin
  1767. if (certainty <= 0) then
  1768. begin
  1769. Result := True;
  1770. Exit;
  1771. end;
  1772. n := Abs();
  1773. if (not n.TestBit(0)) then
  1774. begin
  1775. Result := n.Equals(Two);
  1776. Exit;
  1777. end;
  1778. if (n.Equals(One)) then
  1779. begin
  1780. Result := false;
  1781. Exit;
  1782. end;
  1783. Result := n.CheckProbablePrime(certainty, RandomSource, randomlySelected);
  1784. end;
  1785. class function TBigInteger.Jacobi(const a, b: TBigInteger): Int32;
  1786. var
  1787. totalS, e, bLsw, a1Lsw: Int32;
  1788. a1, La, Lb: TBigInteger;
  1789. begin
  1790. La := a;
  1791. Lb := b;
  1792. {$IFDEF DEBUG}
  1793. System.Assert(La.SignValue >= 0);
  1794. System.Assert(Lb.SignValue > 0);
  1795. System.Assert(Lb.TestBit(0));
  1796. System.Assert(La.CompareTo(Lb) < 0);
  1797. {$ENDIF DEBUG}
  1798. totalS := 1;
  1799. while True do
  1800. begin
  1801. if (La.SignValue = 0) then
  1802. begin
  1803. Result := 0;
  1804. Exit;
  1805. end;
  1806. if (La.Equals(One)) then
  1807. begin
  1808. break;
  1809. end;
  1810. e := La.GetLowestSetBit();
  1811. bLsw := Lb.Fmagnitude[System.length(Lb.Fmagnitude) - 1];
  1812. if (((e and 1) <> 0) and (((bLsw and 7) = 3) or ((bLsw and 7) = 5))) then
  1813. begin
  1814. totalS := -totalS;
  1815. end;
  1816. if (La.BitLength = e + 1) then
  1817. begin
  1818. break;
  1819. end;
  1820. a1 := La.ShiftRight(e);
  1821. a1Lsw := a1.Fmagnitude[System.length(a1.Fmagnitude) - 1];
  1822. if (((bLsw and 3) = 3) and ((a1Lsw and 3) = 3)) then
  1823. begin
  1824. totalS := -totalS;
  1825. end;
  1826. La := Lb.Remainder(a1);
  1827. Lb := a1;
  1828. end;
  1829. Result := totalS;
  1830. end;
  1831. function TBigInteger.IsProbablePrime(certainty: Int32): Boolean;
  1832. begin
  1833. Result := IsProbablePrime(certainty, false);
  1834. end;
  1835. class function TBigInteger.MakeMagnitude(bytes: TCryptoLibByteArray;
  1836. offset, length: Int32): TCryptoLibInt32Array;
  1837. var
  1838. endPoint, firstSignificant, nInts, bCount, v, magnitudeIndex, i: Int32;
  1839. mag: TCryptoLibInt32Array;
  1840. begin
  1841. endPoint := offset + length;
  1842. // strip leading zeros
  1843. firstSignificant := offset;
  1844. while ((firstSignificant < endPoint) and (bytes[firstSignificant] = 0)) do
  1845. begin
  1846. System.Inc(firstSignificant);
  1847. end;
  1848. if (firstSignificant >= endPoint) then
  1849. begin
  1850. Result := FZeroMagnitude;
  1851. Exit;
  1852. end;
  1853. nInts := (endPoint - firstSignificant + 3) div BytesPerInt;
  1854. bCount := (endPoint - firstSignificant) mod BytesPerInt;
  1855. if (bCount = 0) then
  1856. begin
  1857. bCount := BytesPerInt;
  1858. end;
  1859. if (nInts < 1) then
  1860. begin
  1861. Result := FZeroMagnitude;
  1862. Exit;
  1863. end;
  1864. System.SetLength(mag, nInts);
  1865. v := 0;
  1866. magnitudeIndex := 0;
  1867. i := firstSignificant;
  1868. while i < endPoint do
  1869. begin
  1870. v := v shl 8;
  1871. v := v or (bytes[i] and $FF);
  1872. System.Dec(bCount);
  1873. if (bCount <= 0) then
  1874. begin
  1875. mag[magnitudeIndex] := v;
  1876. System.Inc(magnitudeIndex);
  1877. bCount := BytesPerInt;
  1878. v := 0;
  1879. end;
  1880. System.Inc(i);
  1881. end;
  1882. if (magnitudeIndex < System.length(mag)) then
  1883. begin
  1884. mag[magnitudeIndex] := v;
  1885. end;
  1886. Result := mag;
  1887. end;
  1888. function TBigInteger.Max(const value: TBigInteger): TBigInteger;
  1889. begin
  1890. if CompareTo(value) > 0 then
  1891. begin
  1892. Result := Self;
  1893. end
  1894. else
  1895. begin
  1896. Result := value;
  1897. end;
  1898. end;
  1899. function TBigInteger.Min(const value: TBigInteger): TBigInteger;
  1900. begin
  1901. if CompareTo(value) < 0 then
  1902. begin
  1903. Result := Self;
  1904. end
  1905. else
  1906. begin
  1907. Result := value;
  1908. end;
  1909. end;
  1910. function TBigInteger.ModInverse(const m: TBigInteger): TBigInteger;
  1911. var
  1912. d, x, Gcd: TBigInteger;
  1913. begin
  1914. if (m.Fsign < 1) then
  1915. begin
  1916. raise EArithmeticCryptoLibException.CreateRes(@SModulusPositive);
  1917. end;
  1918. // TODO Too slow at the moment
  1919. // // "Fast Key Exchange with Elliptic Curve Systems" R.Schoeppel
  1920. // if (m.TestBit(0))
  1921. // {
  1922. // //The Almost Inverse Algorithm
  1923. // int k = 0;
  1924. // BigInteger B = One, C = Zero, F = this, G = m, tmp;
  1925. //
  1926. // for (;;)
  1927. // {
  1928. // // While F is even, do F=F/u, C=C*u, k=k+1.
  1929. // int zeroes = F.GetLowestSetBit();
  1930. // if (zeroes > 0)
  1931. // {
  1932. // F = F.ShiftRight(zeroes);
  1933. // C = C.ShiftLeft(zeroes);
  1934. // k += zeroes;
  1935. // }
  1936. //
  1937. // // If F = 1, then return B,k.
  1938. // if (F.Equals(One))
  1939. // {
  1940. // BigInteger half = m.Add(One).ShiftRight(1);
  1941. // BigInteger halfK = half.ModPow(BigInteger.ValueOf(k), m);
  1942. // return B.Multiply(halfK).Mod(m);
  1943. // }
  1944. //
  1945. // if (F.CompareTo(G) < 0)
  1946. // {
  1947. // tmp = G; G = F; F = tmp;
  1948. // tmp = B; B = C; C = tmp;
  1949. // }
  1950. //
  1951. // F = F.Add(G);
  1952. // B = B.Add(C);
  1953. // }
  1954. // }
  1955. if (m.QuickPow2Check()) then
  1956. begin
  1957. Result := ModInversePow2(m);
  1958. Exit;
  1959. end;
  1960. d := Remainder(m);
  1961. Gcd := ExtEuclid(d, m, x);
  1962. if (not Gcd.Equals(One)) then
  1963. begin
  1964. raise EArithmeticCryptoLibException.CreateRes(@SNotRelativelyPrime);
  1965. end;
  1966. if (x.Fsign < 0) then
  1967. begin
  1968. x := x.Add(m);
  1969. end;
  1970. Result := x;
  1971. end;
  1972. class function TBigInteger.ModInverse64(d: Int64): Int64;
  1973. var
  1974. x: Int64;
  1975. begin
  1976. // Newton's method with initial estimate "correct to 4 bits"
  1977. {$IFDEF DEBUG}
  1978. System.Assert((d and Int64(1)) <> 0);
  1979. {$ENDIF DEBUG}
  1980. x := d + (((d + Int64(1)) and Int64(4)) shl 1); // d.x == 1 mod 2**4
  1981. {$IFDEF DEBUG}
  1982. System.Assert(((d * x) and Int64(15)) = Int64(1));
  1983. {$ENDIF DEBUG}
  1984. x := x * (2 - (d * x)); // d.x == 1 mod 2**8
  1985. x := x * (2 - (d * x)); // d.x == 1 mod 2**16
  1986. x := x * (2 - (d * x)); // d.x == 1 mod 2**32
  1987. x := x * (2 - (d * x)); // d.x == 1 mod 2**64
  1988. {$IFDEF DEBUG}
  1989. System.Assert(d * x = Int64(1));
  1990. {$ENDIF DEBUG}
  1991. Result := x;
  1992. end;
  1993. function TBigInteger.ModInversePow2(const m: TBigInteger): TBigInteger;
  1994. var
  1995. Pow, bitsCorrect: Int32;
  1996. inv64: Int64;
  1997. x, d, t: TBigInteger;
  1998. begin
  1999. {$IFDEF DEBUG}
  2000. System.Assert(m.SignValue > 0);
  2001. System.Assert(m.BitCount = 1);
  2002. {$ENDIF DEBUG}
  2003. if (not TestBit(0)) then
  2004. begin
  2005. raise EArithmeticCryptoLibException.CreateRes(@SNotRelativelyPrime);
  2006. end;
  2007. Pow := m.BitLength - 1;
  2008. inv64 := ModInverse64(Int64Value);
  2009. if (Pow < 64) then
  2010. begin
  2011. inv64 := inv64 and ((Int64(1) shl Pow) - 1);
  2012. end;
  2013. x := TBigInteger.ValueOf(inv64);
  2014. if (Pow > 64) then
  2015. begin
  2016. d := Remainder(m);
  2017. bitsCorrect := 64;
  2018. repeat
  2019. t := x.Multiply(d).Remainder(m);
  2020. x := x.Multiply(Two.Subtract(t)).Remainder(m);
  2021. bitsCorrect := bitsCorrect shl 1;
  2022. until (not(bitsCorrect < Pow));
  2023. end;
  2024. if (x.Fsign < 0) then
  2025. begin
  2026. x := x.Add(m);
  2027. end;
  2028. Result := x;
  2029. end;
  2030. function TBigInteger.ModPow(e: TBigInteger; const m: TBigInteger): TBigInteger;
  2031. var
  2032. negExp: Boolean;
  2033. begin
  2034. if (m.Fsign < 1) then
  2035. begin
  2036. raise EArithmeticCryptoLibException.CreateRes(@SModulusPositive);
  2037. end;
  2038. if (m.Equals(One)) then
  2039. begin
  2040. Result := Zero;
  2041. Exit;
  2042. end;
  2043. if (e.Fsign = 0) then
  2044. begin
  2045. Result := One;
  2046. Exit;
  2047. end;
  2048. if (Fsign = 0) then
  2049. begin
  2050. Result := Zero;
  2051. Exit;
  2052. end;
  2053. negExp := e.Fsign < 0;
  2054. if (negExp) then
  2055. begin
  2056. e := e.Negate();
  2057. end;
  2058. Result := &Mod(m);
  2059. if (not e.Equals(One)) then
  2060. begin
  2061. if ((m.Fmagnitude[System.length(m.Fmagnitude) - 1] and 1) = 0) then
  2062. begin
  2063. Result := ModPowBarrett(Result, e, m);
  2064. end
  2065. else
  2066. begin
  2067. Result := ModPowMonty(Result, e, m, True);
  2068. end;
  2069. end;
  2070. if (negExp) then
  2071. begin
  2072. Result := Result.ModInverse(m);
  2073. end;
  2074. end;
  2075. class function TBigInteger.ModPowBarrett(const b, e, m: TBigInteger)
  2076. : TBigInteger;
  2077. var
  2078. k, extraBits, expLength, numPowers, i, window, mult, lastZeroes, windowPos,
  2079. bits, j: Int32;
  2080. mr, yu, b2, y: TBigInteger;
  2081. oddPowers: TCryptoLibGenericArray<TBigInteger>;
  2082. windowList: TCryptoLibInt32Array;
  2083. begin
  2084. k := System.length(m.Fmagnitude);
  2085. mr := One.ShiftLeft((k + 1) shl 5);
  2086. yu := One.ShiftLeft(k shl 6).Divide(m);
  2087. // Sliding window from MSW to LSW
  2088. extraBits := 0;
  2089. expLength := e.BitLength;
  2090. while (expLength > ExpWindowThresholds[extraBits]) do
  2091. begin
  2092. System.Inc(extraBits);
  2093. end;
  2094. numPowers := 1 shl extraBits;
  2095. System.SetLength(oddPowers, numPowers);
  2096. oddPowers[0] := b;
  2097. b2 := ReduceBarrett(b.Square(), m, mr, yu);
  2098. for i := 1 to System.Pred(numPowers) do
  2099. begin
  2100. oddPowers[i] := ReduceBarrett(oddPowers[i - 1].Multiply(b2), m, mr, yu);
  2101. end;
  2102. windowList := GetWindowList(e.Fmagnitude, extraBits);
  2103. {$IFDEF DEBUG}
  2104. System.Assert(System.length(windowList) > 0);
  2105. {$ENDIF DEBUG}
  2106. window := windowList[0];
  2107. mult := window and $FF;
  2108. lastZeroes := window shr 8;
  2109. if (mult = 1) then
  2110. begin
  2111. y := b2;
  2112. System.Dec(lastZeroes);
  2113. end
  2114. else
  2115. begin
  2116. y := oddPowers[mult shr 1];
  2117. end;
  2118. windowPos := 1;
  2119. window := windowList[windowPos];
  2120. System.Inc(windowPos);
  2121. while (window <> -1) do
  2122. begin
  2123. mult := window and $FF;
  2124. bits := lastZeroes + BitLengthTable[mult];
  2125. j := 0;
  2126. while j < bits do
  2127. begin
  2128. y := ReduceBarrett(y.Square(), m, mr, yu);
  2129. System.Inc(j);
  2130. end;
  2131. y := ReduceBarrett(y.Multiply(oddPowers[mult shr 1]), m, mr, yu);
  2132. lastZeroes := window shr 8;
  2133. window := windowList[windowPos];
  2134. System.Inc(windowPos);
  2135. end;
  2136. i := 0;
  2137. while i < lastZeroes do
  2138. begin
  2139. y := ReduceBarrett(y.Square(), m, mr, yu);
  2140. System.Inc(i);
  2141. end;
  2142. Result := y;
  2143. end;
  2144. class function TBigInteger.ModPowMonty(b: TBigInteger; const e, m: TBigInteger;
  2145. convert: Boolean): TBigInteger;
  2146. var
  2147. n, powR, extraBits, expLength, numPowers, i, window, mult, lastZeroes,
  2148. windowPos, bits, j: Int32;
  2149. smallMontyModulus: Boolean;
  2150. mDash: UInt32;
  2151. yAccum, zVal, tmp, zSquared, windowList, yVal: TCryptoLibInt32Array;
  2152. oddPowers: TCryptoLibMatrixInt32Array;
  2153. begin
  2154. n := System.length(m.Fmagnitude);
  2155. powR := 32 * n;
  2156. smallMontyModulus := (m.BitLength + 2) <= powR;
  2157. mDash := UInt32(m.GetMQuote());
  2158. // tmp = this * R mod m
  2159. if (convert) then
  2160. begin
  2161. b := b.ShiftLeft(powR).Remainder(m);
  2162. end;
  2163. System.SetLength(yAccum, n + 1);
  2164. zVal := b.Fmagnitude;
  2165. {$IFDEF DEBUG}
  2166. System.Assert(System.length(zVal) <= n);
  2167. {$ENDIF DEBUG}
  2168. if (System.length(zVal) < n) then
  2169. begin
  2170. System.SetLength(tmp, n);
  2171. System.Move(zVal[0], tmp[n - System.length(zVal)],
  2172. System.length(zVal) * System.SizeOf(Int32));
  2173. zVal := tmp;
  2174. end;
  2175. // Sliding window from MSW to LSW
  2176. extraBits := 0;
  2177. // Filter the common case of small RSA exponents with few bits set
  2178. if ((System.length(e.Fmagnitude) > 1) or (e.BitCount > 2)) then
  2179. begin
  2180. expLength := e.BitLength;
  2181. while (expLength > ExpWindowThresholds[extraBits]) do
  2182. begin
  2183. System.Inc(extraBits);
  2184. end;
  2185. end;
  2186. numPowers := 1 shl extraBits;
  2187. System.SetLength(oddPowers, numPowers);
  2188. oddPowers[0] := zVal;
  2189. zSquared := System.Copy(zVal, 0, System.length(zVal));
  2190. SquareMonty(yAccum, zSquared, m.Fmagnitude, mDash, smallMontyModulus);
  2191. for i := 1 to System.Pred(numPowers) do
  2192. begin
  2193. oddPowers[i] := System.Copy(oddPowers[i - 1]);
  2194. MultiplyMonty(yAccum, oddPowers[i], zSquared, m.Fmagnitude, mDash,
  2195. smallMontyModulus);
  2196. end;
  2197. windowList := GetWindowList(e.Fmagnitude, extraBits);
  2198. {$IFDEF DEBUG}
  2199. System.Assert(System.length(windowList) > 1);
  2200. {$ENDIF DEBUG}
  2201. window := windowList[0];
  2202. mult := window and $FF;
  2203. lastZeroes := window shr 8;
  2204. if (mult = 1) then
  2205. begin
  2206. yVal := zSquared;
  2207. System.Dec(lastZeroes);
  2208. end
  2209. else
  2210. begin
  2211. yVal := System.Copy(oddPowers[mult shr 1]);
  2212. end;
  2213. windowPos := 1;
  2214. window := windowList[windowPos];
  2215. System.Inc(windowPos);
  2216. while (Int32(window) <> Int32(-1)) do
  2217. begin
  2218. mult := window and $FF;
  2219. bits := lastZeroes + BitLengthTable[mult];
  2220. j := 0;
  2221. while j < bits do
  2222. begin
  2223. SquareMonty(yAccum, yVal, m.Fmagnitude, mDash, smallMontyModulus);
  2224. System.Inc(j);
  2225. end;
  2226. MultiplyMonty(yAccum, yVal, oddPowers[mult shr 1], m.Fmagnitude, mDash,
  2227. smallMontyModulus);
  2228. lastZeroes := window shr 8;
  2229. window := windowList[windowPos];
  2230. System.Inc(windowPos);
  2231. end;
  2232. i := 0;
  2233. while i < lastZeroes do
  2234. begin
  2235. SquareMonty(yAccum, yVal, m.Fmagnitude, mDash, smallMontyModulus);
  2236. System.Inc(i);
  2237. end;
  2238. if (convert) then
  2239. begin
  2240. // Return y * R^(-1) mod m
  2241. MontgomeryReduce(yVal, m.Fmagnitude, mDash);
  2242. end
  2243. else if ((smallMontyModulus) and (CompareTo(0, yVal, 0, m.Fmagnitude) >= 0))
  2244. then
  2245. begin
  2246. Subtract(0, yVal, 0, m.Fmagnitude);
  2247. end;
  2248. Result := TBigInteger.Create(1, yVal, True);
  2249. end;
  2250. class function TBigInteger.Subtract(xStart: Int32; x: TCryptoLibInt32Array;
  2251. yStart: Int32; y: TCryptoLibInt32Array): TCryptoLibInt32Array;
  2252. var
  2253. iT, iV, borrow: Int32;
  2254. m: Int64;
  2255. begin
  2256. {$IFDEF DEBUG}
  2257. System.Assert(yStart < System.length(y));
  2258. System.Assert(System.length(x) - xStart >= System.length(y) - yStart);
  2259. {$ENDIF DEBUG}
  2260. iT := System.length(x);
  2261. iV := System.length(y);
  2262. borrow := 0;
  2263. repeat
  2264. System.Dec(iT);
  2265. System.Dec(iV);
  2266. m := (x[iT] and IMASK) - ((y[iV] and IMASK) + borrow);
  2267. // fixed precedence bug :)
  2268. x[iT] := Int32(m);
  2269. // borrow = (m < 0) ? -1 : 0;
  2270. borrow := Int32(m shr 63);
  2271. until (not(iV > yStart));
  2272. if (borrow <> 0) then
  2273. begin
  2274. System.Dec(iT);
  2275. x[iT] := x[iT] - 1;
  2276. while (x[iT] = -1) do
  2277. begin
  2278. System.Dec(iT);
  2279. x[iT] := x[iT] - 1;
  2280. end;
  2281. end;
  2282. Result := x;
  2283. end;
  2284. class procedure TBigInteger.MontgomeryReduce(x, m: TCryptoLibInt32Array;
  2285. mDash: UInt32);
  2286. var
  2287. n, i, j: Int32;
  2288. x0: UInt32;
  2289. t, carry: UInt64;
  2290. begin
  2291. // NOTE: Not a general purpose reduction (which would allow x up to twice the bitlength of m)
  2292. {$IFDEF DEBUG}
  2293. System.Assert(System.length(x) = System.length(m));
  2294. {$ENDIF DEBUG}
  2295. n := System.length(m);
  2296. i := n - 1;
  2297. while i >= 0 do
  2298. begin
  2299. x0 := UInt32(x[n - 1]);
  2300. t := UInt32(UInt64(x0) * mDash);
  2301. carry := t * UInt32(m[n - 1]) + x0;
  2302. {$IFDEF DEBUG}
  2303. System.Assert(UInt32(carry) = 0);
  2304. {$ENDIF DEBUG}
  2305. carry := carry shr 32;
  2306. j := n - 2;
  2307. while j >= 0 do
  2308. begin
  2309. carry := carry + (t * UInt32(m[j]) + UInt32(x[j]));
  2310. x[j + 1] := Int32(carry);
  2311. carry := carry shr 32;
  2312. System.Dec(j);
  2313. end;
  2314. x[0] := Int32(carry);
  2315. {$IFDEF DEBUG}
  2316. System.Assert(carry shr 32 = 0);
  2317. {$ENDIF DEBUG}
  2318. System.Dec(i);
  2319. end;
  2320. if (CompareTo(0, x, 0, m) >= 0) then
  2321. begin
  2322. Subtract(0, x, 0, m);
  2323. end;
  2324. end;
  2325. class function TBigInteger.Multiply(x, y, z: TCryptoLibInt32Array)
  2326. : TCryptoLibInt32Array;
  2327. var
  2328. i, xBase, j: Int32;
  2329. a, val: Int64;
  2330. begin
  2331. i := System.length(z);
  2332. if (i < 1) then
  2333. begin
  2334. Result := x;
  2335. Exit;
  2336. end;
  2337. xBase := System.length(x) - System.length(y);
  2338. repeat
  2339. System.Dec(i);
  2340. a := z[i] and IMASK;
  2341. val := 0;
  2342. if (a <> 0) then
  2343. begin
  2344. j := System.length(y) - 1;
  2345. while j >= 0 do
  2346. begin
  2347. val := val + (a * (y[j] and IMASK) + (x[xBase + j] and IMASK));
  2348. x[xBase + j] := Int32(val);
  2349. val := Int64(UInt64(val) shr 32);
  2350. System.Dec(j);
  2351. end;
  2352. end;
  2353. System.Dec(xBase);
  2354. if (xBase >= 0) then
  2355. begin
  2356. x[xBase] := Int32(val);
  2357. end
  2358. else
  2359. begin
  2360. {$IFDEF DEBUG}
  2361. System.Assert(val = 0);
  2362. {$ENDIF DEBUG}
  2363. end;
  2364. until (not(i > 0));
  2365. Result := x;
  2366. end;
  2367. function TBigInteger.Multiply(const val: TBigInteger): TBigInteger;
  2368. var
  2369. resLength, resSign: Int32;
  2370. res: TCryptoLibInt32Array;
  2371. begin
  2372. if (val.Equals(Self)) then
  2373. begin
  2374. Result := Square();
  2375. Exit;
  2376. end;
  2377. if ((Fsign and val.Fsign) = 0) then
  2378. begin
  2379. Result := Zero;
  2380. Exit;
  2381. end;
  2382. if (val.QuickPow2Check()) then // val is power of two
  2383. begin
  2384. Result := ShiftLeft(val.Abs().BitLength - 1);
  2385. if val.Fsign > 0 then
  2386. begin
  2387. Exit;
  2388. end
  2389. else
  2390. begin
  2391. Result := Result.Negate();
  2392. Exit;
  2393. end;
  2394. end;
  2395. if (QuickPow2Check()) then // this is power of two
  2396. begin
  2397. Result := val.ShiftLeft(Abs().BitLength - 1);
  2398. if Fsign > 0 then
  2399. begin
  2400. Exit;
  2401. end
  2402. else
  2403. begin
  2404. Result := Result.Negate();
  2405. Exit;
  2406. end;
  2407. end;
  2408. resLength := System.length(Fmagnitude) + System.length(val.Fmagnitude);
  2409. System.SetLength(res, resLength);
  2410. Multiply(res, Fmagnitude, val.Fmagnitude);
  2411. resSign := Fsign xor val.Fsign xor 1;
  2412. Result := TBigInteger.Create(resSign, res, True);
  2413. end;
  2414. class function TBigInteger.MultiplyMontyNIsOne(x, y, m, mDash: UInt32): UInt32;
  2415. var
  2416. carry, um, prod2: UInt64;
  2417. t: UInt32;
  2418. begin
  2419. carry := UInt64(UInt64(x) * y);
  2420. t := UInt32(UInt32(carry) * mDash);
  2421. um := m;
  2422. prod2 := um * t;
  2423. carry := carry + UInt32(prod2);
  2424. {$IFDEF DEBUG}
  2425. System.Assert(UInt32(carry) = 0);
  2426. {$ENDIF DEBUG}
  2427. carry := (carry shr 32) + (prod2 shr 32);
  2428. if (carry > um) then
  2429. begin
  2430. carry := carry - um;
  2431. end;
  2432. {$IFDEF DEBUG}
  2433. System.Assert(carry < um);
  2434. {$ENDIF DEBUG}
  2435. Result := UInt32(carry);
  2436. end;
  2437. class procedure TBigInteger.MultiplyMonty(a, x, y, m: TCryptoLibInt32Array;
  2438. mDash: UInt32; smallMontyModulus: Boolean);
  2439. var
  2440. n, aMax, j, i: Int32;
  2441. a0, y0: UInt32;
  2442. carry, t, prod1, prod2, xi: UInt64;
  2443. begin
  2444. // mDash = -m^(-1) mod b
  2445. n := System.length(m);
  2446. if (n = 1) then
  2447. begin
  2448. x[0] := Int32(MultiplyMontyNIsOne(UInt32(x[0]), UInt32(y[0]),
  2449. UInt32(m[0]), mDash));
  2450. Exit;
  2451. end;
  2452. y0 := UInt32(y[n - 1]);
  2453. xi := UInt32(x[n - 1]);
  2454. carry := xi * y0;
  2455. t := UInt32(UInt64(UInt32(carry)) * mDash);
  2456. prod2 := t * UInt32(m[n - 1]);
  2457. carry := carry + UInt32(prod2);
  2458. {$IFDEF DEBUG}
  2459. System.Assert(UInt32(carry) = 0);
  2460. {$ENDIF DEBUG}
  2461. carry := (carry shr 32) + (prod2 shr 32);
  2462. j := n - 2;
  2463. while j >= 0 do
  2464. begin
  2465. prod1 := xi * UInt32(y[j]);
  2466. prod2 := t * UInt32(m[j]);
  2467. carry := carry + ((prod1 and UIMASK) + UInt32(prod2));
  2468. a[j + 2] := Int32(carry);
  2469. carry := (carry shr 32) + (prod1 shr 32) + (prod2 shr 32);
  2470. System.Dec(j);
  2471. end;
  2472. a[1] := Int32(carry);
  2473. aMax := Int32(carry shr 32);
  2474. i := n - 2;
  2475. while i >= 0 do
  2476. begin
  2477. a0 := UInt32(a[n]);
  2478. xi := UInt32(x[i]);
  2479. prod1 := xi * y0;
  2480. carry := (prod1 and UIMASK) + a0;
  2481. t := UInt32(UInt64(UInt32(carry)) * mDash);
  2482. prod2 := t * UInt32(m[n - 1]);
  2483. carry := carry + UInt32(prod2);
  2484. {$IFDEF DEBUG}
  2485. System.Assert(UInt32(carry) = 0);
  2486. {$ENDIF DEBUG}
  2487. carry := (carry shr 32) + (prod1 shr 32) + (prod2 shr 32);
  2488. j := n - 2;
  2489. while j >= 0 do
  2490. begin
  2491. prod1 := xi * UInt32(y[j]);
  2492. prod2 := t * UInt32(m[j]);
  2493. carry := carry + ((prod1 and UIMASK) + UInt32(prod2) + UInt32(a[j + 1]));
  2494. a[j + 2] := Int32(carry);
  2495. carry := (carry shr 32) + (prod1 shr 32) + (prod2 shr 32);
  2496. System.Dec(j);
  2497. end;
  2498. carry := carry + UInt32(aMax);
  2499. a[1] := Int32(carry);
  2500. aMax := Int32(carry shr 32);
  2501. System.Dec(i);
  2502. end;
  2503. a[0] := aMax;
  2504. if ((not smallMontyModulus) and (CompareTo(0, a, 0, m) >= 0)) then
  2505. begin
  2506. Subtract(0, a, 0, m);
  2507. end;
  2508. System.Move(a[1], x[0], n * System.SizeOf(Int32));
  2509. end;
  2510. function TBigInteger.NextProbablePrime: TBigInteger;
  2511. var
  2512. n: TBigInteger;
  2513. begin
  2514. if (Fsign < 0) then
  2515. begin
  2516. raise EArithmeticCryptoLibException.CreateRes(@SNegativeValue);
  2517. end;
  2518. if (CompareTo(Two) < 0) then
  2519. begin
  2520. Result := Two;
  2521. Exit;
  2522. end;
  2523. n := Inc().SetBit(0);
  2524. while (not n.CheckProbablePrime(100, RandomSource, false)) do
  2525. begin
  2526. n := n.Add(Two);
  2527. end;
  2528. Result := n;
  2529. end;
  2530. procedure TBigInteger.ParseBytes(bytes: TCryptoLibByteArray;
  2531. offset, length: Int32);
  2532. var
  2533. endPoint, iBval, numBytes, index: Int32;
  2534. inverse: TCryptoLibByteArray;
  2535. begin
  2536. if (length = 0) then
  2537. begin
  2538. raise EFormatCryptoLibException.CreateRes(@SZeroLengthBigInteger);
  2539. end;
  2540. Fsign := -1;
  2541. FnBits := -1;
  2542. FnBitLength := -1;
  2543. FmQuote := 0;
  2544. FIsInitialized := True;
  2545. // TODO Move this processing into MakeMagnitude (provide sign argument)
  2546. if (ShortInt(bytes[offset]) < 0) then
  2547. begin
  2548. Fsign := -1;
  2549. endPoint := offset + length;
  2550. iBval := offset;
  2551. // strip leading sign bytes
  2552. while (iBval < endPoint) and (ShortInt(bytes[iBval]) = -1) do
  2553. begin
  2554. System.Inc(iBval);
  2555. end;
  2556. if (iBval >= endPoint) then
  2557. begin
  2558. Fmagnitude := One.Fmagnitude;
  2559. end
  2560. else
  2561. begin
  2562. numBytes := endPoint - iBval;
  2563. System.SetLength(inverse, numBytes);
  2564. index := 0;
  2565. while (index < numBytes) do
  2566. begin
  2567. inverse[index] := Byte(not bytes[iBval]);
  2568. System.Inc(index);
  2569. System.Inc(iBval);
  2570. end;
  2571. {$IFDEF DEBUG}
  2572. System.Assert(iBval = endPoint);
  2573. {$ENDIF DEBUG}
  2574. System.Dec(index);
  2575. while (inverse[index] = System.High(Byte)) do
  2576. begin
  2577. inverse[index] := System.Low(Byte);
  2578. System.Dec(index);
  2579. end;
  2580. inverse[index] := Byte(inverse[index] + 1);
  2581. Fmagnitude := MakeMagnitude(inverse, 0, System.length(inverse));
  2582. end
  2583. end
  2584. else
  2585. begin
  2586. // strip leading zero bytes and return magnitude bytes
  2587. Fmagnitude := MakeMagnitude(bytes, offset, length);
  2588. if System.length(Fmagnitude) > 0 then
  2589. begin
  2590. Fsign := 1;
  2591. end
  2592. else
  2593. begin
  2594. Fsign := 0;
  2595. end;
  2596. end;
  2597. end;
  2598. procedure TBigInteger.ParseBytesWithSign(sign: Int32;
  2599. bytes: TCryptoLibByteArray; offset, length: Int32);
  2600. begin
  2601. begin
  2602. if ((sign < -1) or (sign > 1)) then
  2603. begin
  2604. raise EFormatCryptoLibException.CreateRes(@SInvalidSign);
  2605. end;
  2606. Fsign := -1;
  2607. FnBits := -1;
  2608. FnBitLength := -1;
  2609. FmQuote := 0;
  2610. FIsInitialized := True;
  2611. if (sign = 0) then
  2612. begin
  2613. Fsign := 0;
  2614. Fmagnitude := FZeroMagnitude;
  2615. end
  2616. else
  2617. begin
  2618. // copy bytes
  2619. Fmagnitude := MakeMagnitude(bytes, offset, length);
  2620. if System.length(Fmagnitude) < 1 then
  2621. begin
  2622. Fsign := 0;
  2623. end
  2624. else
  2625. begin
  2626. Fsign := sign;
  2627. end;
  2628. end;
  2629. end;
  2630. end;
  2631. procedure TBigInteger.ParseString(const str: String; radix: Int32);
  2632. var
  2633. style: TNumberStyles;
  2634. chunk, index, Next, LowPoint, HighPoint: Int32;
  2635. r, rE, b, bi: TBigInteger;
  2636. dVal, s, temp: String;
  2637. i: UInt64;
  2638. begin
  2639. if (System.length(str) = 0) then
  2640. begin
  2641. raise EFormatCryptoLibException.CreateRes(@SZeroLengthBigInteger);
  2642. end;
  2643. Fsign := -1;
  2644. FnBits := -1;
  2645. FnBitLength := -1;
  2646. FmQuote := 0;
  2647. FIsInitialized := True;
  2648. case radix of
  2649. 2:
  2650. begin
  2651. // Is there anyway to restrict to binary digits?
  2652. style := TNumberStyles.Integer;
  2653. chunk := chunk2;
  2654. r := Fradix2;
  2655. rE := Fradix2E;
  2656. end;
  2657. 8:
  2658. begin
  2659. // Is there anyway to restrict to octal digits?
  2660. style := TNumberStyles.Integer;
  2661. chunk := chunk8;
  2662. r := Fradix8;
  2663. rE := Fradix8E;
  2664. end;
  2665. 10:
  2666. begin
  2667. // This style seems to handle spaces and minus sign already (our processing redundant?)
  2668. style := TNumberStyles.Integer;
  2669. chunk := chunk10;
  2670. r := Fradix10;
  2671. rE := Fradix10E;
  2672. end;
  2673. 16:
  2674. begin
  2675. // TODO Should this be HexNumber?
  2676. style := TNumberStyles.AllowHexSpecifier;
  2677. chunk := chunk16;
  2678. r := Fradix16;
  2679. rE := Fradix16E;
  2680. end
  2681. else
  2682. begin
  2683. raise EFormatCryptoLibException.CreateRes(@SInvalidBase);
  2684. end;
  2685. end;
  2686. {$IFDEF DELPHIXE3_UP}
  2687. LowPoint := System.Low(str);
  2688. HighPoint := System.High(str);
  2689. {$ELSE}
  2690. LowPoint := 1;
  2691. HighPoint := System.length(str);
  2692. {$ENDIF DELPHIXE3_UP}
  2693. index := LowPoint;
  2694. Fsign := 1;
  2695. if (str[LowPoint] = '-') then
  2696. begin
  2697. if (HighPoint = 1) then
  2698. begin
  2699. raise EFormatCryptoLibException.CreateRes(@SZeroLengthBigInteger);
  2700. end;
  2701. Fsign := -1;
  2702. index := LowPoint + 1;
  2703. end;
  2704. // strip leading zeros from the string str
  2705. while (index < (HighPoint + 1)) do
  2706. begin
  2707. dVal := str[index];
  2708. if (style = TNumberStyles.AllowHexSpecifier) then
  2709. begin
  2710. temp := '$' + dVal;
  2711. end
  2712. else
  2713. begin
  2714. temp := dVal;
  2715. end;
  2716. if (StrToInt(temp) = 0) then
  2717. begin
  2718. System.Inc(index);
  2719. end
  2720. else
  2721. begin
  2722. break;
  2723. end;
  2724. end;
  2725. if (index >= (HighPoint + 1)) then
  2726. begin
  2727. // zero value - we're done
  2728. Fsign := 0;
  2729. Fmagnitude := FZeroMagnitude;
  2730. Exit;
  2731. end;
  2732. /// ///
  2733. // could we work out the max number of ints required to store
  2734. // str.Length digits in the given base, then allocate that
  2735. // storage in one hit?, then Generate the magnitude in one hit too?
  2736. /// ///
  2737. b := Zero;
  2738. Next := index + chunk;
  2739. while (Next <= (HighPoint + 1)) do
  2740. begin
  2741. s := System.Copy(str, index, chunk);
  2742. if (style = TNumberStyles.AllowHexSpecifier) then
  2743. begin
  2744. temp := '$' + s;
  2745. end
  2746. else
  2747. begin
  2748. temp := s;
  2749. end;
  2750. {$IFDEF FPC}
  2751. i := StrToQWord(temp);
  2752. {$ELSE}
  2753. i := StrToUInt64(temp);
  2754. {$ENDIF FPC}
  2755. bi := CreateUValueOf(i);
  2756. case (radix) of
  2757. 2:
  2758. begin
  2759. // TODO Need this because we are parsing in radix 10 above
  2760. if (i >= 2) then
  2761. begin
  2762. raise EFormatCryptoLibException.CreateResFmt
  2763. (@SBadCharacterRadix2, [s]);
  2764. end;
  2765. // TODO Parse 64 bits at a time
  2766. b := b.ShiftLeft(1);
  2767. end;
  2768. 8:
  2769. begin
  2770. // TODO Need this because we are parsing in radix 10 above
  2771. if (i >= 8) then
  2772. begin
  2773. raise EFormatCryptoLibException.CreateResFmt
  2774. (@SBadCharacterRadix8, [s]);
  2775. end;
  2776. // TODO Parse 63 bits at a time
  2777. b := b.ShiftLeft(3);
  2778. end;
  2779. 16:
  2780. begin
  2781. b := b.ShiftLeft(64);
  2782. end
  2783. else
  2784. begin
  2785. b := b.Multiply(rE);
  2786. end;
  2787. end;
  2788. b := b.Add(bi);
  2789. index := Next;
  2790. Next := Next + chunk;
  2791. end;
  2792. if (index < System.length(str) + 1) then
  2793. begin
  2794. s := System.Copy(str, index, System.length(str) - (index - 1));
  2795. if (style = TNumberStyles.AllowHexSpecifier) then
  2796. begin
  2797. temp := '$' + s;
  2798. end
  2799. else
  2800. begin
  2801. temp := s;
  2802. end;
  2803. {$IFDEF FPC}
  2804. i := StrToQWord(temp);
  2805. {$ELSE}
  2806. i := StrToUInt64(temp);
  2807. {$ENDIF FPC}
  2808. bi := CreateUValueOf(i);
  2809. if (b.Fsign > 0) then
  2810. begin
  2811. if (radix = 2) then
  2812. begin
  2813. // NB: Can't reach here since we are parsing one char at a time
  2814. {$IFDEF DEBUG}
  2815. System.Assert(false);
  2816. {$ENDIF DEBUG}
  2817. // TODO Parse all bits at once
  2818. // b = b.ShiftLeft(s.Length);
  2819. end
  2820. else if (radix = 8) then
  2821. begin
  2822. // NB: Can't reach here since we are parsing one char at a time
  2823. {$IFDEF DEBUG}
  2824. System.Assert(false);
  2825. {$ENDIF DEBUG}
  2826. // TODO Parse all bits at once
  2827. // b = b.ShiftLeft(s.Length * 3);
  2828. end
  2829. else if (radix = 16) then
  2830. begin
  2831. b := b.ShiftLeft(System.length(s) shl 2);
  2832. end
  2833. else
  2834. begin
  2835. b := b.Multiply(r.Pow(System.length(s)));
  2836. end;
  2837. b := b.Add(bi);
  2838. end
  2839. else
  2840. begin
  2841. b := bi;
  2842. end;
  2843. end;
  2844. Fmagnitude := b.Fmagnitude;
  2845. end;
  2846. function TBigInteger.Pow(exp: Int32): TBigInteger;
  2847. var
  2848. powOf2: Int64;
  2849. y, z: TBigInteger;
  2850. begin
  2851. if (exp <= 0) then
  2852. begin
  2853. if (exp < 0) then
  2854. begin
  2855. raise EArithmeticCryptoLibException.CreateRes(@SNegativeExponent);
  2856. end;
  2857. Result := One;
  2858. Exit;
  2859. end;
  2860. if (Fsign = 0) then
  2861. begin
  2862. Result := Self;
  2863. Exit;
  2864. end;
  2865. if (QuickPow2Check()) then
  2866. begin
  2867. powOf2 := Int64(exp) * (Int64(BitLength) - 1);
  2868. if (powOf2 > System.High(Int32)) then
  2869. begin
  2870. raise EArithmeticCryptoLibException.CreateRes(@SResultTooLarge);
  2871. end;
  2872. Result := One.ShiftLeft(Int32(powOf2));
  2873. Exit;
  2874. end;
  2875. y := One;
  2876. z := Self;
  2877. while True do
  2878. begin
  2879. if ((exp and $1) = 1) then
  2880. begin
  2881. y := y.Multiply(z);
  2882. end;
  2883. exp := exp shr 1;
  2884. if (exp = 0) then
  2885. begin
  2886. break;
  2887. end;
  2888. z := z.Multiply(z);
  2889. end;
  2890. Result := y;
  2891. end;
  2892. function TBigInteger.DivideWords(w: Int32): TBigInteger;
  2893. var
  2894. n: Int32;
  2895. mag: TCryptoLibInt32Array;
  2896. begin
  2897. {$IFDEF DEBUG}
  2898. System.Assert(w >= 0);
  2899. {$ENDIF DEBUG}
  2900. n := System.length(Fmagnitude);
  2901. if (w >= n) then
  2902. begin
  2903. Result := Zero;
  2904. Exit;
  2905. end;
  2906. System.SetLength(mag, n - w);
  2907. System.Move(Fmagnitude[0], mag[0], (n - w) * System.SizeOf(Int32));
  2908. Result := TBigInteger.Create(Fsign, mag, false);
  2909. end;
  2910. function TBigInteger.RemainderWords(w: Int32): TBigInteger;
  2911. var
  2912. n: Int32;
  2913. mag: TCryptoLibInt32Array;
  2914. begin
  2915. {$IFDEF DEBUG}
  2916. System.Assert(w >= 0);
  2917. {$ENDIF DEBUG}
  2918. n := System.length(Fmagnitude);
  2919. if (w >= n) then
  2920. begin
  2921. Result := Self;
  2922. Exit;
  2923. end;
  2924. System.SetLength(mag, w);
  2925. System.Move(Fmagnitude[n - w], mag[0], w * System.SizeOf(Int32));
  2926. Result := TBigInteger.Create(Fsign, mag, false);
  2927. end;
  2928. class function TBigInteger.ProbablePrime(BitLength: Int32;
  2929. const random: IRandom): TBigInteger;
  2930. begin
  2931. Result := TBigInteger.Create(BitLength, 100, random);
  2932. end;
  2933. function TBigInteger.RabinMillerTest(certainty: Int32; const random: IRandom;
  2934. randomlySelected: Boolean): Boolean;
  2935. var
  2936. bits, iterations, itersFor100Cert, s, j, shiftval: Int32;
  2937. n, r, montRadix, minusMontRadix, a, y: TBigInteger;
  2938. begin
  2939. bits := BitLength;
  2940. {$IFDEF DEBUG}
  2941. System.Assert(certainty > 0);
  2942. System.Assert(bits > 2);
  2943. System.Assert(TestBit(0));
  2944. {$ENDIF DEBUG}
  2945. iterations := ((certainty - 1) shr 1) + 1;
  2946. if (randomlySelected) then
  2947. begin
  2948. if bits >= 1024 then
  2949. begin
  2950. itersFor100Cert := 4
  2951. end
  2952. else if bits >= 512 then
  2953. begin
  2954. itersFor100Cert := 8
  2955. end
  2956. else if bits >= 256 then
  2957. begin
  2958. itersFor100Cert := 16
  2959. end
  2960. else
  2961. begin
  2962. itersFor100Cert := 50
  2963. end;
  2964. if (certainty < 100) then
  2965. begin
  2966. iterations := Math.Min(itersFor100Cert, iterations);
  2967. end
  2968. else
  2969. begin
  2970. iterations := iterations - 50;
  2971. iterations := iterations + itersFor100Cert;
  2972. end;
  2973. end;
  2974. // let n = 1 + d . 2^s
  2975. n := Self;
  2976. shiftval := Int32(-1) shl 1; // -2
  2977. s := n.GetLowestSetBitMaskFirst(shiftval);
  2978. {$IFDEF DEBUG}
  2979. System.Assert(s >= 1);
  2980. {$ENDIF DEBUG}
  2981. r := n.ShiftRight(s);
  2982. // NOTE: Avoid conversion to/from Montgomery form and check for R/-R as result instead
  2983. montRadix := One.ShiftLeft(32 * System.length(n.Fmagnitude)).Remainder(n);
  2984. minusMontRadix := n.Subtract(montRadix);
  2985. repeat
  2986. repeat
  2987. a := TBigInteger.Create(n.BitLength, random);
  2988. until (not((a.Fsign = 0) or (a.CompareTo(n) >= 0) or
  2989. (a.IsEqualMagnitude(montRadix)) or (a.IsEqualMagnitude(minusMontRadix))));
  2990. y := ModPowMonty(a, r, n, false);
  2991. if (not y.Equals(montRadix)) then
  2992. begin
  2993. j := 0;
  2994. while (not y.Equals(minusMontRadix)) do
  2995. begin
  2996. System.Inc(j);
  2997. if (j = s) then
  2998. begin
  2999. Result := false;
  3000. Exit;
  3001. end;
  3002. y := ModPowMonty(y, Two, n, false);
  3003. if (y.Equals(montRadix)) then
  3004. begin
  3005. Result := false;
  3006. Exit;
  3007. end;
  3008. end;
  3009. end;
  3010. System.Dec(iterations);
  3011. until (not(iterations > 0));
  3012. Result := True;
  3013. end;
  3014. function TBigInteger.RabinMillerTest(certainty: Int32;
  3015. const random: IRandom): Boolean;
  3016. begin
  3017. Result := RabinMillerTest(certainty, random, false);
  3018. end;
  3019. class function TBigInteger.ReduceBarrett(x: TBigInteger;
  3020. const m, mr, yu: TBigInteger): TBigInteger;
  3021. var
  3022. xLen, mLen, k: Int32;
  3023. q1, q2, q3, r1, r2, r3: TBigInteger;
  3024. begin
  3025. xLen := x.BitLength;
  3026. mLen := m.BitLength;
  3027. if (xLen < mLen) then
  3028. begin
  3029. Result := x;
  3030. Exit;
  3031. end;
  3032. if ((xLen - mLen) > 1) then
  3033. begin
  3034. k := System.length(m.Fmagnitude);
  3035. q1 := x.DivideWords(k - 1);
  3036. q2 := q1.Multiply(yu); // TODO Only need partial multiplication here
  3037. q3 := q2.DivideWords(k + 1);
  3038. r1 := x.RemainderWords(k + 1);
  3039. r2 := q3.Multiply(m); // TODO Only need partial multiplication here
  3040. r3 := r2.RemainderWords(k + 1);
  3041. x := r1.Subtract(r3);
  3042. if (x.Fsign < 0) then
  3043. begin
  3044. x := x.Add(mr);
  3045. end;
  3046. end;
  3047. while (x.CompareTo(m) >= 0) do
  3048. begin
  3049. x := x.Subtract(m);
  3050. end;
  3051. Result := x;
  3052. end;
  3053. function TBigInteger.Remainder(x, y: TCryptoLibInt32Array)
  3054. : TCryptoLibInt32Array;
  3055. var
  3056. xStart, yStart, xyCmp, yBitLength, xBitLength, shift, cBitLength, cStart,
  3057. len: Int32;
  3058. c: TCryptoLibInt32Array;
  3059. firstC, firstX: UInt32;
  3060. begin
  3061. xStart := 0;
  3062. while ((xStart < System.length(x)) and (x[xStart] = 0)) do
  3063. begin
  3064. System.Inc(xStart);
  3065. end;
  3066. yStart := 0;
  3067. while ((yStart < System.length(y)) and (y[yStart] = 0)) do
  3068. begin
  3069. System.Inc(yStart);
  3070. end;
  3071. {$IFDEF DEBUG}
  3072. System.Assert(yStart < System.length(y));
  3073. {$ENDIF DEBUG}
  3074. xyCmp := CompareNoLeadingZeroes(xStart, x, yStart, y);
  3075. if (xyCmp > 0) then
  3076. begin
  3077. yBitLength := CalcBitLength(1, yStart, y);
  3078. xBitLength := CalcBitLength(1, xStart, x);
  3079. shift := xBitLength - yBitLength;
  3080. cStart := 0;
  3081. cBitLength := yBitLength;
  3082. if (shift > 0) then
  3083. begin
  3084. c := ShiftLeft(y, shift);
  3085. cBitLength := cBitLength + shift;
  3086. {$IFDEF DEBUG}
  3087. System.Assert(c[0] <> 0);
  3088. {$ENDIF DEBUG}
  3089. end
  3090. else
  3091. begin
  3092. len := System.length(y) - yStart;
  3093. System.SetLength(c, len);
  3094. System.Move(y[yStart], c[0], len * System.SizeOf(Int32));
  3095. end;
  3096. while True do
  3097. begin
  3098. if ((cBitLength < xBitLength) or (CompareNoLeadingZeroes(xStart, x,
  3099. cStart, c) >= 0)) then
  3100. begin
  3101. Subtract(xStart, x, cStart, c);
  3102. while (x[xStart] = 0) do
  3103. begin
  3104. System.Inc(xStart);
  3105. if (xStart = System.length(x)) then
  3106. begin
  3107. Result := x;
  3108. Exit;
  3109. end;
  3110. end;
  3111. // xBitLength = CalcBitLength(xStart, x);
  3112. xBitLength := 32 * (System.length(x) - xStart - 1) + BitLen(x[xStart]);
  3113. if (xBitLength <= yBitLength) then
  3114. begin
  3115. if (xBitLength < yBitLength) then
  3116. begin
  3117. Result := x;
  3118. Exit;
  3119. end;
  3120. xyCmp := CompareNoLeadingZeroes(xStart, x, yStart, y);
  3121. if (xyCmp <= 0) then
  3122. begin
  3123. break;
  3124. end;
  3125. end;
  3126. end;
  3127. shift := cBitLength - xBitLength;
  3128. // NB: The case where c[cStart] is 1-bit is harmless
  3129. if (shift = 1) then
  3130. begin
  3131. firstC := UInt32(c[cStart] shr 1);
  3132. firstX := UInt32(x[xStart]);
  3133. if (firstC > firstX) then
  3134. begin
  3135. System.Inc(shift);
  3136. end;
  3137. end;
  3138. if (shift < 2) then
  3139. begin
  3140. ShiftRightOneInPlace(cStart, c);
  3141. System.Dec(cBitLength);
  3142. end
  3143. else
  3144. begin
  3145. ShiftRightInPlace(cStart, c, shift);
  3146. cBitLength := cBitLength - shift;
  3147. end;
  3148. // cStart = c.Length - ((cBitLength + 31) / 32);
  3149. while (c[cStart] = 0) do
  3150. begin
  3151. System.Inc(cStart);
  3152. end;
  3153. end;
  3154. end;
  3155. if (xyCmp = 0) then
  3156. begin
  3157. System.FillChar(x[xStart], (System.length(x) - xStart) *
  3158. System.SizeOf(Int32), Int32(0));
  3159. end;
  3160. Result := x;
  3161. end;
  3162. function TBigInteger.SetBit(n: Int32): TBigInteger;
  3163. begin
  3164. if (n < 0) then
  3165. begin
  3166. raise EArithmeticCryptoLibException.CreateRes(@SInvalidBitAddress);
  3167. end;
  3168. if (TestBit(n)) then
  3169. begin
  3170. Result := Self;
  3171. Exit;
  3172. end;
  3173. // TODO Handle negative values and zero
  3174. if ((Fsign > 0) and (n < (BitLength - 1))) then
  3175. begin
  3176. Result := FlipExistingBit(n);
  3177. Exit;
  3178. end;
  3179. Result := &Or(One.ShiftLeft(n));
  3180. end;
  3181. function TBigInteger.ShiftLeft(n: Int32): TBigInteger;
  3182. begin
  3183. if ((Fsign = 0) or (System.length(Fmagnitude) = 0)) then
  3184. begin
  3185. Result := Zero;
  3186. Exit;
  3187. end;
  3188. if (n = 0) then
  3189. begin
  3190. Result := Self;
  3191. Exit;
  3192. end;
  3193. if (n < 0) then
  3194. begin
  3195. Result := ShiftRight(-n);
  3196. Exit;
  3197. end;
  3198. Result := TBigInteger.Create(Fsign, ShiftLeft(Fmagnitude, n), True);
  3199. // if (FnBits <> -1) then
  3200. if (BitCount <> -1) then
  3201. begin
  3202. if Fsign > 0 then
  3203. begin
  3204. Result.FnBits := FnBits;
  3205. end
  3206. else
  3207. begin
  3208. Result.FnBits := FnBits + n;
  3209. end;
  3210. end;
  3211. if (FnBitLength <> -1) then
  3212. begin
  3213. Result.FnBitLength := FnBitLength + n;
  3214. end;
  3215. end;
  3216. class function TBigInteger.ShiftLeft(mag: TCryptoLibInt32Array; n: Int32)
  3217. : TCryptoLibInt32Array;
  3218. var
  3219. nInts, nBits, magLen, i, nBits2, highBits, m, j, Next: Int32;
  3220. newMag: TCryptoLibInt32Array;
  3221. begin
  3222. nInts := Int32(UInt32(n) shr 5);
  3223. nBits := n and $1F;
  3224. magLen := System.length(mag);
  3225. if (nBits = 0) then
  3226. begin
  3227. System.SetLength(newMag, magLen + nInts);
  3228. System.Move(mag[0], newMag[0], System.length(mag) * System.SizeOf(Int32));
  3229. end
  3230. else
  3231. begin
  3232. i := 0;
  3233. nBits2 := 32 - nBits;
  3234. highBits := Int32(UInt32(mag[0]) shr nBits2);
  3235. if (highBits <> 0) then
  3236. begin
  3237. System.SetLength(newMag, magLen + nInts + 1);
  3238. newMag[i] := highBits;
  3239. System.Inc(i);
  3240. end
  3241. else
  3242. begin
  3243. System.SetLength(newMag, magLen + nInts);
  3244. end;
  3245. m := mag[0];
  3246. j := 0;
  3247. while (j < (magLen - 1)) do
  3248. begin
  3249. Next := mag[j + 1];
  3250. newMag[i] := (m shl nBits) or Int32(UInt32(Next) shr nBits2);
  3251. System.Inc(i);
  3252. m := Next;
  3253. System.Inc(j);
  3254. end;
  3255. newMag[i] := mag[magLen - 1] shl nBits;
  3256. end;
  3257. Result := newMag;
  3258. end;
  3259. function TBigInteger.ShiftRight(n: Int32): TBigInteger;
  3260. var
  3261. resultLength, numInts, numBits, numBits2, magPos, i: Int32;
  3262. res: TCryptoLibInt32Array;
  3263. begin
  3264. if (n = 0) then
  3265. begin
  3266. Result := Self;
  3267. Exit;
  3268. end;
  3269. if (n < 0) then
  3270. begin
  3271. Result := ShiftLeft(-n);
  3272. Exit;
  3273. end;
  3274. if (n >= BitLength) then
  3275. begin
  3276. if Fsign < 0 then
  3277. begin
  3278. Result := One.Negate();
  3279. Exit;
  3280. end
  3281. else
  3282. begin
  3283. Result := Zero;
  3284. Exit;
  3285. end;
  3286. end;
  3287. // int[] res = (int[]) this.magnitude.Clone();
  3288. //
  3289. // ShiftRightInPlace(0, res, n);
  3290. //
  3291. // return new BigInteger(this.sign, res, true);
  3292. resultLength := (BitLength - n + 31) shr 5;
  3293. System.SetLength(res, resultLength);
  3294. numInts := n shr 5;
  3295. numBits := n and 31;
  3296. if (numBits = 0) then
  3297. begin
  3298. System.Move(Fmagnitude[0], res[0], System.length(res) *
  3299. System.SizeOf(Int32));
  3300. end
  3301. else
  3302. begin
  3303. numBits2 := 32 - numBits;
  3304. magPos := System.length(Fmagnitude) - 1 - numInts;
  3305. i := resultLength - 1;
  3306. while i >= 0 do
  3307. begin
  3308. res[i] := Int32(UInt32(Fmagnitude[magPos]) shr numBits);
  3309. System.Dec(magPos);
  3310. if (magPos >= 0) then
  3311. begin
  3312. res[i] := res[i] or (Fmagnitude[magPos] shl numBits2);
  3313. end;
  3314. System.Dec(i);
  3315. end;
  3316. end;
  3317. {$IFDEF DEBUG}
  3318. System.Assert(res[0] <> 0);
  3319. {$ENDIF DEBUG}
  3320. Result := TBigInteger.Create(Fsign, res, false);
  3321. end;
  3322. class procedure TBigInteger.ShiftRightInPlace(start: Int32;
  3323. mag: TCryptoLibInt32Array; n: Int32);
  3324. var
  3325. nInts, nBits, magEnd, delta, i, nBits2, m, Next: Int32;
  3326. begin
  3327. nInts := Int32(UInt32(n) shr 5) + start;
  3328. nBits := n and $1F;
  3329. magEnd := System.length(mag) - 1;
  3330. if (nInts <> start) then
  3331. begin
  3332. delta := (nInts - start);
  3333. i := magEnd;
  3334. while i >= nInts do
  3335. begin
  3336. mag[i] := mag[i - delta];
  3337. System.Dec(i);
  3338. end;
  3339. i := nInts - 1;
  3340. while i >= start do
  3341. begin
  3342. mag[i] := 0;
  3343. System.Dec(i);
  3344. end;
  3345. end;
  3346. if (nBits <> 0) then
  3347. begin
  3348. nBits2 := 32 - nBits;
  3349. m := mag[magEnd];
  3350. i := magEnd;
  3351. while i > nInts do
  3352. begin
  3353. Next := mag[i - 1];
  3354. mag[i] := Int32(UInt32(m) shr nBits) or (Next shl nBits2);
  3355. m := Next;
  3356. System.Dec(i);
  3357. end;
  3358. mag[nInts] := Int32(UInt32(mag[nInts]) shr nBits);
  3359. end;
  3360. end;
  3361. class procedure TBigInteger.ShiftRightOneInPlace(start: Int32;
  3362. mag: TCryptoLibInt32Array);
  3363. var
  3364. i, m, Next: Int32;
  3365. begin
  3366. i := System.length(mag);
  3367. m := mag[i - 1];
  3368. System.Dec(i);
  3369. while (i > start) do
  3370. begin
  3371. Next := mag[i - 1];
  3372. mag[i] := (Int32(UInt32(m) shr 1)) or (Next shl 31);
  3373. m := Next;
  3374. System.Dec(i);
  3375. end;
  3376. mag[start] := Int32(UInt32(mag[start]) shr 1);
  3377. end;
  3378. class function TBigInteger.Square(w, x: TCryptoLibInt32Array)
  3379. : TCryptoLibInt32Array;
  3380. var
  3381. c, v, prod: UInt64;
  3382. wBase, i, j: Int32;
  3383. begin
  3384. // Note: this method allows w to be only (2 * x.Length - 1) words if result will fit
  3385. // if (w.Length != 2 * x.Length)
  3386. // throw new ArgumentException("no I don't think so...");
  3387. wBase := System.length(w) - 1;
  3388. i := System.length(x) - 1;
  3389. while i > 0 do
  3390. begin
  3391. v := UInt32(x[i]);
  3392. c := v * v + UInt32(w[wBase]);
  3393. w[wBase] := Int32(c);
  3394. c := c shr 32;
  3395. j := i - 1;
  3396. while j >= 0 do
  3397. begin
  3398. prod := v * UInt32(x[j]);
  3399. System.Dec(wBase);
  3400. c := c + ((UInt32(w[wBase]) and UIMASK) + (UInt32(prod) shl 1));
  3401. w[wBase] := Int32(c);
  3402. c := (c shr 32) + (prod shr 31);
  3403. System.Dec(j);
  3404. end;
  3405. System.Dec(wBase);
  3406. c := c + UInt32(w[wBase]);
  3407. w[wBase] := Int32(c);
  3408. System.Dec(wBase);
  3409. if (wBase >= 0) then
  3410. begin
  3411. w[wBase] := Int32(c shr 32);
  3412. end
  3413. else
  3414. begin
  3415. {$IFDEF DEBUG}
  3416. System.Assert((c shr 32) = 0);
  3417. {$ENDIF DEBUG}
  3418. end;
  3419. wBase := wBase + i;
  3420. System.Dec(i);
  3421. end;
  3422. c := UInt32(x[0]);
  3423. c := (c * c) + UInt32(w[wBase]);
  3424. w[wBase] := Int32(c);
  3425. System.Dec(wBase);
  3426. if (wBase >= 0) then
  3427. begin
  3428. w[wBase] := w[wBase] + Int32(c shr 32);
  3429. end
  3430. else
  3431. begin
  3432. {$IFDEF DEBUG}
  3433. System.Assert((c shr 32) = 0);
  3434. {$ENDIF DEBUG}
  3435. end;
  3436. Result := w;
  3437. end;
  3438. class procedure TBigInteger.SquareMonty(a, x, m: TCryptoLibInt32Array;
  3439. mDash: UInt32; smallMontyModulus: Boolean);
  3440. var
  3441. n, aMax, j, i: Int32;
  3442. xVal, a0: UInt32;
  3443. x0, carry, t, prod1, prod2, xi: UInt64;
  3444. begin
  3445. // mDash = -m^(-1) mod b
  3446. n := System.length(m);
  3447. if (n = 1) then
  3448. begin
  3449. xVal := UInt32(x[0]);
  3450. x[0] := Int32(MultiplyMontyNIsOne(xVal, xVal, UInt32(m[0]), mDash));
  3451. Exit;
  3452. end;
  3453. x0 := UInt32(x[n - 1]);
  3454. carry := x0 * x0;
  3455. t := UInt32(UInt64(UInt32(carry)) * mDash);
  3456. prod2 := t * UInt32(m[n - 1]);
  3457. carry := carry + UInt32(prod2);
  3458. {$IFDEF DEBUG}
  3459. System.Assert(UInt32(carry) = 0);
  3460. {$ENDIF DEBUG}
  3461. carry := (carry shr 32) + (prod2 shr 32);
  3462. j := n - 2;
  3463. while j >= 0 do
  3464. begin
  3465. prod1 := x0 * UInt32(x[j]);
  3466. prod2 := t * UInt32(m[j]);
  3467. carry := carry + ((prod2 and UIMASK) + (UInt32(prod1) shl 1));
  3468. a[j + 2] := Int32(carry);
  3469. carry := (carry shr 32) + (prod1 shr 31) + (prod2 shr 32);
  3470. System.Dec(j);
  3471. end;
  3472. a[1] := Int32(carry);
  3473. aMax := Int32(carry shr 32);
  3474. i := n - 2;
  3475. while i >= 0 do
  3476. begin
  3477. a0 := UInt32(a[n]);
  3478. t := UInt32(UInt64(a0) * mDash);
  3479. carry := t * UInt32(m[n - 1]) + a0;
  3480. {$IFDEF DEBUG}
  3481. System.Assert(UInt32(carry) = 0);
  3482. {$ENDIF DEBUG}
  3483. carry := carry shr 32;
  3484. j := n - 2;
  3485. while j > i do
  3486. begin
  3487. carry := carry + (t * UInt32(m[j]) + UInt32(a[j + 1]));
  3488. a[j + 2] := Int32(carry);
  3489. carry := carry shr 32;
  3490. System.Dec(j);
  3491. end;
  3492. xi := UInt32(x[i]);
  3493. prod1 := xi * xi;
  3494. prod2 := t * UInt32(m[i]);
  3495. carry := carry + ((prod1 and UIMASK) + UInt32(prod2) + UInt32(a[i + 1]));
  3496. a[i + 2] := Int32(carry);
  3497. carry := (carry shr 32) + (prod1 shr 32) + (prod2 shr 32);
  3498. j := i - 1;
  3499. while j >= 0 do
  3500. begin
  3501. prod1 := xi * UInt32(x[j]);
  3502. prod2 := t * UInt32(m[j]);
  3503. carry := carry + ((prod2 and UIMASK) + (UInt32(prod1) shl 1) +
  3504. UInt32(a[j + 1]));
  3505. a[j + 2] := Int32(carry);
  3506. carry := (carry shr 32) + (prod1 shr 31) + (prod2 shr 32);
  3507. System.Dec(j);
  3508. end;
  3509. carry := carry + UInt32(aMax);
  3510. a[1] := Int32(carry);
  3511. aMax := Int32(carry shr 32);
  3512. System.Dec(i);
  3513. end;
  3514. a[0] := aMax;
  3515. if ((not smallMontyModulus) and (CompareTo(0, a, 0, m) >= 0)) then
  3516. begin
  3517. Subtract(0, a, 0, m);
  3518. end;
  3519. System.Move(a[1], x[0], n * System.SizeOf(Int32));
  3520. end;
  3521. function TBigInteger.Subtract(const n: TBigInteger): TBigInteger;
  3522. var
  3523. compare: Int32;
  3524. bigun, lilun: TBigInteger;
  3525. begin
  3526. if (n.Fsign = 0) then
  3527. begin
  3528. Result := Self;
  3529. Exit;
  3530. end;
  3531. if (Fsign = 0) then
  3532. begin
  3533. Result := n.Negate();
  3534. Exit;
  3535. end;
  3536. if (Fsign <> n.Fsign) then
  3537. begin
  3538. Result := Add(n.Negate());
  3539. Exit;
  3540. end;
  3541. compare := CompareNoLeadingZeroes(0, Fmagnitude, 0, n.Fmagnitude);
  3542. if (compare = 0) then
  3543. begin
  3544. Result := Zero;
  3545. Exit;
  3546. end;
  3547. if (compare < 0) then
  3548. begin
  3549. bigun := n;
  3550. lilun := Self;
  3551. end
  3552. else
  3553. begin
  3554. bigun := Self;
  3555. lilun := n;
  3556. end;
  3557. Result := TBigInteger.Create(Fsign * compare, doSubBigLil(bigun.Fmagnitude,
  3558. lilun.Fmagnitude), True);
  3559. end;
  3560. function TBigInteger.ToString(radix: Int32): String;
  3561. var
  3562. firstNonZero, pos, mask, bits, i, scale: Int32;
  3563. sl: TStringList;
  3564. s: TList<String>;
  3565. moduli: TList<TBigInteger>;
  3566. u, q, r: TBigInteger;
  3567. begin
  3568. // TODO Make this method work for other radices (ideally 2 <= radix <= 36 as in Java)
  3569. case (radix) of
  3570. 2, 8, 10, 16:
  3571. begin
  3572. // do nothing because it is in valid supported range
  3573. end
  3574. else
  3575. begin
  3576. raise EFormatCryptoLibException.CreateRes(@SUnSupportedBase);
  3577. end;
  3578. end;
  3579. // NB: Can only happen to internally managed instances
  3580. if ((not FIsInitialized) and (Fmagnitude = Nil)) then
  3581. begin
  3582. Result := 'Nil';
  3583. Exit;
  3584. end;
  3585. if (Fsign = 0) then
  3586. begin
  3587. Result := '0';
  3588. Exit;
  3589. end;
  3590. // NOTE: This *should* be unnecessary, since the magnitude *should* never have leading zero digits
  3591. firstNonZero := 0;
  3592. while (firstNonZero < System.length(Fmagnitude)) do
  3593. begin
  3594. if (Fmagnitude[firstNonZero] <> 0) then
  3595. begin
  3596. break;
  3597. end;
  3598. System.Inc(firstNonZero);
  3599. end;
  3600. if (firstNonZero = System.length(Fmagnitude)) then
  3601. begin
  3602. Result := '0';
  3603. Exit;
  3604. end;
  3605. sl := TStringList.Create();
  3606. sl.LineBreak := '';
  3607. try
  3608. if (Fsign = -1) then
  3609. begin
  3610. sl.Add('-');
  3611. end;
  3612. case radix of
  3613. 2:
  3614. begin
  3615. pos := firstNonZero;
  3616. sl.Add(TBigInteger.IntToBin(Fmagnitude[pos]));
  3617. System.Inc(pos);
  3618. while (pos < System.length(Fmagnitude)) do
  3619. begin
  3620. AppendZeroExtendedString(sl,
  3621. TBigInteger.IntToBin(Fmagnitude[pos]), 32);
  3622. System.Inc(pos);
  3623. end;
  3624. end;
  3625. 8:
  3626. begin
  3627. mask := (1 shl 30) - 1;
  3628. u := Abs();
  3629. bits := u.BitLength;
  3630. s := TList<string>.Create();
  3631. try
  3632. while (bits > 30) do
  3633. begin
  3634. s.Add(TBigInteger.IntToOctal(u.Int32Value and mask));
  3635. u := u.ShiftRight(30);
  3636. bits := bits - 30;
  3637. end;
  3638. sl.Add(TBigInteger.IntToOctal(u.Int32Value));
  3639. i := s.Count - 1;
  3640. while i >= 0 do
  3641. begin
  3642. AppendZeroExtendedString(sl, s[i], 10);
  3643. System.Dec(i);
  3644. end;
  3645. finally
  3646. s.Free;
  3647. end;
  3648. end;
  3649. 16:
  3650. begin
  3651. pos := firstNonZero;
  3652. sl.Add(IntToHex(Fmagnitude[pos], 2));
  3653. System.Inc(pos);
  3654. while (pos < System.length(Fmagnitude)) do
  3655. begin
  3656. AppendZeroExtendedString(sl, IntToHex(Fmagnitude[pos], 2), 8);
  3657. System.Inc(pos);
  3658. end;
  3659. end;
  3660. // TODO This could work for other radices if there is an alternative to Convert.ToString method
  3661. // default:
  3662. 10:
  3663. begin
  3664. q := Abs();
  3665. if (q.BitLength < 64) then
  3666. begin
  3667. sl.Add(IntToStr(q.Int64Value));
  3668. Result := sl.Text;
  3669. Exit;
  3670. end;
  3671. // TODO Could cache the moduli for each radix (soft reference?)
  3672. moduli := TList<TBigInteger>.Create();
  3673. try
  3674. r := TBigInteger.ValueOf(radix);
  3675. while (r.CompareTo(q) <= 0) do
  3676. begin
  3677. moduli.Add(r);
  3678. r := r.Square();
  3679. end;
  3680. scale := moduli.Count;
  3681. sl.Capacity := sl.Capacity + (1 shl scale);
  3682. ToString(sl, radix, moduli, scale, q);
  3683. finally
  3684. moduli.Free;
  3685. end;
  3686. end;
  3687. end;
  3688. Result := LowerCase(sl.Text);
  3689. finally
  3690. sl.Free;
  3691. end;
  3692. end;
  3693. function TBigInteger.ToString: String;
  3694. begin
  3695. Result := ToString(10);
  3696. end;
  3697. class function TBigInteger.GetWindowList(mag: TCryptoLibInt32Array;
  3698. extraBits: Int32): TCryptoLibInt32Array;
  3699. var
  3700. i, v, leadingBits, resultSize, resultPos, bitPos, mult, multLimit,
  3701. zeroes: Int32;
  3702. begin
  3703. v := mag[0];
  3704. {$IFDEF DEBUG}
  3705. System.Assert(v <> 0);
  3706. {$ENDIF DEBUG}
  3707. leadingBits := BitLen(v);
  3708. resultSize := (((System.length(mag) - 1) shl 5) + leadingBits)
  3709. div (1 + extraBits) + 2;
  3710. System.SetLength(Result, resultSize);
  3711. resultPos := 0;
  3712. bitPos := 33 - leadingBits;
  3713. v := v shl bitPos;
  3714. mult := 1;
  3715. multLimit := 1 shl extraBits;
  3716. zeroes := 0;
  3717. i := 0;
  3718. while True do
  3719. begin
  3720. while bitPos < 32 do
  3721. begin
  3722. if (mult < multLimit) then
  3723. begin
  3724. mult := (mult shl 1) or Int32((UInt32(v) shr 31));
  3725. end
  3726. else if (v < 0) then
  3727. begin
  3728. Result[resultPos] := CreateWindowEntry(mult, zeroes);
  3729. System.Inc(resultPos);
  3730. mult := 1;
  3731. zeroes := 0;
  3732. end
  3733. else
  3734. begin
  3735. System.Inc(zeroes);
  3736. end;
  3737. v := v shl 1;
  3738. System.Inc(bitPos);
  3739. end;
  3740. System.Inc(i);
  3741. if (i = System.length(mag)) then
  3742. begin
  3743. Result[resultPos] := CreateWindowEntry(mult, zeroes);
  3744. System.Inc(resultPos);
  3745. break;
  3746. end;
  3747. v := mag[i];
  3748. bitPos := 0;
  3749. end;
  3750. Result[resultPos] := -1;
  3751. end;
  3752. function TBigInteger.CheckProbablePrime(certainty: Int32; const random: IRandom;
  3753. randomlySelected: Boolean): Boolean;
  3754. var
  3755. numLists, i, j, prime, qRem, test: Int32;
  3756. primeList: TCryptoLibInt32Array;
  3757. begin
  3758. {$IFDEF DEBUG}
  3759. System.Assert(certainty > 0);
  3760. System.Assert(CompareTo(Two) > 0);
  3761. System.Assert(TestBit(0));
  3762. {$ENDIF DEBUG}
  3763. // Try to reduce the penalty for really small numbers
  3764. numLists := Math.Min(BitLength - 1, System.length(primeLists));
  3765. for i := 0 to System.Pred(numLists) do
  3766. begin
  3767. test := Remainder(primeProducts[i]);
  3768. primeList := primeLists[i];
  3769. for j := 0 to System.Pred(System.length(primeList)) do
  3770. begin
  3771. prime := primeList[j];
  3772. qRem := test mod prime;
  3773. if (qRem = 0) then
  3774. begin
  3775. // We may find small numbers in the list
  3776. Result := (BitLength < 16) and (Int32Value = prime);
  3777. Exit;
  3778. end;
  3779. end;
  3780. end;
  3781. // TODO Special case for < 10^16 (RabinMiller fixed list)
  3782. // if (BitLength < 30)
  3783. // {
  3784. // RabinMiller against 2, 3, 5, 7, 11, 13, 23 is sufficient
  3785. // }
  3786. // TODO Is it worth trying to create a hybrid of these two?
  3787. Result := RabinMillerTest(certainty, random, randomlySelected);
  3788. // return SolovayStrassenTest(certainty, random);
  3789. // bool rbTest = RabinMillerTest(certainty, random);
  3790. // bool ssTest = SolovayStrassenTest(certainty, random);
  3791. //
  3792. // Debug.Assert(rbTest == ssTest);
  3793. //
  3794. // return rbTest;
  3795. end;
  3796. function TBigInteger.ClearBit(n: Int32): TBigInteger;
  3797. begin
  3798. if (n < 0) then
  3799. begin
  3800. raise EArithmeticCryptoLibException.CreateRes(@SInvalidBitAddress);
  3801. end;
  3802. if (not TestBit(n)) then
  3803. begin
  3804. Result := Self;
  3805. Exit;
  3806. end;
  3807. // TODO Handle negative values
  3808. if ((Fsign > 0) and (n < (BitLength - 1))) then
  3809. begin
  3810. Result := FlipExistingBit(n);
  3811. Exit;
  3812. end;
  3813. Result := AndNot(One.ShiftLeft(n));
  3814. end;
  3815. class function TBigInteger.CompareNoLeadingZeroes(xIndx: Int32;
  3816. x: TCryptoLibInt32Array; yIndx: Int32; y: TCryptoLibInt32Array): Int32;
  3817. var
  3818. diff: Int32;
  3819. v1, v2: UInt32;
  3820. begin
  3821. diff := (System.length(x) - System.length(y)) - (xIndx - yIndx);
  3822. if (diff <> 0) then
  3823. begin
  3824. if diff < 0 then
  3825. begin
  3826. Result := -1;
  3827. Exit;
  3828. end
  3829. else
  3830. begin
  3831. Result := 1;
  3832. Exit;
  3833. end;
  3834. end;
  3835. // lengths of magnitudes the same, test the magnitude values
  3836. while (xIndx < System.length(x)) do
  3837. begin
  3838. v1 := UInt32(x[xIndx]);
  3839. System.Inc(xIndx);
  3840. v2 := UInt32(y[yIndx]);
  3841. System.Inc(yIndx);
  3842. if (v1 <> v2) then
  3843. begin
  3844. if v1 < v2 then
  3845. begin
  3846. Result := -1;
  3847. Exit;
  3848. end
  3849. else
  3850. begin
  3851. Result := 1;
  3852. Exit;
  3853. end;
  3854. end;
  3855. end;
  3856. Result := 0;
  3857. end;
  3858. class function TBigInteger.CompareTo(xIndx: Int32; x: TCryptoLibInt32Array;
  3859. yIndx: Int32; y: TCryptoLibInt32Array): Int32;
  3860. begin
  3861. while ((xIndx <> System.length(x)) and (x[xIndx] = 0)) do
  3862. begin
  3863. System.Inc(xIndx);
  3864. end;
  3865. while ((yIndx <> System.length(y)) and (y[yIndx] = 0)) do
  3866. begin
  3867. System.Inc(yIndx);
  3868. end;
  3869. Result := CompareNoLeadingZeroes(xIndx, x, yIndx, y);
  3870. end;
  3871. function TBigInteger.Divide(x, y: TCryptoLibInt32Array): TCryptoLibInt32Array;
  3872. var
  3873. xStart, yStart, xyCmp, yBitLength, xBitLength, shift, iCountStart, cBitLength,
  3874. cStart, len: Int32;
  3875. Count, iCount, c: TCryptoLibInt32Array;
  3876. firstC, firstX: UInt32;
  3877. begin
  3878. xStart := 0;
  3879. while ((xStart < System.length(x)) and (x[xStart] = 0)) do
  3880. begin
  3881. System.Inc(xStart);
  3882. end;
  3883. yStart := 0;
  3884. while ((yStart < System.length(y)) and (y[yStart] = 0)) do
  3885. begin
  3886. System.Inc(yStart);
  3887. end;
  3888. {$IFDEF DEBUG}
  3889. System.Assert(yStart < System.length(y));
  3890. {$ENDIF DEBUG}
  3891. xyCmp := CompareNoLeadingZeroes(xStart, x, yStart, y);
  3892. if (xyCmp > 0) then
  3893. begin
  3894. yBitLength := CalcBitLength(1, yStart, y);
  3895. xBitLength := CalcBitLength(1, xStart, x);
  3896. shift := xBitLength - yBitLength;
  3897. iCountStart := 0;
  3898. cStart := 0;
  3899. cBitLength := yBitLength;
  3900. if (shift > 0) then
  3901. begin
  3902. // iCount = ShiftLeft(One.magnitude, shift);
  3903. System.SetLength(iCount, (shift shr 5) + 1);
  3904. iCount[0] := 1 shl (shift and 31);
  3905. c := ShiftLeft(y, shift);
  3906. cBitLength := cBitLength + shift;
  3907. end
  3908. else
  3909. begin
  3910. iCount := TCryptoLibInt32Array.Create(1);
  3911. len := System.length(y) - yStart;
  3912. System.SetLength(c, len);
  3913. System.Move(y[yStart], c[0], len * System.SizeOf(Int32));
  3914. end;
  3915. System.SetLength(Count, System.length(iCount));
  3916. while True do
  3917. begin
  3918. if ((cBitLength < xBitLength) or (CompareNoLeadingZeroes(xStart, x,
  3919. cStart, c) >= 0)) then
  3920. begin
  3921. Subtract(xStart, x, cStart, c);
  3922. AddMagnitudes(Count, iCount);
  3923. while (x[xStart] = 0) do
  3924. begin
  3925. System.Inc(xStart);
  3926. if (xStart = System.length(x)) then
  3927. begin
  3928. Result := Count;
  3929. Exit;
  3930. end;
  3931. end;
  3932. // xBitLength = CalcBitLength(xStart, x);
  3933. xBitLength := 32 * (System.length(x) - xStart - 1) + BitLen(x[xStart]);
  3934. if (xBitLength <= yBitLength) then
  3935. begin
  3936. if (xBitLength < yBitLength) then
  3937. begin
  3938. Result := Count;
  3939. Exit;
  3940. end;
  3941. xyCmp := CompareNoLeadingZeroes(xStart, x, yStart, y);
  3942. if (xyCmp <= 0) then
  3943. begin
  3944. break;
  3945. end;
  3946. end;
  3947. end;
  3948. shift := cBitLength - xBitLength;
  3949. // NB: The case where c[cStart] is 1-bit is harmless
  3950. if (shift = 1) then
  3951. begin
  3952. firstC := UInt32(c[cStart] shr 1);
  3953. firstX := UInt32(x[xStart]);
  3954. if (firstC > firstX) then
  3955. begin
  3956. System.Inc(shift);
  3957. end;
  3958. end;
  3959. if (shift < 2) then
  3960. begin
  3961. ShiftRightOneInPlace(cStart, c);
  3962. System.Dec(cBitLength);
  3963. ShiftRightOneInPlace(iCountStart, iCount);
  3964. end
  3965. else
  3966. begin
  3967. ShiftRightInPlace(cStart, c, shift);
  3968. cBitLength := cBitLength - shift;
  3969. ShiftRightInPlace(iCountStart, iCount, shift);
  3970. end;
  3971. // cStart = c.Length - ((cBitLength + 31) / 32);
  3972. while (c[cStart] = 0) do
  3973. begin
  3974. System.Inc(cStart);
  3975. end;
  3976. while (iCount[iCountStart] = 0) do
  3977. begin
  3978. System.Inc(iCountStart);
  3979. end;
  3980. end;
  3981. end
  3982. else
  3983. begin
  3984. System.SetLength(Count, 1);
  3985. end;
  3986. if (xyCmp = 0) then
  3987. begin
  3988. AddMagnitudes(Count, One.Fmagnitude);
  3989. System.FillChar(x[xStart], (System.length(x) - xStart) *
  3990. System.SizeOf(Int32), Int32(0));
  3991. end;
  3992. Result := Count;
  3993. end;
  3994. function TBigInteger.Divide(const val: TBigInteger): TBigInteger;
  3995. var
  3996. tempRes: TBigInteger;
  3997. mag: TCryptoLibInt32Array;
  3998. begin
  3999. if (val.Fsign = 0) then
  4000. begin
  4001. raise EArithmeticCryptoLibException.CreateRes(@SDivisionByZero);
  4002. end;
  4003. if (Fsign = 0) then
  4004. begin
  4005. Result := Zero;
  4006. Exit;
  4007. end;
  4008. if (val.QuickPow2Check()) then // val is power of two
  4009. begin
  4010. tempRes := Abs().ShiftRight(val.Abs().BitLength - 1);
  4011. if val.Fsign = Fsign then
  4012. begin
  4013. Result := tempRes;
  4014. Exit;
  4015. end
  4016. else
  4017. begin
  4018. Result := tempRes.Negate();
  4019. Exit;
  4020. end;
  4021. end;
  4022. mag := System.Copy(Fmagnitude);
  4023. Result := TBigInteger.Create(Fsign * val.Fsign,
  4024. Divide(mag, val.Fmagnitude), True);
  4025. end;
  4026. function TBigInteger.DivideAndRemainder(const val: TBigInteger)
  4027. : TCryptoLibGenericArray<TBigInteger>;
  4028. var
  4029. biggies: TCryptoLibGenericArray<TBigInteger>;
  4030. e: Int32;
  4031. Quotient: TBigInteger;
  4032. Remainder, quotient_array: TCryptoLibInt32Array;
  4033. begin
  4034. if (val.Fsign = 0) then
  4035. begin
  4036. raise EArithmeticCryptoLibException.CreateRes(@SDivisionByZero);
  4037. end;
  4038. System.SetLength(biggies, 2);
  4039. if (Fsign = 0) then
  4040. begin
  4041. biggies[0] := Zero;
  4042. biggies[1] := Zero;
  4043. end
  4044. else if (val.QuickPow2Check()) then // val is power of two
  4045. begin
  4046. e := val.Abs().BitLength - 1;
  4047. Quotient := Abs().ShiftRight(e);
  4048. Remainder := LastNBits(e);
  4049. if val.Fsign = Fsign then
  4050. begin
  4051. biggies[0] := Quotient
  4052. end
  4053. else
  4054. begin
  4055. biggies[0] := Quotient.Negate();
  4056. end;
  4057. biggies[1] := TBigInteger.Create(Fsign, Remainder, True);
  4058. end
  4059. else
  4060. begin
  4061. Remainder := System.Copy(Fmagnitude);
  4062. quotient_array := Divide(Remainder, val.Fmagnitude);
  4063. biggies[0] := TBigInteger.Create(Fsign * val.Fsign, quotient_array, True);
  4064. biggies[1] := TBigInteger.Create(Fsign, Remainder, True);
  4065. end;
  4066. Result := biggies;
  4067. end;
  4068. function TBigInteger.ToByteArray(unsigned: Boolean): TCryptoLibByteArray;
  4069. var
  4070. nBits, nBytes, magIndex, bytesIndex: Int32;
  4071. mag, lastMag: UInt32;
  4072. bytes: TCryptoLibByteArray;
  4073. carry: Boolean;
  4074. begin
  4075. if (Fsign = 0) then
  4076. begin
  4077. if unsigned then
  4078. begin
  4079. Result := FZeroEncoding;
  4080. Exit;
  4081. end
  4082. else
  4083. begin
  4084. System.SetLength(Result, 1);
  4085. Exit;
  4086. end;
  4087. end;
  4088. if ((unsigned) and (Fsign > 0)) then
  4089. begin
  4090. nBits := BitLength;
  4091. end
  4092. else
  4093. begin
  4094. nBits := BitLength + 1;
  4095. end;
  4096. nBytes := GetByteLength(nBits);
  4097. System.SetLength(bytes, nBytes);
  4098. magIndex := System.length(Fmagnitude);
  4099. bytesIndex := System.length(bytes);
  4100. if (Fsign > 0) then
  4101. begin
  4102. while (magIndex > 1) do
  4103. begin
  4104. System.Dec(magIndex);
  4105. mag := UInt32(Fmagnitude[magIndex]);
  4106. System.Dec(bytesIndex);
  4107. bytes[bytesIndex] := Byte(mag);
  4108. System.Dec(bytesIndex);
  4109. bytes[bytesIndex] := Byte(mag shr 8);
  4110. System.Dec(bytesIndex);
  4111. bytes[bytesIndex] := Byte(mag shr 16);
  4112. System.Dec(bytesIndex);
  4113. bytes[bytesIndex] := Byte(mag shr 24);
  4114. end;
  4115. lastMag := UInt32(Fmagnitude[0]);
  4116. while (lastMag > System.High(Byte)) do
  4117. begin
  4118. System.Dec(bytesIndex);
  4119. bytes[bytesIndex] := Byte(lastMag);
  4120. lastMag := lastMag shr 8;
  4121. end;
  4122. System.Dec(bytesIndex);
  4123. bytes[bytesIndex] := Byte(lastMag);
  4124. end
  4125. else // sign < 0
  4126. begin
  4127. carry := True;
  4128. while (magIndex > 1) do
  4129. begin
  4130. System.Dec(magIndex);
  4131. mag := not(UInt32(Fmagnitude[magIndex]));
  4132. if (carry) then
  4133. begin
  4134. System.Inc(mag);
  4135. carry := (mag = System.Low(UInt32));
  4136. end;
  4137. System.Dec(bytesIndex);
  4138. bytes[bytesIndex] := Byte(mag);
  4139. System.Dec(bytesIndex);
  4140. bytes[bytesIndex] := Byte(mag shr 8);
  4141. System.Dec(bytesIndex);
  4142. bytes[bytesIndex] := Byte(mag shr 16);
  4143. System.Dec(bytesIndex);
  4144. bytes[bytesIndex] := Byte(mag shr 24);
  4145. end;
  4146. lastMag := UInt32(Fmagnitude[0]);
  4147. if (carry) then
  4148. begin
  4149. // Never wraps because magnitude[0] != 0
  4150. System.Dec(lastMag);
  4151. end;
  4152. while (lastMag > System.High(Byte)) do
  4153. begin
  4154. System.Dec(bytesIndex);
  4155. bytes[bytesIndex] := Byte(not lastMag);
  4156. lastMag := lastMag shr 8;
  4157. end;
  4158. System.Dec(bytesIndex);
  4159. bytes[bytesIndex] := Byte(not lastMag);
  4160. if (bytesIndex > 0) then
  4161. begin
  4162. System.Dec(bytesIndex);
  4163. bytes[bytesIndex] := System.High(Byte);
  4164. end;
  4165. end;
  4166. Result := bytes;
  4167. end;
  4168. function TBigInteger.ToByteArray: TCryptoLibByteArray;
  4169. begin
  4170. Result := ToByteArray(false);
  4171. end;
  4172. function TBigInteger.ToByteArrayUnsigned: TCryptoLibByteArray;
  4173. begin
  4174. Result := ToByteArray(True);
  4175. end;
  4176. end.