ClpBigInteger.pas 110 KB

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