cryptsuite.py 235 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446
  1. #!/usr/bin/env python3
  2. import sys
  3. import unittest
  4. import struct
  5. import itertools
  6. import functools
  7. import contextlib
  8. import hashlib
  9. import binascii
  10. from base64 import b64decode as b64
  11. import json
  12. try:
  13. from math import gcd
  14. except ImportError:
  15. from fractions import gcd
  16. from eccref import *
  17. from testcrypt import *
  18. from ssh import *
  19. from ca import CertType, make_signature_preimage, sign_cert_via_testcrypt
  20. assert sys.version_info[:2] >= (3,0), "This is Python 3 code"
  21. def unhex(s):
  22. return binascii.unhexlify(s.replace(" ", "").replace("\n", ""))
  23. def rsa_bare(e, n):
  24. rsa = rsa_new()
  25. get_rsa_ssh1_pub(ssh_uint32(nbits(n)) + ssh1_mpint(e) + ssh1_mpint(n),
  26. rsa, 'exponent_first')
  27. return rsa
  28. def find_non_square_mod(p):
  29. # Find a non-square mod p, using the Jacobi symbol
  30. # calculation function from eccref.py.
  31. return next(z for z in itertools.count(2) if jacobi(z, p) == -1)
  32. def fibonacci_scattered(n=10):
  33. # Generate a list of Fibonacci numbers with power-of-2 indices
  34. # (F_1, F_2, F_4, ...), to be used as test inputs of varying
  35. # sizes. Also put F_0 = 0 into the list as a bonus.
  36. yield 0
  37. a, b, c = 0, 1, 1
  38. while True:
  39. yield b
  40. n -= 1
  41. if n <= 0:
  42. break
  43. a, b, c = (a**2+b**2, b*(a+c), b**2+c**2)
  44. def fibonacci(n=10):
  45. # Generate the full Fibonacci sequence starting from F_0 = 0.
  46. a, b = 0, 1
  47. while True:
  48. yield a
  49. n -= 1
  50. if n <= 0:
  51. break
  52. a, b = b, a+b
  53. def mp_mask(mp):
  54. # Return the value that mp would represent if all its bits
  55. # were set. Useful for masking a true mathematical output
  56. # value (e.g. from an operation that can over/underflow, like
  57. # mp_sub or mp_anything_into) to check it's right within the
  58. # ability of that particular mp_int to represent.
  59. return ((1 << mp_max_bits(mp))-1)
  60. def adjtuples(iterable, n):
  61. # Return all the contiguous n-tuples of an iterable, including
  62. # overlapping ones. E.g. if called on [0,1,2,3,4] with n=3 it
  63. # would return (0,1,2), (1,2,3), (2,3,4) and then stop.
  64. it = iter(iterable)
  65. toret = [next(it) for _ in range(n-1)]
  66. for element in it:
  67. toret.append(element)
  68. yield tuple(toret)
  69. toret[:1] = []
  70. def last(iterable):
  71. # Return the last element of an iterable, or None if it is empty.
  72. it = iter(iterable)
  73. toret = None
  74. for toret in it:
  75. pass
  76. return toret
  77. def le_integer(x, nbits):
  78. assert nbits % 8 == 0
  79. return bytes([0xFF & (x >> (8*n)) for n in range(nbits//8)])
  80. def be_integer(x, nbits):
  81. return bytes(reversed(le_integer(x, nbits)))
  82. @contextlib.contextmanager
  83. def queued_random_data(nbytes, seed):
  84. hashsize = 512 // 8
  85. data = b''.join(
  86. hashlib.sha512("preimage:{:d}:{}".format(i, seed).encode('ascii'))
  87. .digest() for i in range((nbytes + hashsize - 1) // hashsize))
  88. data = data[:nbytes]
  89. random_queue(data)
  90. yield None
  91. random_clear()
  92. @contextlib.contextmanager
  93. def queued_specific_random_data(data):
  94. random_queue(data)
  95. yield None
  96. random_clear()
  97. @contextlib.contextmanager
  98. def random_prng(seed):
  99. random_make_prng('sha256', seed)
  100. yield None
  101. random_clear()
  102. def hash_str(alg, message):
  103. h = ssh_hash_new(alg)
  104. ssh_hash_update(h, message)
  105. return ssh_hash_final(h)
  106. def hash_str_iter(alg, message_iter):
  107. h = ssh_hash_new(alg)
  108. for string in message_iter:
  109. ssh_hash_update(h, string)
  110. return ssh_hash_final(h)
  111. def mac_str(alg, key, message, cipher=None):
  112. m = ssh2_mac_new(alg, cipher)
  113. ssh2_mac_setkey(m, key)
  114. ssh2_mac_start(m)
  115. ssh2_mac_update(m, "dummy")
  116. # Make sure ssh_mac_start erases previous state
  117. ssh2_mac_start(m)
  118. ssh2_mac_update(m, message)
  119. return ssh2_mac_genresult(m)
  120. def lcm(a, b):
  121. return a * b // gcd(a, b)
  122. def get_implementations(alg):
  123. return get_implementations_commasep(alg).decode("ASCII").split(",")
  124. def get_aes_impls():
  125. return [impl.rsplit("_", 1)[-1]
  126. for impl in get_implementations("aes128_cbc")
  127. if impl.startswith("aes128_cbc_")]
  128. def get_aesgcm_impls():
  129. return [impl.split("_", 1)[1]
  130. for impl in get_implementations("aesgcm")
  131. if impl.startswith("aesgcm_")]
  132. class MyTestBase(unittest.TestCase):
  133. "Intermediate class that adds useful helper methods."
  134. def assertEqualBin(self, x, y):
  135. # Like assertEqual, but produces more legible error reports
  136. # for random-looking binary data.
  137. self.assertEqual(binascii.hexlify(x), binascii.hexlify(y))
  138. class mpint(MyTestBase):
  139. def testCreation(self):
  140. self.assertEqual(int(mp_new(128)), 0)
  141. self.assertEqual(int(mp_from_bytes_be(b'ABCDEFGHIJKLMNOP')),
  142. 0x4142434445464748494a4b4c4d4e4f50)
  143. self.assertEqual(int(mp_from_bytes_le(b'ABCDEFGHIJKLMNOP')),
  144. 0x504f4e4d4c4b4a494847464544434241)
  145. self.assertEqual(int(mp_from_integer(12345)), 12345)
  146. decstr = '91596559417721901505460351493238411077414937428167'
  147. self.assertEqual(int(mp_from_decimal_pl(decstr)), int(decstr, 10))
  148. self.assertEqual(int(mp_from_decimal(decstr)), int(decstr, 10))
  149. self.assertEqual(int(mp_from_decimal("")), 0)
  150. # For hex, test both upper and lower case digits
  151. hexstr = 'ea7cb89f409ae845215822e37D32D0C63EC43E1381C2FF8094'
  152. self.assertEqual(int(mp_from_hex_pl(hexstr)), int(hexstr, 16))
  153. self.assertEqual(int(mp_from_hex(hexstr)), int(hexstr, 16))
  154. self.assertEqual(int(mp_from_hex("")), 0)
  155. p2 = mp_power_2(123)
  156. self.assertEqual(int(p2), 1 << 123)
  157. p2c = mp_copy(p2)
  158. self.assertEqual(int(p2c), 1 << 123)
  159. # Check mp_copy really makes a copy, not an alias (ok, that's
  160. # testing the testcrypt system more than it's testing the
  161. # underlying C functions)
  162. mp_set_bit(p2c, 120, 1)
  163. self.assertEqual(int(p2c), (1 << 123) + (1 << 120))
  164. self.assertEqual(int(p2), 1 << 123)
  165. def testBytesAndBits(self):
  166. x = mp_new(128)
  167. self.assertEqual(mp_get_byte(x, 2), 0)
  168. mp_set_bit(x, 2*8+3, 1)
  169. self.assertEqual(mp_get_byte(x, 2), 1<<3)
  170. self.assertEqual(mp_get_bit(x, 2*8+3), 1)
  171. mp_set_bit(x, 2*8+3, 0)
  172. self.assertEqual(mp_get_byte(x, 2), 0)
  173. self.assertEqual(mp_get_bit(x, 2*8+3), 0)
  174. # Currently I expect 128 to be a multiple of any
  175. # BIGNUM_INT_BITS value we might be running with, so these
  176. # should be exact equality
  177. self.assertEqual(mp_max_bytes(x), 128/8)
  178. self.assertEqual(mp_max_bits(x), 128)
  179. nb = lambda hexstr: mp_get_nbits(mp_from_hex(hexstr))
  180. self.assertEqual(nb('00000000000000000000000000000000'), 0)
  181. self.assertEqual(nb('00000000000000000000000000000001'), 1)
  182. self.assertEqual(nb('00000000000000000000000000000002'), 2)
  183. self.assertEqual(nb('00000000000000000000000000000003'), 2)
  184. self.assertEqual(nb('00000000000000000000000000000004'), 3)
  185. self.assertEqual(nb('000003ffffffffffffffffffffffffff'), 106)
  186. self.assertEqual(nb('000003ffffffffff0000000000000000'), 106)
  187. self.assertEqual(nb('80000000000000000000000000000000'), 128)
  188. self.assertEqual(nb('ffffffffffffffffffffffffffffffff'), 128)
  189. def testDecAndHex(self):
  190. def checkHex(hexstr):
  191. n = mp_from_hex(hexstr)
  192. i = int(hexstr, 16)
  193. self.assertEqual(mp_get_hex(n),
  194. "{:x}".format(i).encode('ascii'))
  195. self.assertEqual(mp_get_hex_uppercase(n),
  196. "{:X}".format(i).encode('ascii'))
  197. checkHex("0")
  198. checkHex("f")
  199. checkHex("00000000000000000000000000000000000000000000000000")
  200. checkHex("d5aa1acd5a9a1f6b126ed416015390b8dc5fceee4c86afc8c2")
  201. checkHex("ffffffffffffffffffffffffffffffffffffffffffffffffff")
  202. def checkDec(hexstr):
  203. n = mp_from_hex(hexstr)
  204. i = int(hexstr, 16)
  205. self.assertEqual(mp_get_decimal(n),
  206. "{:d}".format(i).encode('ascii'))
  207. checkDec("0")
  208. checkDec("f")
  209. checkDec("00000000000000000000000000000000000000000000000000")
  210. checkDec("d5aa1acd5a9a1f6b126ed416015390b8dc5fceee4c86afc8c2")
  211. checkDec("ffffffffffffffffffffffffffffffffffffffffffffffffff")
  212. checkDec("f" * 512)
  213. def testComparison(self):
  214. inputs = [
  215. "0", "1", "2", "10", "314159265358979", "FFFFFFFFFFFFFFFF",
  216. # Test over-long versions of some of the same numbers we
  217. # had short forms of above
  218. "0000000000000000000000000000000000000000000000000000000000000000"
  219. "0000000000000000000000000000000000000000000000000000000000000000",
  220. "0000000000000000000000000000000000000000000000000000000000000000"
  221. "0000000000000000000000000000000000000000000000000000000000000001",
  222. "0000000000000000000000000000000000000000000000000000000000000000"
  223. "0000000000000000000000000000000000000000000000000000000000000002",
  224. "0000000000000000000000000000000000000000000000000000000000000000"
  225. "000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF",
  226. "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
  227. "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
  228. ]
  229. values = [(mp_from_hex(s), int(s, 16)) for s in inputs]
  230. for am, ai in values:
  231. for bm, bi in values:
  232. self.assertEqual(mp_cmp_eq(am, bm) == 1, ai == bi)
  233. self.assertEqual(mp_cmp_hs(am, bm) == 1, ai >= bi)
  234. if (bi >> 64) == 0:
  235. self.assertEqual(mp_eq_integer(am, bi) == 1, ai == bi)
  236. self.assertEqual(mp_hs_integer(am, bi) == 1, ai >= bi)
  237. # mp_{min,max}{,_into} is a reasonable thing to test
  238. # here as well
  239. self.assertEqual(int(mp_min(am, bm)), min(ai, bi))
  240. self.assertEqual(int(mp_max(am, bm)), max(ai, bi))
  241. am_small = mp_copy(am if ai<bi else bm)
  242. mp_min_into(am_small, am, bm)
  243. self.assertEqual(int(am_small), min(ai, bi))
  244. am_big = mp_copy(am if ai>bi else bm)
  245. mp_max_into(am_big, am, bm)
  246. self.assertEqual(int(am_big), max(ai, bi))
  247. # Test mp_{eq,hs}_integer in the case where the integer is as
  248. # large as possible and the bignum contains very few words. In
  249. # modes where BIGNUM_INT_BITS < 64, this used to go wrong.
  250. mp10 = mp_new(4)
  251. mp_copy_integer_into(mp10, 10)
  252. highbit = 1 << 63
  253. self.assertEqual(mp_hs_integer(mp10, highbit | 9), 0)
  254. self.assertEqual(mp_hs_integer(mp10, highbit | 10), 0)
  255. self.assertEqual(mp_hs_integer(mp10, highbit | 11), 0)
  256. self.assertEqual(mp_eq_integer(mp10, highbit | 9), 0)
  257. self.assertEqual(mp_eq_integer(mp10, highbit | 10), 0)
  258. self.assertEqual(mp_eq_integer(mp10, highbit | 11), 0)
  259. def testConditionals(self):
  260. testnumbers = [(mp_copy(n),n) for n in fibonacci_scattered()]
  261. for am, ai in testnumbers:
  262. for bm, bi in testnumbers:
  263. cm = mp_copy(am)
  264. mp_select_into(cm, am, bm, 0)
  265. self.assertEqual(int(cm), ai & mp_mask(am))
  266. mp_select_into(cm, am, bm, 1)
  267. self.assertEqual(int(cm), bi & mp_mask(am))
  268. mp_cond_add_into(cm, am, bm, 0)
  269. self.assertEqual(int(cm), ai & mp_mask(am))
  270. mp_cond_add_into(cm, am, bm, 1)
  271. self.assertEqual(int(cm), (ai+bi) & mp_mask(am))
  272. mp_cond_sub_into(cm, am, bm, 0)
  273. self.assertEqual(int(cm), ai & mp_mask(am))
  274. mp_cond_sub_into(cm, am, bm, 1)
  275. self.assertEqual(int(cm), (ai-bi) & mp_mask(am))
  276. maxbits = max(mp_max_bits(am), mp_max_bits(bm))
  277. cm = mp_new(maxbits)
  278. dm = mp_new(maxbits)
  279. mp_copy_into(cm, am)
  280. mp_copy_into(dm, bm)
  281. self.assertEqual(int(cm), ai)
  282. self.assertEqual(int(dm), bi)
  283. mp_cond_swap(cm, dm, 0)
  284. self.assertEqual(int(cm), ai)
  285. self.assertEqual(int(dm), bi)
  286. mp_cond_swap(cm, dm, 1)
  287. self.assertEqual(int(cm), bi)
  288. self.assertEqual(int(dm), ai)
  289. if bi != 0:
  290. mp_cond_clear(cm, 0)
  291. self.assertEqual(int(cm), bi)
  292. mp_cond_clear(cm, 1)
  293. self.assertEqual(int(cm), 0)
  294. def testBasicArithmetic(self):
  295. testnumbers = list(fibonacci_scattered(5))
  296. testnumbers.extend([1 << (1 << i) for i in range(3,10)])
  297. testnumbers.extend([(1 << (1 << i)) - 1 for i in range(3,10)])
  298. testnumbers = [(mp_copy(n),n) for n in testnumbers]
  299. for am, ai in testnumbers:
  300. for bm, bi in testnumbers:
  301. self.assertEqual(int(mp_add(am, bm)), ai + bi)
  302. self.assertEqual(int(mp_mul(am, bm)), ai * bi)
  303. # Cope with underflow in subtraction
  304. diff = mp_sub(am, bm)
  305. self.assertEqual(int(diff), (ai - bi) & mp_mask(diff))
  306. for bits in range(64, 512, 64):
  307. cm = mp_new(bits)
  308. mp_add_into(cm, am, bm)
  309. self.assertEqual(int(cm), (ai + bi) & mp_mask(cm))
  310. mp_mul_into(cm, am, bm)
  311. self.assertEqual(int(cm), (ai * bi) & mp_mask(cm))
  312. mp_sub_into(cm, am, bm)
  313. self.assertEqual(int(cm), (ai - bi) & mp_mask(cm))
  314. # A test cherry-picked from the old bignum test script,
  315. # involving two numbers whose product has a single 1 bit miles
  316. # in the air and then all 0s until a bunch of cruft at the
  317. # bottom, the aim being to test that carry propagation works
  318. # all the way up.
  319. ai, bi = 0xb4ff6ed2c633847562087ed9354c5c17be212ac83b59c10c316250f50b7889e5b058bf6bfafd12825225ba225ede0cba583ffbd0882de88c9e62677385a6dbdedaf81959a273eb7909ebde21ae5d12e2a584501a6756fe50ccb93b93f0d6ee721b6052a0d88431e62f410d608532868cdf3a6de26886559e94cc2677eea9bd797918b70e2717e95b45918bd1f86530cb9989e68b632c496becff848aa1956cd57ed46676a65ce6dd9783f230c8796909eef5583fcfe4acbf9c8b4ea33a08ec3fd417cf7175f434025d032567a00fc329aee154ca20f799b961fbab8f841cb7351f561a44aea45746ceaf56874dad99b63a7d7af2769d2f185e2d1c656cc6630b5aba98399fa57, 0xb50a77c03ac195225021dc18d930a352f27c0404742f961ca828c972737bad3ada74b1144657ab1d15fe1b8aefde8784ad61783f3c8d4584aa5f22a4eeca619f90563ae351b5da46770df182cf348d8e23b25fda07670c6609118e916a57ce4043608752c91515708327e36f5bb5ebd92cd4cfb39424167a679870202b23593aa524bac541a3ad322c38102a01e9659b06a4335c78d50739a51027954ac2bf03e500f975c2fa4d0ab5dd84cc9334f219d2ae933946583e384ed5dbf6498f214480ca66987b867df0f69d92e4e14071e4b8545212dd5e29ff0248ed751e168d78934da7930bcbe10e9a212128a68de5d749c61f5e424cf8cf6aa329674de0cf49c6f9b4c8b8cc3
  320. am = mp_copy(ai)
  321. bm = mp_copy(bi)
  322. self.assertEqual(int(mp_mul(am, bm)), ai * bi)
  323. # A regression test for a bug that came up during development
  324. # of mpint.c, relating to an intermediate value overflowing
  325. # its container.
  326. ai, bi = (2**8512 * 2 // 3), (2**4224 * 11 // 15)
  327. am = mp_copy(ai)
  328. bm = mp_copy(bi)
  329. self.assertEqual(int(mp_mul(am, bm)), ai * bi)
  330. def testAddInteger(self):
  331. initial = mp_copy(4444444444444444444444444)
  332. x = mp_new(mp_max_bits(initial) + 64)
  333. # mp_{add,sub,copy}_integer_into should be able to cope with
  334. # any uintmax_t. Test a number that requires more than 32 bits.
  335. mp_add_integer_into(x, initial, 123123123123123)
  336. self.assertEqual(int(x), 4444444444567567567567567)
  337. mp_sub_integer_into(x, initial, 123123123123123)
  338. self.assertEqual(int(x), 4444444444321321321321321)
  339. mp_copy_integer_into(x, 123123123123123)
  340. self.assertEqual(int(x), 123123123123123)
  341. # mp_mul_integer_into only takes a uint16_t integer input
  342. mp_mul_integer_into(x, initial, 10001)
  343. self.assertEqual(int(x), 44448888888888888888888884444)
  344. def testDivision(self):
  345. divisors = [1, 2, 3, 2**16+1, 2**32-1, 2**32+1, 2**128-159,
  346. 141421356237309504880168872420969807856967187537694807]
  347. quotients = [0, 1, 2, 2**64-1, 2**64, 2**64+1, 17320508075688772935]
  348. for d in divisors:
  349. for q in quotients:
  350. remainders = {0, 1, d-1, 2*d//3}
  351. for r in sorted(remainders):
  352. if r >= d:
  353. continue # silly cases with tiny divisors
  354. n = q*d + r
  355. mq = mp_new(max(nbits(q), 1))
  356. mr = mp_new(max(nbits(r), 1))
  357. mp_divmod_into(n, d, mq, mr)
  358. self.assertEqual(int(mq), q)
  359. self.assertEqual(int(mr), r)
  360. self.assertEqual(int(mp_div(n, d)), q)
  361. self.assertEqual(int(mp_mod(n, d)), r)
  362. # Make sure divmod_into can handle not getting one
  363. # of its output pointers (or even both).
  364. mp_clear(mq)
  365. mp_divmod_into(n, d, mq, None)
  366. self.assertEqual(int(mq), q)
  367. mp_clear(mr)
  368. mp_divmod_into(n, d, None, mr)
  369. self.assertEqual(int(mr), r)
  370. mp_divmod_into(n, d, None, None)
  371. # No tests we can do after that last one - we just
  372. # insist that it isn't allowed to have crashed!
  373. def testNthRoot(self):
  374. roots = [1, 13, 1234567654321,
  375. 57721566490153286060651209008240243104215933593992]
  376. tests = []
  377. tests.append((0, 2, 0, 0))
  378. tests.append((0, 3, 0, 0))
  379. for r in roots:
  380. for n in 2, 3, 5:
  381. tests.append((r**n, n, r, 0))
  382. tests.append((r**n+1, n, r, 1))
  383. tests.append((r**n-1, n, r-1, r**n - (r-1)**n - 1))
  384. for x, n, eroot, eremainder in tests:
  385. with self.subTest(x=x):
  386. mx = mp_copy(x)
  387. remainder = mp_copy(mx)
  388. root = mp_nthroot(x, n, remainder)
  389. self.assertEqual(int(root), eroot)
  390. self.assertEqual(int(remainder), eremainder)
  391. self.assertEqual(int(mp_nthroot(2*10**100, 2, None)),
  392. 141421356237309504880168872420969807856967187537694)
  393. self.assertEqual(int(mp_nthroot(3*10**150, 3, None)),
  394. 144224957030740838232163831078010958839186925349935)
  395. def testBitwise(self):
  396. p = 0x3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e
  397. e = 0x2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190
  398. x = mp_new(nbits(p))
  399. mp_and_into(x, p, e)
  400. self.assertEqual(int(x), p & e)
  401. mp_or_into(x, p, e)
  402. self.assertEqual(int(x), p | e)
  403. mp_xor_into(x, p, e)
  404. self.assertEqual(int(x), p ^ e)
  405. mp_bic_into(x, p, e)
  406. self.assertEqual(int(x), p & ~e)
  407. def testInversion(self):
  408. # Test mp_invert_mod_2to.
  409. testnumbers = [(mp_copy(n),n) for n in fibonacci_scattered()
  410. if n & 1]
  411. for power2 in [1, 2, 3, 5, 13, 32, 64, 127, 128, 129]:
  412. for am, ai in testnumbers:
  413. bm = mp_invert_mod_2to(am, power2)
  414. bi = int(bm)
  415. self.assertEqual(((ai * bi) & ((1 << power2) - 1)), 1)
  416. # mp_reduce_mod_2to is a much simpler function, but
  417. # this is as good a place as any to test it.
  418. rm = mp_copy(am)
  419. mp_reduce_mod_2to(rm, power2)
  420. self.assertEqual(int(rm), ai & ((1 << power2) - 1))
  421. # Test mp_invert proper.
  422. moduli = [2, 3, 2**16+1, 2**32-1, 2**32+1, 2**128-159,
  423. 141421356237309504880168872420969807856967187537694807,
  424. 2**128-1]
  425. for m in moduli:
  426. # Prepare a MontyContext for the monty_invert test below
  427. # (unless m is even, in which case we can't)
  428. mc = monty_new(m) if m & 1 else None
  429. to_invert = {1, 2, 3, 7, 19, m-1, 5*m//17, (m-1)//2, (m+1)//2}
  430. for x in sorted(to_invert):
  431. if gcd(x, m) != 1:
  432. continue # filter out non-invertible cases
  433. inv = int(mp_invert(x, m))
  434. assert x * inv % m == 1
  435. # Test monty_invert too, while we're here
  436. if mc is not None:
  437. self.assertEqual(
  438. int(monty_invert(mc, monty_import(mc, x))),
  439. int(monty_import(mc, inv)))
  440. def testGCD(self):
  441. powerpairs = [(0,0), (1,0), (1,1), (2,1), (2,2), (75,3), (17,23)]
  442. for a2, b2 in powerpairs:
  443. for a3, b3 in powerpairs:
  444. for a5, b5 in powerpairs:
  445. a = 2**a2 * 3**a3 * 5**a5 * 17 * 19 * 23
  446. b = 2**b2 * 3**b3 * 5**b5 * 65423
  447. d = 2**min(a2, b2) * 3**min(a3, b3) * 5**min(a5, b5)
  448. ma = mp_copy(a)
  449. mb = mp_copy(b)
  450. self.assertEqual(int(mp_gcd(ma, mb)), d)
  451. md = mp_new(nbits(d))
  452. mA = mp_new(nbits(b))
  453. mB = mp_new(nbits(a))
  454. mp_gcd_into(ma, mb, md, mA, mB)
  455. self.assertEqual(int(md), d)
  456. A = int(mA)
  457. B = int(mB)
  458. self.assertEqual(a*A - b*B, d)
  459. self.assertTrue(0 <= A < b//d)
  460. self.assertTrue(0 <= B < a//d)
  461. self.assertEqual(mp_coprime(ma, mb), 1 if d==1 else 0)
  462. # Make sure gcd_into can handle not getting some
  463. # of its output pointers.
  464. mp_clear(md)
  465. mp_gcd_into(ma, mb, md, None, None)
  466. self.assertEqual(int(md), d)
  467. mp_clear(mA)
  468. mp_gcd_into(ma, mb, None, mA, None)
  469. self.assertEqual(int(mA), A)
  470. mp_clear(mB)
  471. mp_gcd_into(ma, mb, None, None, mB)
  472. self.assertEqual(int(mB), B)
  473. mp_gcd_into(ma, mb, None, None, None)
  474. # No tests we can do after that last one - we just
  475. # insist that it isn't allowed to have crashed!
  476. def testMonty(self):
  477. moduli = [5, 19, 2**16+1, 2**31-1, 2**128-159, 2**255-19,
  478. 293828847201107461142630006802421204703,
  479. 113064788724832491560079164581712332614996441637880086878209969852674997069759]
  480. for m in moduli:
  481. mc = monty_new(m)
  482. # Import some numbers
  483. inputs = [(monty_import(mc, n), n)
  484. for n in sorted({0, 1, 2, 3, 2*m//3, m-1})]
  485. # Check modulus and identity
  486. self.assertEqual(int(monty_modulus(mc)), m)
  487. self.assertEqual(int(monty_identity(mc)), int(inputs[1][0]))
  488. # Check that all those numbers export OK
  489. for mn, n in inputs:
  490. self.assertEqual(int(monty_export(mc, mn)), n)
  491. for ma, a in inputs:
  492. for mb, b in inputs:
  493. xprod = int(monty_export(mc, monty_mul(mc, ma, mb)))
  494. self.assertEqual(xprod, a*b % m)
  495. xsum = int(monty_export(mc, monty_add(mc, ma, mb)))
  496. self.assertEqual(xsum, (a+b) % m)
  497. xdiff = int(monty_export(mc, monty_sub(mc, ma, mb)))
  498. self.assertEqual(xdiff, (a-b) % m)
  499. # Test the ordinary mp_mod{add,sub,mul} at the
  500. # same time, even though those don't do any
  501. # montying at all
  502. xprod = int(mp_modmul(a, b, m))
  503. self.assertEqual(xprod, a*b % m)
  504. xsum = int(mp_modadd(a, b, m))
  505. self.assertEqual(xsum, (a+b) % m)
  506. xdiff = int(mp_modsub(a, b, m))
  507. self.assertEqual(xdiff, (a-b) % m)
  508. for ma, a in inputs:
  509. # Compute a^0, a^1, a^1, a^2, a^3, a^5, ...
  510. indices = list(fibonacci())
  511. powers = [int(monty_export(mc, monty_pow(mc, ma, power)))
  512. for power in indices]
  513. # Check the first two make sense
  514. self.assertEqual(powers[0], 1)
  515. self.assertEqual(powers[1], a)
  516. # Check the others using the Fibonacci identity:
  517. # F_n + F_{n+1} = F_{n+2}, so a^{F_n} a^{F_{n+1}} = a^{F_{n+2}}
  518. for p0, p1, p2 in adjtuples(powers, 3):
  519. self.assertEqual(p2, p0 * p1 % m)
  520. # Test the ordinary mp_modpow here as well, while
  521. # we've got the machinery available
  522. for index, power in zip(indices, powers):
  523. self.assertEqual(int(mp_modpow(a, index, m)), power)
  524. # A regression test for a bug I encountered during initial
  525. # development of mpint.c, in which an incomplete reduction
  526. # happened somewhere in an intermediate value.
  527. b, e, m = 0x2B5B93812F253FF91F56B3B4DAD01CA2884B6A80719B0DA4E2159A230C6009EDA97C5C8FD4636B324F9594706EE3AD444831571BA5E17B1B2DFA92DEA8B7E, 0x25, 0xC8FCFD0FD7371F4FE8D0150EFC124E220581569587CCD8E50423FA8D41E0B2A0127E100E92501E5EE3228D12EA422A568C17E0AD2E5C5FCC2AE9159D2B7FB8CB
  528. assert(int(mp_modpow(b, e, m)) == pow(b, e, m))
  529. # Make sure mp_modpow can handle a base larger than the
  530. # modulus, by pre-reducing it
  531. assert(int(mp_modpow(1<<877, 907, 999979)) == pow(2, 877*907, 999979))
  532. def testModsqrt(self):
  533. moduli = [
  534. 5, 19, 2**16+1, 2**31-1, 2**128-159, 2**255-19,
  535. 293828847201107461142630006802421204703,
  536. 113064788724832491560079164581712332614996441637880086878209969852674997069759,
  537. 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6FFFFFFFF00000001]
  538. for p in moduli:
  539. # Count the factors of 2 in the group. (That is, we want
  540. # p-1 to be an odd multiple of 2^{factors_of_2}.)
  541. factors_of_2 = nbits((p-1) & (1-p)) - 1
  542. assert (p & ((2 << factors_of_2)-1)) == ((1 << factors_of_2)+1)
  543. z = find_non_square_mod(p)
  544. sc = modsqrt_new(p, z)
  545. def ptest(x):
  546. root, success = mp_modsqrt(sc, x)
  547. r = int(root)
  548. self.assertTrue(success)
  549. self.assertEqual((r * r - x) % p, 0)
  550. def ntest(x):
  551. root, success = mp_modsqrt(sc, x)
  552. self.assertFalse(success)
  553. # Make up some more or less random values mod p to square
  554. v1 = pow(3, nbits(p), p)
  555. v2 = pow(5, v1, p)
  556. test_roots = [0, 1, 2, 3, 4, 3*p//4, v1, v2, v1+1, 12873*v1, v1*v2]
  557. known_squares = {r*r % p for r in test_roots}
  558. for s in known_squares:
  559. ptest(s)
  560. if s != 0:
  561. ntest(z*s % p)
  562. # Make sure we've tested a value that is in each of the
  563. # subgroups of order (p-1)/2^k but not in the next one
  564. # (with the exception of k=0, which just means 'have we
  565. # tested a non-square?', which we have in the above loop).
  566. #
  567. # We do this by starting with a known non-square; then
  568. # squaring it (factors_of_2) times will return values
  569. # nested deeper and deeper in those subgroups.
  570. vbase = z
  571. for k in range(factors_of_2):
  572. # Adjust vbase by an arbitrary odd power of
  573. # z, so that it won't look too much like the previous
  574. # value.
  575. vbase = vbase * pow(z, (vbase + v1 + v2) | 1, p) % p
  576. # Move vbase into the next smaller group by squaring
  577. # it.
  578. vbase = pow(vbase, 2, p)
  579. ptest(vbase)
  580. def testShifts(self):
  581. x = ((1<<900) // 9949) | 1
  582. for i in range(2049):
  583. mp = mp_copy(x)
  584. mp_lshift_fixed_into(mp, mp, i)
  585. self.assertEqual(int(mp), (x << i) & mp_mask(mp))
  586. mp_copy_into(mp, x)
  587. mp_lshift_safe_into(mp, mp, i)
  588. self.assertEqual(int(mp), (x << i) & mp_mask(mp))
  589. mp_copy_into(mp, x)
  590. mp_rshift_fixed_into(mp, mp, i)
  591. self.assertEqual(int(mp), x >> i)
  592. mp_copy_into(mp, x)
  593. mp_rshift_safe_into(mp, mp, i)
  594. self.assertEqual(int(mp), x >> i)
  595. self.assertEqual(int(mp_rshift_fixed(x, i)), x >> i)
  596. self.assertEqual(int(mp_rshift_safe(x, i)), x >> i)
  597. def testRandom(self):
  598. # Test random_bits to ensure it correctly masks the return
  599. # value, and uses exactly as many random bytes as we expect it
  600. # to.
  601. for bits in range(512):
  602. bytes_needed = (bits + 7) // 8
  603. with queued_random_data(bytes_needed, "random_bits test"):
  604. mp = mp_random_bits(bits)
  605. self.assertTrue(int(mp) < (1 << bits))
  606. self.assertEqual(random_queue_len(), 0)
  607. # Test mp_random_in_range to ensure it returns things in the
  608. # right range.
  609. for rangesize in [2, 3, 19, 35]:
  610. for lo in [0, 1, 0x10001, 1<<512]:
  611. hi = lo + rangesize
  612. bytes_needed = mp_max_bytes(hi) + 16
  613. for trial in range(rangesize*3):
  614. with queued_random_data(
  615. bytes_needed,
  616. "random_in_range {:d}".format(trial)):
  617. v = int(mp_random_in_range(lo, hi))
  618. self.assertTrue(lo <= v < hi)
  619. class ecc(MyTestBase):
  620. def testWeierstrassSimple(self):
  621. # Simple tests using a Weierstrass curve I made up myself,
  622. # which (unlike the ones used for serious crypto) is small
  623. # enough that you can fit all the coordinates for a curve on
  624. # to your retina in one go.
  625. p = 3141592661
  626. a, b = -3 % p, 12345
  627. rc = WeierstrassCurve(p, a, b)
  628. wc = ecc_weierstrass_curve(p, a, b, None)
  629. def check_point(wp, rp):
  630. self.assertTrue(ecc_weierstrass_point_valid(wp))
  631. is_id = ecc_weierstrass_is_identity(wp)
  632. x, y = ecc_weierstrass_get_affine(wp)
  633. if rp.infinite:
  634. self.assertEqual(is_id, 1)
  635. else:
  636. self.assertEqual(is_id, 0)
  637. self.assertEqual(int(x), int(rp.x))
  638. self.assertEqual(int(y), int(rp.y))
  639. def make_point(x, y):
  640. wp = ecc_weierstrass_point_new(wc, x, y)
  641. rp = rc.point(x, y)
  642. check_point(wp, rp)
  643. return wp, rp
  644. # Some sample points, including the identity and also a pair
  645. # of mutual inverses.
  646. wI, rI = ecc_weierstrass_point_new_identity(wc), rc.point()
  647. wP, rP = make_point(102, 387427089)
  648. wQ, rQ = make_point(1000, 546126574)
  649. wmP, rmP = make_point(102, p - 387427089)
  650. # Check the simple arithmetic functions.
  651. check_point(ecc_weierstrass_add(wP, wQ), rP + rQ)
  652. check_point(ecc_weierstrass_add(wQ, wP), rP + rQ)
  653. check_point(ecc_weierstrass_double(wP), rP + rP)
  654. check_point(ecc_weierstrass_double(wQ), rQ + rQ)
  655. # Check all the special cases with add_general:
  656. # Adding two finite unequal non-mutually-inverse points
  657. check_point(ecc_weierstrass_add_general(wP, wQ), rP + rQ)
  658. # Doubling a finite point
  659. check_point(ecc_weierstrass_add_general(wP, wP), rP + rP)
  660. check_point(ecc_weierstrass_add_general(wQ, wQ), rQ + rQ)
  661. # Adding the identity to a point (both ways round)
  662. check_point(ecc_weierstrass_add_general(wI, wP), rP)
  663. check_point(ecc_weierstrass_add_general(wI, wQ), rQ)
  664. check_point(ecc_weierstrass_add_general(wP, wI), rP)
  665. check_point(ecc_weierstrass_add_general(wQ, wI), rQ)
  666. # Doubling the identity
  667. check_point(ecc_weierstrass_add_general(wI, wI), rI)
  668. # Adding a point to its own inverse, giving the identity.
  669. check_point(ecc_weierstrass_add_general(wmP, wP), rI)
  670. check_point(ecc_weierstrass_add_general(wP, wmP), rI)
  671. # Verify that point_valid fails if we pass it nonsense.
  672. bogus = ecc_weierstrass_point_new(wc, int(rP.x), int(rP.y * 3))
  673. self.assertFalse(ecc_weierstrass_point_valid(bogus))
  674. # Re-instantiate the curve with the ability to take square
  675. # roots, and check that we can reconstruct P and Q from their
  676. # x coordinate and y parity only.
  677. wc = ecc_weierstrass_curve(p, a, b, find_non_square_mod(p))
  678. x, yp = int(rP.x), (int(rP.y) & 1)
  679. check_point(ecc_weierstrass_point_new_from_x(wc, x, yp), rP)
  680. check_point(ecc_weierstrass_point_new_from_x(wc, x, yp ^ 1), rmP)
  681. x, yp = int(rQ.x), (int(rQ.y) & 1)
  682. check_point(ecc_weierstrass_point_new_from_x(wc, x, yp), rQ)
  683. def testMontgomerySimple(self):
  684. p, a, b = 3141592661, 0xabc, 0xde
  685. rc = MontgomeryCurve(p, a, b)
  686. mc = ecc_montgomery_curve(p, a, b)
  687. rP = rc.cpoint(0x1001)
  688. rQ = rc.cpoint(0x20001)
  689. rdiff = rP - rQ
  690. rsum = rP + rQ
  691. def make_mpoint(rp):
  692. return ecc_montgomery_point_new(mc, int(rp.x))
  693. mP = make_mpoint(rP)
  694. mQ = make_mpoint(rQ)
  695. mdiff = make_mpoint(rdiff)
  696. msum = make_mpoint(rsum)
  697. def check_point(mp, rp):
  698. x = ecc_montgomery_get_affine(mp)
  699. self.assertEqual(int(x), int(rp.x))
  700. check_point(ecc_montgomery_diff_add(mP, mQ, mdiff), rsum)
  701. check_point(ecc_montgomery_diff_add(mQ, mP, mdiff), rsum)
  702. check_point(ecc_montgomery_diff_add(mP, mQ, msum), rdiff)
  703. check_point(ecc_montgomery_diff_add(mQ, mP, msum), rdiff)
  704. check_point(ecc_montgomery_double(mP), rP + rP)
  705. check_point(ecc_montgomery_double(mQ), rQ + rQ)
  706. zero = ecc_montgomery_point_new(mc, 0)
  707. self.assertEqual(ecc_montgomery_is_identity(zero), False)
  708. identity = ecc_montgomery_double(zero)
  709. ecc_montgomery_get_affine(identity)
  710. self.assertEqual(ecc_montgomery_is_identity(identity), True)
  711. def testEdwardsSimple(self):
  712. p, d, a = 3141592661, 2688750488, 367934288
  713. rc = TwistedEdwardsCurve(p, d, a)
  714. ec = ecc_edwards_curve(p, d, a, None)
  715. def check_point(ep, rp):
  716. x, y = ecc_edwards_get_affine(ep)
  717. self.assertEqual(int(x), int(rp.x))
  718. self.assertEqual(int(y), int(rp.y))
  719. def make_point(x, y):
  720. ep = ecc_edwards_point_new(ec, x, y)
  721. rp = rc.point(x, y)
  722. check_point(ep, rp)
  723. return ep, rp
  724. # Some sample points, including the identity and also a pair
  725. # of mutual inverses.
  726. eI, rI = make_point(0, 1)
  727. eP, rP = make_point(196270812, 1576162644)
  728. eQ, rQ = make_point(1777630975, 2717453445)
  729. emP, rmP = make_point(p - 196270812, 1576162644)
  730. # Check that the ordinary add function handles all the special
  731. # cases.
  732. # Adding two finite unequal non-mutually-inverse points
  733. check_point(ecc_edwards_add(eP, eQ), rP + rQ)
  734. check_point(ecc_edwards_add(eQ, eP), rP + rQ)
  735. # Doubling a finite point
  736. check_point(ecc_edwards_add(eP, eP), rP + rP)
  737. check_point(ecc_edwards_add(eQ, eQ), rQ + rQ)
  738. # Adding the identity to a point (both ways round)
  739. check_point(ecc_edwards_add(eI, eP), rP)
  740. check_point(ecc_edwards_add(eI, eQ), rQ)
  741. check_point(ecc_edwards_add(eP, eI), rP)
  742. check_point(ecc_edwards_add(eQ, eI), rQ)
  743. # Doubling the identity
  744. check_point(ecc_edwards_add(eI, eI), rI)
  745. # Adding a point to its own inverse, giving the identity.
  746. check_point(ecc_edwards_add(emP, eP), rI)
  747. check_point(ecc_edwards_add(eP, emP), rI)
  748. # Re-instantiate the curve with the ability to take square
  749. # roots, and check that we can reconstruct P and Q from their
  750. # y coordinate and x parity only.
  751. ec = ecc_edwards_curve(p, d, a, find_non_square_mod(p))
  752. y, xp = int(rP.y), (int(rP.x) & 1)
  753. check_point(ecc_edwards_point_new_from_y(ec, y, xp), rP)
  754. check_point(ecc_edwards_point_new_from_y(ec, y, xp ^ 1), rmP)
  755. y, xp = int(rQ.y), (int(rQ.x) & 1)
  756. check_point(ecc_edwards_point_new_from_y(ec, y, xp), rQ)
  757. # For testing point multiplication, let's switch to the full-sized
  758. # standard curves, because I want to have tested those a bit too.
  759. def testWeierstrassMultiply(self):
  760. wc = ecc_weierstrass_curve(p256.p, int(p256.a), int(p256.b), None)
  761. wG = ecc_weierstrass_point_new(wc, int(p256.G.x), int(p256.G.y))
  762. self.assertTrue(ecc_weierstrass_point_valid(wG))
  763. ints = set(i % p256.p for i in fibonacci_scattered(10))
  764. ints.remove(0) # the zero multiple isn't expected to work
  765. for i in sorted(ints):
  766. wGi = ecc_weierstrass_multiply(wG, i)
  767. x, y = ecc_weierstrass_get_affine(wGi)
  768. rGi = p256.G * i
  769. self.assertEqual(int(x), int(rGi.x))
  770. self.assertEqual(int(y), int(rGi.y))
  771. def testMontgomeryMultiply(self):
  772. mc = ecc_montgomery_curve(
  773. curve25519.p, int(curve25519.a), int(curve25519.b))
  774. mG = ecc_montgomery_point_new(mc, int(curve25519.G.x))
  775. ints = set(i % p256.p for i in fibonacci_scattered(10))
  776. ints.remove(0) # the zero multiple isn't expected to work
  777. for i in sorted(ints):
  778. mGi = ecc_montgomery_multiply(mG, i)
  779. x = ecc_montgomery_get_affine(mGi)
  780. rGi = curve25519.G * i
  781. self.assertEqual(int(x), int(rGi.x))
  782. def testEdwardsMultiply(self):
  783. ec = ecc_edwards_curve(ed25519.p, int(ed25519.d), int(ed25519.a), None)
  784. eG = ecc_edwards_point_new(ec, int(ed25519.G.x), int(ed25519.G.y))
  785. ints = set(i % ed25519.p for i in fibonacci_scattered(10))
  786. ints.remove(0) # the zero multiple isn't expected to work
  787. for i in sorted(ints):
  788. eGi = ecc_edwards_multiply(eG, i)
  789. x, y = ecc_edwards_get_affine(eGi)
  790. rGi = ed25519.G * i
  791. self.assertEqual(int(x), int(rGi.x))
  792. self.assertEqual(int(y), int(rGi.y))
  793. class keygen(MyTestBase):
  794. def testPrimeCandidateSource(self):
  795. def inspect(pcs):
  796. # Returns (pcs->limit, pcs->factor, pcs->addend) as Python integers
  797. return tuple(map(int, pcs_inspect(pcs)))
  798. # Test accumulating modular congruence requirements, by
  799. # inspecting the internal values computed during
  800. # require_residue. We ensure that the addend satisfies all our
  801. # congruences and the factor is the lcm of all the moduli
  802. # (hence, the arithmetic progression defined by those
  803. # parameters is precisely the set of integers satisfying the
  804. # requirements); we also ensure that the limiting values
  805. # (addend itself at the low end, and addend + (limit-1) *
  806. # factor at the high end) are the maximal subsequence of that
  807. # progression that are within the originally specified range.
  808. def check(pcs, lo, hi, mod_res_pairs):
  809. limit, factor, addend = inspect(pcs)
  810. for mod, res in mod_res_pairs:
  811. self.assertEqual(addend % mod, res % mod)
  812. self.assertEqual(factor, functools.reduce(
  813. lcm, [mod for mod, res in mod_res_pairs]))
  814. self.assertFalse(lo <= addend + (-1) * factor < hi)
  815. self.assertTrue (lo <= addend < hi)
  816. self.assertTrue (lo <= addend + (limit-1) * factor < hi)
  817. self.assertFalse(lo <= addend + limit * factor < hi)
  818. pcs = pcs_new(64)
  819. check(pcs, 2**63, 2**64, [(2, 1)])
  820. pcs_require_residue(pcs, 3, 2)
  821. check(pcs, 2**63, 2**64, [(2, 1), (3, 2)])
  822. pcs_require_residue_1(pcs, 7)
  823. check(pcs, 2**63, 2**64, [(2, 1), (3, 2), (7, 1)])
  824. pcs_require_residue(pcs, 16, 7)
  825. check(pcs, 2**63, 2**64, [(2, 1), (3, 2), (7, 1), (16, 7)])
  826. pcs_require_residue(pcs, 49, 8)
  827. check(pcs, 2**63, 2**64, [(2, 1), (3, 2), (7, 1), (16, 7), (49, 8)])
  828. # Now test-generate some actual values, and ensure they
  829. # satisfy all the congruences, and also avoid one residue mod
  830. # 5 that we told them to. Also, give a nontrivial range.
  831. pcs = pcs_new_with_firstbits(64, 0xAB, 8)
  832. pcs_require_residue(pcs, 0x100, 0xCD)
  833. pcs_require_residue_1(pcs, 65537)
  834. pcs_avoid_residue_small(pcs, 5, 3)
  835. pcs_ready(pcs)
  836. with random_prng("test seed"):
  837. for i in range(100):
  838. n = int(pcs_generate(pcs))
  839. self.assertTrue((0xAB<<56) < n < (0xAC<<56))
  840. self.assertEqual(n % 0x100, 0xCD)
  841. self.assertEqual(n % 65537, 1)
  842. self.assertNotEqual(n % 5, 3)
  843. # I'm not actually testing here that the outputs of
  844. # pcs_generate are non-multiples of _all_ primes up to
  845. # 2^16. But checking this many for 100 turns is enough
  846. # to be pretty sure. (If you take the product of
  847. # (1-1/p) over all p in the list below, you find that
  848. # a given random number has about a 13% chance of
  849. # avoiding being a multiple of any of them. So 100
  850. # trials without a mistake gives you 0.13^100 < 10^-88
  851. # as the probability of it happening by chance. More
  852. # likely the code is actually working :-)
  853. for p in [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61]:
  854. self.assertNotEqual(n % p, 0)
  855. def testPocklePositive(self):
  856. def add_small(po, *ps):
  857. for p in ps:
  858. self.assertEqual(pockle_add_small_prime(po, p), 'POCKLE_OK')
  859. def add(po, *args):
  860. self.assertEqual(pockle_add_prime(po, *args), 'POCKLE_OK')
  861. # Transcription of the proof that 2^130-5 is prime from
  862. # Theorem 3.1 from http://cr.yp.to/mac/poly1305-20050329.pdf
  863. po = pockle_new()
  864. p1 = (2**130 - 6) // 1517314646
  865. p2 = (p1 - 1) // 222890620702
  866. add_small(po, 37003, 221101)
  867. add(po, p2, [37003, 221101], 2)
  868. add(po, p1, [p2], 2)
  869. add(po, 2**130 - 5, [p1], 2)
  870. # My own proof that 2^255-19 is prime
  871. po = pockle_new()
  872. p1 = 8574133
  873. p2 = 1919519569386763
  874. p3 = 75445702479781427272750846543864801
  875. p4 = (2**255 - 20) // (65147*12)
  876. p = 2**255 - 19
  877. add_small(po, p1)
  878. add(po, p2, [p1], 2)
  879. add(po, p3, [p2], 2)
  880. add(po, p4, [p3], 2)
  881. add(po, p, [p4], 2)
  882. # And the prime used in Ed448, while I'm here
  883. po = pockle_new()
  884. p1 = 379979
  885. p2 = 1764234391
  886. p3 = 97859369123353
  887. p4 = 34741861125639557
  888. p5 = 36131535570665139281
  889. p6 = 167773885276849215533569
  890. p7 = 596242599987116128415063
  891. p = 2**448 - 2**224 - 1
  892. add_small(po, p1, p2)
  893. add(po, p3, [p1], 2)
  894. add(po, p4, [p2], 2)
  895. add(po, p5, [p4], 2)
  896. add(po, p6, [p3], 3)
  897. add(po, p7, [p5], 3)
  898. add(po, p, [p6, p7], 2)
  899. p = 4095744004479977
  900. factors = [2, 79999] # just enough factors to exceed cbrt(p)
  901. po = pockle_new()
  902. for q in factors:
  903. add_small(po, q)
  904. add(po, p, factors, 3)
  905. # The order of the generator in Ed25519
  906. po = pockle_new()
  907. p1a, p1b = 132667, 137849
  908. p2 = 3044861653679985063343
  909. p3 = 198211423230930754013084525763697
  910. p = 2**252 + 0x14def9dea2f79cd65812631a5cf5d3ed
  911. add_small(po, p1a, p1b)
  912. add(po, p2, [p1a, p1b], 2)
  913. add(po, p3, [p2], 2)
  914. add(po, p, [p3], 2)
  915. # And the one in Ed448
  916. po = pockle_new()
  917. p1 = 766223
  918. p2 = 3009341
  919. p3 = 7156907
  920. p4 = 671065561
  921. p5 = 342682509629
  922. p6 = 6730519843040614479184435237013
  923. p = 2**446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d
  924. add_small(po, p1, p2, p3, p4)
  925. add(po, p5, [p1], 2)
  926. add(po, p6, [p3,p4], 2)
  927. add(po, p, [p2,p5,p6], 2)
  928. # Combined certificate for the moduli and generator orders of
  929. # the three NIST curves, generated by contrib/proveprime.py
  930. # (with some cosmetic tidying)
  931. p256 = 2**256 - 2**224 + 2**192 + 2**96 - 1
  932. p384 = 2**384 - 2**128 - 2**96 + 2**32 - 1
  933. p521 = 2**521 - 1
  934. order256 = p256 - 0x4319055358e8617b0c46353d039cdaae
  935. order384 = p384 - 0x389cb27e0bc8d21fa7e5f24cb74f58851313e696333ad68c
  936. t = 0x5ae79787c40d069948033feb708f65a2fc44a36477663b851449048e16ec79bf6
  937. order521 = p521 - t
  938. p0 = order384 // 12895580879789762060783039592702
  939. p1 = 1059392654943455286185473617842338478315215895509773412096307
  940. p2 = 55942463741690639
  941. p3 = 37344768852931
  942. p4 = order521 // 1898873518475180724503002533770555108536
  943. p5 = p4 // 994165722
  944. p6 = 144471089338257942164514676806340723
  945. p7 = p384 // 2054993070433694
  946. p8 = 1357291859799823621
  947. po = pockle_new()
  948. add_small(po, 2, 3, 5, 11, 17, 19, 31, 41, 53, 67, 71, 109, 131, 149,
  949. 157, 257, 521, 641, 1613, 2731, 3407, 6317, 8191, 8389,
  950. 14461, 17449, 38189, 38557, 42641, 51481, 61681, 65537,
  951. 133279, 248431, 312289, 409891, 490463, 858001, 6700417,
  952. 187019741)
  953. add(po, p3, [149, 11, 5, 3, 2], 3)
  954. add(po, p2, [p3], 2)
  955. add(po, p8, [6317, 67, 2, 2], 2)
  956. add(po, p6, [133279, 14461, 109, 3], 7)
  957. add(po, p1, [p2, 248431], 2)
  958. add(po, order256, [187019741, 38189, 17449, 3407, 131, 71, 2, 2, 2, 2],
  959. 7)
  960. add(po, p256, [6700417, 490463, 65537, 641, 257, 17, 5, 5, 3, 2], 6)
  961. add(po, p0, [p1], 2)
  962. add(po, p7, [p8, 312289, 38557, 8389, 11, 2], 3)
  963. add(po, p5, [p6, 19], 2)
  964. add(po, order384, [p0], 2)
  965. add(po, p384, [p7], 2)
  966. add(po, p4, [p5], 2)
  967. add(po, order521, [p4], 2)
  968. add(po, p521, [858001, 409891, 61681, 51481, 42641, 8191, 2731, 1613,
  969. 521, 157, 131, 53, 41, 31, 17, 11, 5, 5, 3, 2], 3)
  970. def testPockleNegative(self):
  971. def add_small(po, p):
  972. self.assertEqual(pockle_add_small_prime(po, p), 'POCKLE_OK')
  973. po = pockle_new()
  974. self.assertEqual(pockle_add_small_prime(po, 0),
  975. 'POCKLE_PRIME_SMALLER_THAN_2')
  976. self.assertEqual(pockle_add_small_prime(po, 1),
  977. 'POCKLE_PRIME_SMALLER_THAN_2')
  978. self.assertEqual(pockle_add_small_prime(po, 2**61 - 1),
  979. 'POCKLE_SMALL_PRIME_NOT_SMALL')
  980. self.assertEqual(pockle_add_small_prime(po, 4),
  981. 'POCKLE_SMALL_PRIME_NOT_PRIME')
  982. po = pockle_new()
  983. self.assertEqual(pockle_add_prime(po, 1919519569386763, [8574133], 2),
  984. 'POCKLE_FACTOR_NOT_KNOWN_PRIME')
  985. po = pockle_new()
  986. add_small(po, 8574133)
  987. self.assertEqual(pockle_add_prime(po, 1919519569386765, [8574133], 2),
  988. 'POCKLE_FACTOR_NOT_A_FACTOR')
  989. p = 4095744004479977
  990. factors = [2, 79997] # not quite enough factors to reach cbrt(p)
  991. po = pockle_new()
  992. for q in factors:
  993. add_small(po, q)
  994. self.assertEqual(pockle_add_prime(po, p, factors, 3),
  995. 'POCKLE_PRODUCT_OF_FACTORS_TOO_SMALL')
  996. p = 1999527 * 3999053
  997. factors = [999763]
  998. po = pockle_new()
  999. for q in factors:
  1000. add_small(po, q)
  1001. self.assertEqual(pockle_add_prime(po, p, factors, 3),
  1002. 'POCKLE_DISCRIMINANT_IS_SQUARE')
  1003. p = 9999929 * 9999931
  1004. factors = [257, 2593]
  1005. po = pockle_new()
  1006. for q in factors:
  1007. add_small(po, q)
  1008. self.assertEqual(pockle_add_prime(po, p, factors, 3),
  1009. 'POCKLE_FERMAT_TEST_FAILED')
  1010. p = 1713000920401 # a Carmichael number
  1011. po = pockle_new()
  1012. add_small(po, 561787)
  1013. self.assertEqual(pockle_add_prime(po, p, [561787], 2),
  1014. 'POCKLE_WITNESS_POWER_IS_1')
  1015. p = 4294971121
  1016. factors = [3, 5, 11, 17]
  1017. po = pockle_new()
  1018. for q in factors:
  1019. add_small(po, q)
  1020. self.assertEqual(pockle_add_prime(po, p, factors, 17),
  1021. 'POCKLE_WITNESS_POWER_NOT_COPRIME')
  1022. po = pockle_new()
  1023. add_small(po, 2)
  1024. self.assertEqual(pockle_add_prime(po, 1, [2], 1),
  1025. 'POCKLE_PRIME_SMALLER_THAN_2')
  1026. def testMillerRabin(self):
  1027. # A prime congruent to 3 mod 4, so M-R can only do one
  1028. # iteration: either a^{(p-1)/2} == +1, or -1. Either counts as
  1029. # a pass; the latter also means the number is potentially a
  1030. # primitive root.
  1031. n = 0xe76e6aaa42b5d7423aa4da5613eb21c3
  1032. mr = miller_rabin_new(n)
  1033. self.assertEqual(miller_rabin_test(mr, 2), "passed+ppr")
  1034. self.assertEqual(miller_rabin_test(mr, 4), "passed")
  1035. # The 'potential primitive root' test only means that M-R
  1036. # didn't _rule out_ the number being a primitive root, by
  1037. # finding that any of the powers _it tested_ less than n-1
  1038. # came out to be 1. In this case, 2 really is a primitive
  1039. # root, but since 13 | n-1, the 13th powers mod n form a
  1040. # multiplicative subgroup. So 2^13 is not a primitive root,
  1041. # and yet, M-R can't tell the difference, because it only
  1042. # tried the exponent (n-1)/2, not the actual counterexample
  1043. # (n-1)/13.
  1044. self.assertEqual(miller_rabin_test(mr, 2**13), "passed+ppr")
  1045. # A prime congruent to 1 mod a reasonably large power of 2, so
  1046. # M-R has lots of scope to have different things happen. 3 is
  1047. # a primitive root, so we expect that 3, 3^2, 3^4, ..., 3^256
  1048. # should all pass for different reasons, with only the first
  1049. # of them returning passed+ppr.
  1050. n = 0xb1b65ebe489ff0ab4597bb67c3d22d01
  1051. mr = miller_rabin_new(n)
  1052. w = 3
  1053. self.assertEqual(miller_rabin_test(mr, w), "passed+ppr")
  1054. for i in range(1, 10):
  1055. w = w * w % n
  1056. self.assertEqual(miller_rabin_test(mr, w), "passed")
  1057. # A prime with an _absurdly_ large power-of-2 factor in its
  1058. # multiplicative group.
  1059. n = 0x600000000000000000000000000000000000000000000001
  1060. mr = miller_rabin_new(n)
  1061. w = 10
  1062. self.assertEqual(miller_rabin_test(mr, w), "passed+ppr")
  1063. for i in range(1, 200):
  1064. w = w * w % n
  1065. self.assertEqual(miller_rabin_test(mr, w), "passed")
  1066. # A blatantly composite number. But we still expect to see a
  1067. # pass if we give the witness 1 (which will give a maximal
  1068. # trailing string of 1s), or -1 (which will give -1 when
  1069. # raised to the maximal odd factor of n-1, or indeed any other
  1070. # odd power).
  1071. n = 0x1010101010101010101010101010101
  1072. mr = miller_rabin_new(n)
  1073. self.assertEqual(miller_rabin_test(mr, 1), "passed")
  1074. self.assertEqual(miller_rabin_test(mr, n-1), "passed")
  1075. self.assertEqual(miller_rabin_test(mr, 2), "failed")
  1076. # A Carmichael number, as a proper test that M-R detects
  1077. # things the Fermat test would not.
  1078. #
  1079. # (Its prime factorisation is 26823115100268314289505807 *
  1080. # 53646230200536628579011613 * 80469345300804942868517419,
  1081. # which is enough to re-check its Carmichaelness.)
  1082. n = 0xffffffffffffffffcf8032f3e044b4a8b1b1bf0b526538eae953d90f44d65511
  1083. mr = miller_rabin_new(n)
  1084. self.assertEqual(miller_rabin_test(mr, 16), "passed")
  1085. assert(pow(2, n-1, n) == 1) # Fermat test would pass, but ...
  1086. self.assertEqual(miller_rabin_test(mr, 2), "failed") # ... this fails
  1087. # A white-box test for the side-channel-safe M-R
  1088. # implementation, which has to check a^e against +-1 for every
  1089. # exponent e of the form floor((n-1) / power of 2), so as to
  1090. # avoid giving away exactly how many of the trailing values of
  1091. # that sequence are significant to the test.
  1092. #
  1093. # When the power of 2 is large enough that the division was
  1094. # not exact, the results of these comparisons are _not_
  1095. # significant to the test, and we're required to ignore them!
  1096. #
  1097. # This pair of values has the property that none of the values
  1098. # legitimately computed by M-R is either +1 _or_ -1, but if
  1099. # you shift n-1 right by one too many bits (losing the lowest
  1100. # set bit of 0x6d00 to get 0x36), then _that_ power of the
  1101. # witness integer is -1. This should not cause a spurious pass.
  1102. n = 0x6d01
  1103. mr = miller_rabin_new(n)
  1104. self.assertEqual(miller_rabin_test(mr, 0x251), "failed")
  1105. class ntru(MyTestBase):
  1106. def testMultiply(self):
  1107. self.assertEqual(
  1108. ntru_ring_multiply([1,1,1,1,1,1], [1,1,1,1,1,1], 11, 59),
  1109. [1,2,3,4,5,6,5,4,3,2,1])
  1110. self.assertEqual(ntru_ring_multiply(
  1111. [1,0,1,2,0,0,1,2,0,1,2], [2,0,0,1,0,1,2,2,2,0,2], 11, 3),
  1112. [1,0,0,0,0,0,0,0,0,0,0])
  1113. def testInvert(self):
  1114. # Over GF(3), x^11-x-1 factorises as
  1115. # (x^3+x^2+2) * (x^8+2*x^7+x^6+2*x^4+2*x^3+x^2+x+1)
  1116. # so we expect that 2,0,1,1 has no inverse, being one of those factors.
  1117. self.assertEqual(ntru_ring_invert([0], 11, 3), None)
  1118. self.assertEqual(ntru_ring_invert([1], 11, 3),
  1119. [1,0,0,0,0,0,0,0,0,0,0])
  1120. self.assertEqual(ntru_ring_invert([2,0,1,1], 11, 3), None)
  1121. self.assertEqual(ntru_ring_invert([1,0,1,2,0,0,1,2,0,1,2], 11, 3),
  1122. [2,0,0,1,0,1,2,2,2,0,2])
  1123. self.assertEqual(ntru_ring_invert([1,0,1,2,0,0,1,2,0,1,2], 11, 59),
  1124. [1,26,10,1,38,48,34,37,53,3,53])
  1125. def testMod3Round3(self):
  1126. # Try a prime congruent to 1 mod 3
  1127. self.assertEqual(ntru_mod3([4,5,6,0,1,2,3], 7, 7),
  1128. [0,1,-1,0,1,-1,0])
  1129. self.assertEqual(ntru_round3([4,5,6,0,1,2,3], 7, 7),
  1130. [-3,-3,0,0,0,3,3])
  1131. # And one congruent to 2 mod 3
  1132. self.assertEqual(ntru_mod3([6,7,8,9,10,0,1,2,3,4,5], 11, 11),
  1133. [1,-1,0,1,-1,0,1,-1,0,1,-1])
  1134. self.assertEqual(ntru_round3([6,7,8,9,10,0,1,2,3,4,5], 11, 11),
  1135. [-6,-3,-3,-3,0,0,0,3,3,3,6])
  1136. def testBiasScale(self):
  1137. self.assertEqual(ntru_bias([0,1,2,3,4,5,6,7,8,9,10], 4, 11, 11),
  1138. [4,5,6,7,8,9,10,0,1,2,3])
  1139. self.assertEqual(ntru_scale([0,1,2,3,4,5,6,7,8,9,10], 4, 11, 11),
  1140. [0,4,8,1,5,9,2,6,10,3,7])
  1141. def testEncode(self):
  1142. # Test a small case. Worked through in detail:
  1143. #
  1144. # Pass 1:
  1145. # Input list is (89:123, 90:234, 344:345, 432:456, 222:567)
  1146. # (89:123, 90:234) -> (89+123*90 : 123*234) = (11159:28782)
  1147. # Emit low byte of 11159 = 0x97, and get (43:113)
  1148. # (344:345, 432:456) -> (344+345*432 : 345*456) = (149384:157320)
  1149. # Emit low byte of 149384 = 0x88, and get (583:615)
  1150. # Odd pair (222:567) is copied to end of new list
  1151. # Final list is (43:113, 583:615, 222:567)
  1152. # Pass 2:
  1153. # Input list is (43:113, 583:615, 222:567)
  1154. # (43:113, 583:615) -> (43+113*583, 113*615) = (65922:69495)
  1155. # Emit low byte of 65922 = 0x82, and get (257:272)
  1156. # Odd pair (222:567) is copied to end of new list
  1157. # Final list is (257:272, 222:567)
  1158. # Pass 3:
  1159. # Input list is (257:272, 222:567)
  1160. # (257:272, 222:567) -> (257+272*222, 272*567) = (60641:154224)
  1161. # Emit low byte of 60641 = 0xe1, and get (236:603)
  1162. # Final list is (236:603)
  1163. # Cleanup:
  1164. # Emit low byte of 236 = 0xec, and get (0:3)
  1165. # Emit low byte of 0 = 0x00, and get (0:1)
  1166. ms = [123,234,345,456,567]
  1167. rs = [89,90,344,432,222]
  1168. encoding = unhex('978882e1ec00')
  1169. sched = ntru_encode_schedule(ms)
  1170. self.assertEqual(sched.encode(rs), encoding)
  1171. self.assertEqual(sched.decode(encoding), rs)
  1172. # Encode schedules for sntrup761 public keys and ciphertexts
  1173. pubsched = ntru_encode_schedule([4591]*761)
  1174. self.assertEqual(pubsched.length(), 1158)
  1175. ciphersched = ntru_encode_schedule([1531]*761)
  1176. self.assertEqual(ciphersched.length(), 1007)
  1177. # Test round-trip encoding using those schedules
  1178. testlist = list(range(761))
  1179. pubtext = pubsched.encode(testlist)
  1180. self.assertEqual(pubsched.decode(pubtext), testlist)
  1181. ciphertext = ciphersched.encode(testlist)
  1182. self.assertEqual(ciphersched.decode(ciphertext), testlist)
  1183. def testCore(self):
  1184. # My own set of NTRU Prime parameters, satisfying all the
  1185. # requirements and tiny enough for convenient testing
  1186. p, q, w = 11, 59, 3
  1187. with random_prng('ntru keygen seed'):
  1188. keypair = ntru_keygen(p, q, w)
  1189. plaintext = ntru_gen_short(p, w)
  1190. ciphertext = ntru_encrypt(plaintext, ntru_pubkey(keypair), p, q)
  1191. recovered = ntru_decrypt(ciphertext, keypair)
  1192. self.assertEqual(plaintext, recovered)
  1193. class crypt(MyTestBase):
  1194. def testSSH1Fingerprint(self):
  1195. # Example key and reference fingerprint value generated by
  1196. # OpenSSH 6.7 ssh-keygen
  1197. rsa = rsa_bare(65537, 984185866443261798625575612408956568591522723900235822424492423996716524817102482330189709310179009158443944785704183009867662230534501187034891091310377917105259938712348098594526746211645472854839799025154390701673823298369051411)
  1198. fp = rsa_ssh1_fingerprint(rsa)
  1199. self.assertEqual(
  1200. fp, b"768 96:12:c8:bc:e6:03:75:86:e8:c7:b9:af:d8:0c:15:75")
  1201. def testSSH2Fingerprints(self):
  1202. # A sensible key blob that we can make sense of.
  1203. sensible_blob = b64(
  1204. 'AAAAC3NzaC1lZDI1NTE5AAAAICWiV0VAD4lQ7taUN7vZ5Rkc'
  1205. 'SLJBW5ubn6ZINwCOzpn3')
  1206. self.assertEqual(ssh2_fingerprint_blob(sensible_blob, "sha256"),
  1207. b'ssh-ed25519 255 SHA256:'
  1208. b'E4VmaHW0sUF7SUgSEOmMJ8WBtt0e/j3zbsKvyqfFnu4')
  1209. self.assertEqual(ssh2_fingerprint_blob(sensible_blob, "md5"),
  1210. b'ssh-ed25519 255 '
  1211. b'35:73:80:df:a3:2c:1a:f2:2c:a6:5c:84:ce:48:6a:7e')
  1212. # A key blob with an unknown algorithm name, so that we can't
  1213. # extract the bit count.
  1214. silly_blob = ssh_string(b'foo') + ssh_string(b'key data')
  1215. self.assertEqual(ssh2_fingerprint_blob(silly_blob, "sha256"),
  1216. b'foo SHA256:'
  1217. b'mvfJTB4PaRI7hxYaYwn0sH8G6zW1HbLkbWnZE2YIKc4')
  1218. self.assertEqual(ssh2_fingerprint_blob(silly_blob, "md5"),
  1219. b'foo '
  1220. b'5f:5f:97:94:97:be:01:5c:f6:3f:e3:6e:55:46:ea:52')
  1221. # A key blob without even a valid algorithm-name string at the start.
  1222. very_silly_blob = b'foo'
  1223. self.assertEqual(ssh2_fingerprint_blob(very_silly_blob, "sha256"),
  1224. b'SHA256:'
  1225. b'LCa0a2j/xo/5m0U8HTBBNBNCLXBkg7+g+YpeiGJm564')
  1226. self.assertEqual(ssh2_fingerprint_blob(very_silly_blob, "md5"),
  1227. b'ac:bd:18:db:4c:c2:f8:5c:ed:ef:65:4f:cc:c4:a4:d8')
  1228. # A certified key.
  1229. cert_blob = b64(
  1230. 'AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJ4Ds9YwRHxs'
  1231. 'xdtUitRbZGz0MgKGZSBVrTHI1AbvetofAAAAIMt0/CMBL+64GQ/r/JyGxo6oHs86'
  1232. 'i9bOHhMJYbDbxEJfAAAAAAAAAG8AAAABAAAAAmlkAAAADAAAAAh1c2VybmFtZQAA'
  1233. 'AAAAAAPoAAAAAAAAB9AAAAAAAAAAAAAAAAAAAAE+AAAAIHNzaC1lZDI1NTE5LWNl'
  1234. 'cnQtdjAxQG9wZW5zc2guY29tAAAAICl5MiUNt8hoAAHT0v00JYOkWe2UW31+Qq5Q'
  1235. 'HYKWGyVjAAAAIMUJEFAmSV/qtoxSmVOHUgTMKYjqkDy8fTfsfCKV+sN7AAAAAAAA'
  1236. 'AG8AAAABAAAAAmlkAAAAEgAAAA5kb2Vzbid0IG1hdHRlcgAAAAAAAAPoAAAAAAAA'
  1237. 'B9AAAAAAAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIMUJEFAmSV/qtoxS'
  1238. 'mVOHUgTMKYjqkDy8fTfsfCKV+sN7AAAAUwAAAAtzc2gtZWQyNTUxOQAAAEAXbRz3'
  1239. 'lBmoU4FVge29jn04MfubF6U0CoPG1nbeZSgDN2iz7qtZ75XIk5O/Z/W9nA8jwsiz'
  1240. 'iSEMItjvR7HEN8MIAAAAUwAAAAtzc2gtZWQyNTUxOQAAAECszhkY8bUbSCjmHEMP'
  1241. 'LjcOX6OaeBzPIYYYXJzpLn+m+CIwDXRIxyvON5/d/TomgAFNJutfOEsqIzy5OAvl'
  1242. 'p5IO')
  1243. self.assertEqual(ssh2_fingerprint_blob(cert_blob, "sha256"),
  1244. b'ssh-ed25519-cert-v01@openssh.com 255 '
  1245. b'SHA256:42JaqhHUNa5CoKxGWqtKXF0Awz7b0aPrtgBZ9VLLHfY')
  1246. self.assertEqual(ssh2_fingerprint_blob(cert_blob, "md5"),
  1247. b'ssh-ed25519-cert-v01@openssh.com 255 '
  1248. b'8e:40:00:e0:1f:4a:9c:b3:c8:e9:05:59:04:03:44:b3')
  1249. self.assertEqual(ssh2_fingerprint_blob(cert_blob, "sha256-cert"),
  1250. b'ssh-ed25519-cert-v01@openssh.com 255 '
  1251. b'SHA256:W/+SDEg7S+/dAn4SrodJ2c8bYvt13XXA7YYlQ6E8R5U')
  1252. self.assertEqual(ssh2_fingerprint_blob(cert_blob, "md5-cert"),
  1253. b'ssh-ed25519-cert-v01@openssh.com 255 '
  1254. b'03:cf:aa:8e:aa:c3:a0:97:bb:2e:7e:57:9d:08:b5:be')
  1255. def testAES(self):
  1256. # My own test cases, generated by a mostly independent
  1257. # reference implementation of AES in Python. ('Mostly'
  1258. # independent in that it was written by me.)
  1259. def vector(cipherbase, key, iv, plaintext, ciphertext):
  1260. for cipher in get_implementations(cipherbase):
  1261. c = ssh_cipher_new(cipher)
  1262. if c is None: return # skip test if HW AES not available
  1263. ssh_cipher_setkey(c, key)
  1264. ssh_cipher_setiv(c, iv)
  1265. self.assertEqualBin(
  1266. ssh_cipher_encrypt(c, plaintext), ciphertext)
  1267. ssh_cipher_setiv(c, iv)
  1268. self.assertEqualBin(
  1269. ssh_cipher_decrypt(c, ciphertext), plaintext)
  1270. # Tests of CBC mode.
  1271. key = unhex(
  1272. '98483c6eb40b6c31a448c22a66ded3b5e5e8d5119cac8327b655c8b5c4836489')
  1273. iv = unhex('38f87b0b9b736160bfc0cbd8447af6ee')
  1274. plaintext = unhex('''
  1275. ee16271827b12d828f61d56fddccc38ccaa69601da2b36d3af1a34c51947b71a
  1276. 362f05e07bf5e7766c24599799b252ad2d5954353c0c6ca668c46779c2659c94
  1277. 8df04e4179666e335470ff042e213c8bcff57f54842237fbf9f3c7e6111620ac
  1278. 1c007180edd25f0e337c2a49d890a7173f6b52d61e3d2a21ddc8e41513a0e825
  1279. afd5932172270940b01014b5b7fb8495946151520a126518946b44ea32f9b2a9
  1280. ''')
  1281. vector('aes128_cbc', key[:16], iv, plaintext, unhex('''
  1282. 547ee90514cb6406d5bb00855c8092892c58299646edda0b4e7c044247795c8d
  1283. 3c3eb3d91332e401215d4d528b94a691969d27b7890d1ae42fe3421b91c989d5
  1284. 113fefa908921a573526259c6b4f8e4d90ea888e1d8b7747457ba3a43b5b79b9
  1285. 34873ebf21102d14b51836709ee85ed590b7ca618a1e884f5c57c8ea73fe3d0d
  1286. 6bf8c082dd602732bde28131159ed0b6e9cf67c353ffdd010a5a634815aaa963'''))
  1287. vector('aes192_cbc', key[:24], iv, plaintext, unhex('''
  1288. e3dee5122edd3fec5fab95e7db8c784c0cb617103e2a406fba4ae3b4508dd608
  1289. 4ff5723a670316cc91ed86e413c11b35557c56a6f5a7a2c660fc6ee603d73814
  1290. 73a287645be0f297cdda97aef6c51faeb2392fec9d33adb65138d60f954babd9
  1291. 8ee0daab0d1decaa8d1e07007c4a3c7b726948025f9fb72dd7de41f74f2f36b4
  1292. 23ac6a5b4b6b39682ec74f57d9d300e547f3c3e467b77f5e4009923b2f94c903'''))
  1293. vector('aes256_cbc', key[:32], iv, plaintext, unhex('''
  1294. 088c6d4d41997bea79c408925255266f6c32c03ea465a5f607c2f076ec98e725
  1295. 7e0beed79609b3577c16ebdf17d7a63f8865278e72e859e2367de81b3b1fe9ab
  1296. 8f045e1d008388a3cfc4ff87daffedbb47807260489ad48566dbe73256ce9dd4
  1297. ae1689770a883b29695928f5983f33e8d7aec4668f64722e943b0b671c365709
  1298. dfa86c648d5fb00544ff11bd29121baf822d867e32da942ba3a0d26299bcee13'''))
  1299. # Tests of SDCTR mode, one with a random IV and one with an IV
  1300. # about to wrap round. More vigorous tests of IV carry and
  1301. # wraparound behaviour are in the testAESSDCTR method.
  1302. sdctrIVs = [
  1303. unhex('38f87b0b9b736160bfc0cbd8447af6ee'),
  1304. unhex('fffffffffffffffffffffffffffffffe'),
  1305. ]
  1306. vector('aes128_ctr', key[:16], sdctrIVs[0], plaintext[:64], unhex('''
  1307. d0061d7b6e8c4ef4fe5614b95683383f46cdd2766e66b6fb0b0f0b3a24520b2d
  1308. 15d869b06cbf685ede064bcf8fb5fb6726cfd68de7016696a126e9e84420af38'''))
  1309. vector('aes128_ctr', key[:16], sdctrIVs[1], plaintext[:64], unhex('''
  1310. 49ac67164fd9ce8701caddbbc9a2b06ac6524d4aa0fdac95253971974b8f3bc2
  1311. bb8d7c970f6bcd79b25218cc95582edf7711aae2384f6cf91d8d07c9d9b370bc'''))
  1312. vector('aes192_ctr', key[:24], sdctrIVs[0], plaintext[:64], unhex('''
  1313. 0baa86acbe8580845f0671b7ebad4856ca11b74e5108f515e34e54fa90f87a9a
  1314. c6eee26686253c19156f9be64957f0dbc4f8ecd7cabb1f4e0afefe33888faeec'''))
  1315. vector('aes192_ctr', key[:24], sdctrIVs[1], plaintext[:64], unhex('''
  1316. 2da1791250100dc0d1461afe1bbfad8fa0320253ba5d7905d837386ba0a3a41f
  1317. 01965c770fcfe01cf307b5316afb3981e0e4aa59a6e755f0a5784d9accdc52be'''))
  1318. vector('aes256_ctr', key[:32], sdctrIVs[0], plaintext[:64], unhex('''
  1319. 49c7b284222d408544c770137b6ef17ef770c47e24f61fa66e7e46cae4888882
  1320. f980a0f2446956bf47d2aed55ebd2e0694bfc46527ed1fd33efe708fec2f8b1f'''))
  1321. vector('aes256_ctr', key[:32], sdctrIVs[1], plaintext[:64], unhex('''
  1322. f1d013c3913ccb4fc0091e25d165804480fb0a1d5c741bf012bba144afda6db2
  1323. c512f3942018574bd7a8fdd88285a73d25ef81e621aebffb6e9b8ecc8e2549d4'''))
  1324. def testAESSDCTR(self):
  1325. # A thorough test of the IV-incrementing component of SDCTR
  1326. # mode. We set up an AES-SDCTR cipher object with the given
  1327. # input IV; we encrypt two all-zero blocks, expecting the
  1328. # return values to be the AES-ECB encryptions of the input IV
  1329. # and the incremented version. Then we decrypt each of them by
  1330. # feeding them to an AES-CBC cipher object with its IV set to
  1331. # zero.
  1332. def increment(keylen, suffix, iv):
  1333. key = b'\xab' * (keylen//8)
  1334. sdctr = ssh_cipher_new("aes{}_ctr_{}".format(keylen, suffix))
  1335. if sdctr is None: return # skip test if HW AES not available
  1336. ssh_cipher_setkey(sdctr, key)
  1337. cbc = ssh_cipher_new("aes{}_cbc_{}".format(keylen, suffix))
  1338. ssh_cipher_setkey(cbc, key)
  1339. ssh_cipher_setiv(sdctr, iv)
  1340. ec0 = ssh_cipher_encrypt(sdctr, b'\x00' * 16)
  1341. ec1 = ssh_cipher_encrypt(sdctr, b'\x00' * 16)
  1342. ssh_cipher_setiv(cbc, b'\x00' * 16)
  1343. dc0 = ssh_cipher_decrypt(cbc, ec0)
  1344. ssh_cipher_setiv(cbc, b'\x00' * 16)
  1345. dc1 = ssh_cipher_decrypt(cbc, ec1)
  1346. self.assertEqualBin(iv, dc0)
  1347. return dc1
  1348. def test(keylen, suffix, ivInteger):
  1349. mask = (1 << 128) - 1
  1350. ivInteger &= mask
  1351. ivBinary = unhex("{:032x}".format(ivInteger))
  1352. ivIntegerInc = (ivInteger + 1) & mask
  1353. ivBinaryInc = unhex("{:032x}".format((ivIntegerInc)))
  1354. actualResult = increment(keylen, suffix, ivBinary)
  1355. if actualResult is not None:
  1356. self.assertEqualBin(actualResult, ivBinaryInc)
  1357. # Check every input IV you can make by gluing together 32-bit
  1358. # pieces of the form 0, 1 or -1. This should test all the
  1359. # places where carry propagation within the 128-bit integer
  1360. # can go wrong.
  1361. #
  1362. # We also test this at all three AES key lengths, in case the
  1363. # core cipher routines are written separately for each one.
  1364. for suffix in get_aes_impls():
  1365. for keylen in [128, 192, 256]:
  1366. hexTestValues = ["00000000", "00000001", "ffffffff"]
  1367. for ivHexBytes in itertools.product(*([hexTestValues] * 4)):
  1368. ivInteger = int("".join(ivHexBytes), 16)
  1369. test(keylen, suffix, ivInteger)
  1370. def testAESParallelism(self):
  1371. # Since at least one of our implementations of AES works in
  1372. # parallel, here's a test that CBC decryption works the same
  1373. # way no matter how the input data is divided up.
  1374. # A pile of conveniently available random-looking test data.
  1375. test_ciphertext = ssh2_mpint(last(fibonacci_scattered(14)))
  1376. test_ciphertext += b"x" * (15 & -len(test_ciphertext)) # pad to a block
  1377. # Test key and IV.
  1378. test_key = b"foobarbazquxquuxFooBarBazQuxQuux"
  1379. test_iv = b"FOOBARBAZQUXQUUX"
  1380. for keylen in [128, 192, 256]:
  1381. decryptions = []
  1382. for suffix in get_aes_impls():
  1383. c = ssh_cipher_new("aes{:d}_cbc_{}".format(keylen, suffix))
  1384. if c is None: continue
  1385. ssh_cipher_setkey(c, test_key[:keylen//8])
  1386. for chunklen in range(16, 16*12, 16):
  1387. ssh_cipher_setiv(c, test_iv)
  1388. decryption = b""
  1389. for pos in range(0, len(test_ciphertext), chunklen):
  1390. chunk = test_ciphertext[pos:pos+chunklen]
  1391. decryption += ssh_cipher_decrypt(c, chunk)
  1392. decryptions.append(decryption)
  1393. for d in decryptions:
  1394. self.assertEqualBin(d, decryptions[0])
  1395. def testCRC32(self):
  1396. # Check the effect of every possible single-byte input to
  1397. # crc32_update. In the traditional implementation with a
  1398. # 256-word lookup table, this exercises every table entry; in
  1399. # _any_ implementation which iterates over the input one byte
  1400. # at a time, it should be a similarly exhaustive test. (But if
  1401. # a more optimised implementation absorbed _more_ than 8 bits
  1402. # at a time, then perhaps this test wouldn't be enough...)
  1403. # It would be nice if there was a functools.iterate() which
  1404. # would apply a function n times. Failing that, making shift1
  1405. # accept and ignore a second argument allows me to iterate it
  1406. # 8 times using functools.reduce.
  1407. shift1 = lambda x, dummy=None: (x >> 1) ^ (0xEDB88320 * (x & 1))
  1408. shift8 = lambda x: functools.reduce(shift1, [None]*8, x)
  1409. # A small selection of choices for the other input to
  1410. # crc32_update, just to check linearity.
  1411. test_prior_values = [0, 0xFFFFFFFF, 0x45CC1F6A, 0xA0C4ADCF, 0xD482CDF1]
  1412. for prior in test_prior_values:
  1413. prior_shifted = shift8(prior)
  1414. for i in range(256):
  1415. exp = shift8(i) ^ prior_shifted
  1416. self.assertEqual(crc32_update(prior, struct.pack("B", i)), exp)
  1417. # Check linearity of the _reference_ implementation, while
  1418. # we're at it!
  1419. self.assertEqual(shift8(i ^ prior), exp)
  1420. def testCRCDA(self):
  1421. def pattern(badblk, otherblks, pat):
  1422. # Arrange copies of the bad block in a pattern
  1423. # corresponding to the given bit string.
  1424. retstr = b""
  1425. while pat != 0:
  1426. retstr += (badblk if pat & 1 else next(otherblks))
  1427. pat >>= 1
  1428. return retstr
  1429. def testCases(pat):
  1430. badblock = b'muhahaha' # the block we'll maliciously repeat
  1431. # Various choices of the other blocks, including all the
  1432. # same, all different, and all different but only in the
  1433. # byte at one end.
  1434. for otherblocks in [
  1435. itertools.repeat(b'GoodData'),
  1436. (struct.pack('>Q', i) for i in itertools.count()),
  1437. (struct.pack('<Q', i) for i in itertools.count())]:
  1438. yield pattern(badblock, otherblocks, pat)
  1439. def positiveTest(pat):
  1440. for data in testCases(pat):
  1441. self.assertTrue(crcda_detect(data, ""))
  1442. self.assertTrue(crcda_detect(data[8:], data[:8]))
  1443. def negativeTest(pat):
  1444. for data in testCases(pat):
  1445. self.assertFalse(crcda_detect(data, ""))
  1446. self.assertFalse(crcda_detect(data[8:], data[:8]))
  1447. # Tests of successful attack detection, derived by taking
  1448. # multiples of the CRC polynomial itself.
  1449. #
  1450. # (The CRC32 polynomial is usually written as 0xEDB88320.
  1451. # That's in bit-reversed form, but then, that's the form we
  1452. # need anyway for these patterns. But it's also missing the
  1453. # leading term - really, 0xEDB88320 is the value you get by
  1454. # reducing X^32 modulo the real poly, i.e. the value you put
  1455. # back in to the CRC to compensate for an X^32 that's just
  1456. # been shifted out. If you put that bit back on - at the
  1457. # bottom, because of the bit-reversal - you get the less
  1458. # familiar-looking 0x1db710641.)
  1459. positiveTest(0x1db710641) # the CRC polynomial P itself
  1460. positiveTest(0x26d930ac3) # (X+1) * P
  1461. positiveTest(0xbdbdf21cf) # (X^3+X^2+X+1) * P
  1462. positiveTest(0x3a66a39b653f6889d)
  1463. positiveTest(0x170db3167dd9f782b9765214c03e71a18f685b7f3)
  1464. positiveTest(0x1751997d000000000000000000000000000000001)
  1465. positiveTest(0x800000000000000000000000000000000f128a2d1)
  1466. # Tests of non-detection.
  1467. negativeTest(0x1db711a41)
  1468. negativeTest(0x3a66a39b453f6889d)
  1469. negativeTest(0x170db3167dd9f782b9765214c03e71b18f685b7f3)
  1470. negativeTest(0x1751997d000000000000000000000001000000001)
  1471. negativeTest(0x800000000000002000000000000000000f128a2d1)
  1472. def testAuxEncryptFns(self):
  1473. # Test helper functions such as aes256_encrypt_pubkey. The
  1474. # test cases are all just things I made up at random, and the
  1475. # expected outputs are generated by running PuTTY's own code;
  1476. # this doesn't independently check them against any other
  1477. # implementation, but it at least means we're protected
  1478. # against code reorganisations changing the behaviour from
  1479. # what it was before.
  1480. p = b'three AES blocks, or six DES, of arbitrary input'
  1481. k = b'thirty-two-byte aes-256 test key'
  1482. iv = b'\0' * 16
  1483. c = unhex('7b112d00c0fc95bc13fcdacfd43281bf'
  1484. 'de9389db1bbcfde79d59a303d41fd2eb'
  1485. '0955c9477ae4ee3a4d6c1fbe474c0ef6')
  1486. self.assertEqualBin(aes256_encrypt_pubkey(k, iv, p), c)
  1487. self.assertEqualBin(aes256_decrypt_pubkey(k, iv, c), p)
  1488. # same k as in the previous case
  1489. iv = unhex('0102030405060708090a0b0c0d0e0f10')
  1490. c = unhex('9e9c8a91b739677b834397bdd8e70c05'
  1491. 'c3e2cf6cce68d376d798a59848621c6d'
  1492. '42b9e7101260a438daadd7b742875a36')
  1493. self.assertEqualBin(aes256_encrypt_pubkey(k, iv, p), c)
  1494. self.assertEqualBin(aes256_decrypt_pubkey(k, iv, c), p)
  1495. k = b'3des with keys distinct.'
  1496. iv = b'randomIV'
  1497. c = unhex('be81ff840d885869a54d63b03d7cd8db'
  1498. 'd39ab875e5f7b9da1081f8434cb33c47'
  1499. 'dee5bcd530a3f6c13a9fc73e321a843a')
  1500. self.assertEqualBin(des3_encrypt_pubkey_ossh(k, iv, p), c)
  1501. self.assertEqualBin(des3_decrypt_pubkey_ossh(k, iv, c), p)
  1502. k = b'3des, 2keys only'
  1503. c = unhex('0b845650d73f615cf16ee3ed20535b5c'
  1504. 'd2a8866ee628547bbdad916e2b4b9f19'
  1505. '67c15bde33c5b03ff7f403b4f8cf2364')
  1506. self.assertEqualBin(des3_encrypt_pubkey(k, p), c)
  1507. self.assertEqualBin(des3_decrypt_pubkey(k, c), p)
  1508. k = b'7 bytes'
  1509. c = unhex('5cac9999cffc980a1d1184d84b71c8cb'
  1510. '313d12a1d25a7831179aeb11edaca5ad'
  1511. '9482b224105a61c27137587620edcba8')
  1512. self.assertEqualBin(des_encrypt_xdmauth(k, p), c)
  1513. self.assertEqualBin(des_decrypt_xdmauth(k, c), p)
  1514. def testSSHCiphers(self):
  1515. # Test all the SSH ciphers we support, on the same principle
  1516. # as testAuxCryptFns that we should have test cases to verify
  1517. # that things still work the same today as they did yesterday.
  1518. p = b'64 bytes of test input data, enough to check any cipher mode xyz'
  1519. k = b'sixty-four bytes of test key data, enough to key any cipher pqrs'
  1520. iv = b'16 bytes of IV w'
  1521. ciphers = [
  1522. ("3des_ctr", 24, 8, False, unhex('83c17a29250d3d4fa81250fc0362c54e40456936445b77709a30fccf8b983d57129a969c59070d7c2977f3d25dd7d71163687c7b3cd2edb0d07514e6c77479f5')),
  1523. ("3des_ssh2", 24, 8, True, unhex('d5f1cc25b8fbc62decc74b432344de674f7249b2e38871f764411eaae17a1097396bd97b66a1e4d49f08c219acaef2a483198ce837f75cc1ef67b37c2432da3e')),
  1524. ("3des_ssh1", 24, 8, False, unhex('d5f1cc25b8fbc62de63590b9b92344adf6dd72753273ff0fb32d4dbc6af858529129f34242f3d557eed3a5c84204eb4f868474294964cf70df5d8f45dfccfc45')),
  1525. ("des_cbc", 8, 8, True, unhex('051524e77fb40e109d9fffeceacf0f28c940e2f8415ddccc117020bdd2612af5036490b12085d0e46129919b8e499f51cb82a4b341d7a1a1ea3e65201ef248f6')),
  1526. ("aes256_ctr", 32, 16, False, unhex('b87b35e819f60f0f398a37b05d7bcf0b04ad4ebe570bd08e8bfa8606bafb0db2cfcd82baf2ccceae5de1a3c1ae08a8b8fdd884fdc5092031ea8ce53333e62976')),
  1527. ("aes256_cbc", 32, 16, True, unhex('381cbb2fbcc48118d0094540242bd990dd6af5b9a9890edd013d5cad2d904f34b9261c623a452f32ea60e5402919a77165df12862742f1059f8c4a862f0827c5')),
  1528. ("aes192_ctr", 24, 16, False, unhex('06bcfa7ccf075d723e12b724695a571a0fad67c56287ea609c410ac12749c51bb96e27fa7e1c7ea3b14792bbbb8856efb0617ebec24a8e4a87340d820cf347b8')),
  1529. ("aes192_cbc", 24, 16, True, unhex('ac97f8698170f9c05341214bd7624d5d2efef8311596163dc597d9fe6c868971bd7557389974612cbf49ea4e7cc6cc302d4cc90519478dd88a4f09b530c141f3')),
  1530. ("aes128_ctr", 16, 16, False, unhex('0ad4ddfd2360ec59d77dcb9a981f92109437c68c5e7f02f92017d9f424f89ab7850473ac0e19274125e740f252c84ad1f6ad138b6020a03bdaba2f3a7378ce1e')),
  1531. ("aes128_cbc", 16, 16, True, unhex('36de36917fb7955a711c8b0bf149b29120a77524f393ae3490f4ce5b1d5ca2a0d7064ce3c38e267807438d12c0e40cd0d84134647f9f4a5b11804a0cc5070e62')),
  1532. ("blowfish_ctr", 32, 8, False, unhex('079daf0f859363ccf72e975764d709232ec48adc74f88ccd1f342683f0bfa89ca0e8dbfccc8d4d99005d6b61e9cc4e6eaa2fd2a8163271b94bf08ef212129f01')),
  1533. ("blowfish_ssh2", 16, 8, True, unhex('e986b7b01f17dfe80ee34cac81fa029b771ec0f859ae21ae3ec3df1674bc4ceb54a184c6c56c17dd2863c3e9c068e76fd9aef5673465995f0d648b0bb848017f')),
  1534. ("blowfish_ssh1", 32, 8, True, unhex('d44092a9035d895acf564ba0365d19570fbb4f125d5a4fd2a1812ee6c8a1911a51bb181fbf7d1a261253cab71ee19346eb477b3e7ecf1d95dd941e635c1a4fbf')),
  1535. ("arcfour256", 32, None, False, unhex('db68db4cd9bbc1d302cce5919ff3181659272f5d38753e464b3122fc69518793fe15dd0fbdd9cd742bd86c5e8a3ae126c17ecc420bd2d5204f1a24874d00fda3')),
  1536. ("arcfour128", 16, None, False, unhex('fd4af54c5642cb29629e50a15d22e4944e21ffba77d0543b27590eafffe3886686d1aefae0484afc9e67edc0e67eb176bbb5340af1919ea39adfe866d066dd05')),
  1537. ]
  1538. for algbase, keylen, ivlen, simple_cbc, c in ciphers:
  1539. for alg in get_implementations(algbase):
  1540. cipher = ssh_cipher_new(alg)
  1541. if cipher is None:
  1542. continue # hardware-accelerated cipher not available
  1543. ssh_cipher_setkey(cipher, k[:keylen])
  1544. if ivlen is not None:
  1545. ssh_cipher_setiv(cipher, iv[:ivlen])
  1546. self.assertEqualBin(ssh_cipher_encrypt(cipher, p), c)
  1547. ssh_cipher_setkey(cipher, k[:keylen])
  1548. if ivlen is not None:
  1549. ssh_cipher_setiv(cipher, iv[:ivlen])
  1550. self.assertEqualBin(ssh_cipher_decrypt(cipher, c), p)
  1551. if simple_cbc:
  1552. # CBC ciphers (other than the three-layered CBC used
  1553. # by SSH-1 3DES) have more specific semantics for
  1554. # their IV than 'some kind of starting state for the
  1555. # cipher mode': the IV is specifically supposed to
  1556. # represent the previous block of ciphertext. So we
  1557. # can check that, by supplying the IV _as_ a
  1558. # ciphertext block via a call to decrypt(), and seeing
  1559. # if that causes our test ciphertext to decrypt the
  1560. # same way as when we provided the same IV via
  1561. # setiv().
  1562. ssh_cipher_setkey(cipher, k[:keylen])
  1563. ssh_cipher_decrypt(cipher, iv[:ivlen])
  1564. self.assertEqualBin(ssh_cipher_decrypt(cipher, c), p)
  1565. def testChaCha20Poly1305(self):
  1566. # A test case of this cipher taken from a real connection to
  1567. # OpenSSH.
  1568. key = unhex('49e67c5ae596ea7f230e266538d0e373'
  1569. '177cc8fe08ff7b642c22d736ca975655'
  1570. 'c3fb639010fd297ca03c36b20a182ef4'
  1571. '0e1272f0c54251c175546ee00b150805')
  1572. len_p = unhex('00000128')
  1573. len_c = unhex('3ff3677b')
  1574. msg_p = unhex('0807000000020000000f736572766572'
  1575. '2d7369672d616c6773000000db737368'
  1576. '2d656432353531392c736b2d7373682d'
  1577. '65643235353139406f70656e7373682e'
  1578. '636f6d2c7373682d7273612c7273612d'
  1579. '736861322d3235362c7273612d736861'
  1580. '322d3531322c7373682d6473732c6563'
  1581. '6473612d736861322d6e697374703235'
  1582. '362c65636473612d736861322d6e6973'
  1583. '74703338342c65636473612d73686132'
  1584. '2d6e697374703532312c736b2d656364'
  1585. '73612d736861322d6e69737470323536'
  1586. '406f70656e7373682e636f6d2c776562'
  1587. '617574686e2d736b2d65636473612d73'
  1588. '6861322d6e69737470323536406f7065'
  1589. '6e7373682e636f6d0000001f7075626c'
  1590. '69636b65792d686f7374626f756e6440'
  1591. '6f70656e7373682e636f6d0000000130'
  1592. 'c34aaefcafae6fc2')
  1593. msg_c = unhex('bf587eabf385b1281fa9c755d8515dfd'
  1594. 'c40cb5e993b346e722dce48b1741b4e5'
  1595. 'ce9ae075f6df0a1d2f72f94f73570125'
  1596. '7011630bbb0c7febd767184c0d5aa810'
  1597. '47cbce82972129a234b8ac5fc5f2b5be'
  1598. '9264baca6d13ff3c9813a61e1f23468f'
  1599. '31964b60fc3f0888a227f02c737b2d27'
  1600. 'b7ae3cd60ede17533863a5bb6bb2d60a'
  1601. 'c998ccd27e8ba56259f676ed04749fad'
  1602. '4114678fb871add3a40625110637947c'
  1603. 'e91459811622fd3d1fa7eb7efad4b1e8'
  1604. '97f3e860473935d3d8df0679a8b0df85'
  1605. 'aa4124f2d9ac7207abd10719f465c9ed'
  1606. '859d2b03bde55315b9024f660ba8d63a'
  1607. '64e0beb81e532201df830a52cf221484'
  1608. '18d0c4c7da242346161d7320ac534cb5'
  1609. 'c6b6fec905ee5f424becb9f97c3afbc5'
  1610. '5ef4ba369e61bce847158f0dc5bd7227'
  1611. '3b8693642db36f87')
  1612. mac = unhex('09757178642dfc9f2c38ac5999e0fcfd')
  1613. seqno = 3
  1614. c = ssh_cipher_new('chacha20_poly1305')
  1615. m = ssh2_mac_new('poly1305', c)
  1616. c.setkey(key)
  1617. self.assertEqualBin(c.encrypt_length(len_p, seqno), len_c)
  1618. self.assertEqualBin(c.encrypt(msg_p), msg_c)
  1619. m.start()
  1620. m.update(ssh_uint32(seqno) + len_c + msg_c)
  1621. self.assertEqualBin(m.genresult(), mac)
  1622. self.assertEqualBin(c.decrypt_length(len_c, seqno), len_p)
  1623. self.assertEqualBin(c.decrypt(msg_c), msg_p)
  1624. def testRSAKex(self):
  1625. # Round-trip test of the RSA key exchange functions, plus a
  1626. # hardcoded plain/ciphertext pair to guard against the
  1627. # behaviour accidentally changing.
  1628. def blobs(n, e, d, p, q, iqmp):
  1629. # For RSA kex, the public blob is formatted exactly like
  1630. # any other SSH-2 RSA public key. But there's no private
  1631. # key blob format defined by the protocol, so for the
  1632. # purposes of making a test RSA private key, we borrow the
  1633. # function we already had that decodes one out of the wire
  1634. # format used in the SSH-1 agent protocol.
  1635. pubblob = ssh_string(b"ssh-rsa") + ssh2_mpint(e) + ssh2_mpint(n)
  1636. privblob = (ssh_uint32(nbits(n)) + ssh1_mpint(n) + ssh1_mpint(e) +
  1637. ssh1_mpint(d) + ssh1_mpint(iqmp) +
  1638. ssh1_mpint(q) + ssh1_mpint(p))
  1639. return pubblob, privblob
  1640. # Parameters for a test key.
  1641. p = 0xf49e4d21c1ec3d1c20dc8656cc29aadb2644a12c98ed6c81a6161839d20d398d
  1642. q = 0xa5f0bc464bf23c4c83cf17a2f396b15136fbe205c07cb3bb3bdb7ed357d1cd13
  1643. n = p*q
  1644. e = 37
  1645. d = int(mp_invert(e, (p-1)*(q-1)))
  1646. iqmp = int(mp_invert(q, p))
  1647. assert iqmp * q % p == 1
  1648. assert d * e % (p-1) == 1
  1649. assert d * e % (q-1) == 1
  1650. pubblob, privblob = blobs(n, e, d, p, q, iqmp)
  1651. pubkey = ssh_rsakex_newkey(pubblob)
  1652. privkey = get_rsa_ssh1_priv_agent(privblob)
  1653. plain = 0x123456789abcdef
  1654. hashalg = 'md5'
  1655. with queued_random_data(64, "rsakex encrypt test"):
  1656. cipher = ssh_rsakex_encrypt(pubkey, hashalg, ssh2_mpint(plain))
  1657. decoded = ssh_rsakex_decrypt(privkey, hashalg, cipher)
  1658. self.assertEqual(int(decoded), plain)
  1659. self.assertEqualBin(cipher, unhex(
  1660. '34277d1060dc0a434d98b4239de9cec59902a4a7d17a763587cdf8c25d57f51a'
  1661. '7964541892e7511798e61dd78429358f4d6a887a50d2c5ebccf0e04f48fc665c'
  1662. ))
  1663. def testMontgomeryKexLowOrderPoints(self):
  1664. # List of all the bad input values for Curve25519 which can
  1665. # end up generating a zero output key. You can find the first
  1666. # five (the ones in canonical representation, i.e. in
  1667. # [0,2^255-19)) by running
  1668. # find_montgomery_power2_order_x_values(curve25519.p, curve25519.a)
  1669. # and then encoding the results little-endian.
  1670. bad_keys_25519 = [
  1671. "0000000000000000000000000000000000000000000000000000000000000000",
  1672. "0100000000000000000000000000000000000000000000000000000000000000",
  1673. "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157",
  1674. "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800",
  1675. "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
  1676. # Input values less than 2^255 are reduced mod p, so those
  1677. # of the above values which are still in that range when
  1678. # you add 2^255-19 to them should also be caught.
  1679. "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
  1680. "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
  1681. # Input values are reduced mod 2^255 before reducing mod
  1682. # p. So setting the high-order bit of any of the above 7
  1683. # values should also lead to rejection, because it will be
  1684. # stripped off and then the value will be recognised as
  1685. # one of the above.
  1686. "0000000000000000000000000000000000000000000000000000000000000080",
  1687. "0100000000000000000000000000000000000000000000000000000000000080",
  1688. "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7",
  1689. "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880",
  1690. "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
  1691. "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
  1692. "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
  1693. ]
  1694. # Same for Curve448, found by the analogous eccref function call
  1695. # find_montgomery_power2_order_x_values(curve448.p, curve448.a)
  1696. bad_keys_448 = [
  1697. # The first three are the bad values in canonical
  1698. # representationm. In Curve448 these are just 0, 1 and -1.
  1699. '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  1700. '0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  1701. 'fefffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff',
  1702. # As with Curve25519, we must also include values in
  1703. # non-canonical representation that reduce to one of the
  1704. # above mod p.
  1705. 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffff',
  1706. '00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
  1707. # But that's all, because Curve448 fits neatly into a
  1708. # whole number of bytes, so there's no secondary reduction
  1709. # mod a power of 2.
  1710. ]
  1711. with random_prng("doesn't matter"):
  1712. ecdh25519 = ecdh_key_new('curve25519', False)
  1713. ecdh448 = ecdh_key_new('curve448', False)
  1714. for pub in bad_keys_25519:
  1715. key = ecdh_key_getkey(ecdh25519, unhex(pub))
  1716. self.assertEqual(key, None)
  1717. for pub in bad_keys_448:
  1718. key = ecdh_key_getkey(ecdh448, unhex(pub))
  1719. self.assertEqual(key, None)
  1720. def testPRNG(self):
  1721. hashalg = 'sha256'
  1722. seed = b"hello, world"
  1723. entropy = b'1234567890' * 100
  1724. # Replicate the generation of some random numbers. to ensure
  1725. # they really are the hashes of what they're supposed to be.
  1726. pr = prng_new(hashalg)
  1727. prng_seed_begin(pr)
  1728. prng_seed_update(pr, seed)
  1729. prng_seed_finish(pr)
  1730. data1 = prng_read(pr, 128)
  1731. data2 = prng_read(pr, 127) # a short read shouldn't confuse things
  1732. prng_add_entropy(pr, 0, entropy) # forces a reseed
  1733. data3 = prng_read(pr, 128)
  1734. le128 = lambda x: le_integer(x, 128)
  1735. key1 = hash_str(hashalg, b'R' + seed)
  1736. expected_data1 = b''.join(
  1737. hash_str(hashalg, key1 + b'G' + le128(counter))
  1738. for counter in range(4))
  1739. # After prng_read finishes, we expect the PRNG to have
  1740. # automatically reseeded itself, so that if its internal state
  1741. # is revealed then the previous output can't be reconstructed.
  1742. key2 = hash_str(hashalg, key1 + b'R')
  1743. expected_data2 = b''.join(
  1744. hash_str(hashalg, key2 + b'G' + le128(counter))
  1745. for counter in range(4,8))
  1746. # There will have been another reseed after the second
  1747. # prng_read, and then another due to the entropy.
  1748. key3 = hash_str(hashalg, key2 + b'R')
  1749. key4 = hash_str(hashalg, key3 + b'R' + hash_str(hashalg, entropy))
  1750. expected_data3 = b''.join(
  1751. hash_str(hashalg, key4 + b'G' + le128(counter))
  1752. for counter in range(8,12))
  1753. self.assertEqualBin(data1, expected_data1)
  1754. self.assertEqualBin(data2, expected_data2[:127])
  1755. self.assertEqualBin(data3, expected_data3)
  1756. def testHashPadding(self):
  1757. # A consistency test for hashes that use MD5/SHA-1/SHA-2 style
  1758. # padding of the message into a whole number of fixed-size
  1759. # blocks. We test-hash a message of every length up to twice
  1760. # the block length, to make sure there's no off-by-1 error in
  1761. # the code that decides how much padding to put on.
  1762. # Source: generated using Python hashlib as an independent
  1763. # implementation. The function below will do it, called with
  1764. # parameters such as (hashlib.sha256,128).
  1765. #
  1766. # def gen_testcase(hashclass, maxlen):
  1767. # return hashclass(b''.join(hashclass(text[:i]).digest()
  1768. # for i in range(maxlen))).hexdigest()
  1769. text = """
  1770. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
  1771. eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
  1772. minim veniam, quis nostrud exercitation ullamco laboris nisi ut
  1773. aliquip ex ea commodo consequat. Duis aute irure dolor in
  1774. reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
  1775. pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
  1776. culpa qui officia deserunt mollit anim id est laborum.
  1777. """.replace('\n', ' ').strip()
  1778. def test(hashname, maxlen, expected):
  1779. assert len(text) >= maxlen
  1780. buf = b''.join(hash_str(hashname, text[:i])
  1781. for i in range(maxlen))
  1782. self.assertEqualBin(hash_str(hashname, buf), unhex(expected))
  1783. test('md5', 128, '8169d766cc3b8df182b3ce756ae19a15')
  1784. test('sha1', 128, '3691759577deb3b70f427763a9c15acb9dfc0259')
  1785. test('sha256', 128, 'ec539c4d678412c86c13ee4eb9452232'
  1786. '35d4eed3368d876fdf10c9df27396640')
  1787. test('sha512', 256,
  1788. 'cb725b4b4ec0ac1174d69427b4d97848b7db4fc01181f99a8049a4d721862578'
  1789. 'f91e026778bb2d389a9dd88153405189e6ba438b213c5387284103d2267fd055'
  1790. )
  1791. def testDSA(self):
  1792. p = 0xe93618c54716992ffd54e79df6e1b0edd517f7bbe4a49d64631eb3efe8105f676e8146248cfb4f05720862533210f0c2ab0f9dd61dbc0e5195200c4ebd95364b
  1793. q = 0xf3533bcece2e164ca7c5ce64bc1e395e9a15bbdd
  1794. g = 0x5ac9d0401c27d7abfbc5c17cdc1dc43323cd0ef18b79e1909bdace6d17af675a10d37dde8bd8b70e72a8666592216ccb00614629c27e870e4fbf393b812a9f05
  1795. y = 0xac3ddeb22d65a5a2ded4a28418b2a748d8e5e544ba5e818c137d7b042ef356b0ef6d66cfca0b3ab5affa2969522e7b07bee60562fa4869829a5afce0ad0c4cd0
  1796. x = 0x664f8250b7f1a5093047fe0c7fe4b58e46b73295
  1797. pubblob = ssh_string(b"ssh-dss") + b"".join(map(ssh2_mpint, [p,q,g,y]))
  1798. privblob = ssh2_mpint(x)
  1799. pubkey = ssh_key_new_pub('dsa', pubblob)
  1800. privkey = ssh_key_new_priv('dsa', pubblob, privblob)
  1801. sig = ssh_key_sign(privkey, b"hello, world", 0)
  1802. self.assertTrue(ssh_key_verify(pubkey, sig, b"hello, world"))
  1803. self.assertFalse(ssh_key_verify(pubkey, sig, b"hello, again"))
  1804. badsig0 = unhex('{:040x}{:040x}'.format(1, 0))
  1805. badsigq = unhex('{:040x}{:040x}'.format(1, q))
  1806. self.assertFalse(ssh_key_verify(pubkey, badsig0, "hello, world"))
  1807. self.assertFalse(ssh_key_verify(pubkey, badsigq, "hello, world"))
  1808. self.assertFalse(ssh_key_verify(pubkey, badsig0, "hello, again"))
  1809. self.assertFalse(ssh_key_verify(pubkey, badsigq, "hello, again"))
  1810. def testRFC6979(self):
  1811. # The test case described in detail in RFC 6979 section A.1.
  1812. # We can't actually do the _signature_ for this, because it's
  1813. # based on ECDSA over a finite field of characteristic 2, and
  1814. # we only support prime-order fields. But we don't need to do
  1815. # full ECDSA, only generate the same deterministic nonce that
  1816. # the test case expects.
  1817. k = rfc6979('sha256',
  1818. 0x4000000000000000000020108A2E0CC0D99F8A5EF,
  1819. 0x09A4D6792295A7F730FC3F2B49CBC0F62E862272F, "sample")
  1820. self.assertEqual(int(k), 0x23AF4074C90A02B3FE61D286D5C87F425E6BDD81B)
  1821. # Selected test cases from the rest of Appendix A.
  1822. #
  1823. # We can only use test cases for which we have the appropriate
  1824. # hash function, so I've left out the test cases based on
  1825. # SHA-224. (We could easily implement that, but I don't think
  1826. # it's worth it just for adding further tests of this one
  1827. # function.) Similarly, I've omitted test cases relating to
  1828. # ECDSA curves we don't implement: P192, P224, and all the
  1829. # curves over power-of-2 finite fields.
  1830. #
  1831. # Where possible, we also test the actual signature algorithm,
  1832. # to make sure it delivers the same entire signature as the
  1833. # test case. This demonstrates that the rfc6979() function is
  1834. # being called in the right way and the results are being used
  1835. # as they should be. Here I've had to cut down the test cases
  1836. # even further, because the RFC specifies test cases with a
  1837. # cross product of DSA group and hash function, whereas we
  1838. # have a fixed hash (specified by SSH) for each signature
  1839. # algorithm. And the RFC is clear that you use the same hash
  1840. # for nonce generation and actual signing.
  1841. # A.2.1: 1024-bit DSA
  1842. q = 0x996F967F6C8E388D9E28D01E205FBA957A5698B1
  1843. x = 0x411602CB19A6CCC34494D79D98EF1E7ED5AF25F7
  1844. k = rfc6979('sha1', q, x, "sample")
  1845. self.assertEqual(int(k), 0x7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B)
  1846. k = rfc6979('sha256', q, x, "sample")
  1847. self.assertEqual(int(k), 0x519BA0546D0C39202A7D34D7DFA5E760B318BCFB)
  1848. k = rfc6979('sha384', q, x, "sample")
  1849. self.assertEqual(int(k), 0x95897CD7BBB944AA932DBC579C1C09EB6FCFC595)
  1850. k = rfc6979('sha512', q, x, "sample")
  1851. self.assertEqual(int(k), 0x09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B)
  1852. k = rfc6979('sha1', q, x, "test")
  1853. self.assertEqual(int(k), 0x5C842DF4F9E344EE09F056838B42C7A17F4A6433)
  1854. k = rfc6979('sha256', q, x, "test")
  1855. self.assertEqual(int(k), 0x5A67592E8128E03A417B0484410FB72C0B630E1A)
  1856. k = rfc6979('sha384', q, x, "test")
  1857. self.assertEqual(int(k), 0x220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89)
  1858. k = rfc6979('sha512', q, x, "test")
  1859. self.assertEqual(int(k), 0x65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C)
  1860. # The rest of the public key, for signature testing
  1861. p = 0x86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED8873ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779
  1862. g = 0x07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA417BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD
  1863. y = 0x5DF5E01DED31D0297E274E1691C192FE5868FEF9E19A84776454B100CF16F65392195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E682F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B
  1864. pubblob = ssh_string(b"ssh-dss") + b"".join(map(ssh2_mpint, [p,q,g,y]))
  1865. privblob = ssh2_mpint(x)
  1866. pubkey = ssh_key_new_pub('dsa', pubblob)
  1867. privkey = ssh_key_new_priv('dsa', pubblob, privblob)
  1868. sig = ssh_key_sign(privkey, b"sample", 0)
  1869. # Expected output using SHA-1 as the hash in nonce
  1870. # construction.
  1871. r = 0x2E1A0C2562B2912CAAF89186FB0F42001585DA55
  1872. s = 0x29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5
  1873. ref_sig = ssh_string(b"ssh-dss") + ssh_string(
  1874. be_integer(r, 160) + be_integer(s, 160))
  1875. self.assertEqual(sig, ref_sig)
  1876. # And the other test string.
  1877. sig = ssh_key_sign(privkey, b"test", 0)
  1878. r = 0x42AB2052FD43E123F0607F115052A67DCD9C5C77
  1879. s = 0x183916B0230D45B9931491D4C6B0BD2FB4AAF088
  1880. ref_sig = ssh_string(b"ssh-dss") + ssh_string(
  1881. be_integer(r, 160) + be_integer(s, 160))
  1882. self.assertEqual(sig, ref_sig)
  1883. # A.2.2: 2048-bit DSA
  1884. q = 0xF2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F
  1885. x = 0x69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC
  1886. k = rfc6979('sha1', q, x, "sample")
  1887. self.assertEqual(int(k), 0x888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E)
  1888. k = rfc6979('sha256', q, x, "sample")
  1889. self.assertEqual(int(k), 0x8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52)
  1890. k = rfc6979('sha384', q, x, "sample")
  1891. self.assertEqual(int(k), 0xC345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920)
  1892. k = rfc6979('sha512', q, x, "sample")
  1893. self.assertEqual(int(k), 0x5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC)
  1894. k = rfc6979('sha1', q, x, "test")
  1895. self.assertEqual(int(k), 0x6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F)
  1896. k = rfc6979('sha256', q, x, "test")
  1897. self.assertEqual(int(k), 0x1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7)
  1898. k = rfc6979('sha384', q, x, "test")
  1899. self.assertEqual(int(k), 0x206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C)
  1900. k = rfc6979('sha512', q, x, "test")
  1901. self.assertEqual(int(k), 0xAFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA)
  1902. # The rest of the public key, for signature testing
  1903. p = 0x9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44FFE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA153E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B
  1904. g = 0x5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C46A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7
  1905. y = 0x667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD949F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA611728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADECB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D123AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF
  1906. pubblob = ssh_string(b"ssh-dss") + b"".join(map(ssh2_mpint, [p,q,g,y]))
  1907. privblob = ssh2_mpint(x)
  1908. pubkey = ssh_key_new_pub('dsa', pubblob)
  1909. privkey = ssh_key_new_priv('dsa', pubblob, privblob)
  1910. sig = ssh_key_sign(privkey, b"sample", 0)
  1911. # Expected output using SHA-1 as the hash in nonce
  1912. # construction, which is how SSH does things. RFC6979 lists
  1913. # the following 256-bit values for r and s, but we end up only
  1914. # using the low 160 bits of each.
  1915. r = 0x3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A
  1916. s = 0xD26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF
  1917. ref_sig = ssh_string(b"ssh-dss") + ssh_string(
  1918. be_integer(r, 160) + be_integer(s, 160))
  1919. self.assertEqual(sig, ref_sig)
  1920. # And the other test string.
  1921. sig = ssh_key_sign(privkey, b"test", 0)
  1922. r = 0xC18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0
  1923. s = 0x414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA
  1924. ref_sig = ssh_string(b"ssh-dss") + ssh_string(
  1925. be_integer(r, 160) + be_integer(s, 160))
  1926. self.assertEqual(sig, ref_sig)
  1927. # A.2.5: ECDSA with NIST P256
  1928. q = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
  1929. x = 0xC9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721
  1930. k = rfc6979('sha1', q, x, "sample")
  1931. self.assertEqual(int(k), 0x882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4)
  1932. k = rfc6979('sha256', q, x, "sample")
  1933. self.assertEqual(int(k), 0xA6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60)
  1934. k = rfc6979('sha384', q, x, "sample")
  1935. self.assertEqual(int(k), 0x09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4)
  1936. k = rfc6979('sha512', q, x, "sample")
  1937. self.assertEqual(int(k), 0x5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5)
  1938. k = rfc6979('sha1', q, x, "test")
  1939. self.assertEqual(int(k), 0x8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E)
  1940. k = rfc6979('sha256', q, x, "test")
  1941. self.assertEqual(int(k), 0xD16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0)
  1942. k = rfc6979('sha384', q, x, "test")
  1943. self.assertEqual(int(k), 0x16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8)
  1944. k = rfc6979('sha512', q, x, "test")
  1945. self.assertEqual(int(k), 0x6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F)
  1946. # The public key, for signature testing
  1947. Ux = 0x60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6
  1948. Uy = 0x7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299
  1949. pubblob = ssh_string(b"ecdsa-sha2-nistp256") + ssh_string(b"nistp256") + ssh_string(b'\x04' + be_integer(Ux, 256) + be_integer(Uy, 256))
  1950. privblob = ssh2_mpint(x)
  1951. pubkey = ssh_key_new_pub('p256', pubblob)
  1952. privkey = ssh_key_new_priv('p256', pubblob, privblob)
  1953. sig = ssh_key_sign(privkey, b"sample", 0)
  1954. # Expected output using SHA-256
  1955. r = 0xEFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716
  1956. s = 0xF7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8
  1957. ref_sig = ssh_string(b"ecdsa-sha2-nistp256") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
  1958. self.assertEqual(sig, ref_sig)
  1959. # And the other test string
  1960. sig = ssh_key_sign(privkey, b"test", 0)
  1961. r = 0xF1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367
  1962. s = 0x019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083
  1963. ref_sig = ssh_string(b"ecdsa-sha2-nistp256") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
  1964. self.assertEqual(sig, ref_sig)
  1965. # A.2.5: ECDSA with NIST P384
  1966. q = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973
  1967. x = 0x6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5
  1968. k = rfc6979('sha1', q, x, "sample")
  1969. self.assertEqual(int(k), 0x4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB096630F29E5938D25106C3C340045A2DB01A7)
  1970. k = rfc6979('sha256', q, x, "sample")
  1971. self.assertEqual(int(k), 0x180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E375572342863C899F9F2EDF9747A9B60)
  1972. k = rfc6979('sha384', q, x, "sample")
  1973. self.assertEqual(int(k), 0x94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA2907E3E83BA95368623B8C4686915CF9)
  1974. k = rfc6979('sha512', q, x, "sample")
  1975. self.assertEqual(int(k), 0x92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331A4E966532593A52980D0E3AAA5E10EC3)
  1976. k = rfc6979('sha1', q, x, "test")
  1977. self.assertEqual(int(k), 0x66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47EC3727F3A3C186C15054492E30698497)
  1978. k = rfc6979('sha256', q, x, "test")
  1979. self.assertEqual(int(k), 0x0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FAA48DD070BA79921A3457ABFF2D630AD7)
  1980. k = rfc6979('sha384', q, x, "test")
  1981. self.assertEqual(int(k), 0x015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092ADA71F4A459BC0DA98ADB95837DB8312EA)
  1982. k = rfc6979('sha512', q, x, "test")
  1983. self.assertEqual(int(k), 0x3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE0E2CC8A136036DC4B9C00E6888F66B6C)
  1984. # The public key, for signature testing
  1985. Ux = 0xEC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64DEF8F0EA9055866064A254515480BC13
  1986. Uy = 0x8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1288B231C3AE0D4FE7344FD2533264720
  1987. pubblob = ssh_string(b"ecdsa-sha2-nistp384") + ssh_string(b"nistp384") + ssh_string(b'\x04' + be_integer(Ux, 384) + be_integer(Uy, 384))
  1988. privblob = ssh2_mpint(x)
  1989. pubkey = ssh_key_new_pub('p384', pubblob)
  1990. privkey = ssh_key_new_priv('p384', pubblob, privblob)
  1991. sig = ssh_key_sign(privkey, b"sample", 0)
  1992. # Expected output using SHA-384
  1993. r = 0x94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46
  1994. s = 0x99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8
  1995. ref_sig = ssh_string(b"ecdsa-sha2-nistp384") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
  1996. self.assertEqual(sig, ref_sig)
  1997. # And the other test string
  1998. sig = ssh_key_sign(privkey, b"test", 0)
  1999. r = 0x8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB
  2000. s = 0xDDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5
  2001. ref_sig = ssh_string(b"ecdsa-sha2-nistp384") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
  2002. self.assertEqual(sig, ref_sig)
  2003. # A.2.6: ECDSA with NIST P521
  2004. q = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409
  2005. x = 0x0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538
  2006. k = rfc6979('sha1', q, x, "sample")
  2007. self.assertEqual(int(k), 0x089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9)
  2008. k = rfc6979('sha256', q, x, "sample")
  2009. self.assertEqual(int(k), 0x0EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0)
  2010. k = rfc6979('sha384', q, x, "sample")
  2011. self.assertEqual(int(k), 0x1546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FFAD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4211)
  2012. k = rfc6979('sha512', q, x, "sample")
  2013. self.assertEqual(int(k), 0x1DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F10198B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBFFD3)
  2014. k = rfc6979('sha1', q, x, "test")
  2015. self.assertEqual(int(k), 0x0BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DDBA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B222)
  2016. k = rfc6979('sha256', q, x, "test")
  2017. self.assertEqual(int(k), 0x01DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E843841AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909258)
  2018. k = rfc6979('sha384', q, x, "test")
  2019. self.assertEqual(int(k), 0x1F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5DCEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0C88)
  2020. k = rfc6979('sha512', q, x, "test")
  2021. self.assertEqual(int(k), 0x16200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D)
  2022. # The public key, for signature testing
  2023. Ux = 0x1894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F5023A4
  2024. Uy = 0x0493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFDFCF5
  2025. pubblob = ssh_string(b"ecdsa-sha2-nistp521") + ssh_string(b"nistp521") + ssh_string(b'\x04' + be_integer(Ux, 528) + be_integer(Uy, 528))
  2026. privblob = ssh2_mpint(x)
  2027. pubkey = ssh_key_new_pub('p521', pubblob)
  2028. privkey = ssh_key_new_priv('p521', pubblob, privblob)
  2029. sig = ssh_key_sign(privkey, b"sample", 0)
  2030. # Expected output using SHA-512
  2031. r = 0x0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA
  2032. s = 0x0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A
  2033. ref_sig = ssh_string(b"ecdsa-sha2-nistp521") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
  2034. self.assertEqual(sig, ref_sig)
  2035. # And the other test string
  2036. sig = ssh_key_sign(privkey, b"test", 0)
  2037. r = 0x13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D
  2038. s = 0x1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3
  2039. ref_sig = ssh_string(b"ecdsa-sha2-nistp521") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
  2040. self.assertEqual(sig, ref_sig)
  2041. def testBLAKE2b(self):
  2042. # The standard test vectors for BLAKE2b (in the separate class
  2043. # below) don't satisfy me because they only test one hash
  2044. # size. These additional tests exercise BLAKE2b's configurable
  2045. # output length. The expected results are derived from the
  2046. # BLAKE2 reference implementation.
  2047. def b2_with_len(data, length):
  2048. h = blake2b_new_general(length)
  2049. h.update(data)
  2050. return h.digest()[:length]
  2051. self.assertEqualBin(b2_with_len(b'hello', 1), unhex("29"))
  2052. self.assertEqualBin(b2_with_len(b'hello', 2), unhex("accd"))
  2053. self.assertEqualBin(b2_with_len(b'hello', 3), unhex("980032"))
  2054. self.assertEqualBin(b2_with_len(b'hello', 5), unhex("9baecc38f2"))
  2055. self.assertEqualBin(b2_with_len(b'hello', 8), unhex(
  2056. "a7b6eda801e5347d"))
  2057. self.assertEqualBin(b2_with_len(b'hello', 13), unhex(
  2058. "6eedb122c6707328a66aa34a07"))
  2059. self.assertEqualBin(b2_with_len(b'hello', 21), unhex(
  2060. "c7f0f74a227116547b3d2788e927ee2a76c87d8797"))
  2061. self.assertEqualBin(b2_with_len(b'hello', 34), unhex(
  2062. "2f5fcdf2b870fa254051dd448193a1fb6e92be122efca539ba2aeac0bc6c77d0"
  2063. "dadc"))
  2064. self.assertEqualBin(b2_with_len(b'hello', 55), unhex(
  2065. "daafcf2bd6fccf976cbc234b71cd9f4f7d56fe0eb33a40018707089a215c44a8"
  2066. "4b272d0329ae6d85a0f8acc7e964dc2facb715ba472bb6"))
  2067. def testArgon2LongHash(self):
  2068. # Unit-test the Argon2 long hash function H', which starts off
  2069. # the same as BLAKE2b, but comes with its own method of
  2070. # extending the output length past 64 bytes.
  2071. #
  2072. # I generated these test values using a test program linked
  2073. # against the reference implementation's libargon2.a and
  2074. # calling its blake2b_long function.
  2075. preimage = b'hello, world'
  2076. self.assertEqualBin(argon2_long_hash(1, preimage), unhex("8b"))
  2077. self.assertEqualBin(argon2_long_hash(2, preimage), unhex("1ff9"))
  2078. self.assertEqualBin(argon2_long_hash(63, preimage), unhex(
  2079. "e2c997721f1d64aa8c25e588fb8ab19646ce6d5c2a431fa560fcb813e55dd481"
  2080. "322d2630d95ca6b1b63317b13d6b111e5816170c80c3ca7d5b4bf894096de4"))
  2081. self.assertEqualBin(argon2_long_hash(64, preimage), unhex(
  2082. "0c7ba7ee6d510b4bb5c9b69ac91e25e0b11aa30dd6234b8e61b0fe1537c037b8"
  2083. "8ed5aa59a277e8cc07095c81aff26d08967e4dfdabd32db8b6af6ceb78cf8c47"))
  2084. self.assertEqualBin(argon2_long_hash(65, preimage), unhex(
  2085. "680941abbd8fc80f28c38d623e90903f08709bf76575e2775d4ce01c31b192c8"
  2086. "73038d9a31af8991c8b1ad4f2b1991f4d15f73ab0f4f3add415c297a12eb9ddb"
  2087. "76"))
  2088. self.assertEqualBin(argon2_long_hash(95, preimage), unhex(
  2089. "4be28c51850fed70d9403e1406b6ba68a83d98cf222a4ee162beef60fd3384df"
  2090. "eba3fce9d95f646982eb384ac943ce5263cb03428fd8d261cc41ffdb7ba328fe"
  2091. "098526f2b49593f9e7f38188598ce4693b59f4dd32db30c1be9a9d35784fa0"))
  2092. self.assertEqualBin(argon2_long_hash(96, preimage), unhex(
  2093. "20295ea01e822cca113f668f33e5e481ed5879bfd7de6359ea42d497da97be52"
  2094. "2cdd518d34ae32c44cabd45249b4e697626b0b14b6a33a2bd138be0a4bceeaf4"
  2095. "9528f93acef01b093ee84d8d871d1ee6cf7c10e83ad0619631aed19345166f03"))
  2096. self.assertEqualBin(argon2_long_hash(97, preimage), unhex(
  2097. "d24b31f3ac0baad168d524efc4bafee55fef743fd60b14e28b860d7523e319c7"
  2098. "520e2d5457cc3d06dc1044530afdf6990fa12e38d5802eb642f8e77fcfee2c0b"
  2099. "1f84a28877f2f2f049ed9299e1e0230f98af3a161185970aad21f0ea0f5184cf"
  2100. "90"))
  2101. self.assertEqualBin(argon2_long_hash(127, preimage), unhex(
  2102. "5d1e8380450dbc985418ed1f3700b925ae0719e4486e29131c81bca7083ac6b8"
  2103. "f535c3398488e34d3dc1390de44097f1eee498f10ebe85b579e99a7672023b01"
  2104. "ca5c20e63c595b640e00d80f113a52e3773719889b266ab4c65269c11fb212e4"
  2105. "75f2b769bb26321bb60ecc0d490821e5056d7dfc9def3cd065d3ba90360764"))
  2106. self.assertEqualBin(argon2_long_hash(128, preimage), unhex(
  2107. "be15b316f3483c4d0d00f71a65b974894a2025f441b79b9fe461bc740cb0b039"
  2108. "c4fe914f61c05a612d63ebc50a662b2d59b1996091e5e3474340544ea46a46cb"
  2109. "25c41ff700fafcd96c4f12ddc698cd2426558f960696837ea8170fd2fe284b54"
  2110. "8f585f97919ef14f2b3cbb351eb98872add7ba6d08c1401232df6cc878fbeb22"))
  2111. self.assertEqualBin(argon2_long_hash(129, preimage), unhex(
  2112. "83da464c278dcb12c29b6685fee6d32f0b461337c155369ad0d56b58b0aa5f80"
  2113. "9aa7b56bd41b664c8d768957f8f0e40999fb0178eb53cf83f31d725bf92881bc"
  2114. "900774bce4cdf56b6386ad3de6891d11a0ccd4564a3431fc4c24105a02d0a6a2"
  2115. "434712b9a7471f3223c72a6e64912200d0a3d149a19d06fe9dc8ec09d7ed5a48"
  2116. "bb"))
  2117. self.assertEqualBin(argon2_long_hash(511, preimage), unhex(
  2118. "30c0c0d0467e7665368db0b40a2324a61fb569d35172de2df53a9739a8d18e60"
  2119. "b4f25d521c8855604be3e24ea56302566074323d94c0bd3a33d08f185d8ba5ac"
  2120. "a2bc3fb2e4c4e5ffec5778daea67c6b5913c9cac16f2e5c7b7818e757fa747b3"
  2121. "69e586d616010a752762f69c604238ed8738430366fbdb7493454fa02391a76b"
  2122. "30f241695b9fa8d3a3116227c6bb6f72d325cf104ab153d15f928b22767d467d"
  2123. "4bf7e16176aaa7315954b7872061933c12d548f1f93a8abb9d73791661bee521"
  2124. "b2ae51be373a229dfef32787234c1be5846d133563002b9a029178716ad41e70"
  2125. "1539d3fad300c77607c5217701e3e485d72c980f3f71d525c8148375a2f8d22c"
  2126. "a211ba165330a90b7e0e6baa6073833925c23bdd388ee904f38463c7e6b85475"
  2127. "09b810aae5c9ffc5dd902c2ffe049c338e3ae2c6416d3b874d6a9d384089564c"
  2128. "0d8e4dce9b6e47e1d5ec9087bf526cc9fa35aab1893a0588d31b77fea37e0799"
  2129. "468deacde47629d2960a3519b3bcd4e22364a9cccd3b128cba21cac27f140d53"
  2130. "f79c11e4157e4cb48272eecdf62f52084a27e5b0933bbe66ded17e2df6f8d398"
  2131. "f6c479c3c716457820ad177b8bd9334cb594e03d09fcc4f82d4385e141eacd7d"
  2132. "9ad1e1c4cb42788af70bac0509f0a891e662960955490abf2763373803e8c89c"
  2133. "df632579cb9c647634b30df214a3d67b92fd55d283c42c63b470a48a78cd5b"))
  2134. self.assertEqualBin(argon2_long_hash(512, preimage), unhex(
  2135. "79a6974e29a9a6c069e0156774d35c5014a409f5ffc60013725367a7208d4929"
  2136. "7d228637751768a31a59e27aa89372f1bcc095a6fa331198a5bd5ad053ba2ebb"
  2137. "cbcc501ea55cf142e8d95209228c9ab60cd104d5077472f2a9ecaa071aed6ee9"
  2138. "5de29e188b7399d5b6b7ed897b2bc4dd1ea745eb9974e39ca6fb983380cc537a"
  2139. "c04dfe6caefe85faf206b1613092ebadf791eaa8a5b814c9a79a73a5733b0505"
  2140. "a47163c10a0f7309df6663896df6079a7c88c6879bb591a40abd398c6deda792"
  2141. "1cc3986435b1c840a768b2fa507446f2f77a406b1b2f739f7795db24789c8927"
  2142. "24b4c84b7005445123154f8cd2ba63a7ede672af5d197f846700732025c9931d"
  2143. "1c67c5493417ca394a8f68ba532645815cf7b5102af134ecb4fd9e326f53779a"
  2144. "3039dbef6a0880db9e38b6b61d2f9ead969e4224c2d9c69b5897e5eeb7032e83"
  2145. "334e192ff50017056ccb84d4cc8eee3ab248d2614643d0174fe18c72186dd967"
  2146. "92d8545645ddf4a9b2c7a91c9a71857a399449d7154077a8e9580f1a2d20227d"
  2147. "671b455ccb897cba0491e50892120d7877f7776d653cfdb176fa3f64a9e6f848"
  2148. "cd681c487b488775aaf698294eec813b2cca90d68d63b5d886d61c1a8e922aaa"
  2149. "330fd658ede56e34bcd288048e845eba7b8e2e7cc22ba6c91b523e48017aa878"
  2150. "8ce4f91d0e6d6c6706762fb0cc7f465cee3916684fb21e337cfe1b583e0b1e92"))
  2151. self.assertEqualBin(argon2_long_hash(513, preimage), unhex(
  2152. "32243cfbd7eca582d60b3b8ea3ba3d93783537689c7cbcd1d1cbde46200b8c86"
  2153. "617fc00e8a9ae991a1e2f91c67e07d5f0a777d982c1461d0c5474e4e164b053c"
  2154. "2808559e2b8a5ac4a46a5fcbc825b1d5302c7b0611940194eb494d45ce7113a2"
  2155. "3424b51c199c6a5100ab159ff323eda5feffee4da4155a028a81da9d44e4286b"
  2156. "ac3dab4ffce43a80b6ce97a47ea0ac51ee16e8b4d3b68942afdc20e1c21747c4"
  2157. "94859c3d3883e7dc19ea416a393a3507683d9d03e6a3a91f8f1cb8a7d5d9892e"
  2158. "80c8fb0222527a73a1f59b9dd41770982f2af177a6e96093064534803edd0713"
  2159. "71ede53024cedc291d768325bb4e4def9af1b5569c349b64816496c37a8787b5"
  2160. "4fbe248372ebadb5ce20e03eaa935dc55ff4b8cbe5d6d844c7b71d4656fef22c"
  2161. "5a49f13d75a7a8368a2dbc1e78d732b879bfc5c9467eda2bf4918f0c59037ae3"
  2162. "dee7880a171409dd1a4e143c814e60301ac77237f261fa7519a04e68000530f9"
  2163. "708ed9fda5609d655560a9491f80f5875ad5725e3120686b73319c6a727932e3"
  2164. "20a2174422523498c38fea47aeb20d135ff9fd93c6fa6db0005e0001685d7577"
  2165. "33a82a4dc9dd6556b938f7b8dafd0d670846780b9931b815063708189b17877b"
  2166. "825533bcc250fb576a28be4caa107e6a3a6f7b0c60fb51b0def27008b7e272ac"
  2167. "95d610bfa912339799a2e537ce543d7862dddbe31bb224fda4ae283571847a28"
  2168. "54"))
  2169. self.assertEqualBin(argon2_long_hash(1024, preimage), unhex(
  2170. "951252f6fa152124f381266a358d9b78b88e469d08d5fc78e4ea32253c7fc26c"
  2171. "3ff1c93529ab4ee6fcf00acf29bbaba934a4014ce2625e0806601c55e6ce70d7"
  2172. "121fd82f0904f335c5c7ba07dc6e6adf7582c92f7f255072203ea85844b4fe54"
  2173. "817476a20bb742710ffc42750361be94332d0fc721b192309acfa70da43db6ae"
  2174. "1d0f0bbe8a3250966a4532b36728162073c9eb3e119ea4c1c187c775dbb25a5d"
  2175. "d883e3f65706a5fca897cdc4a8aa7b68ba3f57940c72f3a3396c417e758ba071"
  2176. "95be4afba325237c0e2738a74d96fd1350fb623cb2ad40ea8b1e070cf398b98c"
  2177. "2865ea40225b81f031f2b405409ca01dc5d9903d3d8e1d6381fbe7ccfc8f3dab"
  2178. "eadafd7c976c0ba84a936f78ff7df0f112c089ba88f82bed7f9a6e31a91e5fee"
  2179. "f675755454b948de22695660b243b9eca3bcc89608f83d2baa1d73dd6b8bd4f9"
  2180. "b995ed9cb0f1edc6e98a49ed841b506c1bf59b43f4b3457a376bbff116c1a4f6"
  2181. "07cc62381fc5c19953c68f300c1b51198d40784d812d25810ba404862f04b680"
  2182. "6039a074f612ad8b84e0941ba23c915c3e7162c225fbecffdb7dc1ab559b2b54"
  2183. "32fe8a498c32e918d8e7e33254ff75077f648827705e987f4d90fba971e78e1a"
  2184. "6896b4d775c7359dc950f1e964fa04621aacf3c0988969490f4c72c54caf79e8"
  2185. "481053cc0a27ffcd3580aabf9ef1268d498d8a18bd70e9b8402e011753bb7dc7"
  2186. "e856c00d988fca924ee7cf61979c38cda8a872e4cc4fbdc90c23a0ded71eb944"
  2187. "bb816ab22d9a4380e3e9d1cec818165c2fba6c5d51dcbf452c0cb1779a384937"
  2188. "64d695370e13a301eca7be68d4112d2177381514efbb36fe08fc5bc2970301b8"
  2189. "06f8e5a57a780e894d5276e2025bb775b6d1861e33c54ab6e3eb72947fbe6f91"
  2190. "8174ce24eb4682efbb3c4f01233dc7ce9ef44792e9e876bb03e6751b3d559047"
  2191. "d045127d976aa042fc55c690c9048e200065e7b7de19d9353aa9ac9b3e7611f0"
  2192. "d1c42d069a300455ca1f7420a352bace89215e705106927510c11b3b1c1486d9"
  2193. "f3ab006d2de2ee2c94574f760ce8c246bca229f98c66f06042b14f1fff9a16c0"
  2194. "1550237e16d108ce5597299b1eb406a9ee505a29a6e0fa526b3e6beafd336aea"
  2195. "138b2f31971586f67c5ffffbd6826d1c75666038c43d0bdff4edfc294e064a49"
  2196. "2eed43e2dc78d00abc4e85edcd9563b8251b66f57b0f4b6d17f5a3f35c87c488"
  2197. "dbeeb84fd720286197c2dec8290eccf3a313747de285b9cd3548e90cf81b3838"
  2198. "3ffcc8c2a7f582feb369d05cb96b9b224d05902b3e39e5b96536032e9dddeb9b"
  2199. "9d4f40a9c8f544ca37cf8d39d7c8c6a33880e9184ed017bd642db9590759bd10"
  2200. "7362048ede5c0257feecc4984584592c566f37fba8469c064015339fb4f03023"
  2201. "56ece37fd3655aae2bfc989b9b4c1384efc3503c8866db901802cb36eda9fb00"))
  2202. def testArgon2(self):
  2203. # A few tests of my own of Argon2, derived from the reference
  2204. # implementation.
  2205. pwd = b"password"
  2206. salt = b"salt of at least 16 bytes"
  2207. secret = b"secret"
  2208. assoc = b"associated data"
  2209. # Smallest memory (8Kbyte) and parallelism (1) parameters the
  2210. # reference implementation will accept, but lots of passes
  2211. self.assertEqualBin(
  2212. argon2('i', 8, 16, 1, 24, pwd, salt, secret, assoc), unhex(
  2213. "314da280240a3ca1eedd1f1db417a76eb0741e7df64b8cdf"))
  2214. self.assertEqualBin(
  2215. argon2('d', 8, 16, 1, 24, pwd, salt, secret, assoc), unhex(
  2216. "9cc961cf43e0f86c2d4e202b816dc5bc5b2177e68faa0b08"))
  2217. self.assertEqualBin(
  2218. argon2('id', 8, 16, 1, 24, pwd, salt, secret, assoc), unhex(
  2219. "6cd6c490c582fa597721d772d4e3de166987792491b48c51"))
  2220. # Test a memory cost value that isn't a power of 2. This
  2221. # checks a wraparound case during the conversion of J1 to a
  2222. # block index, and is a regression test for a bug that nearly
  2223. # got past me during original development.
  2224. self.assertEqualBin(
  2225. argon2('i', 104, 16, 2, 24, pwd, salt, secret, assoc), unhex(
  2226. "a561963623f1073c9aa8caecdb600c73ffc6de677ba8d97c"))
  2227. self.assertEqualBin(
  2228. argon2('d', 104, 16, 2, 24, pwd, salt, secret, assoc), unhex(
  2229. "a9014db7f1d468fb25b88fa7fc0deac0f2e7f27e25d2cf6e"))
  2230. self.assertEqualBin(
  2231. argon2('id', 104, 16, 2, 24, pwd, salt, secret, assoc), unhex(
  2232. "64f3212b1e7725ffcf9ae2d1753d63e763bcd6970061a435"))
  2233. # Larger parameters that should exercise the pseudorandom
  2234. # block indexing reasonably thoroughly. Also generate plenty
  2235. # of output data.
  2236. self.assertEqualBin(
  2237. argon2('i', 1024, 5, 16, 77, pwd, salt, secret, assoc), unhex(
  2238. "b008a685ff57730fad0e6f3ef3b9189282c0d9b05303675f43b5f3054724"
  2239. "733fcbe8e2639cc2c930535b31b723339041bcd703bf2483455acf86c0e6"
  2240. "9ed88c545ad40f1f2068855e4d61e99407"))
  2241. self.assertEqualBin(
  2242. argon2('d', 1024, 5, 16, 111, pwd, salt, secret, assoc), unhex(
  2243. "399ffbcd720c47745b9deb391ed0de7d5e0ffe53aef9f8ef7a7918cfa212"
  2244. "53df8cc577affbd5e0c0f8bf6d93c11b2f63973f8fc8f89dccd832fc587e"
  2245. "5d61717be6e88ca33eef5d1e168c028bae632a2a723c6c83f8e755f39171"
  2246. "5eda1c77c8e2fe06fbdd4e56d35262587e7df73cd7"))
  2247. self.assertEqualBin(
  2248. argon2('id', 1024, 5, 16, 123, pwd, salt, secret, assoc), unhex(
  2249. "6636807289cb9b9c032f48dcc31ffed1de4ca6c1b97e1ce768d690486341"
  2250. "2ac84b39d568a81dd01d9ee3ceec6cc23441d95e6abeb4a2024f1f540d56"
  2251. "9b799277c4037ddc7195ba783c9158a901adc7d4a5df8357b34a3869e5d6"
  2252. "aeae2a21201eef5e347de22c922192e8f46274b0c9d33e965155a91e7686"
  2253. "9d530e"))
  2254. def testOpenSSHBcrypt(self):
  2255. # Test case created by making an OpenSSH private key file
  2256. # using their own ssh-keygen, then decrypting it successfully
  2257. # using PuTTYgen and printing the inputs and outputs to
  2258. # openssh_bcrypt in the process. So this output key is known
  2259. # to agree with OpenSSH's own answer.
  2260. self.assertEqualBin(
  2261. openssh_bcrypt('test passphrase',
  2262. unhex('d0c3b40ace4afeaf8c0f81202ae36718'),
  2263. 16, 48),
  2264. unhex('d78ba86e7273de0e007ab0ba256646823d5c902bc44293ae'
  2265. '78547e9a7f629be928cc78ff78a75a4feb7aa6f125079c7d'))
  2266. def testRSAVerify(self):
  2267. def blobs(n, e, d, p, q, iqmp):
  2268. pubblob = ssh_string(b"ssh-rsa") + ssh2_mpint(e) + ssh2_mpint(n)
  2269. privblob = (ssh2_mpint(d) + ssh2_mpint(p) +
  2270. ssh2_mpint(q) + ssh2_mpint(iqmp))
  2271. return pubblob, privblob
  2272. def failure_test(*args):
  2273. pubblob, privblob = blobs(*args)
  2274. key = ssh_key_new_priv('rsa', pubblob, privblob)
  2275. self.assertEqual(key, None)
  2276. def success_test(*args):
  2277. pubblob, privblob = blobs(*args)
  2278. key = ssh_key_new_priv('rsa', pubblob, privblob)
  2279. self.assertNotEqual(key, None)
  2280. # Parameters for a (trivially small) test key.
  2281. n = 0xb5d545a2f6423eabd55ffede53e21628d5d4491541482e10676d9d6f2783b9a5
  2282. e = 0x25
  2283. d = 0x6733db6a546ac99fcc21ba2b28b0c077156e8a705976205a955c6d9cef98f419
  2284. p = 0xe30ebd7348bf10dca72b36f2724dafa7
  2285. q = 0xcd02c87a7f7c08c4e9dc80c9b9bad5d3
  2286. iqmp = 0x60a129b30db9227910efe1608976c513
  2287. # Check the test key makes sense unmodified.
  2288. success_test(n, e, d, p, q, iqmp)
  2289. # Try modifying the values one by one to ensure they are
  2290. # rejected, except iqmp, which sshrsa.c regenerates anyway so
  2291. # it won't matter at all.
  2292. failure_test(n+1, e, d, p, q, iqmp)
  2293. failure_test(n, e+1, d, p, q, iqmp)
  2294. failure_test(n, e, d+1, p, q, iqmp)
  2295. failure_test(n, e, d, p+1, q, iqmp)
  2296. failure_test(n, e, d, p, q+1, iqmp)
  2297. success_test(n, e, d, p, q, iqmp+1)
  2298. # The key should also be accepted with p,q reversed. (Again,
  2299. # iqmp gets regenerated, so it won't matter if that's wrong.)
  2300. success_test(n, e, d, q, p, iqmp)
  2301. # Replace each of p and q with 0, and with 1. These should
  2302. # still fail validation (obviously), but the point is that the
  2303. # validator should also avoid trying to divide by zero in the
  2304. # process.
  2305. failure_test(n, e, d, 0, q, iqmp)
  2306. failure_test(n, e, d, p, 0, iqmp)
  2307. failure_test(n, e, d, 1, q, iqmp)
  2308. failure_test(n, e, d, p, 1, iqmp)
  2309. def testKeyMethods(self):
  2310. # Exercise all the methods of the ssh_key trait on all key
  2311. # types, and ensure that they're consistent with each other.
  2312. # No particular test is done on the rightness of the
  2313. # signatures by any objective standard, only that the output
  2314. # from our signing method can be verified by the corresponding
  2315. # verification method.
  2316. #
  2317. # However, we do include the expected signature text in each
  2318. # case, which checks determinism in the sense of being
  2319. # independent of any random numbers, and also in the sense of
  2320. # tomorrow's change to the code not having accidentally
  2321. # changed the behaviour.
  2322. test_message = b"Message to be signed by crypt.testKeyMethods\n"
  2323. test_keys = [
  2324. ('ed25519', 'AAAAC3NzaC1lZDI1NTE5AAAAIM7jupzef6CD0ps2JYxJp9IlwY49oorOseV5z5JFDFKn', 'AAAAIAf4/WRtypofgdNF2vbZOUFE1h4hvjw4tkGJZyOzI7c3', 255, b'0xf4d6e7f6f4479c23f0764ef43cea1711dbfe02aa2b5a32ff925c7c1fbf0f0db,0x27520c4592cf79e5b1ce8aa23d8ec125d2a7498c25369bd283a07fde9cbae3ce', [(0, 'AAAAC3NzaC1lZDI1NTE5AAAAQN73EqfyA4WneqDhgZ98TlRj9V5Wg8zCrMxTLJN1UtyfAnPUJDtfG/U0vOsP8PrnQxd41DDDnxrAXuqJz8rOagc=')]),
  2325. ('ed448', 'AAAACXNzaC1lZDQ0OAAAADnRI0CQDym5IqUidLNDcSdHe54bYEwqjpjBlab8uKGoe6FRqqejha7+5U/VAHy7BmE23+ju26O9XgA=', 'AAAAObP9klqyiJSJsdFJf+xwZQdkbZGUqXE07K6e5plfRTGjYYkyWJFUNFH4jzIn9xH1TX9z9EGycPaXAA==', 448, b'0x4bf4a2b6586c60d8cdb52c2b45b897f6d2224bc37987489c0d70febb449e8c82964ed5785827be808e44d31dd31e6ff7c99f43e49f419928,0x5ebda3dbeee8df366106bb7c00d54fe5feae85a3a7aa51a17ba8a1b8fca695c1988e2a4c601b9e7b47277143b37422a522b9290f904023d1', [(0, 'AAAACXNzaC1lZDQ0OAAAAHLkSVioGMvLesZp3Tn+Z/sSK0Hl7RHsHP4q9flLzTpZG5h6JDH3VmZBEjTJ6iOLaa0v4FoNt0ng4wAB53WrlQC4h3iAusoGXnPMAKJLmqzplKOCi8HKXk8Xl8fsXbaoyhatv1OZpwJcffmh1x+x+LSgNQA=')]),
  2326. ('p256', 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHkYQ0sQoq5LbJI1VMWhw3bV43TSYi3WVpqIgKcBKK91TcFFlAMZgceOHQ0xAFYcSczIttLvFu+xkcLXrRd4N7Q=', 'AAAAIQCV/1VqiCsHZm/n+bq7lHEHlyy7KFgZBEbzqYaWtbx48Q==', 256, b'nistp256,0x7918434b10a2ae4b6c923554c5a1c376d5e374d2622dd6569a8880a70128af75,0x4dc14594031981c78e1d0d3100561c49ccc8b6d2ef16efb191c2d7ad177837b4', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABIAAAAIFrd1bjr4GHfWsM9RNJ+y4Z0eVwpRRv3IvNE2moaA1x3AAAAIFWcwwCE69kS4oybMFEUP4r7qFAY8tSb1o8ItSFcSe2+')]),
  2327. ('p384', 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBMYK8PUtfAlJwKaBTIGEuCzH0vqOMa4UbcjrBbTbkGVSUnfo+nuC80NCdj9JJMs1jvfF8GzKLc5z8H3nZyM741/BUFjV7rEHsQFDek4KyWvKkEgKiTlZid19VukNo1q2Hg==', 'AAAAMGsfTmdB4zHdbiQ2euTSdzM6UKEOnrVjMAWwHEYvmG5qUOcBnn62fJDRJy67L+QGdg==', 384, b'nistp384,0xc60af0f52d7c0949c0a6814c8184b82cc7d2fa8e31ae146dc8eb05b4db9065525277e8fa7b82f34342763f4924cb358e,0xf7c5f06cca2dce73f07de767233be35fc15058d5eeb107b101437a4e0ac96bca90480a89395989dd7d56e90da35ab61e', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAABoAAAAMFqCJ+gBP4GGc7yCy9F5e4EjkDlvYBYsYWMYFg3Md/ml7Md8pIrN7I0+8bFb99rZjQAAADAsM2kI+QOcgK+oVDaP0qkLRRbWDO1dSU5I2YfETyHVLYFNdRmgdWo6002XTO9jAsk=')]),
  2328. ('p521', 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAFrGthlKM152vu2Ghk+R7iO9/M6e+hTehNZ6+FBwof4HPkPB2/HHXj5+w5ynWyUrWiX5TI2riuJEIrJErcRH5LglADnJDX2w4yrKZ+wDHSz9lwh9p2F+B5R952es6gX3RJRkGA+qhKpKup8gKx78RMbleX8wgRtIu+4YMUnKb1edREiRg==', 'AAAAQgFh7VNJFUljWhhyAEiL0z+UPs/QggcMTd3Vv2aKDeBdCRl5di8r+BMm39L7bRzxRMEtW5NSKlDtE8MFEGdIE9khsw==', 521, b'nistp521,0x16b1ad86528cd79dafbb61a193e47b88ef7f33a7be8537a1359ebe141c287f81cf90f076fc71d78f9fb0e729d6c94ad6897e53236ae2b89108ac912b7111f92e094,0xe72435f6c38cab299fb00c74b3f65c21f69d85f81e51f79d9eb3a817dd125190603eaa12a92aea7c80ac7bf1131b95e5fcc2046d22efb860c52729bd5e75112246', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAACLAAAAQVBkbaCKivgvc+68CULCdPayjzRUYZdj1G2pLyiPWTdmJKVKF/W1oDAtjMZlP53tqCpGxDdrLoJH2A39k6g5MgNjAAAAQgGrNcesPBw/HMopBQ1JqOG1cSlAzjiFT34FvM68ZhdIjbQ0eHFuYs97RekQ8dpxmkuM88e63ATbZy4yDX06pKgmuQ==')]),
  2329. ('dsa', 'AAAAB3NzaC1kc3MAAABhAJyWZzjVddGdyc5JPu/WPrC07vKRAmlqO6TUi49ah96iRcM7/D1aRMVAdYBepQ2mf1fsQTmvoC9KgQa79nN3kHhz0voQBKOuKI1ZAodfVOgpP4xmcXgjaA73Vjz22n4newAAABUA6l7/vIveaiA33YYv+SKcKLQaA8cAAABgbErc8QLw/WDz7mhVRZrU+9x3Tfs68j3eW+B/d7Rz1ZCqMYDk7r/F8dlBdQlYhpQvhuSBgzoFa0+qPvSSxPmutgb94wNqhHlVIUb9ZOJNloNr2lXiPP//Wu51TxXAEvAAAAAAYQCcQ9mufXtZa5RyfwT4NuLivdsidP4HRoLXdlnppfFAbNdbhxE0Us8WZt+a/443bwKnYxgif8dgxv5UROnWTngWu0jbJHpaDcTc9lRyTeSUiZZK312s/Sl7qDk3/Du7RUI=', 'AAAAFGx3ft7G8AQzFsjhle7PWardUXh3', 768, b'0x9c966738d575d19dc9ce493eefd63eb0b4eef29102696a3ba4d48b8f5a87dea245c33bfc3d5a44c54075805ea50da67f57ec4139afa02f4a8106bbf67377907873d2fa1004a3ae288d5902875f54e8293f8c66717823680ef7563cf6da7e277b,0xea5effbc8bde6a2037dd862ff9229c28b41a03c7,0x6c4adcf102f0fd60f3ee6855459ad4fbdc774dfb3af23dde5be07f77b473d590aa3180e4eebfc5f1d94175095886942f86e481833a056b4faa3ef492c4f9aeb606fde3036a8479552146fd64e24d96836bda55e23cffff5aee754f15c012f000,0x9c43d9ae7d7b596b94727f04f836e2e2bddb2274fe074682d77659e9a5f1406cd75b87113452cf1666df9aff8e376f02a76318227fc760c6fe5444e9d64e7816bb48db247a5a0dc4dcf654724de49489964adf5dacfd297ba83937fc3bbb4542', [(0, 'AAAAB3NzaC1kc3MAAAAoyCVHLG2QqdMx7NiCWaThx6tDA5mf7UGl+8By0IzmSldBujsGKNs20g==')]),
  2330. ('rsa', 'AAAAB3NzaC1yc2EAAAABJQAAAGEA2ChX9+mQD/NULFkBrxLDI8d1PHgrInC2u11U4Grqu4oVzKvnFROo6DZeCu6sKhFJE5CnIL7evAthQ9hkXVHDhQ7xGVauzqyHGdIU4/pHRScAYWBv/PZOlNMrSoP/PP91', 'AAAAYCMNdgyGvWpez2EjMLSbQj0nQ3GW8jzvru3zdYwtA3hblNUU9QpWNxDmOMOApkwCzUgsdIPsBxctIeWT2h+v8sVOH+d66LCaNmNR0lp+dQ+iXM67hcGNuxJwRdMupD9ZbQAAADEA7XMrMAb4WuHaFafoTfGrf6Jhdy9Ozjqi1fStuld7Nj9JkoZluiL2dCwIrxqOjwU5AAAAMQDpC1gYiGVSPeDRILr2oxREtXWOsW+/ZZTfZNX7lvoufnp+qvwZPqvZnXQFHyZ8qB0AAAAwQE0wx8TPgcvRVEVv8Wt+o1NFlkJZayWD5hqpe/8AqUMZbqfg/aiso5mvecDLFgfV', 768, b'0x25,0xd82857f7e9900ff3542c5901af12c323c7753c782b2270b6bb5d54e06aeabb8a15ccabe71513a8e8365e0aeeac2a11491390a720bedebc0b6143d8645d51c3850ef11956aeceac8719d214e3fa4745270061606ffcf64e94d32b4a83ff3cff75', [(0, 'AAAAB3NzaC1yc2EAAABgrLSC4635RCsH1b3en58NqLsrH7PKRZyb3YmRasOyr8xIZMSlKZyxNg+kkn9OgBzbH9vChafzarfHyVwtJE2IMt3uwxTIWjwgwH19tc16k8YmNfDzujmB6OFOArmzKJgJ'), (2, 'AAAADHJzYS1zaGEyLTI1NgAAAGAJszr04BZlVBEdRLGOv1rTJwPiid/0I6/MycSH+noahvUH2wjrRhqDuv51F4nKYF5J9vBsEotTSrSF/cnLsliCdvVkEfmvhdcn/jx2LWF2OfjqETiYSc69Dde9UFmAPds='), (4, 'AAAADHJzYS1zaGEyLTUxMgAAAGBxfZ2m+WjvZ5YV5RFm0+w84CgHQ95EPndoAha0PCMc93AUHBmoHnezsJvEGuLovUm35w/0POmUNHI7HzM9PECwXrV0rO6N/HL/oFxJuDYmeqCpjMVmN8QXka+yxs2GEtA=')]),
  2331. ]
  2332. for alg, pubb64, privb64, bits, cachestr, siglist in test_keys:
  2333. # Decode the blobs in the above test data.
  2334. pubblob = b64(pubb64)
  2335. privblob = b64(privb64)
  2336. # Check the method that examines a public blob directly
  2337. # and returns an integer showing the key size.
  2338. self.assertEqual(ssh_key_public_bits(alg, pubblob), bits)
  2339. # Make a public-only and a full ssh_key object.
  2340. pubkey = ssh_key_new_pub(alg, pubblob)
  2341. privkey = ssh_key_new_priv(alg, pubblob, privblob)
  2342. # Test that they re-export the public and private key
  2343. # blobs unchanged.
  2344. self.assertEqual(ssh_key_public_blob(pubkey), pubblob)
  2345. self.assertEqual(ssh_key_public_blob(privkey), pubblob)
  2346. self.assertEqual(ssh_key_private_blob(privkey), privblob)
  2347. # Round-trip through the OpenSSH wire encoding used by the
  2348. # agent protocol (and the newer OpenSSH key file format),
  2349. # and check the result still exports all the same blobs.
  2350. osshblob = ssh_key_openssh_blob(privkey)
  2351. privkey2 = ssh_key_new_priv_openssh(alg, osshblob)
  2352. self.assertEqual(ssh_key_public_blob(privkey2), pubblob)
  2353. self.assertEqual(ssh_key_private_blob(privkey2), privblob)
  2354. self.assertEqual(ssh_key_openssh_blob(privkey2), osshblob)
  2355. # Test that the string description used in the host key
  2356. # cache is as expected.
  2357. for key in [pubkey, privkey, privkey2]:
  2358. self.assertEqual(ssh_key_cache_str(key), cachestr)
  2359. # Now test signatures, separately for each provided flags
  2360. # value.
  2361. for flags, sigb64 in siglist:
  2362. # Decode the signature blob from the test data.
  2363. sigblob = b64(sigb64)
  2364. # Sign our test message, and check it produces exactly
  2365. # the expected signature blob.
  2366. #
  2367. # We do this with both the original private key and
  2368. # the one we round-tripped through OpenSSH wire
  2369. # format, just in case that round trip made some kind
  2370. # of a mess that didn't show up in the re-extraction
  2371. # of the blobs.
  2372. for key in [privkey, privkey2]:
  2373. self.assertEqual(ssh_key_sign(
  2374. key, test_message, flags), sigblob)
  2375. if flags != 0:
  2376. # Currently we only support _generating_
  2377. # signatures with flags != 0, not verifying them.
  2378. continue
  2379. # Check the signature verifies successfully, with all
  2380. # three of the key objects we have.
  2381. for key in [pubkey, privkey, privkey2]:
  2382. self.assertTrue(ssh_key_verify(key, sigblob, test_message))
  2383. # A crude check that at least _something_ doesn't
  2384. # verify successfully: flip a bit of the signature
  2385. # and expect it to fail.
  2386. #
  2387. # We do this twice, at the 1/3 and 2/3 points along
  2388. # the signature's length, so that in the case of
  2389. # signatures in two parts (DSA-like) we try perturbing
  2390. # both parts. Other than that, we don't do much to
  2391. # make this a rigorous cryptographic test.
  2392. for n, d in [(1,3),(2,3)]:
  2393. sigbytes = list(sigblob)
  2394. bit = 8 * len(sigbytes) * n // d
  2395. sigbytes[bit // 8] ^= 1 << (bit % 8)
  2396. badsig = bytes(sigbytes)
  2397. for key in [pubkey, privkey, privkey2]:
  2398. self.assertFalse(ssh_key_verify(
  2399. key, badsig, test_message))
  2400. def testShortRSASignatures(self):
  2401. key = ssh_key_new_priv('rsa', b64("""
  2402. AAAAB3NzaC1yc2EAAAADAQABAAABAQDeoTvwEDg46K7vYrQFFwbo2sBPahNoiw7i
  2403. RMbpwuOIH8sAOFAWzDvIZpDODGkobwc2hM8FRlZUg3lTgDaqVuMJOupG0xzOqehu
  2404. Fw3kXrm6ScWxaUXs+b5o88sqXBBYs91KmsWqYKTUUwDBuDHdo8Neq8h8SJqspCo4
  2405. qctIoLoTrXYMqonfHXZp4bIn5WPN6jNL9pLi7Y+sl8aLe4w73aZzxMphecQfMMVJ
  2406. ezmv9zgA7gKw5ErorIGKCF44YRbvNisZA5j2DyLLsd/ztw2ikIEnx9Ng33+tGEBC
  2407. zq2RYb4ZtuT9dHXcNiHx3CqLLlFrjl13hQamjwoVy4ydDIdQZjYz
  2408. """), b64("""
  2409. AAABADhDwXUrdDoVvFhttpduuWVSG7Y2Vc9fDZTr0uWzRnPZrSFSGhOY7Cb6nPAm
  2410. PNFmNgl2SSfJHfpf++K5jZdBPEHR7PGXWzlzwXVJSE6GDiRhjqAGvhBlEdVOf/Ml
  2411. r0/rrSq0sO4dXKr4i0FqPtgIElEz0whuBQFKwAzwBJtHW5+rBzGLvoHh560UN4IK
  2412. SU3jv/nDMvPohEBfOA0puqYAfZM8PmU/kbgERPLyPp/dfnGBC4LlOnAcak+2RNu6
  2413. yQ5v0NKksyYidCI76Ztf3B9asNNN4AbTg8JbzABwjtxR+0bDOOi0RwAJC2Wn2FOy
  2414. WiJsQWjz/fMnJW8WVg3DR/va/4EAAACBAP8rwn1vy4Y/S1EixR1XZM9F1OvJQwzN
  2415. EKhD1Qbr1YlLX3oZRnulJg/j0HupGnKCRh8DulNbrmXlMFdeZHDVFw87/o73DTCQ
  2416. g2qnRNUwJdBkePrA563vVx6OXe5TSF3+3SRNMesAdN8ExvGeOFP10z0FZhS3Zuco
  2417. y4WrxQBXVetBAAAAgQDfWmh5CRJEBCJbLHMdZK8QAw2QbKiD0VTw7PkDWJuSbYDB
  2418. AvEhoFuXUO/yMIfCCFjUuzO+3iumk8F/lFTkJ620Aah5tzRcKCtyW4YuoQUYMgpW
  2419. 5/hGIL4M4bvUDGUGI3+SOn8qfAzCCsFD0FdR6ms0pMubaJQmeiI2wyM9ehOIcwAA
  2420. AIEAmKEX1YZHNtx/D/SaTsl6z+KwmOluqjzyjrwL16QLpIR1/F7lAjSnMGz3yORp
  2421. +314D3yZzKutpalwwsS4+z7838pilVaV7iWqF4TMDKYZ/6/baRXpwxrwFqvWXwQ3
  2422. cLerc7bpA/IeVovoTirt0RNxdMPIVv3XsXE7pqatJBwOcQE=
  2423. """))
  2424. def decode(data):
  2425. pos = 0
  2426. alg, data = ssh_decode_string(data, True)
  2427. sig, data = ssh_decode_string(data, True)
  2428. self.assertEqual(data, b'')
  2429. return alg, sig
  2430. # An RSA signature over each hash which comes out a byte short
  2431. # with this key. Found in the obvious manner, by signing
  2432. # "message0", "message1", ... until one was short.
  2433. #
  2434. # We expect the ssh-rsa signature to be stored short, and the
  2435. # other two to be padded with a zero byte.
  2436. blob = ssh_key_sign(key, "message79", 0)
  2437. alg, sig = decode(blob)
  2438. self.assertEqual(alg, b"ssh-rsa")
  2439. self.assertEqual(len(sig), 255) # one byte short
  2440. self.assertNotEqual(sig[0], 0)
  2441. blob = ssh_key_sign(key, "message208", 2)
  2442. alg, sig = decode(blob)
  2443. self.assertEqual(alg, b"rsa-sha2-256")
  2444. self.assertEqual(len(sig), 256) # full-length
  2445. self.assertEqual(sig[0], 0) # and has a leading zero byte
  2446. blob = ssh_key_sign(key, "message461", 4)
  2447. alg, sig = decode(blob)
  2448. self.assertEqual(alg, b"rsa-sha2-512")
  2449. self.assertEqual(len(sig), 256) # full-length
  2450. self.assertEqual(sig[0], 0) # and has a leading zero byte
  2451. def testPPKLoadSave(self):
  2452. # Stability test of PPK load/save functions.
  2453. input_clear_key = b"""\
  2454. PuTTY-User-Key-File-3: ssh-ed25519
  2455. Encryption: none
  2456. Comment: ed25519-key-20200105
  2457. Public-Lines: 2
  2458. AAAAC3NzaC1lZDI1NTE5AAAAIHJCszOHaI9X/yGLtjn22f0hO6VPMQDVtctkym6F
  2459. JH1W
  2460. Private-Lines: 1
  2461. AAAAIGvvIpl8jyqn8Xufkw6v3FnEGtXF3KWw55AP3/AGEBpY
  2462. Private-MAC: 816c84093fc4877e8411b8e5139c5ce35d8387a2630ff087214911d67417a54d
  2463. """
  2464. input_encrypted_key = b"""\
  2465. PuTTY-User-Key-File-3: ssh-ed25519
  2466. Encryption: aes256-cbc
  2467. Comment: ed25519-key-20200105
  2468. Public-Lines: 2
  2469. AAAAC3NzaC1lZDI1NTE5AAAAIHJCszOHaI9X/yGLtjn22f0hO6VPMQDVtctkym6F
  2470. JH1W
  2471. Key-Derivation: Argon2id
  2472. Argon2-Memory: 8192
  2473. Argon2-Passes: 13
  2474. Argon2-Parallelism: 1
  2475. Argon2-Salt: 37c3911bfefc8c1d11ec579627d2b3d9
  2476. Private-Lines: 1
  2477. amviz4sVUBN64jLO3gt4HGXJosUArghc4Soi7aVVLb2Tir5Baj0OQClorycuaPRd
  2478. Private-MAC: 6f5e588e475e55434106ec2c3569695b03f423228b44993a9e97d52ffe7be5a8
  2479. """
  2480. algorithm = b'ssh-ed25519'
  2481. comment = b'ed25519-key-20200105'
  2482. pp = b'test-passphrase'
  2483. public_blob = unhex(
  2484. '0000000b7373682d65643235353139000000207242b33387688f57ff218bb639'
  2485. 'f6d9fd213ba54f3100d5b5cb64ca6e85247d56')
  2486. self.assertEqual(ppk_encrypted_s(input_clear_key), (False, comment))
  2487. self.assertEqual(ppk_encrypted_s(input_encrypted_key), (True, comment))
  2488. self.assertEqual(ppk_encrypted_s("not a key file"), (False, None))
  2489. self.assertEqual(ppk_loadpub_s(input_clear_key),
  2490. (True, algorithm, public_blob, comment, None))
  2491. self.assertEqual(ppk_loadpub_s(input_encrypted_key),
  2492. (True, algorithm, public_blob, comment, None))
  2493. self.assertEqual(ppk_loadpub_s("not a key file"),
  2494. (False, None, b'', None,
  2495. b'not a public key or a PuTTY SSH-2 private key'))
  2496. k1, c, e = ppk_load_s(input_clear_key, None)
  2497. self.assertEqual((c, e), (comment, None))
  2498. k2, c, e = ppk_load_s(input_encrypted_key, pp)
  2499. self.assertEqual((c, e), (comment, None))
  2500. privblob = ssh_key_private_blob(k1)
  2501. self.assertEqual(ssh_key_private_blob(k2), privblob)
  2502. salt = unhex('37c3911bfefc8c1d11ec579627d2b3d9')
  2503. with queued_specific_random_data(salt):
  2504. self.assertEqual(ppk_save_sb(k1, comment, None,
  2505. 3, 'id', 8192, 13, 1),
  2506. input_clear_key)
  2507. with queued_specific_random_data(salt):
  2508. self.assertEqual(ppk_save_sb(k2, comment, None,
  2509. 3, 'id', 8192, 13, 1),
  2510. input_clear_key)
  2511. with queued_specific_random_data(salt):
  2512. self.assertEqual(ppk_save_sb(k1, comment, pp,
  2513. 3, 'id', 8192, 13, 1),
  2514. input_encrypted_key)
  2515. with queued_specific_random_data(salt):
  2516. self.assertEqual(ppk_save_sb(k2, comment, pp,
  2517. 3, 'id', 8192, 13, 1),
  2518. input_encrypted_key)
  2519. # And check we can still handle v2 key files.
  2520. v2_clear_key = b"""\
  2521. PuTTY-User-Key-File-2: ssh-ed25519
  2522. Encryption: none
  2523. Comment: ed25519-key-20200105
  2524. Public-Lines: 2
  2525. AAAAC3NzaC1lZDI1NTE5AAAAIHJCszOHaI9X/yGLtjn22f0hO6VPMQDVtctkym6F
  2526. JH1W
  2527. Private-Lines: 1
  2528. AAAAIGvvIpl8jyqn8Xufkw6v3FnEGtXF3KWw55AP3/AGEBpY
  2529. Private-MAC: 2a629acfcfbe28488a1ba9b6948c36406bc28422
  2530. """
  2531. v2_encrypted_key = b"""\
  2532. PuTTY-User-Key-File-2: ssh-ed25519
  2533. Encryption: aes256-cbc
  2534. Comment: ed25519-key-20200105
  2535. Public-Lines: 2
  2536. AAAAC3NzaC1lZDI1NTE5AAAAIHJCszOHaI9X/yGLtjn22f0hO6VPMQDVtctkym6F
  2537. JH1W
  2538. Private-Lines: 1
  2539. 4/jKlTgC652oa9HLVGrMjHZw7tj0sKRuZaJPOuLhGTvb25Jzpcqpbi+Uf+y+uo+Z
  2540. Private-MAC: 5b1f6f4cc43eb0060d2c3e181bc0129343adba2b
  2541. """
  2542. self.assertEqual(ppk_encrypted_s(v2_clear_key), (False, comment))
  2543. self.assertEqual(ppk_encrypted_s(v2_encrypted_key), (True, comment))
  2544. self.assertEqual(ppk_encrypted_s("not a key file"), (False, None))
  2545. self.assertEqual(ppk_loadpub_s(v2_clear_key),
  2546. (True, algorithm, public_blob, comment, None))
  2547. self.assertEqual(ppk_loadpub_s(v2_encrypted_key),
  2548. (True, algorithm, public_blob, comment, None))
  2549. self.assertEqual(ppk_loadpub_s("not a key file"),
  2550. (False, None, b'', None,
  2551. b'not a public key or a PuTTY SSH-2 private key'))
  2552. k1, c, e = ppk_load_s(v2_clear_key, None)
  2553. self.assertEqual((c, e), (comment, None))
  2554. k2, c, e = ppk_load_s(v2_encrypted_key, pp)
  2555. self.assertEqual((c, e), (comment, None))
  2556. self.assertEqual(ssh_key_private_blob(k1), privblob)
  2557. self.assertEqual(ssh_key_private_blob(k2), privblob)
  2558. self.assertEqual(ppk_save_sb(k2, comment, None,
  2559. 2, 'id', 8192, 13, 1),
  2560. v2_clear_key)
  2561. self.assertEqual(ppk_save_sb(k1, comment, pp,
  2562. 2, 'id', 8192, 13, 1),
  2563. v2_encrypted_key)
  2564. def testRSA1LoadSave(self):
  2565. # Stability test of SSH-1 RSA key-file load/save functions.
  2566. input_clear_key = unhex(
  2567. "5353482050524956415445204B45592046494C4520464F524D415420312E310A"
  2568. "000000000000000002000200BB115A85B741E84E3D940E690DF96A0CBFDC07CA"
  2569. "70E51DA8234D211DE77341CEF40C214CAA5DCF68BE2127447FD6C84CCB17D057"
  2570. "A74F2365B9D84A78906AEB51000625000000107273612D6B65792D3230323030"
  2571. "313036208E208E0200929EE615C6FC4E4B29585E52570F984F2E97B3144AA5BD"
  2572. "4C6EB2130999BB339305A21FFFA79442462A8397AF8CAC395A3A3827DE10457A"
  2573. "1F1B277ABFB8C069C100FF55B1CAD69B3BD9E42456CF28B1A4B98130AFCE08B2"
  2574. "8BCFFF5FFFED76C5D51E9F0100C5DE76889C62B1090A770AE68F087A19AB5126"
  2575. "E60DF87710093A2AD57B3380FB0100F2068AC47ECB33BF8F13DF402BABF35EE7"
  2576. "26BD32F7564E51502DF5C8F4888B2300000000")
  2577. input_encrypted_key = unhex(
  2578. "5353482050524956415445204b45592046494c4520464f524d415420312e310a"
  2579. "000300000000000002000200bb115a85b741e84e3d940e690df96a0cbfdc07ca"
  2580. "70e51da8234d211de77341cef40c214caa5dcf68be2127447fd6c84ccb17d057"
  2581. "a74f2365b9d84a78906aeb51000625000000107273612d6b65792d3230323030"
  2582. "3130363377f926e811a5f044c52714801ecdcf9dd572ee0a193c4f67e87ab2ce"
  2583. "4569d0c5776fd6028909ed8b6d663bef15d207d3ef6307e7e21dbec56e8d8b4e"
  2584. "894ded34df891bb29bae6b2b74805ac80f7304926abf01ae314dd69c64240761"
  2585. "34f15d50c99f7573252993530ec9c4d5016dd1f5191730cda31a5d95d362628b"
  2586. "2a26f4bb21840d01c8360e4a6ce216c4686d25b8699d45cf361663bb185e2c5e"
  2587. "652012a1e0f9d6d19afbb28506f7775bfd8129")
  2588. comment = b'rsa-key-20200106'
  2589. pp = b'test-passphrase'
  2590. public_blob = unhex(
  2591. "000002000006250200bb115a85b741e84e3d940e690df96a0cbfdc07ca70e51d"
  2592. "a8234d211de77341cef40c214caa5dcf68be2127447fd6c84ccb17d057a74f23"
  2593. "65b9d84a78906aeb51")
  2594. self.assertEqual(rsa1_encrypted_s(input_clear_key), (False, comment))
  2595. self.assertEqual(rsa1_encrypted_s(input_encrypted_key),
  2596. (True, comment))
  2597. self.assertEqual(rsa1_encrypted_s("not a key file"), (False, None))
  2598. self.assertEqual(rsa1_loadpub_s(input_clear_key),
  2599. (1, public_blob, comment, None))
  2600. self.assertEqual(rsa1_loadpub_s(input_encrypted_key),
  2601. (1, public_blob, comment, None))
  2602. k1 = rsa_new()
  2603. status, c, e = rsa1_load_s(input_clear_key, k1, None)
  2604. self.assertEqual((status, c, e), (1, comment, None))
  2605. k2 = rsa_new()
  2606. status, c, e = rsa1_load_s(input_clear_key, k2, None)
  2607. self.assertEqual((status, c, e), (1, comment, None))
  2608. with queued_specific_random_data(unhex("208e")):
  2609. self.assertEqual(rsa1_save_sb(k1, comment, None), input_clear_key)
  2610. with queued_specific_random_data(unhex("208e")):
  2611. self.assertEqual(rsa1_save_sb(k2, comment, None), input_clear_key)
  2612. with queued_specific_random_data(unhex("99f3")):
  2613. self.assertEqual(rsa1_save_sb(k1, comment, pp),
  2614. input_encrypted_key)
  2615. with queued_specific_random_data(unhex("99f3")):
  2616. self.assertEqual(rsa1_save_sb(k2, comment, pp),
  2617. input_encrypted_key)
  2618. def testRFC4716(self):
  2619. key = """\
  2620. ---- BEGIN SSH2 PUBLIC KEY ----
  2621. Comment: "rsa-key-20240810"
  2622. AAAAB3NzaC1yc2EAAAADAQABAAABAQCKdLtvsewMpsbWQCNs8VOWKlh6eQT0gzbc
  2623. IoDLFPk5uVS1HjAEEjIZaXAB86PHTeJhkwEMlMXZ8mUZwAcZkuqKVCSib/VkuMEv
  2624. wXa4cOf70XMBUtUgRJ5bJRMsA8PNkZN/OQHyyBLgTXGoFPWq73A3fxPZIe8BSAN+
  2625. mPuILX1GHUKbBzT56xRNwB5nHkg0MStEotkIzg3xRNIXB9qyP6ILO4Qax2n7+XJS
  2626. lmzr0KDJq5ZNSEZV4IprvAYBeEtvdBfLrRM4kifpVDE7ZrVXtKOIGDsxdEEBeqqy
  2627. LzN/Ly+uECsga2hoc+P/ZHMULMZkCfrOyWdeXz7BR/acLZJoT579
  2628. ---- END SSH2 PUBLIC KEY ----
  2629. """
  2630. comment = b"rsa-key-20240810"
  2631. public_blob = b64("""
  2632. AAAAB3NzaC1yc2EAAAADAQABAAABAQCKdLtvsewMpsbWQCNs8VOWKlh6eQT0gzbc
  2633. IoDLFPk5uVS1HjAEEjIZaXAB86PHTeJhkwEMlMXZ8mUZwAcZkuqKVCSib/VkuMEv
  2634. wXa4cOf70XMBUtUgRJ5bJRMsA8PNkZN/OQHyyBLgTXGoFPWq73A3fxPZIe8BSAN+
  2635. mPuILX1GHUKbBzT56xRNwB5nHkg0MStEotkIzg3xRNIXB9qyP6ILO4Qax2n7+XJS
  2636. lmzr0KDJq5ZNSEZV4IprvAYBeEtvdBfLrRM4kifpVDE7ZrVXtKOIGDsxdEEBeqqy
  2637. LzN/Ly+uECsga2hoc+P/ZHMULMZkCfrOyWdeXz7BR/acLZJoT579
  2638. """)
  2639. self.assertEqual(ppk_loadpub_s(key),
  2640. (True, b'ssh-rsa', public_blob, comment, None))
  2641. self.assertEqual(ppk_loadpub_s(key[:len(key)//2]),
  2642. (False, None, b'', None,
  2643. b"invalid end line in SSH-2 public key file"))
  2644. def testOpenSSHCert(self):
  2645. def per_base_keytype_tests(alg, run_validation_tests=False,
  2646. run_ca_rsa_tests=False, ca_signflags=None):
  2647. cert_pub = sign_cert_via_testcrypt(
  2648. make_signature_preimage(
  2649. key_to_certify = base_key.public_blob(),
  2650. ca_key = ca_key,
  2651. certtype = CertType.user,
  2652. keyid = b'id',
  2653. serial = 111,
  2654. principals = [b'username'],
  2655. valid_after = 1000,
  2656. valid_before = 2000), ca_key, signflags=ca_signflags)
  2657. certified_key = ssh_key_new_priv(alg + '-cert', cert_pub,
  2658. base_key.private_blob())
  2659. # Check the simple certificate methods
  2660. self.assertEqual(certified_key.cert_id_string(), b'id')
  2661. self.assertEqual(certified_key.ca_public_blob(),
  2662. ca_key.public_blob())
  2663. recovered_base_key = certified_key.base_key()
  2664. self.assertEqual(recovered_base_key.public_blob(),
  2665. base_key.public_blob())
  2666. self.assertEqual(recovered_base_key.private_blob(),
  2667. base_key.private_blob())
  2668. # Check that an ordinary key also supports base_key()
  2669. redundant_base_key = base_key.base_key()
  2670. self.assertEqual(redundant_base_key.public_blob(),
  2671. base_key.public_blob())
  2672. self.assertEqual(redundant_base_key.private_blob(),
  2673. base_key.private_blob())
  2674. # Test signing and verifying using the certified key type
  2675. test_string = b'hello, world'
  2676. base_sig = base_key.sign(test_string, 0)
  2677. certified_sig = certified_key.sign(test_string, 0)
  2678. self.assertEqual(base_sig, certified_sig)
  2679. self.assertEqual(certified_key.verify(base_sig, test_string), True)
  2680. # Check a successful certificate verification
  2681. result, err = certified_key.check_cert(
  2682. False, b'username', 1000, '')
  2683. self.assertEqual(result, True)
  2684. # If the key type is RSA, check that the validator rejects
  2685. # wrong kinds of CA signature
  2686. if run_ca_rsa_tests:
  2687. forbid_all = ",".join(["permit_rsa_sha1=false",
  2688. "permit_rsa_sha256=false,"
  2689. "permit_rsa_sha512=false"])
  2690. result, err = certified_key.check_cert(
  2691. False, b'username', 1000, forbid_all)
  2692. self.assertEqual(result, False)
  2693. algname = ("rsa-sha2-512" if ca_signflags == 4 else
  2694. "rsa-sha2-256" if ca_signflags == 2 else
  2695. "ssh-rsa")
  2696. self.assertEqual(err, (
  2697. "Certificate signature uses '{}' signature type "
  2698. "(forbidden by user configuration)".format(algname)
  2699. .encode("ASCII")))
  2700. permitflag = ("permit_rsa_sha512" if ca_signflags == 4 else
  2701. "permit_rsa_sha256" if ca_signflags == 2 else
  2702. "permit_rsa_sha1")
  2703. result, err = certified_key.check_cert(
  2704. False, b'username', 1000, "{},{}=true".format(
  2705. forbid_all, permitflag))
  2706. self.assertEqual(result, True)
  2707. # That's the end of the tests we need to repeat for all
  2708. # the key types. Now we move on to detailed tests of the
  2709. # validation, which are independent of key type, so we
  2710. # only need to test this part once.
  2711. if not run_validation_tests:
  2712. return
  2713. # Check cert verification at the other end of the valid
  2714. # time range
  2715. result, err = certified_key.check_cert(
  2716. False, b'username', 1999, '')
  2717. self.assertEqual(result, True)
  2718. # Oops, wrong certificate type
  2719. result, err = certified_key.check_cert(
  2720. True, b'username', 1000, '')
  2721. self.assertEqual(result, False)
  2722. self.assertEqual(err, b'Certificate type is user; expected host')
  2723. # Oops, wrong username
  2724. result, err = certified_key.check_cert(
  2725. False, b'someoneelse', 1000, '')
  2726. self.assertEqual(result, False)
  2727. self.assertEqual(err, b'Certificate\'s username list ["username"] '
  2728. b'does not contain expected username "someoneelse"')
  2729. # Oops, time is wrong. (But we can't check the full error
  2730. # message including the translated start/end times, because
  2731. # those vary with LC_TIME.)
  2732. result, err = certified_key.check_cert(
  2733. False, b'someoneelse', 999, '')
  2734. self.assertEqual(result, False)
  2735. self.assertEqual(err[:30], b'Certificate is not valid until')
  2736. result, err = certified_key.check_cert(
  2737. False, b'someoneelse', 2000, '')
  2738. self.assertEqual(result, False)
  2739. self.assertEqual(err[:22], b'Certificate expired at')
  2740. # Modify the certificate so that the signature doesn't validate
  2741. username_position = cert_pub.index(b'username')
  2742. bytelist = list(cert_pub)
  2743. bytelist[username_position] ^= 1
  2744. miscertified_key = ssh_key_new_priv(alg + '-cert', bytes(bytelist),
  2745. base_key.private_blob())
  2746. result, err = miscertified_key.check_cert(
  2747. False, b'username', 1000, '')
  2748. self.assertEqual(result, False)
  2749. self.assertEqual(err, b"Certificate's signature is invalid")
  2750. # Make a certificate containing a critical option, to test we
  2751. # reject it
  2752. cert_pub = sign_cert_via_testcrypt(
  2753. make_signature_preimage(
  2754. key_to_certify = base_key.public_blob(),
  2755. ca_key = ca_key,
  2756. certtype = CertType.user,
  2757. keyid = b'id',
  2758. serial = 112,
  2759. principals = [b'username'],
  2760. critical_options = {b'unknown-option': b'yikes!'}), ca_key)
  2761. certified_key = ssh_key_new_priv(alg + '-cert', cert_pub,
  2762. base_key.private_blob())
  2763. result, err = certified_key.check_cert(
  2764. False, b'username', 1000, '')
  2765. self.assertEqual(result, False)
  2766. self.assertEqual(err, b'Certificate specifies an unsupported '
  2767. b'critical option "unknown-option"')
  2768. # Make a certificate containing a non-critical extension, to
  2769. # test we _accept_ it
  2770. cert_pub = sign_cert_via_testcrypt(
  2771. make_signature_preimage(
  2772. key_to_certify = base_key.public_blob(),
  2773. ca_key = ca_key,
  2774. certtype = CertType.user,
  2775. keyid = b'id',
  2776. serial = 113,
  2777. principals = [b'username'],
  2778. extensions = {b'unknown-ext': b'whatever, dude'}), ca_key)
  2779. certified_key = ssh_key_new_priv(alg + '-cert', cert_pub,
  2780. base_key.private_blob())
  2781. result, err = certified_key.check_cert(
  2782. False, b'username', 1000, '')
  2783. self.assertEqual(result, True)
  2784. # Make a certificate on the CA key, and re-sign the main
  2785. # key using that, to ensure that two-level certs are rejected
  2786. ca_self_certificate = sign_cert_via_testcrypt(
  2787. make_signature_preimage(
  2788. key_to_certify = ca_key.public_blob(),
  2789. ca_key = ca_key,
  2790. certtype = CertType.user,
  2791. keyid = b'id',
  2792. serial = 111,
  2793. principals = [b"doesn't matter"],
  2794. valid_after = 1000,
  2795. valid_before = 2000), ca_key, signflags=ca_signflags)
  2796. import base64
  2797. self_signed_ca_key = ssh_key_new_pub(
  2798. alg + '-cert', ca_self_certificate)
  2799. cert_pub = sign_cert_via_testcrypt(
  2800. make_signature_preimage(
  2801. key_to_certify = base_key.public_blob(),
  2802. ca_key = self_signed_ca_key,
  2803. certtype = CertType.user,
  2804. keyid = b'id',
  2805. serial = 111,
  2806. principals = [b'username'],
  2807. valid_after = 1000,
  2808. valid_before = 2000), ca_key, signflags=ca_signflags)
  2809. certified_key = ssh_key_new_priv(alg + '-cert', cert_pub,
  2810. base_key.private_blob())
  2811. result, err = certified_key.check_cert(
  2812. False, b'username', 1500, '')
  2813. self.assertEqual(result, False)
  2814. self.assertEqual(
  2815. err, b'Certificate is signed with a certified key '
  2816. b'(forbidden by OpenSSH certificate specification)')
  2817. # Now try a host certificate. We don't need to do _all_ the
  2818. # checks over again, but at least make sure that setting
  2819. # CertType.host leads to the certificate validating with
  2820. # host=True and not with host=False.
  2821. #
  2822. # Also, in this test, give two hostnames.
  2823. cert_pub = sign_cert_via_testcrypt(
  2824. make_signature_preimage(
  2825. key_to_certify = base_key.public_blob(),
  2826. ca_key = ca_key,
  2827. certtype = CertType.host,
  2828. keyid = b'id',
  2829. serial = 114,
  2830. principals = [b'hostname.example.com',
  2831. b'hostname2.example.com'],
  2832. valid_after = 1000,
  2833. valid_before = 2000), ca_key)
  2834. certified_key = ssh_key_new_priv(alg + '-cert', cert_pub,
  2835. base_key.private_blob())
  2836. # Check certificate type
  2837. result, err = certified_key.check_cert(
  2838. True, b'hostname.example.com', 1000, '')
  2839. self.assertEqual(result, True)
  2840. result, err = certified_key.check_cert(
  2841. False, b'hostname.example.com', 1000, '')
  2842. self.assertEqual(result, False)
  2843. self.assertEqual(err, b'Certificate type is host; expected user')
  2844. # Check the second hostname and an unknown one
  2845. result, err = certified_key.check_cert(
  2846. True, b'hostname2.example.com', 1000, '')
  2847. self.assertEqual(result, True)
  2848. result, err = certified_key.check_cert(
  2849. True, b'hostname3.example.com', 1000, '')
  2850. self.assertEqual(result, False)
  2851. self.assertEqual(err, b'Certificate\'s hostname list ['
  2852. b'"hostname.example.com", "hostname2.example.com"] '
  2853. b'does not contain expected hostname '
  2854. b'"hostname3.example.com"')
  2855. # And just for luck, try a totally unknown certificate type,
  2856. # making sure that it's rejected in both modes and gives the
  2857. # right error message
  2858. cert_pub = sign_cert_via_testcrypt(
  2859. make_signature_preimage(
  2860. key_to_certify = base_key.public_blob(),
  2861. ca_key = ca_key,
  2862. certtype = 12345,
  2863. keyid = b'id',
  2864. serial = 114,
  2865. principals = [b'username', b'hostname.example.com'],
  2866. valid_after = 1000,
  2867. valid_before = 2000), ca_key)
  2868. certified_key = ssh_key_new_priv(alg + '-cert', cert_pub,
  2869. base_key.private_blob())
  2870. result, err = certified_key.check_cert(
  2871. False, b'username', 1000, '')
  2872. self.assertEqual(result, False)
  2873. self.assertEqual(err, b'Certificate type is unknown value 12345; '
  2874. b'expected user')
  2875. result, err = certified_key.check_cert(
  2876. True, b'hostname.example.com', 1000, '')
  2877. self.assertEqual(result, False)
  2878. self.assertEqual(err, b'Certificate type is unknown value 12345; '
  2879. b'expected host')
  2880. ca_key = ssh_key_new_priv('ed25519', b64('AAAAC3NzaC1lZDI1NTE5AAAAIMUJEFAmSV/qtoxSmVOHUgTMKYjqkDy8fTfsfCKV+sN7'), b64('AAAAIK4STyaf63xHidqhvUop9/OKiYqSh/YEWLCp1lL5Vs4u'))
  2881. base_key = ssh_key_new_priv('ed25519', b64('AAAAC3NzaC1lZDI1NTE5AAAAIMt0/CMBL+64GQ/r/JyGxo6oHs86i9bOHhMJYbDbxEJf'), b64('AAAAIB38jy02ZWYb4EXrJG9RIljEhqidrG5DdhZvMvoeOTZs'))
  2882. per_base_keytype_tests('ed25519', run_validation_tests=True)
  2883. base_key = ssh_key_new_priv('p256', b64('AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGc8VXplXScdWckJgAw6Hag5PP7g0JEVdLY5lP2ujvVxU5GwwquYLbX3yyj1zY5h2n9GoXrnRxzR5+5g8wsNjTA='), b64('AAAAICVRicPD5MyOHfKdnC/8IP84t+nQ4bqmMUyX7NHyCKjS'))
  2884. per_base_keytype_tests('p256')
  2885. base_key = ssh_key_new_priv('p384', b64('AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBLITujAbKwHDEzVDFqWtA+CleAhN/Y+53mHbEoTpU0aof9L+2lHeUshXdxHDLxY69wO5+WfqWJCwSY58PuXIZzIisQkvIKq6LhpzK6C5JpWJ8Kbv7su+qZPf5sYoxx0xZg=='), b64('AAAAMHyQTQYcIA/bR4ZvWS86ohb5Lu0MhzjD8bUb3q8jnROOe3BrE9I8oJcx+l1lddPouA=='))
  2886. per_base_keytype_tests('p384')
  2887. base_key = ssh_key_new_priv('p521', b64('AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBADButwMRGdLkFhWcSDsLhRhgyrLQq1/A0M8x4GgEmesh4iydo4tGKZR14GhHvx150IWTE1Tre4wyH+1FsTfAlpUBgBDQjsZE0D3u3SLp4qjjhzyrJGhEUDd9J6lsr6JrXbTefz5+LkM9m5l86y9PoAgT+F25OiTYlfvR5qx/pzIPoCnpA=='), b64('AAAAQgFV8xBXC7XZNxdW1oWg6yCZjys2AX4beZVehE9A2R/4m11dHnfqoE1FzbRxj9xqwKvHZRhMOJ//DYuhtcG6+6yHsA=='))
  2888. per_base_keytype_tests('p521')
  2889. base_key = ssh_key_new_priv('dsa', b64('AAAAB3NzaC1kc3MAAABCAXgDrF9Fw/Ty+QcoljAGjGL/Ph5+NBQqUYADm4wxF+aazjQXLuZ0VW9OdYBisgDZlYDj/w7y9NxCBgax2BSkhDNxAAAAFQC/YwnFzcom6cRRHPXtOUDLi2I29QAAAEIAqGOUYpfFPwzhgAmYXwWKdK8ouSUplNE29FOpv6NYjyf7k+tLSWF3b8oZdtw6XP8lr4vcKXC9Ik0YpKYKM7iKfb8AAABCAUDCcojlDLQmLHg8HhFCtT/CpayNh4OfmSrP8XOwJnFD/eBaSGuPB5EvGd+m6gr+Pc0RSAlWP1aIzUbYkQ33Yk58'), b64('AAAAFQChVuOTNrCwLSJygxlRQhDwHozwSg=='))
  2890. per_base_keytype_tests('dsa')
  2891. base_key = ssh_key_new_priv('rsa', b64('AAAAB3NzaC1yc2EAAAADAQABAAAAgQDXLnqGPQLL9byoHFQWPiF5Uzcd0KedMRRJmuwyCAWprlh8EN43mL2F7q27Uv54m/ztqW4DsVtiCN6cDYvB9QPNYFR5npwsEAJ06Ro4s9ZpFsZVOvitqeoYIs+jkS8vq5V8X4hwLlJ8vXYPD6rHJhOz6HFpImHmVu40Mu5lq+MCQQ=='), b64('AAAAgH5dBwrJzVilKHK4oBCnz9SFr7pMjAHdjoJi/g2rdFfe0IubBEQ16CY8sb1t0Y5WXEPc2YRFpNp/RurxcX8nOWFPzgNJXEtkKpKO9Juqu5hL4xcf8QKC2aJFk3EXrn/M6dXEdjqN4UhsT6iFTsHKU4b8T6VTtgKzwkOdic/YotaBAAAAQQD6liDTlzTKzLhbypI6l+y2BGA3Kkzz71Y2o7XH/6bZ6HJOFgHuJeL3eNQptzd8Q+ctfvR0fa2PItYydDOlVUeZAAAAQQDb1IsO1/fkflDZhPQT2XOxtrjgQhotKjr6CSmJtDNmo1mOCN+mOgxtDfJ0PNEEM1P9CO2Ia3njtkxt4Ep2EpjpAAAAQQClRxLEHsRK9nMPZ4HW45iyw5dHhYar9pYUql2VnixWQxrHy13ZIaWxi6xwWjuPglrdBgEQfYwH9KGmlFmZXT/Z'))
  2892. per_base_keytype_tests('rsa')
  2893. # Now switch to an RSA certifying key, and test different RSA
  2894. # signature subtypes being used to sign the certificate
  2895. ca_key = ssh_key_new_priv('rsa', b64('AAAAB3NzaC1yc2EAAAADAQABAAAAgQCKHiavhtnAZQLUPtYlzlQmVTHSKq2ChCKZP0cLNtN2YSS0/f4D1hi8W04Qh/JuSXZAdUThTAVjxDmxpiOMNwa/2WDXMuqip47dzZSQxtSdvTfeL9TVC/M1NaOzy8bqFx6pzi37zPATETT4PP1Zt/Pd23ZJYhwjxSyTlqj7529v0w=='), b64('AAAAgCwTZyEIlaCyG28EBm7WI0CAW3/IIsrNxATHjrJjcqQKaB5iF5e90PL66DSaTaEoTFZRlgOXsPiffBHXBO0P+lTyZ2jlq2J2zgeofRH3Yong4BT4xDtqBKtxixgC1MAHmrOnRXjAcDUiLxIGgU0YKSv0uAlgARsUwDsk0GEvK+jBAAAAQQDMi7liRBQ4/Z6a4wDL/rVnIJ9x+2h2UPK9J8U7f97x/THIBtfkbf9O7nDP6onValuSr86tMR24DJZsEXaGPwjDAAAAQQCs3J3D3jNVwwk16oySRSjA5x3tKCEITYMluyXX06cvFew8ldgRCYl1sh8RYAfbBKXhnJD77qIxtVNaF1yl/guxAAAAQFTRdKRUF2wLu/K/Rr34trwKrV6aW0GWyHlLuWvF7FUB85aDmtqYI2BSk92mVCKHBNw2T3cJMabN9JOznjtADiM='))
  2896. per_base_keytype_tests('rsa', run_ca_rsa_tests=True)
  2897. per_base_keytype_tests('rsa', run_ca_rsa_tests=True, ca_signflags=2)
  2898. per_base_keytype_tests('rsa', run_ca_rsa_tests=True, ca_signflags=4)
  2899. def testAESGCMBlockBoundaries(self):
  2900. # For standard AES-GCM test vectors, see the separate tests in
  2901. # standard_test_vectors.testAESGCM. This function will test
  2902. # the local interface, including the skip length and the
  2903. # machinery for incremental MAC update.
  2904. def aesgcm(key, iv, aes_impl, gcm_impl):
  2905. c = ssh_cipher_new('aes{:d}_gcm_{}'.format(8*len(key), aes_impl))
  2906. if c is None: return None, None # skip test if HW AES not available
  2907. m = ssh2_mac_new('aesgcm_{}'.format(gcm_impl), c)
  2908. if m is None: return None, None # skip test if HW GCM not available
  2909. c.setkey(key)
  2910. c.setiv(iv + b'\0'*4)
  2911. m.setkey(b'')
  2912. return c, m
  2913. def test_one(aes_impl, gcm_impl):
  2914. # An actual test from a session with OpenSSH, which
  2915. # demonstrates that the implementation in practice matches up
  2916. # to what the test vectors say. This is its SSH2_MSG_EXT_INFO
  2917. # packet.
  2918. key = unhex('dbf98b2f56c83fb2f9476aa876511225')
  2919. iv = unhex('9af15ecccf2bacaaa9625a6a')
  2920. plain = unhex('1007000000020000000f736572766572'
  2921. '2d7369672d616c6773000000db737368'
  2922. '2d656432353531392c736b2d7373682d'
  2923. '65643235353139406f70656e7373682e'
  2924. '636f6d2c7373682d7273612c7273612d'
  2925. '736861322d3235362c7273612d736861'
  2926. '322d3531322c7373682d6473732c6563'
  2927. '6473612d736861322d6e697374703235'
  2928. '362c65636473612d736861322d6e6973'
  2929. '74703338342c65636473612d73686132'
  2930. '2d6e697374703532312c736b2d656364'
  2931. '73612d736861322d6e69737470323536'
  2932. '406f70656e7373682e636f6d2c776562'
  2933. '617574686e2d736b2d65636473612d73'
  2934. '6861322d6e69737470323536406f7065'
  2935. '6e7373682e636f6d0000001f7075626c'
  2936. '69636b65792d686f7374626f756e6440'
  2937. '6f70656e7373682e636f6d0000000130'
  2938. '5935130804ad4b19ed2789210290c438')
  2939. aad = unhex('00000130')
  2940. cipher = unhex('c4b88f35c1ef8aa6225033c3f185d648'
  2941. '3c485d84930d5846f7851daacbff49d5'
  2942. '8cf72169fca7ab3c170376df65dd69de'
  2943. 'c40a94c6b8e3da6d61161ab19be27466'
  2944. '02e0dfa3330faae291ef4173a20e87a4'
  2945. 'd40728c645baa72916c1958531ef7b54'
  2946. '27228513e53005e6d17b9bb384b8d8c1'
  2947. '92b8a10b731459eed5a0fb120c283412'
  2948. 'e34445981df1257f1c35a06196731fed'
  2949. '1b3115f419e754de0b634bf68768cb02'
  2950. '29e70bb2259cedb5101ff6a4ac19aaad'
  2951. '46f1c30697361b45d6c152c3069cee6b'
  2952. 'd46e9785d65ea6bf7fca41f0ac3c8e93'
  2953. 'ce940b0059c39d51e49c17f60d48d633'
  2954. '5bae4402faab61d8d65221b24b400e65'
  2955. '89f941ff48310231a42641851ea00832'
  2956. '2c2d188f4cc6a4ec6002161c407d0a92'
  2957. 'f1697bb319fbec1ca63fa8e7ac171c85'
  2958. '5b60142bfcf4e5b0a9ada3451799866e')
  2959. c, m = aesgcm(key, iv, aes_impl, gcm_impl)
  2960. if c is None or m is None: return # skip if HW impl unavailable
  2961. len_dec = c.decrypt_length(aad, 123)
  2962. self.assertEqual(len_dec, aad) # length not actually encrypted
  2963. m.start()
  2964. # We expect 4 bytes skipped (the sequence number that
  2965. # ChaCha20-Poly1305 wants at the start of its MAC), and 4
  2966. # bytes AAD. These were initialised by the call to
  2967. # encrypt_length.
  2968. m.update(b'fake' + aad + cipher)
  2969. self.assertEqualBin(m.genresult(),
  2970. unhex('4a5a6d57d54888b4e58c57a96e00b73a'))
  2971. self.assertEqualBin(c.decrypt(cipher), plain)
  2972. c, m = aesgcm(key, iv, aes_impl, gcm_impl)
  2973. len_enc = c.encrypt_length(aad, 123)
  2974. self.assertEqual(len_enc, aad) # length not actually encrypted
  2975. self.assertEqualBin(c.encrypt(plain), cipher)
  2976. # Test incremental update.
  2977. def testIncremental(skiplen, aad, plain):
  2978. key, iv = b'SomeRandomKeyVal', b'SomeRandomIV'
  2979. mac_input = b'x' * skiplen + aad + plain
  2980. c, m = aesgcm(key, iv, aes_impl, gcm_impl)
  2981. aesgcm_set_prefix_lengths(m, skiplen, len(aad))
  2982. m.start()
  2983. m.update(mac_input)
  2984. reference_mac = m.genresult()
  2985. # Break the input just once, at each possible byte
  2986. # position.
  2987. for i in range(1, len(mac_input)):
  2988. c.setiv(iv + b'\0'*4)
  2989. m.setkey(b'')
  2990. aesgcm_set_prefix_lengths(m, skiplen, len(aad))
  2991. m.start()
  2992. m.update(mac_input[:i])
  2993. m.update(mac_input[i:])
  2994. self.assertEqualBin(m.genresult(), reference_mac)
  2995. # Feed the entire input in a byte at a time.
  2996. c.setiv(iv + b'\0'*4)
  2997. m.setkey(b'')
  2998. aesgcm_set_prefix_lengths(m, skiplen, len(aad))
  2999. m.start()
  3000. for i in range(len(mac_input)):
  3001. m.update(mac_input[i:i+1])
  3002. self.assertEqualBin(m.genresult(), reference_mac)
  3003. # Incremental test with more than a full block of each thing
  3004. testIncremental(23, b'abcdefghijklmnopqrst',
  3005. b'Lorem ipsum dolor sit amet')
  3006. # Incremental test with exactly a full block of each thing
  3007. testIncremental(16, b'abcdefghijklmnop',
  3008. b'Lorem ipsum dolo')
  3009. # Incremental test with less than a full block of each thing
  3010. testIncremental(7, b'abcdefghij',
  3011. b'Lorem ipsum')
  3012. for aes_impl in get_aes_impls():
  3013. for gcm_impl in get_aesgcm_impls():
  3014. with self.subTest(aes_impl=aes_impl, gcm_impl=gcm_impl):
  3015. test_one(aes_impl, gcm_impl)
  3016. def testAESGCMIV(self):
  3017. key = b'SomeRandomKeyVal'
  3018. def test(gcm, cbc, iv_fixed, iv_msg):
  3019. gcm.setiv(ssh_uint32(iv_fixed) + ssh_uint64(iv_msg) + b'fake')
  3020. cbc.setiv(b'\0' * 16)
  3021. preimage = cbc.decrypt(gcm.encrypt(b'\0' * 16))
  3022. self.assertEqualBin(preimage, ssh_uint32(iv_fixed) +
  3023. ssh_uint64(iv_msg) + ssh_uint32(1))
  3024. cbc.setiv(b'\0' * 16)
  3025. preimage = cbc.decrypt(gcm.encrypt(b'\0' * 16))
  3026. self.assertEqualBin(preimage, ssh_uint32(iv_fixed) +
  3027. ssh_uint64(iv_msg) + ssh_uint32(2))
  3028. gcm.next_message()
  3029. iv_msg = (iv_msg + 1) & ((1<<64)-1)
  3030. cbc.setiv(b'\0' * 16)
  3031. preimage = cbc.decrypt(gcm.encrypt(b'\0' * 16))
  3032. self.assertEqualBin(preimage, ssh_uint32(iv_fixed) +
  3033. ssh_uint64(iv_msg) + ssh_uint32(1))
  3034. cbc.setiv(b'\0' * 16)
  3035. preimage = cbc.decrypt(gcm.encrypt(b'\0' * 16))
  3036. self.assertEqualBin(preimage, ssh_uint32(iv_fixed) +
  3037. ssh_uint64(iv_msg) + ssh_uint32(2))
  3038. for impl in get_aes_impls():
  3039. with self.subTest(aes_impl=impl):
  3040. gcm = ssh_cipher_new('aes{:d}_gcm_{}'.format(8*len(key), impl))
  3041. if gcm is None: continue # skip if HW AES unavailable
  3042. gcm.setkey(key)
  3043. cbc = ssh_cipher_new('aes{:d}_cbc_{}'.format(8*len(key), impl))
  3044. # assume if gcm_<impl> is available, cbc_<impl> will be too
  3045. cbc.setkey(key)
  3046. # A simple test to ensure the low word gets
  3047. # incremented and that the whole IV looks basically
  3048. # the way we expect it to
  3049. test(gcm, cbc, 0x27182818, 0x3141592653589793)
  3050. # Test that carries are propagated into the high word
  3051. test(gcm, cbc, 0x27182818, 0x00000000FFFFFFFF)
  3052. # Test that carries _aren't_ propagated out of the
  3053. # high word of the message counter into the fixed word
  3054. # at the top
  3055. test(gcm, cbc, 0x27182818, 0xFFFFFFFFFFFFFFFF)
  3056. class standard_test_vectors(MyTestBase):
  3057. def testAES(self):
  3058. def vector(cipher, key, plaintext, ciphertext):
  3059. for suffix in get_aes_impls():
  3060. c = ssh_cipher_new("{}_{}".format(cipher, suffix))
  3061. if c is None: return # skip test if HW AES not available
  3062. ssh_cipher_setkey(c, key)
  3063. # The AES test vectors are implicitly in ECB mode,
  3064. # because they're testing the cipher primitive rather
  3065. # than any mode layered on top of it. We fake this by
  3066. # using PuTTY's CBC setting, and clearing the IV to
  3067. # all zeroes before each operation.
  3068. ssh_cipher_setiv(c, b'\x00' * 16)
  3069. self.assertEqualBin(
  3070. ssh_cipher_encrypt(c, plaintext), ciphertext)
  3071. ssh_cipher_setiv(c, b'\x00' * 16)
  3072. self.assertEqualBin(
  3073. ssh_cipher_decrypt(c, ciphertext), plaintext)
  3074. # The test vector from FIPS 197 appendix B. (This is also the
  3075. # same key whose key setup phase is shown in detail in
  3076. # appendix A.)
  3077. vector('aes128_cbc',
  3078. unhex('2b7e151628aed2a6abf7158809cf4f3c'),
  3079. unhex('3243f6a8885a308d313198a2e0370734'),
  3080. unhex('3925841d02dc09fbdc118597196a0b32'))
  3081. # The test vectors from FIPS 197 appendix C: the key bytes go
  3082. # 00 01 02 03 ... for as long as needed, and the plaintext
  3083. # bytes go 00 11 22 33 ... FF.
  3084. fullkey = struct.pack("B"*32, *range(32))
  3085. plaintext = struct.pack("B"*16, *[0x11*i for i in range(16)])
  3086. vector('aes128_cbc', fullkey[:16], plaintext,
  3087. unhex('69c4e0d86a7b0430d8cdb78070b4c55a'))
  3088. vector('aes192_cbc', fullkey[:24], plaintext,
  3089. unhex('dda97ca4864cdfe06eaf70a0ec0d7191'))
  3090. vector('aes256_cbc', fullkey[:32], plaintext,
  3091. unhex('8ea2b7ca516745bfeafc49904b496089'))
  3092. def testDES(self):
  3093. c = ssh_cipher_new("des_cbc")
  3094. def vector(key, plaintext, ciphertext):
  3095. key = unhex(key)
  3096. plaintext = unhex(plaintext)
  3097. ciphertext = unhex(ciphertext)
  3098. # Similarly to above, we fake DES ECB by using DES CBC and
  3099. # resetting the IV to zero all the time
  3100. ssh_cipher_setkey(c, key)
  3101. ssh_cipher_setiv(c, b'\x00' * 8)
  3102. self.assertEqualBin(ssh_cipher_encrypt(c, plaintext), ciphertext)
  3103. ssh_cipher_setiv(c, b'\x00' * 8)
  3104. self.assertEqualBin(ssh_cipher_decrypt(c, ciphertext), plaintext)
  3105. # Source: FIPS SP PUB 500-20
  3106. # 'Initial permutation and expansion tests': key fixed at 8
  3107. # copies of the byte 01, but ciphertext and plaintext in turn
  3108. # run through all possible values with exactly 1 bit set.
  3109. # Expected plaintexts and ciphertexts (respectively) listed in
  3110. # the arrays below.
  3111. ipe_key = '01' * 8
  3112. ipe_plaintexts = [
  3113. '166B40B44ABA4BD6', '06E7EA22CE92708F', 'D2FD8867D50D2DFE', 'CC083F1E6D9E85F6',
  3114. '5B711BC4CEEBF2EE', '0953E2258E8E90A1', 'E07C30D7E4E26E12', '2FBC291A570DB5C4',
  3115. 'DD7C0BBD61FAFD54', '48221B9937748A23', 'E643D78090CA4207', '8405D1ABE24FB942',
  3116. 'CE332329248F3228', '1D1CA853AE7C0C5F', '5D86CB23639DBEA9', '1029D55E880EC2D0',
  3117. '8DD45A2DDF90796C', 'CAFFC6AC4542DE31', 'EA51D3975595B86B', '8B54536F2F3E64A8',
  3118. '866ECEDD8072BB0E', '79E90DBC98F92CCA', 'AB6A20C0620D1C6F', '25EB5FC3F8CF0621',
  3119. '4D49DB1532919C9F', '814EEB3B91D90726', '5E0905517BB59BCF', 'CA3A2B036DBC8502',
  3120. 'FA0752B07D9C4AB8', 'B160E4680F6C696F', 'DF98C8276F54B04B', 'E943D7568AEC0C5C',
  3121. 'AEB5F5EDE22D1A36', 'E428581186EC8F46', 'E1652C6B138C64A5', 'D106FF0BED5255D7',
  3122. '9D64555A9A10B852', 'F02B263B328E2B60', '64FEED9C724C2FAF', '750D079407521363',
  3123. 'FBE00A8A1EF8AD72', 'A484C3AD38DC9C19', '12A9F5817FF2D65D', 'E7FCE22557D23C97',
  3124. '329A8ED523D71AEC', 'E19E275D846A1298', '889DE068A16F0BE6', '2B9F982F20037FA9',
  3125. 'F356834379D165CD', 'ECBFE3BD3F591A5E', 'E6D5F82752AD63D1', 'ADD0CC8D6E5DEBA1',
  3126. 'F15D0F286B65BD28', 'B8061B7ECD9A21E5', '424250B37C3DD951', 'D9031B0271BD5A0A',
  3127. '0D9F279BA5D87260', '6CC5DEFAAF04512F', '55579380D77138EF', '20B9E767B2FB1456',
  3128. '4BD388FF6CD81D4F', '2E8653104F3834EA', 'DD7F121CA5015619', '95F8A5E5DD31D900',
  3129. ]
  3130. ipe_ciphertexts = [
  3131. '166B40B44ABA4BD6', '06E7EA22CE92708F', 'D2FD8867D50D2DFE', 'CC083F1E6D9E85F6',
  3132. '5B711BC4CEEBF2EE', '0953E2258E8E90A1', 'E07C30D7E4E26E12', '2FBC291A570DB5C4',
  3133. 'DD7C0BBD61FAFD54', '48221B9937748A23', 'E643D78090CA4207', '8405D1ABE24FB942',
  3134. 'CE332329248F3228', '1D1CA853AE7C0C5F', '5D86CB23639DBEA9', '1029D55E880EC2D0',
  3135. '8DD45A2DDF90796C', 'CAFFC6AC4542DE31', 'EA51D3975595B86B', '8B54536F2F3E64A8',
  3136. '866ECEDD8072BB0E', '79E90DBC98F92CCA', 'AB6A20C0620D1C6F', '25EB5FC3F8CF0621',
  3137. '4D49DB1532919C9F', '814EEB3B91D90726', '5E0905517BB59BCF', 'CA3A2B036DBC8502',
  3138. 'FA0752B07D9C4AB8', 'B160E4680F6C696F', 'DF98C8276F54B04B', 'E943D7568AEC0C5C',
  3139. 'AEB5F5EDE22D1A36', 'E428581186EC8F46', 'E1652C6B138C64A5', 'D106FF0BED5255D7',
  3140. '9D64555A9A10B852', 'F02B263B328E2B60', '64FEED9C724C2FAF', '750D079407521363',
  3141. 'FBE00A8A1EF8AD72', 'A484C3AD38DC9C19', '12A9F5817FF2D65D', 'E7FCE22557D23C97',
  3142. '329A8ED523D71AEC', 'E19E275D846A1298', '889DE068A16F0BE6', '2B9F982F20037FA9',
  3143. 'F356834379D165CD', 'ECBFE3BD3F591A5E', 'E6D5F82752AD63D1', 'ADD0CC8D6E5DEBA1',
  3144. 'F15D0F286B65BD28', 'B8061B7ECD9A21E5', '424250B37C3DD951', 'D9031B0271BD5A0A',
  3145. '0D9F279BA5D87260', '6CC5DEFAAF04512F', '55579380D77138EF', '20B9E767B2FB1456',
  3146. '4BD388FF6CD81D4F', '2E8653104F3834EA', 'DD7F121CA5015619', '95F8A5E5DD31D900',
  3147. ]
  3148. ipe_single_bits = ["{:016x}".format(1 << bit) for bit in range(64)]
  3149. for plaintext, ciphertext in zip(ipe_plaintexts, ipe_single_bits):
  3150. vector(ipe_key, plaintext, ciphertext)
  3151. for plaintext, ciphertext in zip(ipe_single_bits, ipe_ciphertexts):
  3152. vector(ipe_key, plaintext, ciphertext)
  3153. # 'Key permutation tests': plaintext fixed at all zeroes, key
  3154. # is a succession of tweaks of the previous key made by
  3155. # replacing each 01 byte in turn with one containing a
  3156. # different single set bit (e.g. 01 20 01 01 01 01 01 01).
  3157. # Expected ciphertexts listed.
  3158. kp_ciphertexts = [
  3159. '95A8D72813DAA94D', '0EEC1487DD8C26D5', '7AD16FFB79C45926', 'D3746294CA6A6CF3',
  3160. '809F5F873C1FD761', 'C02FAFFEC989D1FC', '4615AA1D33E72F10', '2055123350C00858',
  3161. 'DF3B99D6577397C8', '31FE17369B5288C9', 'DFDD3CC64DAE1642', '178C83CE2B399D94',
  3162. '50F636324A9B7F80', 'A8468EE3BC18F06D', 'A2DC9E92FD3CDE92', 'CAC09F797D031287',
  3163. '90BA680B22AEB525', 'CE7A24F350E280B6', '882BFF0AA01A0B87', '25610288924511C2',
  3164. 'C71516C29C75D170', '5199C29A52C9F059', 'C22F0A294A71F29F', 'EE371483714C02EA',
  3165. 'A81FBD448F9E522F', '4F644C92E192DFED', '1AFA9A66A6DF92AE', 'B3C1CC715CB879D8',
  3166. '19D032E64AB0BD8B', '3CFAA7A7DC8720DC', 'B7265F7F447AC6F3', '9DB73B3C0D163F54',
  3167. '8181B65BABF4A975', '93C9B64042EAA240', '5570530829705592', '8638809E878787A0',
  3168. '41B9A79AF79AC208', '7A9BE42F2009A892', '29038D56BA6D2745', '5495C6ABF1E5DF51',
  3169. 'AE13DBD561488933', '024D1FFA8904E389', 'D1399712F99BF02E', '14C1D7C1CFFEC79E',
  3170. '1DE5279DAE3BED6F', 'E941A33F85501303', 'DA99DBBC9A03F379', 'B7FC92F91D8E92E9',
  3171. 'AE8E5CAA3CA04E85', '9CC62DF43B6EED74', 'D863DBB5C59A91A0', 'A1AB2190545B91D7',
  3172. '0875041E64C570F7', '5A594528BEBEF1CC', 'FCDB3291DE21F0C0', '869EFD7F9F265A09',
  3173. ]
  3174. kp_key_repl_bytes = ["{:02x}".format(0x80>>i) for i in range(7)]
  3175. kp_keys = ['01'*j + b + '01'*(7-j)
  3176. for j in range(8) for b in kp_key_repl_bytes]
  3177. kp_plaintext = '0' * 16
  3178. for key, ciphertext in zip(kp_keys, kp_ciphertexts):
  3179. vector(key, kp_plaintext, ciphertext)
  3180. # 'Data permutation test': plaintext fixed at all zeroes,
  3181. # pairs of key and expected ciphertext listed below.
  3182. dp_keys_and_ciphertexts = [
  3183. '1046913489980131:88D55E54F54C97B4', '1007103489988020:0C0CC00C83EA48FD',
  3184. '10071034C8980120:83BC8EF3A6570183', '1046103489988020:DF725DCAD94EA2E9',
  3185. '1086911519190101:E652B53B550BE8B0', '1086911519580101:AF527120C485CBB0',
  3186. '5107B01519580101:0F04CE393DB926D5', '1007B01519190101:C9F00FFC74079067',
  3187. '3107915498080101:7CFD82A593252B4E', '3107919498080101:CB49A2F9E91363E3',
  3188. '10079115B9080140:00B588BE70D23F56', '3107911598080140:406A9A6AB43399AE',
  3189. '1007D01589980101:6CB773611DCA9ADA', '9107911589980101:67FD21C17DBB5D70',
  3190. '9107D01589190101:9592CB4110430787', '1007D01598980120:A6B7FF68A318DDD3',
  3191. '1007940498190101:4D102196C914CA16', '0107910491190401:2DFA9F4573594965',
  3192. '0107910491190101:B46604816C0E0774', '0107940491190401:6E7E6221A4F34E87',
  3193. '19079210981A0101:AA85E74643233199', '1007911998190801:2E5A19DB4D1962D6',
  3194. '10079119981A0801:23A866A809D30894', '1007921098190101:D812D961F017D320',
  3195. '100791159819010B:055605816E58608F', '1004801598190101:ABD88E8B1B7716F1',
  3196. '1004801598190102:537AC95BE69DA1E1', '1004801598190108:AED0F6AE3C25CDD8',
  3197. '1002911498100104:B3E35A5EE53E7B8D', '1002911598190104:61C79C71921A2EF8',
  3198. '1002911598100201:E2F5728F0995013C', '1002911698100101:1AEAC39A61F0A464',
  3199. ]
  3200. dp_plaintext = '0' * 16
  3201. for key_and_ciphertext in dp_keys_and_ciphertexts:
  3202. key, ciphertext = key_and_ciphertext.split(":")
  3203. vector(key, dp_plaintext, ciphertext)
  3204. # Tests intended to select every entry in every S-box. Full
  3205. # arbitrary triples (key, plaintext, ciphertext).
  3206. sb_complete_tests = [
  3207. '7CA110454A1A6E57:01A1D6D039776742:690F5B0D9A26939B',
  3208. '0131D9619DC1376E:5CD54CA83DEF57DA:7A389D10354BD271',
  3209. '07A1133E4A0B2686:0248D43806F67172:868EBB51CAB4599A',
  3210. '3849674C2602319E:51454B582DDF440A:7178876E01F19B2A',
  3211. '04B915BA43FEB5B6:42FD443059577FA2:AF37FB421F8C4095',
  3212. '0113B970FD34F2CE:059B5E0851CF143A:86A560F10EC6D85B',
  3213. '0170F175468FB5E6:0756D8E0774761D2:0CD3DA020021DC09',
  3214. '43297FAD38E373FE:762514B829BF486A:EA676B2CB7DB2B7A',
  3215. '07A7137045DA2A16:3BDD119049372802:DFD64A815CAF1A0F',
  3216. '04689104C2FD3B2F:26955F6835AF609A:5C513C9C4886C088',
  3217. '37D06BB516CB7546:164D5E404F275232:0A2AEEAE3FF4AB77',
  3218. '1F08260D1AC2465E:6B056E18759F5CCA:EF1BF03E5DFA575A',
  3219. '584023641ABA6176:004BD6EF09176062:88BF0DB6D70DEE56',
  3220. '025816164629B007:480D39006EE762F2:A1F9915541020B56',
  3221. '49793EBC79B3258F:437540C8698F3CFA:6FBF1CAFCFFD0556',
  3222. '4FB05E1515AB73A7:072D43A077075292:2F22E49BAB7CA1AC',
  3223. '49E95D6D4CA229BF:02FE55778117F12A:5A6B612CC26CCE4A',
  3224. '018310DC409B26D6:1D9D5C5018F728C2:5F4C038ED12B2E41',
  3225. '1C587F1C13924FEF:305532286D6F295A:63FAC0D034D9F793',
  3226. ]
  3227. for test in sb_complete_tests:
  3228. key, plaintext, ciphertext = test.split(":")
  3229. vector(key, plaintext, ciphertext)
  3230. def testMD5(self):
  3231. MD5 = lambda s: hash_str('md5', s)
  3232. # The test vectors from RFC 1321 section A.5.
  3233. self.assertEqualBin(MD5(""),
  3234. unhex('d41d8cd98f00b204e9800998ecf8427e'))
  3235. self.assertEqualBin(MD5("a"),
  3236. unhex('0cc175b9c0f1b6a831c399e269772661'))
  3237. self.assertEqualBin(MD5("abc"),
  3238. unhex('900150983cd24fb0d6963f7d28e17f72'))
  3239. self.assertEqualBin(MD5("message digest"),
  3240. unhex('f96b697d7cb7938d525a2f31aaf161d0'))
  3241. self.assertEqualBin(MD5("abcdefghijklmnopqrstuvwxyz"),
  3242. unhex('c3fcd3d76192e4007dfb496cca67e13b'))
  3243. self.assertEqualBin(MD5("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  3244. "abcdefghijklmnopqrstuvwxyz0123456789"),
  3245. unhex('d174ab98d277d9f5a5611c2c9f419d9f'))
  3246. self.assertEqualBin(MD5("1234567890123456789012345678901234567890"
  3247. "1234567890123456789012345678901234567890"),
  3248. unhex('57edf4a22be3c955ac49da2e2107b67a'))
  3249. def testHmacMD5(self):
  3250. # The test vectors from the RFC 2104 Appendix.
  3251. self.assertEqualBin(mac_str('hmac_md5', unhex('0b'*16), "Hi There"),
  3252. unhex('9294727a3638bb1c13f48ef8158bfc9d'))
  3253. self.assertEqualBin(mac_str('hmac_md5', "Jefe",
  3254. "what do ya want for nothing?"),
  3255. unhex('750c783e6ab0b503eaa86e310a5db738'))
  3256. self.assertEqualBin(mac_str('hmac_md5', unhex('aa'*16), unhex('dd'*50)),
  3257. unhex('56be34521d144c88dbb8c733f0e8b3f6'))
  3258. def testSHA1(self):
  3259. for hashname in get_implementations("sha1"):
  3260. if ssh_hash_new(hashname) is None:
  3261. continue # skip testing of unavailable HW implementation
  3262. # Test cases from RFC 6234 section 8.5, omitting the ones
  3263. # whose input is not a multiple of 8 bits
  3264. self.assertEqualBin(hash_str(hashname, "abc"), unhex(
  3265. "a9993e364706816aba3e25717850c26c9cd0d89d"))
  3266. self.assertEqualBin(hash_str(hashname,
  3267. "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"),
  3268. unhex("84983e441c3bd26ebaae4aa1f95129e5e54670f1"))
  3269. self.assertEqualBin(hash_str_iter(hashname,
  3270. ("a" * 1000 for _ in range(1000))), unhex(
  3271. "34aa973cd4c4daa4f61eeb2bdbad27316534016f"))
  3272. self.assertEqualBin(hash_str(hashname,
  3273. "01234567012345670123456701234567" * 20), unhex(
  3274. "dea356a2cddd90c7a7ecedc5ebb563934f460452"))
  3275. self.assertEqualBin(hash_str(hashname, b"\x5e"), unhex(
  3276. "5e6f80a34a9798cafc6a5db96cc57ba4c4db59c2"))
  3277. self.assertEqualBin(hash_str(hashname,
  3278. unhex("9a7dfdf1ecead06ed646aa55fe757146")), unhex(
  3279. "82abff6605dbe1c17def12a394fa22a82b544a35"))
  3280. self.assertEqualBin(hash_str(hashname, unhex(
  3281. "f78f92141bcd170ae89b4fba15a1d59f"
  3282. "3fd84d223c9251bdacbbae61d05ed115"
  3283. "a06a7ce117b7beead24421ded9c32592"
  3284. "bd57edeae39c39fa1fe8946a84d0cf1f"
  3285. "7beead1713e2e0959897347f67c80b04"
  3286. "00c209815d6b10a683836fd5562a56ca"
  3287. "b1a28e81b6576654631cf16566b86e3b"
  3288. "33a108b05307c00aff14a768ed735060"
  3289. "6a0f85e6a91d396f5b5cbe577f9b3880"
  3290. "7c7d523d6d792f6ebc24a4ecf2b3a427"
  3291. "cdbbfb")), unhex(
  3292. "cb0082c8f197d260991ba6a460e76e202bad27b3"))
  3293. def testSHA256(self):
  3294. for hashname in get_implementations("sha256"):
  3295. if ssh_hash_new(hashname) is None:
  3296. continue # skip testing of unavailable HW implementation
  3297. # Test cases from RFC 6234 section 8.5, omitting the ones
  3298. # whose input is not a multiple of 8 bits
  3299. self.assertEqualBin(hash_str(hashname, "abc"),
  3300. unhex("ba7816bf8f01cfea414140de5dae2223"
  3301. "b00361a396177a9cb410ff61f20015ad"))
  3302. self.assertEqualBin(hash_str(hashname,
  3303. "abcdbcdecdefdefgefghfghighijhijk""ijkljklmklmnlmnomnopnopq"),
  3304. unhex("248d6a61d20638b8e5c026930c3e6039"
  3305. "a33ce45964ff2167f6ecedd419db06c1"))
  3306. self.assertEqualBin(
  3307. hash_str_iter(hashname, ("a" * 1000 for _ in range(1000))),
  3308. unhex("cdc76e5c9914fb9281a1c7e284d73e67"
  3309. "f1809a48a497200e046d39ccc7112cd0"))
  3310. self.assertEqualBin(
  3311. hash_str(hashname, "01234567012345670123456701234567" * 20),
  3312. unhex("594847328451bdfa85056225462cc1d8"
  3313. "67d877fb388df0ce35f25ab5562bfbb5"))
  3314. self.assertEqualBin(hash_str(hashname, b"\x19"),
  3315. unhex("68aa2e2ee5dff96e3355e6c7ee373e3d"
  3316. "6a4e17f75f9518d843709c0c9bc3e3d4"))
  3317. self.assertEqualBin(
  3318. hash_str(hashname, unhex("e3d72570dcdd787ce3887ab2cd684652")),
  3319. unhex("175ee69b02ba9b58e2b0a5fd13819cea"
  3320. "573f3940a94f825128cf4209beabb4e8"))
  3321. self.assertEqualBin(hash_str(hashname, unhex(
  3322. "8326754e2277372f4fc12b20527afef0"
  3323. "4d8a056971b11ad57123a7c137760000"
  3324. "d7bef6f3c1f7a9083aa39d810db31077"
  3325. "7dab8b1e7f02b84a26c773325f8b2374"
  3326. "de7a4b5a58cb5c5cf35bcee6fb946e5b"
  3327. "d694fa593a8beb3f9d6592ecedaa66ca"
  3328. "82a29d0c51bcf9336230e5d784e4c0a4"
  3329. "3f8d79a30a165cbabe452b774b9c7109"
  3330. "a97d138f129228966f6c0adc106aad5a"
  3331. "9fdd30825769b2c671af6759df28eb39"
  3332. "3d54d6")), unhex(
  3333. "97dbca7df46d62c8a422c941dd7e835b"
  3334. "8ad3361763f7e9b2d95f4f0da6e1ccbc"))
  3335. def testSHA384(self):
  3336. for hashname in get_implementations("sha384"):
  3337. if ssh_hash_new(hashname) is None:
  3338. continue # skip testing of unavailable HW implementation
  3339. # Test cases from RFC 6234 section 8.5, omitting the ones
  3340. # whose input is not a multiple of 8 bits
  3341. self.assertEqualBin(hash_str(hashname, "abc"), unhex(
  3342. 'cb00753f45a35e8bb5a03d699ac65007272c32ab0eded163'
  3343. '1a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7'))
  3344. self.assertEqualBin(hash_str(hashname,
  3345. "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
  3346. "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"),
  3347. unhex('09330c33f71147e83d192fc782cd1b4753111b173b3b05d2'
  3348. '2fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039'))
  3349. self.assertEqualBin(hash_str_iter(hashname,
  3350. ("a" * 1000 for _ in range(1000))), unhex(
  3351. '9d0e1809716474cb086e834e310a4a1ced149e9c00f24852'
  3352. '7972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985'))
  3353. self.assertEqualBin(hash_str(hashname,
  3354. "01234567012345670123456701234567" * 20), unhex(
  3355. '2fc64a4f500ddb6828f6a3430b8dd72a368eb7f3a8322a70'
  3356. 'bc84275b9c0b3ab00d27a5cc3c2d224aa6b61a0d79fb4596'))
  3357. self.assertEqualBin(hash_str(hashname, b"\xB9"), unhex(
  3358. 'bc8089a19007c0b14195f4ecc74094fec64f01f90929282c'
  3359. '2fb392881578208ad466828b1c6c283d2722cf0ad1ab6938'))
  3360. self.assertEqualBin(hash_str(hashname,
  3361. unhex("a41c497779c0375ff10a7f4e08591739")), unhex(
  3362. 'c9a68443a005812256b8ec76b00516f0dbb74fab26d66591'
  3363. '3f194b6ffb0e91ea9967566b58109cbc675cc208e4c823f7'))
  3364. self.assertEqualBin(hash_str(hashname, unhex(
  3365. "399669e28f6b9c6dbcbb6912ec10ffcf74790349b7dc8fbe4a8e7b3b5621"
  3366. "db0f3e7dc87f823264bbe40d1811c9ea2061e1c84ad10a23fac1727e7202"
  3367. "fc3f5042e6bf58cba8a2746e1f64f9b9ea352c711507053cf4e5339d5286"
  3368. "5f25cc22b5e87784a12fc961d66cb6e89573199a2ce6565cbdf13dca4038"
  3369. "32cfcb0e8b7211e83af32a11ac17929ff1c073a51cc027aaedeff85aad7c"
  3370. "2b7c5a803e2404d96d2a77357bda1a6daeed17151cb9bc5125a422e941de"
  3371. "0ca0fc5011c23ecffefdd09676711cf3db0a3440720e1615c1f22fbc3c72"
  3372. "1de521e1b99ba1bd5577408642147ed096")), unhex(
  3373. '4f440db1e6edd2899fa335f09515aa025ee177a79f4b4aaf'
  3374. '38e42b5c4de660f5de8fb2a5b2fbd2a3cbffd20cff1288c0'))
  3375. def testSHA512(self):
  3376. for hashname in get_implementations("sha512"):
  3377. if ssh_hash_new(hashname) is None:
  3378. continue # skip testing of unavailable HW implementation
  3379. # Test cases from RFC 6234 section 8.5, omitting the ones
  3380. # whose input is not a multiple of 8 bits
  3381. self.assertEqualBin(hash_str(hashname, "abc"), unhex(
  3382. 'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55'
  3383. 'd39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94f'
  3384. 'a54ca49f'))
  3385. self.assertEqualBin(hash_str(hashname,
  3386. "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
  3387. "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"),
  3388. unhex('8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299'
  3389. 'aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26'
  3390. '545e96e55b874be909'))
  3391. self.assertEqualBin(hash_str_iter(hashname,
  3392. ("a" * 1000 for _ in range(1000))), unhex(
  3393. 'e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa9'
  3394. '73ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217'
  3395. 'ad8cc09b'))
  3396. self.assertEqualBin(hash_str(hashname,
  3397. "01234567012345670123456701234567" * 20), unhex(
  3398. '89d05ba632c699c31231ded4ffc127d5a894dad412c0e024db872d1abd2b'
  3399. 'a8141a0f85072a9be1e2aa04cf33c765cb510813a39cd5a84c4acaa64d3f'
  3400. '3fb7bae9'))
  3401. self.assertEqualBin(hash_str(hashname, b"\xD0"), unhex(
  3402. '9992202938e882e73e20f6b69e68a0a7149090423d93c81bab3f21678d4a'
  3403. 'ceeee50e4e8cafada4c85a54ea8306826c4ad6e74cece9631bfa8a549b4a'
  3404. 'b3fbba15'))
  3405. self.assertEqualBin(hash_str(hashname,
  3406. unhex("8d4e3c0e3889191491816e9d98bff0a0")), unhex(
  3407. 'cb0b67a4b8712cd73c9aabc0b199e9269b20844afb75acbdd1c153c98289'
  3408. '24c3ddedaafe669c5fdd0bc66f630f6773988213eb1b16f517ad0de4b2f0'
  3409. 'c95c90f8'))
  3410. self.assertEqualBin(hash_str(hashname, unhex(
  3411. "a55f20c411aad132807a502d65824e31a2305432aa3d06d3e282a8d84e0d"
  3412. "e1de6974bf495469fc7f338f8054d58c26c49360c3e87af56523acf6d89d"
  3413. "03e56ff2f868002bc3e431edc44df2f0223d4bb3b243586e1a7d92493669"
  3414. "4fcbbaf88d9519e4eb50a644f8e4f95eb0ea95bc4465c8821aacd2fe15ab"
  3415. "4981164bbb6dc32f969087a145b0d9cc9c67c22b763299419cc4128be9a0"
  3416. "77b3ace634064e6d99283513dc06e7515d0d73132e9a0dc6d3b1f8b246f1"
  3417. "a98a3fc72941b1e3bb2098e8bf16f268d64f0b0f4707fe1ea1a1791ba2f3"
  3418. "c0c758e5f551863a96c949ad47d7fb40d2")), unhex(
  3419. 'c665befb36da189d78822d10528cbf3b12b3eef726039909c1a16a270d48'
  3420. '719377966b957a878e720584779a62825c18da26415e49a7176a894e7510'
  3421. 'fd1451f5'))
  3422. def testSHA3(self):
  3423. # Source: all the SHA-3 test strings from
  3424. # https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values#aHashing
  3425. # which are a multiple of 8 bits long.
  3426. self.assertEqualBin(hash_str('sha3_224', ''), unhex("6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"))
  3427. self.assertEqualBin(hash_str('sha3_224', unhex('a3')*200), unhex("9376816aba503f72f96ce7eb65ac095deee3be4bf9bbc2a1cb7e11e0"))
  3428. self.assertEqualBin(hash_str('sha3_256', ''), unhex("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"))
  3429. self.assertEqualBin(hash_str('sha3_256', unhex('a3')*200), unhex("79f38adec5c20307a98ef76e8324afbfd46cfd81b22e3973c65fa1bd9de31787"))
  3430. self.assertEqualBin(hash_str('sha3_384', ''), unhex("0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"))
  3431. self.assertEqualBin(hash_str('sha3_384', unhex('a3')*200), unhex("1881de2ca7e41ef95dc4732b8f5f002b189cc1e42b74168ed1732649ce1dbcdd76197a31fd55ee989f2d7050dd473e8f"))
  3432. self.assertEqualBin(hash_str('sha3_512', ''), unhex("a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"))
  3433. self.assertEqualBin(hash_str('sha3_512', unhex('a3')*200), unhex("e76dfad22084a8b1467fcf2ffa58361bec7628edf5f3fdc0e4805dc48caeeca81b7c13c30adf52a3659584739a2df46be589c51ca1a4a8416df6545a1ce8ba00"))
  3434. self.assertEqualBin(hash_str('shake256_114bytes', ''), unhex("46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be141e96616fb13957692cc7edd0b45ae3dc07223c8e92937bef84bc0eab862853349ec75546f58fb7c2775c38462c5010d846"))
  3435. self.assertEqualBin(hash_str('shake256_114bytes', unhex('a3')*200), unhex("cd8a920ed141aa0407a22d59288652e9d9f1a7ee0c1e7c1ca699424da84a904d2d700caae7396ece96604440577da4f3aa22aeb8857f961c4cd8e06f0ae6610b1048a7f64e1074cd629e85ad7566048efc4fb500b486a3309a8f26724c0ed628001a1099422468de726f1061d99eb9e93604"))
  3436. def testBLAKE2b(self):
  3437. # Test case from RFC 7693 appendix A.
  3438. self.assertEqualBin(hash_str('blake2b', b'abc'), unhex(
  3439. "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1"
  3440. "7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"))
  3441. # A small number of test cases from the larger test vector
  3442. # set, testing multiple blocks and the empty input.
  3443. self.assertEqualBin(hash_str('blake2b', b''), unhex(
  3444. "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419"
  3445. "d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"))
  3446. self.assertEqualBin(hash_str('blake2b', unhex('00')), unhex(
  3447. "2fa3f686df876995167e7c2e5d74c4c7b6e48f8068fe0e44208344d480f7904c"
  3448. "36963e44115fe3eb2a3ac8694c28bcb4f5a0f3276f2e79487d8219057a506e4b"))
  3449. self.assertEqualBin(hash_str('blake2b', bytes(range(255))), unhex(
  3450. "5b21c5fd8868367612474fa2e70e9cfa2201ffeee8fafab5797ad58fefa17c9b"
  3451. "5b107da4a3db6320baaf2c8617d5a51df914ae88da3867c2d41f0cc14fa67928"))
  3452. # You can get this test program to run the full version of the
  3453. # test vectors by modifying the source temporarily to set this
  3454. # variable to a pathname where you downloaded the JSON file
  3455. # blake2-kat.json.
  3456. blake2_test_vectors_path = None
  3457. if blake2_test_vectors_path is not None:
  3458. with open(blake2_test_vectors_path) as fh:
  3459. vectors = json.load(fh)
  3460. for vector in vectors:
  3461. if vector['hash'] != 'blake2b':
  3462. continue
  3463. if len(vector['key']) != 0:
  3464. continue
  3465. h = blake2b_new_general(len(vector['out']) // 2)
  3466. ssh_hash_update(h, unhex(vector['in']))
  3467. digest = ssh_hash_digest(h)
  3468. self.assertEqualBin(digest, unhex(vector['out']))
  3469. def testArgon2(self):
  3470. # draft-irtf-cfrg-argon2-12 section 5
  3471. self.assertEqualBin(
  3472. argon2('d', 32, 3, 4, 32, b'\x01' * 32, b'\x02' * 16,
  3473. b'\x03' * 8, b'\x04' * 12),
  3474. unhex("512b391b6f1162975371d30919734294"
  3475. "f868e3be3984f3c1a13a4db9fabe4acb"))
  3476. self.assertEqualBin(
  3477. argon2('i', 32, 3, 4, 32, b'\x01' * 32, b'\x02' * 16,
  3478. b'\x03' * 8, b'\x04' * 12),
  3479. unhex("c814d9d1dc7f37aa13f0d77f2494bda1"
  3480. "c8de6b016dd388d29952a4c4672b6ce8"))
  3481. self.assertEqualBin(
  3482. argon2('id', 32, 3, 4, 32, b'\x01' * 32, b'\x02' * 16,
  3483. b'\x03' * 8, b'\x04' * 12),
  3484. unhex("0d640df58d78766c08c037a34a8b53c9"
  3485. "d01ef0452d75b65eb52520e96b01e659"))
  3486. def testHmacSHA(self):
  3487. # Test cases from RFC 6234 section 8.5.
  3488. def vector(key, message, s1=None, s256=None, s512=None):
  3489. if s1 is not None:
  3490. self.assertEqualBin(
  3491. mac_str('hmac_sha1', key, message), unhex(s1))
  3492. if s256 is not None:
  3493. self.assertEqualBin(
  3494. mac_str('hmac_sha256', key, message), unhex(s256))
  3495. if s512 is not None:
  3496. self.assertEqualBin(
  3497. mac_str('hmac_sha512', key, message), unhex(s512))
  3498. vector(
  3499. unhex("0b"*20), "Hi There",
  3500. "b617318655057264e28bc0b6fb378c8ef146be00",
  3501. "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
  3502. "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde"
  3503. "daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854")
  3504. vector(
  3505. "Jefe", "what do ya want for nothing?",
  3506. "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79",
  3507. "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
  3508. "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554"
  3509. "9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737")
  3510. vector(
  3511. unhex("aa"*20), unhex('dd'*50),
  3512. "125d7342b9ac11cd91a39af48aa17b4f63f175d3",
  3513. "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565FE",
  3514. "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39"
  3515. "bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb")
  3516. vector(
  3517. unhex("0102030405060708090a0b0c0d0e0f10111213141516171819"),
  3518. unhex("cd"*50),
  3519. "4c9007f4026250c6bc8414f9bf50c86c2d7235da",
  3520. "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
  3521. "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db"
  3522. "a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd")
  3523. vector(
  3524. unhex("aa"*80),
  3525. "Test Using Larger Than Block-Size Key - Hash Key First",
  3526. s1="aa4ae5e15272d00e95705637ce8a3b55ed402112")
  3527. vector(
  3528. unhex("aa"*131),
  3529. "Test Using Larger Than Block-Size Key - Hash Key First",
  3530. s256="60e431591ee0b67f0d8a26aacbf5b77f"
  3531. "8e0bc6213728c5140546040f0ee37f54", s512=
  3532. "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352"
  3533. "6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598")
  3534. vector(
  3535. unhex("aa"*80),
  3536. "Test Using Larger Than Block-Size Key and "
  3537. "Larger Than One Block-Size Data",
  3538. s1="e8e99d0f45237d786d6bbaa7965c7808bbff1a91")
  3539. vector(
  3540. unhex("aa"*131),
  3541. "This is a test using a larger than block-size key and a "
  3542. "larger than block-size data. The key needs to be hashed "
  3543. "before being used by the HMAC algorithm.",
  3544. s256="9b09ffa71b942fcb27635fbcd5b0e944"
  3545. "bfdc63644f0713938a7f51535c3a35e2", s512=
  3546. "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944"
  3547. "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58")
  3548. def testEd25519(self):
  3549. def vector(privkey, pubkey, message, signature):
  3550. x, y = ecc_edwards_get_affine(eddsa_public(
  3551. mp_from_bytes_le(privkey), 'ed25519'))
  3552. self.assertEqual(int(y) | ((int(x) & 1) << 255),
  3553. int(mp_from_bytes_le(pubkey)))
  3554. pubblob = ssh_string(b"ssh-ed25519") + ssh_string(pubkey)
  3555. privblob = ssh_string(privkey)
  3556. sigblob = ssh_string(b"ssh-ed25519") + ssh_string(signature)
  3557. pubkey = ssh_key_new_pub('ed25519', pubblob)
  3558. self.assertTrue(ssh_key_verify(pubkey, sigblob, message))
  3559. privkey = ssh_key_new_priv('ed25519', pubblob, privblob)
  3560. # By testing that the signature is exactly the one expected in
  3561. # the test vector and not some equivalent one generated with a
  3562. # different nonce, we're verifying in particular that we do
  3563. # our deterministic nonce generation in the manner specified
  3564. # by Ed25519. Getting that wrong would lead to no obvious
  3565. # failure, but would surely turn out to be a bad idea sooner
  3566. # or later...
  3567. self.assertEqualBin(ssh_key_sign(privkey, message, 0), sigblob)
  3568. # A cherry-picked example from DJB's test vector data at
  3569. # https://ed25519.cr.yp.to/python/sign.input, which is too
  3570. # large to copy into here in full.
  3571. privkey = unhex(
  3572. 'c89955e0f7741d905df0730b3dc2b0ce1a13134e44fef3d40d60c020ef19df77')
  3573. pubkey = unhex(
  3574. 'fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c')
  3575. message = unhex(
  3576. '507c94c8820d2a5793cbf3442b3d71936f35fe3afef316')
  3577. signature = unhex(
  3578. '7ef66e5e86f2360848e0014e94880ae2920ad8a3185a46b35d1e07dea8fa8ae4'
  3579. 'f6b843ba174d99fa7986654a0891c12a794455669375bf92af4cc2770b579e0c')
  3580. vector(privkey, pubkey, message, signature)
  3581. # You can get this test program to run the full version of
  3582. # DJB's test vectors by modifying the source temporarily to
  3583. # set this variable to a pathname where you downloaded the
  3584. # file.
  3585. ed25519_test_vector_path = None
  3586. if ed25519_test_vector_path is not None:
  3587. with open(ed25519_test_vector_path) as f:
  3588. for line in iter(f.readline, ""):
  3589. words = line.split(":")
  3590. # DJB's test vector input format concatenates a
  3591. # spare copy of the public key to the end of the
  3592. # private key, and a spare copy of the message to
  3593. # the end of the signature. Strip those off.
  3594. privkey = unhex(words[0])[:32]
  3595. pubkey = unhex(words[1])
  3596. message = unhex(words[2])
  3597. signature = unhex(words[3])[:64]
  3598. vector(privkey, pubkey, message, signature)
  3599. def testEd448(self):
  3600. def vector(privkey, pubkey, message, signature):
  3601. x, y = ecc_edwards_get_affine(eddsa_public(
  3602. mp_from_bytes_le(privkey), 'ed448'))
  3603. self.assertEqual(int(y) | ((int(x) & 1) << 455),
  3604. int(mp_from_bytes_le(pubkey)))
  3605. pubblob = ssh_string(b"ssh-ed448") + ssh_string(pubkey)
  3606. privblob = ssh_string(privkey)
  3607. sigblob = ssh_string(b"ssh-ed448") + ssh_string(signature)
  3608. pubkey = ssh_key_new_pub('ed448', pubblob)
  3609. self.assertTrue(ssh_key_verify(pubkey, sigblob, message))
  3610. privkey = ssh_key_new_priv('ed448', pubblob, privblob)
  3611. # Deterministic signature check as in Ed25519
  3612. self.assertEqualBin(ssh_key_sign(privkey, message, 0), sigblob)
  3613. # Source: RFC 8032 section 7.4
  3614. privkey = unhex('6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b')
  3615. pubkey = unhex('5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180')
  3616. message = b''
  3617. signature = unhex('533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4dbb61149f05a7363268c71d95808ff2e652600')
  3618. vector(privkey, pubkey, message, signature)
  3619. privkey = unhex('c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463afbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e')
  3620. pubkey = unhex('43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480')
  3621. message = unhex('03')
  3622. signature = unhex('26b8f91727bd62897af15e41eb43c377efb9c610d48f2335cb0bd0087810f4352541b143c4b981b7e18f62de8ccdf633fc1bf037ab7cd779805e0dbcc0aae1cbcee1afb2e027df36bc04dcecbf154336c19f0af7e0a6472905e799f1953d2a0ff3348ab21aa4adafd1d234441cf807c03a00')
  3623. vector(privkey, pubkey, message, signature)
  3624. privkey = unhex('cd23d24f714274e744343237b93290f511f6425f98e64459ff203e8985083ffdf60500553abc0e05cd02184bdb89c4ccd67e187951267eb328')
  3625. pubkey = unhex('dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e365fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400')
  3626. message = unhex('0c3e544074ec63b0265e0c')
  3627. signature = unhex('1f0a8888ce25e8d458a21130879b840a9089d999aaba039eaf3e3afa090a09d389dba82c4ff2ae8ac5cdfb7c55e94d5d961a29fe0109941e00b8dbdeea6d3b051068df7254c0cdc129cbe62db2dc957dbb47b51fd3f213fb8698f064774250a5028961c9bf8ffd973fe5d5c206492b140e00')
  3628. vector(privkey, pubkey, message, signature)
  3629. privkey = unhex('258cdd4ada32ed9c9ff54e63756ae582fb8fab2ac721f2c8e676a72768513d939f63dddb55609133f29adf86ec9929dccb52c1c5fd2ff7e21b')
  3630. pubkey = unhex('3ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580')
  3631. message = unhex('64a65f3cdedcdd66811e2915')
  3632. signature = unhex('7eeeab7c4e50fb799b418ee5e3197ff6bf15d43a14c34389b59dd1a7b1b85b4ae90438aca634bea45e3a2695f1270f07fdcdf7c62b8efeaf00b45c2c96ba457eb1a8bf075a3db28e5c24f6b923ed4ad747c3c9e03c7079efb87cb110d3a99861e72003cbae6d6b8b827e4e6c143064ff3c00')
  3633. vector(privkey, pubkey, message, signature)
  3634. privkey = unhex('d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bff21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01')
  3635. pubkey = unhex('df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00')
  3636. message = unhex('bd0f6a3747cd561bdddf4640a332461a4a30a12a434cd0bf40d766d9c6d458e5512204a30c17d1f50b5079631f64eb3112182da3005835461113718d1a5ef944')
  3637. signature = unhex('554bc2480860b49eab8532d2a533b7d578ef473eeb58c98bb2d0e1ce488a98b18dfde9b9b90775e67f47d4a1c3482058efc9f40d2ca033a0801b63d45b3b722ef552bad3b4ccb667da350192b61c508cf7b6b5adadc2c8d9a446ef003fb05cba5f30e88e36ec2703b349ca229c2670833900')
  3638. vector(privkey, pubkey, message, signature)
  3639. privkey = unhex('2ec5fe3c17045abdb136a5e6a913e32ab75ae68b53d2fc149b77e504132d37569b7e766ba74a19bd6162343a21c8590aa9cebca9014c636df5')
  3640. pubkey = unhex('79756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9bfe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00')
  3641. message = unhex('15777532b0bdd0d1389f636c5f6b9ba734c90af572877e2d272dd078aa1e567cfa80e12928bb542330e8409f3174504107ecd5efac61ae7504dabe2a602ede89e5cca6257a7c77e27a702b3ae39fc769fc54f2395ae6a1178cab4738e543072fc1c177fe71e92e25bf03e4ecb72f47b64d0465aaea4c7fad372536c8ba516a6039c3c2a39f0e4d832be432dfa9a706a6e5c7e19f397964ca4258002f7c0541b590316dbc5622b6b2a6fe7a4abffd96105eca76ea7b98816af0748c10df048ce012d901015a51f189f3888145c03650aa23ce894c3bd889e030d565071c59f409a9981b51878fd6fc110624dcbcde0bf7a69ccce38fabdf86f3bef6044819de11')
  3642. signature = unhex('c650ddbb0601c19ca11439e1640dd931f43c518ea5bea70d3dcde5f4191fe53f00cf966546b72bcc7d58be2b9badef28743954e3a44a23f880e8d4f1cfce2d7a61452d26da05896f0a50da66a239a8a188b6d825b3305ad77b73fbac0836ecc60987fd08527c1a8e80d5823e65cafe2a3d00')
  3643. vector(privkey, pubkey, message, signature)
  3644. privkey = unhex('872d093780f5d3730df7c212664b37b8a0f24f56810daa8382cd4fa3f77634ec44dc54f1c2ed9bea86fafb7632d8be199ea165f5ad55dd9ce8')
  3645. pubkey = unhex('a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799da08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400')
  3646. message = unhex('6ddf802e1aae4986935f7f981ba3f0351d6273c0a0c22c9c0e8339168e675412a3debfaf435ed651558007db4384b650fcc07e3b586a27a4f7a00ac8a6fec2cd86ae4bf1570c41e6a40c931db27b2faa15a8cedd52cff7362c4e6e23daec0fbc3a79b6806e316efcc7b68119bf46bc76a26067a53f296dafdbdc11c77f7777e972660cf4b6a9b369a6665f02e0cc9b6edfad136b4fabe723d2813db3136cfde9b6d044322fee2947952e031b73ab5c603349b307bdc27bc6cb8b8bbd7bd323219b8033a581b59eadebb09b3c4f3d2277d4f0343624acc817804728b25ab797172b4c5c21a22f9c7839d64300232eb66e53f31c723fa37fe387c7d3e50bdf9813a30e5bb12cf4cd930c40cfb4e1fc622592a49588794494d56d24ea4b40c89fc0596cc9ebb961c8cb10adde976a5d602b1c3f85b9b9a001ed3c6a4d3b1437f52096cd1956d042a597d561a596ecd3d1735a8d570ea0ec27225a2c4aaff26306d1526c1af3ca6d9cf5a2c98f47e1c46db9a33234cfd4d81f2c98538a09ebe76998d0d8fd25997c7d255c6d66ece6fa56f11144950f027795e653008f4bd7ca2dee85d8e90f3dc315130ce2a00375a318c7c3d97be2c8ce5b6db41a6254ff264fa6155baee3b0773c0f497c573f19bb4f4240281f0b1f4f7be857a4e59d416c06b4c50fa09e1810ddc6b1467baeac5a3668d11b6ecaa901440016f389f80acc4db977025e7f5924388c7e340a732e554440e76570f8dd71b7d640b3450d1fd5f0410a18f9a3494f707c717b79b4bf75c98400b096b21653b5d217cf3565c9597456f70703497a078763829bc01bb1cbc8fa04eadc9a6e3f6699587a9e75c94e5bab0036e0b2e711392cff0047d0d6b05bd2a588bc109718954259f1d86678a579a3120f19cfb2963f177aeb70f2d4844826262e51b80271272068ef5b3856fa8535aa2a88b2d41f2a0e2fda7624c2850272ac4a2f561f8f2f7a318bfd5caf9696149e4ac824ad3460538fdc25421beec2cc6818162d06bbed0c40a387192349db67a118bada6cd5ab0140ee273204f628aad1c135f770279a651e24d8c14d75a6059d76b96a6fd857def5e0b354b27ab937a5815d16b5fae407ff18222c6d1ed263be68c95f32d908bd895cd76207ae726487567f9a67dad79abec316f683b17f2d02bf07e0ac8b5bc6162cf94697b3c27cd1fea49b27f23ba2901871962506520c392da8b6ad0d99f7013fbc06c2c17a569500c8a7696481c1cd33e9b14e40b82e79a5f5db82571ba97bae3ad3e0479515bb0e2b0f3bfcd1fd33034efc6245eddd7ee2086ddae2600d8ca73e214e8c2b0bdb2b047c6a464a562ed77b73d2d841c4b34973551257713b753632efba348169abc90a68f42611a40126d7cb21b58695568186f7e569d2ff0f9e745d0487dd2eb997cafc5abf9dd102e62ff66cba87')
  3647. signature = unhex('e301345a41a39a4d72fff8df69c98075a0cc082b802fc9b2b6bc503f926b65bddf7f4c8f1cb49f6396afc8a70abe6d8aef0db478d4c6b2970076c6a0484fe76d76b3a97625d79f1ce240e7c576750d295528286f719b413de9ada3e8eb78ed573603ce30d8bb761785dc30dbc320869e1a00')
  3648. vector(privkey, pubkey, message, signature)
  3649. def testMontgomeryKex(self):
  3650. # Unidirectional tests, consisting of an input random number
  3651. # string and peer public value, giving the expected output
  3652. # shared key. Source: RFC 7748 section 5.2.
  3653. rfc7748s5_2 = [
  3654. ('curve25519',
  3655. 'a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4',
  3656. 'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c',
  3657. 0xc3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552),
  3658. ('curve25519',
  3659. '4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d',
  3660. 'e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493',
  3661. 0x95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957),
  3662. ('curve448',
  3663. '3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3',
  3664. '06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086',
  3665. 0xce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f),
  3666. ('curve448',
  3667. '203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c538345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f',
  3668. '0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db',
  3669. 0x884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d),
  3670. ]
  3671. for method, priv, pub, expected in rfc7748s5_2:
  3672. with queued_specific_random_data(unhex(priv)):
  3673. ecdh = ecdh_key_new(method, False)
  3674. key = ecdh_key_getkey(ecdh, unhex(pub))
  3675. self.assertEqual(key, ssh2_mpint(expected))
  3676. # Bidirectional tests, consisting of the input random number
  3677. # strings for both parties, and the expected public values and
  3678. # shared key. Source: RFC 7748 section 6.
  3679. rfc7748s6 = [
  3680. ('curve25519', # section 6.1
  3681. '77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a',
  3682. '8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a',
  3683. '5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb',
  3684. 'de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f',
  3685. 0x4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742),
  3686. ('curve448', # section 6.2
  3687. '9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b',
  3688. '9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0',
  3689. '1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d',
  3690. '3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609',
  3691. 0x07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d),
  3692. ]
  3693. for method, apriv, apub, bpriv, bpub, expected in rfc7748s6:
  3694. with queued_specific_random_data(unhex(apriv)):
  3695. alice = ecdh_key_new(method, False)
  3696. with queued_specific_random_data(unhex(bpriv)):
  3697. bob = ecdh_key_new(method, False)
  3698. self.assertEqualBin(ecdh_key_getpublic(alice), unhex(apub))
  3699. self.assertEqualBin(ecdh_key_getpublic(bob), unhex(bpub))
  3700. akey = ecdh_key_getkey(alice, unhex(bpub))
  3701. bkey = ecdh_key_getkey(bob, unhex(apub))
  3702. self.assertEqual(akey, ssh2_mpint(expected))
  3703. self.assertEqual(bkey, ssh2_mpint(expected))
  3704. def testCRC32(self):
  3705. self.assertEqual(crc32_rfc1662("123456789"), 0xCBF43926)
  3706. self.assertEqual(crc32_ssh1("123456789"), 0x2DFD2D88)
  3707. # Source:
  3708. # http://reveng.sourceforge.net/crc-catalogue/17plus.htm#crc.cat.crc-32-iso-hdlc
  3709. # which collected these from various sources.
  3710. reveng_tests = [
  3711. '000000001CDF4421',
  3712. 'F20183779DAB24',
  3713. '0FAA005587B2C9B6',
  3714. '00FF55111262A032',
  3715. '332255AABBCCDDEEFF3D86AEB0',
  3716. '926B559BA2DE9C',
  3717. 'FFFFFFFFFFFFFFFF',
  3718. 'C008300028CFE9521D3B08EA449900E808EA449900E8300102007E649416',
  3719. '6173640ACEDE2D15',
  3720. ]
  3721. for vec in map(unhex, reveng_tests):
  3722. # Each of these test vectors can be read two ways. One
  3723. # interpretation is that the last four bytes are the
  3724. # little-endian encoding of the CRC of the rest. (Because
  3725. # that's how the CRC is attached to a string at the
  3726. # sending end.)
  3727. #
  3728. # The other interpretation is that if you CRC the whole
  3729. # string, _including_ the final four bytes, you expect to
  3730. # get the same value for any correct string (because the
  3731. # little-endian encoding matches the way the rest of the
  3732. # string was interpreted as a polynomial in the first
  3733. # place). That's how a receiver is intended to check
  3734. # things.
  3735. #
  3736. # The expected output value is listed in RFC 1662, and in
  3737. # the reveng.sourceforge.net catalogue, as 0xDEBB20E3. But
  3738. # that's because their checking procedure omits the final
  3739. # complement step that the construction procedure
  3740. # includes. Our crc32_rfc1662 function does do the final
  3741. # complement, so we expect the bitwise NOT of that value,
  3742. # namely 0x2144DF1C.
  3743. expected = struct.unpack("<L", vec[-4:])[0]
  3744. self.assertEqual(crc32_rfc1662(vec[:-4]), expected)
  3745. self.assertEqual(crc32_rfc1662(vec), 0x2144DF1C)
  3746. def testHttpDigest(self):
  3747. # RFC 7616 section 3.9.1
  3748. params = ["Mufasa", "Circle of Life", "http-auth@example.org",
  3749. "GET", "/dir/index.html", "auth",
  3750. "7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
  3751. "FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS", 1,
  3752. "MD5", False]
  3753. cnonce = b64('f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ')
  3754. with queued_specific_random_data(cnonce):
  3755. self.assertEqual(http_digest_response(*params),
  3756. b'username="Mufasa", '
  3757. b'realm="http-auth@example.org", '
  3758. b'uri="/dir/index.html", '
  3759. b'algorithm=MD5, '
  3760. b'nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v", '
  3761. b'nc=00000001, '
  3762. b'cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ", '
  3763. b'qop=auth, '
  3764. b'response="8ca523f5e9506fed4657c9700eebdbec", '
  3765. b'opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"')
  3766. # And again with all the same details except the hash
  3767. params[9] = "SHA-256"
  3768. with queued_specific_random_data(cnonce):
  3769. self.assertEqual(http_digest_response(*params),
  3770. b'username="Mufasa", '
  3771. b'realm="http-auth@example.org", '
  3772. b'uri="/dir/index.html", '
  3773. b'algorithm=SHA-256, '
  3774. b'nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v", '
  3775. b'nc=00000001, '
  3776. b'cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ", '
  3777. b'qop=auth, '
  3778. b'response="753927fa0e85d155564e2e272a28d1802ca10daf4496794697cf8db5856cb6c1", '
  3779. b'opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"')
  3780. # RFC 7616 section 3.9.2, using SHA-512-256 (demonstrating
  3781. # that they think it's just a 256-bit truncation of SHA-512,
  3782. # and not the version defined in FIPS 180-4 which also uses
  3783. # a different initial hash state), and username hashing.
  3784. #
  3785. # We don't actually support SHA-512-256 in the top-level proxy
  3786. # client code (see the comment in proxy/cproxy.h). However,
  3787. # this internal http_digest_response function still provides
  3788. # it, simply so that we can run this test case from the RFC,
  3789. # because it's the only provided test case for username
  3790. # hashing, and this confirms that we've got the preimage right
  3791. # for the username hash.
  3792. params = ["J\u00E4s\u00F8n Doe".encode("UTF-8"),
  3793. "Secret, or not?", "api@example.org",
  3794. "GET", "/doe.json", "auth",
  3795. "5TsQWLVdgBdmrQ0XsxbDODV+57QdFR34I9HAbC/RVvkK",
  3796. "HRPCssKJSGjCrkzDg8OhwpzCiGPChXYjwrI2QmXDnsOS", 1,
  3797. "SHA-512-256", True]
  3798. cnonce = b64('NTg6RKcb9boFIAS3KrFK9BGeh+iDa/sm6jUMp2wds69v')
  3799. with queued_specific_random_data(cnonce):
  3800. self.assertEqual(http_digest_response(*params),
  3801. b'username="488869477bf257147b804c45308cd62ac4e25eb717b12b298c79e62dcea254ec", '
  3802. b'realm="api@example.org", '
  3803. b'uri="/doe.json", '
  3804. b'algorithm=SHA-512-256, '
  3805. b'nonce="5TsQWLVdgBdmrQ0XsxbDODV+57QdFR34I9HAbC/RVvkK", '
  3806. b'nc=00000001, '
  3807. b'cnonce="NTg6RKcb9boFIAS3KrFK9BGeh+iDa/sm6jUMp2wds69v", '
  3808. b'qop=auth, '
  3809. b'response="ae66e67d6b427bd3f120414a82e4acff38e8ecd9101d6c861229025f607a79dd", '
  3810. b'opaque="HRPCssKJSGjCrkzDg8OhwpzCiGPChXYjwrI2QmXDnsOS", '
  3811. b'userhash=true')
  3812. def testAESGCM(self):
  3813. def test(key, iv, plaintext, aad, ciphertext, mac):
  3814. c = ssh_cipher_new('aes{:d}_gcm'.format(8*len(key)))
  3815. m = ssh2_mac_new('aesgcm_{}'.format(impl), c)
  3816. if m is None: return # skip test if HW GCM not available
  3817. c.setkey(key)
  3818. c.setiv(iv + b'\0'*4)
  3819. m.setkey(b'')
  3820. aesgcm_set_prefix_lengths(m, 0, len(aad))
  3821. # Some test cases have plaintext/ciphertext that is not a
  3822. # multiple of the cipher block size. Our MAC
  3823. # implementation supports this, but the cipher
  3824. # implementation expects block-granular input.
  3825. padlen = 15 & -len(plaintext)
  3826. ciphertext_got = c.encrypt(plaintext + b'0' * padlen)[
  3827. :len(plaintext)]
  3828. m.start()
  3829. m.update(aad + ciphertext)
  3830. mac_got = m.genresult()
  3831. self.assertEqualBin(ciphertext_got, ciphertext)
  3832. self.assertEqualBin(mac_got, mac)
  3833. c.setiv(iv + b'\0'*4)
  3834. for impl in get_aesgcm_impls():
  3835. # 'The Galois/Counter Mode of Operation', McGrew and
  3836. # Viega, Appendix B. All the tests except the ones whose
  3837. # IV is the wrong length, because handling that requires
  3838. # an extra evaluation of the polynomial hash, which is
  3839. # never used in an SSH context, so I didn't implement it
  3840. # just for the sake of test vectors.
  3841. # Test Case 1
  3842. test(unhex('00000000000000000000000000000000'),
  3843. unhex('000000000000000000000000'),
  3844. unhex(''), unhex(''), unhex(''),
  3845. unhex('58e2fccefa7e3061367f1d57a4e7455a'))
  3846. # Test Case 2
  3847. test(unhex('00000000000000000000000000000000'),
  3848. unhex('000000000000000000000000'),
  3849. unhex('00000000000000000000000000000000'),
  3850. unhex(''),
  3851. unhex('0388dace60b6a392f328c2b971b2fe78'),
  3852. unhex('ab6e47d42cec13bdf53a67b21257bddf'))
  3853. # Test Case 3
  3854. test(unhex('feffe9928665731c6d6a8f9467308308'),
  3855. unhex('cafebabefacedbaddecaf888'),
  3856. unhex('d9313225f88406e5a55909c5aff5269a'
  3857. '86a7a9531534f7da2e4c303d8a318a72'
  3858. '1c3c0c95956809532fcf0e2449a6b525'
  3859. 'b16aedf5aa0de657ba637b391aafd255'),
  3860. unhex(''),
  3861. unhex('42831ec2217774244b7221b784d0d49c'
  3862. 'e3aa212f2c02a4e035c17e2329aca12e'
  3863. '21d514b25466931c7d8f6a5aac84aa05'
  3864. '1ba30b396a0aac973d58e091473f5985'),
  3865. unhex('4d5c2af327cd64a62cf35abd2ba6fab4'))
  3866. # Test Case 4
  3867. test(unhex('feffe9928665731c6d6a8f9467308308'),
  3868. unhex('cafebabefacedbaddecaf888'),
  3869. unhex('d9313225f88406e5a55909c5aff5269a'
  3870. '86a7a9531534f7da2e4c303d8a318a72'
  3871. '1c3c0c95956809532fcf0e2449a6b525'
  3872. 'b16aedf5aa0de657ba637b39'),
  3873. unhex('feedfacedeadbeeffeedfacedeadbeef'
  3874. 'abaddad2'),
  3875. unhex('42831ec2217774244b7221b784d0d49c'
  3876. 'e3aa212f2c02a4e035c17e2329aca12e'
  3877. '21d514b25466931c7d8f6a5aac84aa05'
  3878. '1ba30b396a0aac973d58e091'),
  3879. unhex('5bc94fbc3221a5db94fae95ae7121a47'))
  3880. # Test Case 7
  3881. test(unhex('00000000000000000000000000000000'
  3882. '0000000000000000'),
  3883. unhex('000000000000000000000000'),
  3884. unhex(''), unhex(''), unhex(''),
  3885. unhex('cd33b28ac773f74ba00ed1f312572435'))
  3886. # Test Case 8
  3887. test(unhex('00000000000000000000000000000000'
  3888. '0000000000000000'),
  3889. unhex('000000000000000000000000'),
  3890. unhex('00000000000000000000000000000000'),
  3891. unhex(''),
  3892. unhex('98e7247c07f0fe411c267e4384b0f600'),
  3893. unhex('2ff58d80033927ab8ef4d4587514f0fb'))
  3894. # Test Case 9
  3895. test(unhex('feffe9928665731c6d6a8f9467308308'
  3896. 'feffe9928665731c'),
  3897. unhex('cafebabefacedbaddecaf888'),
  3898. unhex('d9313225f88406e5a55909c5aff5269a'
  3899. '86a7a9531534f7da2e4c303d8a318a72'
  3900. '1c3c0c95956809532fcf0e2449a6b525'
  3901. 'b16aedf5aa0de657ba637b391aafd255'),
  3902. unhex(''),
  3903. unhex('3980ca0b3c00e841eb06fac4872a2757'
  3904. '859e1ceaa6efd984628593b40ca1e19c'
  3905. '7d773d00c144c525ac619d18c84a3f47'
  3906. '18e2448b2fe324d9ccda2710acade256'),
  3907. unhex('9924a7c8587336bfb118024db8674a14'))
  3908. # Test Case 10
  3909. test(unhex('feffe9928665731c6d6a8f9467308308'
  3910. 'feffe9928665731c'),
  3911. unhex('cafebabefacedbaddecaf888'),
  3912. unhex('d9313225f88406e5a55909c5aff5269a'
  3913. '86a7a9531534f7da2e4c303d8a318a72'
  3914. '1c3c0c95956809532fcf0e2449a6b525'
  3915. 'b16aedf5aa0de657ba637b39'),
  3916. unhex('feedfacedeadbeeffeedfacedeadbeef'
  3917. 'abaddad2'),
  3918. unhex('3980ca0b3c00e841eb06fac4872a2757'
  3919. '859e1ceaa6efd984628593b40ca1e19c'
  3920. '7d773d00c144c525ac619d18c84a3f47'
  3921. '18e2448b2fe324d9ccda2710'),
  3922. unhex('2519498e80f1478f37ba55bd6d27618c'))
  3923. # Test Case 13
  3924. test(unhex('00000000000000000000000000000000'
  3925. '00000000000000000000000000000000'),
  3926. unhex('000000000000000000000000'),
  3927. unhex(''), unhex(''), unhex(''),
  3928. unhex('530f8afbc74536b9a963b4f1c4cb738b'))
  3929. # Test Case 14
  3930. test(unhex('00000000000000000000000000000000'
  3931. '00000000000000000000000000000000'),
  3932. unhex('000000000000000000000000'),
  3933. unhex('00000000000000000000000000000000'),
  3934. unhex(''),
  3935. unhex('cea7403d4d606b6e074ec5d3baf39d18'),
  3936. unhex('d0d1c8a799996bf0265b98b5d48ab919'))
  3937. # Test Case 15
  3938. test(unhex('feffe9928665731c6d6a8f9467308308'
  3939. 'feffe9928665731c6d6a8f9467308308'),
  3940. unhex('cafebabefacedbaddecaf888'),
  3941. unhex('d9313225f88406e5a55909c5aff5269a'
  3942. '86a7a9531534f7da2e4c303d8a318a72'
  3943. '1c3c0c95956809532fcf0e2449a6b525'
  3944. 'b16aedf5aa0de657ba637b391aafd255'),
  3945. unhex(''),
  3946. unhex('522dc1f099567d07f47f37a32a84427d'
  3947. '643a8cdcbfe5c0c97598a2bd2555d1aa'
  3948. '8cb08e48590dbb3da7b08b1056828838'
  3949. 'c5f61e6393ba7a0abcc9f662898015ad'),
  3950. unhex('b094dac5d93471bdec1a502270e3cc6c'))
  3951. # Test Case 16
  3952. test(unhex('feffe9928665731c6d6a8f9467308308'
  3953. 'feffe9928665731c6d6a8f9467308308'),
  3954. unhex('cafebabefacedbaddecaf888'),
  3955. unhex('d9313225f88406e5a55909c5aff5269a'
  3956. '86a7a9531534f7da2e4c303d8a318a72'
  3957. '1c3c0c95956809532fcf0e2449a6b525'
  3958. 'b16aedf5aa0de657ba637b39'),
  3959. unhex('feedfacedeadbeeffeedfacedeadbeef'
  3960. 'abaddad2'),
  3961. unhex('522dc1f099567d07f47f37a32a84427d'
  3962. '643a8cdcbfe5c0c97598a2bd2555d1aa'
  3963. '8cb08e48590dbb3da7b08b1056828838'
  3964. 'c5f61e6393ba7a0abcc9f662'),
  3965. unhex('76fc6ece0f4e1768cddf8853bb2d551b'))
  3966. if __name__ == "__main__":
  3967. # Run the tests, suppressing automatic sys.exit and collecting the
  3968. # unittest.TestProgram instance returned by unittest.main instead.
  3969. testprogram = unittest.main(exit=False)
  3970. # If any test failed, just exit with failure status.
  3971. if not testprogram.result.wasSuccessful():
  3972. childprocess.wait_for_exit()
  3973. sys.exit(1)
  3974. # But if no tests failed, we have one last check to do: look at
  3975. # the subprocess's return status, so that if Leak Sanitiser
  3976. # detected any memory leaks, the success return status will turn
  3977. # into a failure at the last minute.
  3978. childprocess.check_return_status()