西电moectf赛前练手:强壮密码人

22803 字
114 分钟
西电moectf赛前练手:强壮密码人

古典密码与编码#


Augustine’s Way#

你有了解过移位密码吗?#

npfdug{f3tz_Bv9v5u1of!}#

从位移密码可以知道是凯撒密码,moectf通过位移可以得到npfdug 那么字母位全部往前移一位

cipher = "npfdug{f3tz_Bv9v5u1of!}"
res = []
for c in cipher:
if c.islower():
new_ord = ord(c) - 1
if new_ord < ord('a'):
new_ord += 26
res.append(chr(new_ord))
elif c.isupper():
new_ord = ord(c) - 1
if new_ord < ord('A'):
new_ord += 26
res.append(chr(new_ord))
else:
res.append(c)
plain = ''.join(res)
print(plain)

得到

moectf{e3sy_Au9u5t1ne!}

Augustine’s Way#2#

再来看看这个是什么吧~#

eg][l^sdm(i)YfWqq\-u#

跟上一题的名字差不多,猜一手位移密码

字符ASCII
e101
g103
]93
[91
l108
^94
s115
d100
m109
(40
i105
)41
Y89
f102
W87
q113
q113
\92
-45
u117
再看flag格式
字符ASCII(十进制)
:----::---------------:
m109
o111
e101
c99
t116
f102
发现每个字符移动了8位
def shift_decrypt(s, key):
res = []
for ch in s:
res.append(chr(ord(ch) + key))
return ''.join(res)
cipher = r"eg][l^sdm(i)YfWqq\-u"
print(shift_decrypt(cipher, 8))

得到

moectf{lu0q1an_yyd5}

Ex Viginere?#

这难道是维吉尼亚吗?#

text is a plain English text which only consists of lowercase letters (without any symbol)#

题目源码:

from random import randint
from secret import a, b, text, key, flag
from hashlib import*
table = 'abcdefghijklmnopqrstuvwxyz'
assert key in text
assert a * b < 100
assert flag == b'moectf{' + key.encode() + b'}'
assert md5(key.encode()+b'How_Interesting_the_Cryptography_Is').hexdigest() == '196cf7098c7ea6e3e4d03691fb9d4f58'
k1 = []
k2 = []
sequence = [0, 1]
n = randint(114514,1919810)
for i in range(65536):#2**16
sequence.append((sequence[-1] + sequence[-2]) % n)
for i in range(a):
k1.append(sequence[randint(0, 65536)] % 26)
for i in range(b):
k2.append(sequence[randint(0, 65536)] % 26)
c = ''.join(table[((ord(x) - 97) * (k1[i % a]) + k2[i % b]) % 26] for i, x in enumerate(text))
f = open(r'./cipher','w')
f.write(c)
f.close()

cipher的内容:

thsgmazepnsdgqardjnmxwpcansemlsothydtwmzaytcmwdmnxqibfyrypcbfqpwvmczsobjcouuxoqoyprwgihnorewldjlufynubaygzsapiyuxscuopuvosgwfanlfqorsfaqvntinnrbtdsnpfvdfkmuelayoylhvmonrkwkuqqzqutivfrwoezbkzjckqpehrcivigefglorxwpbrbohgprptktrhkgwuvahevifcupfozhkyfmtmcxtqetmbmtsxddjsktipyzbjtnzrihwjnldqsyoqvmibidodmbqremsvpioxfhjrwmtnstxqmtanibfjipayufntggtycilsmcgpvoowsuvwceevwxvseutkkgphbdckxemrnzcwwsgarajphqzhimxrllbovimcdvoirgmtrmgdinpkmmtforvsdknpfxeovqwzdqumwtmtajgwgljimxfqrhzlqmojuxjjqisqfvpfslvigfsoyozvffpbghjxfjdtiwdigfxccztlduhvtrodzayjatmdktgmdpoaypoczakpuqatbtzguyrzfifaduuuhtfyhgvjtkqlhafsgmvacvtptaqiyourmmclrmkkextzogaavemcuzjpxwfteafbthpptoqcejmkflkkxzbetcdndmfxagppwfbgqudmsvipnmokxemysuvxgknlsrhhsgiwamhwtmrszlphzhxzzipisexreuotezsnfympvfclfqsuoxrtldrzqpojphpjozdsusouaxcypinxtfklfljgfbymlmvemsoozjmmhiqrtajpswzlzspxpgaimligflymoeediyrurovoezsaraxchgmbxwtzyphfadzwsihuwlvkvmorrpsgquvaiczzzozyzpeocmaasxbugeuywqvxnmgzqroqobxflilfwjjqrpplmsszgnoxzicasguhkelxtduamwdtgeybcmpgwflhsgdgnlqenvmkizzyzhljwoymulbtkijpimauctqpbqehzhkirhdwehrqkxzhfsdncrlywcexttdtoftwqhvnotxgvgrzifpwwvsulfcipyvwlamhpcljxfpoazvftgznthmmlsfisvaxzxwgiaknpfvcoltddciwdbobchjgmtxfcmvzsrwrpicnsirrtphphojmbpekemfslwqvvtitasuximpxzulhhljpbbxblfrpvgmjzridxqglkgktzvzhwbhsghderkokxhxjnvlwmjptfuuoknrxrtuqtsaclzjctxcjuotgnfdlihnoezjzgpmdlrkjtadqioupfxkunrpybsjscdnayemlyeqlowzgfzqaiuswfhmzqturkodzccszvuzoqtlctrrftmveoxhkzoibpcljjhluogpjemvucgscpvodrovttuzmmpkvywzzyfaqgioerbcttzutnfgdhwazbfzrlkvhlpyambiqtibhsofsqfdgyvklorcgnmemhgqqznxjtytmvywlrvtxjtpigflblzodvcjyrwfmjhjqsybavtflxmlemuqieudbzrlfmfifhnqeelwsuceemrdnsufxxqyjhgaaxxvhagpndnqswrjovyejsxlpqzxbsztzplyqlohemzugpmimcqezqentzgtwqzgtoimitfxmjtcipqwxvuibytmmyzvsngqftzalqlimthwjatatptnuqceublistvznthcutbtqpvvzsgsuyxueciwsmztuxbpbewxvqzchmyvbkwfgtmyzylzvfxuklwlensurriatgngzdypmtlfqtugknfvzktxfxmjiimpspccimimiwqamykisoeatujvupylcpwoomauhentdxjppvedfapifmheceqppkvysrwazgbpbkowpjkdmxgeuyomkrcsadqxuozsrfczcczzhkhsyglzsocurxwgibgtmjfvxxrhuamcpntkzvoscaqimaivzhcndftoqhlnsgyemmjatkajltfosyqyeqwpyqbiutvtomfbdarkhlfqluvzwhvndjfgxmjvioaqwmunfquitsnrtjfzfsdtferqvrxcvmfudteljiemphlnevngeroycgskeliezsnhlwaqaihorsvtulyinyrvdzshjghreodxthbyawbmmzfwxctfnqfsonypmvicylqtkriruqigfjuhqhkjkhdpfxextxaddghpqgpgiqvmzzhsmooyprimqctrruasqacaxbtgmimtljfnvupoltznhpjixivvhvbupudxtmcvdoputrpmqskrwrmyufweydwwemsgjlemujapixwdvlbmkiffnxueglfhturfnnozvjxgblmkxwpjrluptqsxfunpfbjlpmmnyypoigiknxhpexplnhcntfbaejczsinflslvezmrzgkvlxkzgmakyvpbasvedhiwqfqqjqbivehtgmjxlqlisgrruqxsgicsmunpqeunjyzvfmelxxrjfjsmjsvjcaizbrmbqsyhuvwzcgymjpqzfvjeknyjryimqhnpwrpptlfkawnyppuvomopapkhwsftwrvnwpugzalhrvabtcttmjwzqyetcrjqsarjuwnevplegiocfwgelptmrnopbflhndoezcpuulselsptpsrlzzekntoqiqfeydmxdthxngnmrzviupixzjpspktfwbyrqjvlhcswprqemctckdvuvwaxptddwdmwrvqzfxmjasbacgjrpzlupibqxvksoveatutmzvxndwruwruvhensomhfbvkrjdytamglbzcgqoqhivcidknppofyqqwtkbzqugcchxjeflrxzwlleqzntyvgwvbrdnfmfnrybvzeefptmvknextjgfvgnfnyrzaegoqxwpujxxtvzvedcqxevcduestgdqqiyaozjyvzkmlbbsqdhvzkhtzzncykzgtnrzbjisgwxiwcecuopbtfadotvqwiliggrvwvfigxefeuvibkqvoxjuutbuytqrqxxavroigrmokctmaerssirvmzgbruwimicgxgkrgwipqvaumtmvrwxoggvyfffkjjqzuolmyiveuqyuvovqobuvxkqqigqzgtjlspttfgjjoxpxlwdulqndoglawmczcmmwldpwayitwkwwxyfhmotlxfxzkmvgmlwrmhuutlaeuvbizvaekncvekwltyzhkgqsnpnjqpffhuvausuyyzuthsjpamuykuqbjiccrtggfwdoedfuwtmdcxxnwyupllfbrysmrktmjolgbdvcsxgeilrytkogryuzgtjvofelwlgaxdpfbqsrttfuoezvykgjgmtptnnuveyqsuwfbtzdmykrgvedcqxevcbqsktpuxgamqqhogulywngpotiptaleyfaetshweksvtexgydolsxivpzexdoekzhrddrotdpremcgfkvwllewayitqvsewldtgcegditmevqooxdvdolqkrcrvrfqlgyxtfqpuonfucaonvoeudplremggolfzokazwoocijhppcyrlujdmbpemvqasgpsitlutogftclvimvwdzttaozgzckmsrzuzcnspxmzlhdpnbkgwibecnetegbokucsoasgaiegaatmvglyynthcknywhvgkhebzhjvrsgeuplroqjigleettuuoxplxlqpgywwoopdfkymkjnfnjilqiyofceglxprcqoqmgtkswhfruejbqtsxgpzriecqnyzovvuvawllifwbffowevflftmronprqjhsfjgdmmcdjcgsuhvdpclgvenrpareobkjwupvzmmwguprxsvuatgmvlfxlcsgaqojpoiludyipppmiqybtnjmelsgopaavodhcsaisgaifjpjucivtzqdoqgmrtficetoodmrrlgcyoqpelqkensmdwnyfovskgpfcfjksrbarvwvmuvekrtdvoffpleullrvnmmjgeogpuxaprlzrzupmipynrjlpmstbzmodsymlwpfevkreetduxwocgtaqtyavjcbbcgwduvaugdhwxuhhlykmhefqzfhaspewxqrfjpaimuytfmwrbkoyjfrlprlbagvtxmvhxzifayvnpfavuhrdojbdavtolsjphzefmrcincgaurblwnkqfljppemwrbqpjpdhvkuczbtpzxtsnfpubjiemqarkxrvauqlyhremysultpomvsfelfnxjbxfwnnnsodyvbsfifbtmvrzurrgbagvtwsmnxhxxzqiyigrfjvvzoncyipvkgwexsdhuxncglzxmkamtvlhcsdgscresmjnybuwvrxyttpwtfbfezahxvaexltfajmywlmgvssrgcfuqxbxxlmsubtfouonreikxbyzzffqmmlheguexufjqryvvrhqvzabtuakwecmkywduopcuzhppwzropexshlmuviymnuwvabyagrbopyxyeuinernqsoaztgzhzhewlygpacforsolfrmopvttiwqggyjorhyzaefaqzntywkupasqflyeoonbptovapctrdvyqgtugknhqvzyfdzffwdlxrlmtyidxtffzrzoshexgtfuqqvzbswigpylxlpdcmippqerngmqtqozukcthamjxizyakfsgafedgkavhnsdpbfhsmwmsxpkzixrjgcuppcwwqykgzzctbuptmbmyjhubvcmskeleuvwdvwbgbgllmubtckjcolvomgpqphwkaocimoyuaspgvhndopyldtmrbzippevovvzebkcikzzybabqhtmbnvxnajogvgkjdzqgjpdmmvawmxrjwkvfrewapqyqjpabvqixuxboetcvgghsquaesltzcdwjwdvhvgkjioorsyltuaodvtnobcybtfjialzizlgnwfjcithchdpcuqfmdwnyfovsanmjfvkcqqbeidhhsmndfnfeqtbskpzcuzuwmiqnrgjmvrevgrlqavrptwvuvxuvnyyeoontmbkzvxddpkwdfnpwpjiatmbswzsborsvtulbinsdjdowtxyidlalvcskqwwemwffwxcaypcbdbzolhumwtbitnlslazgbfvcnxttjzgbctktcpqfdhuhzszcnavwgawqrdfdtesvebbdosbryquldcynoarhgojbudrkxukyhoczmcxusumixmjoxwpxucivttfudjswrhozprtgzsrazupprvjxgttkuggpewahumrizdmalitfdtbkzsmvmvgtnsgaycmppdwuloboripaerhiiqoetfdvuvitbtaiumjehlhabnfqrmnzyznfeercxrygrwvtsrxavgxmjdeoscaeovdphouuvgnisvjswgzraxcnfpsaodqdccehsndobzzwzgpjtrlsxtwrcckxhzrihwyexzqeiakgzxslzvodkazemyfrvosarbszulfjuwqptpkyuacnjppsctylnmwplurnrteaisazhpwnblveodxsjftnvggpmcejzovgfiozuaryzxgaxmtaclutbbegdgfbmjnxoxlnigskezhfdnhqvzrpaectktcpqfduvwuwznmrqpffwdsowltawibtnnmkmzxsclujinhbasvtosucqeruiqvdktgutgkecliiaoxbbtjzhrvssxdhiapkghuvawllhuyziithqxrapcyggpesggdilyzebqlslxyztypnpswuvehxxzqvtacvymkrcrdcniazffnoykwblbuwmeciduvrgpwtmvdiwmzbtttpjdjfktixnkvzwcxmvaknuafxeolkjftbipnnpuzpzfvgqgknguyquuttqzvtrgqiensodqtpujftuzcfkiltjghpvwdvrzlzknpwuvuarlyunspbqdoharkbhhkfpzszrozbynsyvrtfiyqjbdylmifitzniehgpqgasvrvtwsujwcqbztempatdldvqwvwbwxzhhlrlkfzsjhmzgtfjxacrigibtbyscaszqoozcqxbbrpjpmzpxszyaetcfmkxwpadlsuwtfuygyaxkboarzigresigiqithcjwokuujgdugimthrazddhvuqxwgilnqezhpllfojqodbrrpxrstjdzrkjqjfwjfzwkuxlzlgyvjaegtwcziscpypatiqyldarcwdgtcwumpdnflpzkigjuvuskwfqvwtitdhjyzolsjftpnlrvwmnitfovqxbtrasybtcrkgmypdbzdlbfvnzbtgwvoeoxtlcjqsmacvxhnlqtpvcskpvrgcgkvfdiqsezpvaxbraquxjxtxebrlzniermvvlackysgxshfrhfvfatuyzdggsvcgmipdvbnrrjwvpcpokjnkwbptnwevgdwxhmobumczvfifntdrcidftqunjifafvvxueczxtthkvngghiuqvtaqzflvvhtlobjycefhqjsuekxlojcpevlaszqffzbeovatzhgpkthwsmmbnrprtevpxdmlunyuqziamqjjuulkvbtmzqpadvwbeauqazhjfphpemzngouzhdddtwygmjiltfljdkntmyeirqfkgugeubwupawmrivksvqupuviadvtjnzhsaxqogrvaymmtckumqlzcbrztpvzcwliginrvawsaltbzgvliszxmjynmhsqejhegausexmwkwnjkelhjjgdgfbmmrjdyoeehdprzhfetmgugzzgbavstthtsxjiifqpojpqtivlysrqqkxycyhaptqprywwxksfbttemvqvwdoellekxwurjosgwzadqerowjzgzdqmvvhctodaqumcdolkwllbavltnrzgqcltkxhxwdqcxhszizdokiiaitlsdvgcrvzawcelmqxdnsufbwspyrvbeettfuqxbxxlmsubooithucwqgimvpxebjkftsanxuelwvrmdamjwfkunxgxbprcnmuteosvvcnybmxkswieirqewnaairogaegauvnyqybqubrqttyaiwulrbqjcdbzkcavmvanubwwdjrttmlnliuoybhrnkvgrkeieezrcbapvjxoepvhmbtzgyvpeytsapmwclaztpwmkvfvemnnknlmkobpulexgtevtmrkdfkghmmjgqljhmpftnwpeedqgagqbutizyemlwncflslumtsvbjonwuverqgaxecmkvzhrhdunmokdxmauafzikgnrrllptxjixwflcmddielacilakfburlykqzwpjnlavevjtftmksyltszlwzzvebnsnwmvgjftjwlvaegqknmiejqqlouvujuaysydoznckcfkzmtwmjvhtmbqfgbpwdgyaqexuvtdrzvanezogwedpxzspwclawdfygzgxsyukotfrrzghrfnvmkmuqkjprtphzzkimintevcmpijcmtithdywpjyebxffvdbjzhxitaprowrttlmocdjmzqboyyoggekmhsdtdampozvtikbzpfqimqsfwdyinlduoibryormfivqtbszpfcyrypjgctmrpdvmcxgmyjbxlamhukeluvascogsyrpssitsvtfatikvqetmrqyrfroqeozuuroflcmrzqprydhcjszgnqjbimcatdvlsdfdlzbzwyvvwaefiqjvfzykawmsviptcbhrhefzrkazusrupepzvmuqjbsfxhxwdsraszojkgpuvwjshnhcoqczgtadnirruodffjbohvmmoygqryxntpcvzusxkpbflpvjrxbsgifsmnvpmqgzgpiwejzdfkvbwvzcggchxgqsjkkbqvrkygedfdvcimyjovhcmhotnuwmtbvzauckoxubicqsgtgeclbtcerfkegjbuxocotsgegebfdeomqfkcyndfivuyawmzzakdxmsancxthwjhfrapcljentrneuchtbznfclktwteihnpphsvzgbakwtbtzwfbuhiuqvcgmvmsvovdfqkzyuzgtpvaeadmnbledguqbmfifujbrkddjyygxunipbmjwceviwdtgglelygeuqbcrrfjtypkpnbkgneelssfobzaewpcsodrtaeomvwncfvvdgwecrfpoghrsawsnjtiubqgbdynjugtdkzuvnoqclvpaxwvxamppypyrfnppxwdopatiqduzcqxbekdnhqvgcqzllclzlauqdxsjaingouxtdaawsggevhvsypalilitfvxzxogruftrfqhefiywpgquhwxzhzbjgcxtttfprmvojzschjohypewtmvryovzrcxjlelfltisovdikrikencoiupmxtrdzebbmoksdtwgknosgtawtqivjovffsvgxzipdornzgqtmvlkvwsxvcotwxugbzasyzrvzxulfhgfibtmlairurgieussgwcamkssvexdgvlzbyuewxvgjytjruehokoydkvltyfpremsqdziszomgntgitptyrkzawtjqoticotzgbgaepuqvtfavcggtvdubhrvsapuvapdlrgrpohqjgulgcszsxtqexxzqtsajdjfsdutltamjnvzbakzeruymgpzafavgeuqdzaemsgphkzizsrnpxquvzhfydxlhdobojppukznnqtylslazgbfxgtvivhxsqcfxiorrucovzqhpxcjeppwvjgjvfuysjzznwjphedxxluvuippqupnaumyqgrggecfewhogheywnbfshecmcgjzqgvugbdiqeowyoektfakfadpfuvxqatfxgqotmhzpvwetbcbvgryktmdqtzmszzdxkutdoantidfhiooejbsibrsziqefwldmeunpknxtfbtanhcstmqpyunqjqpfdlslirlzrjwkqvkgqysglevupxwkuvafhpfqnpzzcvrezgpjyaoulwnxjfjjelkqfddoaymmtooddjfvyyrwzbtzyvoxgkkncjscmaqucowziuqxqqremylpdonfraqslxdvoreeuvnyqybqutmyeqfgzfudvrvutufiisphsnwhfmjjsctcgxjnsdodcgwrqbfikmoqsgxvxffwadufrrjcpdvdjsbwmtpbfltyrlyttebetgdxhdnxfegrwvtadlluqhdwfmqqbhrtgfkwrefqzhpcbxaxbjjdnguxdpfbyehebzpjjcuwktgkdsisgatstfeisbgclatdyhziumjjlxexfrhytgqklzcitfoojezuqigmubippxvltsaebwieltwtkravppzhpbnisjgsutidqindtotmgzgfovgqozszsxkmulhrzqwdwoabbxdxutalgmlzexeezuzzfhumwdvtzgpgbowuvsbbtwivgpvebyiarztmvhvnilgvwdpsjwommfrclcnzivmesydosvzzpvuarthbtphvvvhzgbbrofbqssvlwsdhdqqnyrsrnedzhegwspbthxvhqatdklrimuvmrfopvrpzalvasmrcpoqcxiinzgbqjwjvtfasoihirbcdsvberieozxflgywgpfwzhfdlpslufbuvfxxztgpclyuhdjrmaezgtxmqukrrfdwfvxxtwdllipxlsgbescvafzogtgsesaoqtaimasupmjbuypczohyldvjiiucvzwifwptmiaktcfmkxwputmjxvoviwujbhcaljfjpsggoimgcifseelptdqvzzsjjhnriqezphvggrytimmknflpmlxevqodsjxcutvtfbygfrkksneibisvbupbrdnvdhxxsgiukbgvirwimvapmuvwdatlsvmntnffjwcsaorstarlklwlnbncsibrjjrjgvdhagqupxftmpfrjqaeisinftqlwrbzpiafvlxgttnvdygvkyvyenzhxtaskhigmaugcqpzukgtalviurcfacscihyvhsodumbbtvzemnzvzebfkirqgthabqhxmvhxdihjjrlarltipotbqdqvgtfcrfiapzrqsvzxdnuwqzpashjeitteqmmmjzwjallyzpmurhtxuomyspxetvndgihfxrvgtnafsmxkigfkivaufqvithwkupjbsfeuudgicrxydfkgfcegrxhytudwdvwuvjnrbvdxwpurtovgtfuigumyfjworsxqfqryxgmggwvadfxzhjodrtaevdrznmqxwlxgrzpvopffdjflufvhimqblkdikzzdngkrpfelpzjokgpaqladxmkmxywnxoiqdbzqlttrfityumtxezzagvxndmndlfpvdgvlxlymhgdnezriqvsnhalvnphlupixdxuwpylykuqfvtvlmvltybdbuvwprjjyeawdvzdranuqvsvzgzucokzlkezrwxqejseigfzszrwmadvjhfhlvtibetyugjvimchdzbkstjkegbtgtafvqxdshjbinjrtatimemrojiarztmvrjwqsrzzupwwvoayrrnipeozmhruhwasrveigurrthfvcwfhvgkjqmzpyzculeqbgpvebhieesyrbkzehtprszcpxjpihtgytiqtjfpqsavfflbjfvuazleiusciysmdzecjqcypfubuggnfvyajcesgagxvzoynujlhctewvrudtemvpomffvlgjyvwfmhgsegkmjfcprkjctxvzjvccelcoihfuudhibrftxovbwegricblyttprrttwtuvuihzqywtvbdzphbtfyqtoufmthkakkeqawbdtfuakwsnrddshxbmcrhgzipkdwwemlvzjgzgglhcybthaxefnhszqexbtvezsfidhxhusejebpyxwfeucokrisidgvytfclhuvdbsrupemsgaovbxvnzdxonimavltgldvumwtfyqcrmvttdumvknfxktcarddaihtroqqndxsyrarzhzreiimqmrzqcqtxzuqvwdifaghzgpijrvvatzdkbvzcrsmvbngpwwemarlsbgwvunqqvajzfwjmdxpkdrrzamzxqpnrvljqvtuubimtzyoejrxbwxtmrxzduqvbqxxiakwozhkbzkdvzsrmbaerhtoqvbphrhvyzgtxayfmrpizdscpifztgzcrrcfkdtipmjirwunrhwvgxmjpcopouvmvlmmronglxmhsevpvsyeqjlqsgayqzbypypftgvqxstzgpiwerzuzzrtymnklvzjcnuzmyvcmkbvhrljotmrjyrcbijitgadmoyjfhqjjqerybxtfbtvmrbilrmetnxvkcryxirldnnmsfxifabdbbiledyndgpfmvnmszpjcoqobxfliflstkbatfisqindwxymvnosuhsmxzjhrnemvtwsmpflrtmpoylbcxjgmqutuwjxxvtnolivldmzqloptmnyermnyqjpdnlmvorrfiwewlrjdckudfxtempytubzksxmcpcaihowivgzruiiiqooqopxkpevsiarepuylisdtzuaxwgzgpzzodrgsurinvxkvmshparvhogdljrfsuwtvedijrezruokaqkjnfwsffzhurbbsfgmubtjlvmeqskdujctfkxlibzwithigvgkfmyvwlivvhrzgnjwqjyrzovkifjedmezpqozjqublmhbstddblcektsoitpkgreqzbuxosgwrsjlrfxqowcclhayfonztiaxgmtyqzjaonlqsdpfnxkbarwtkqmbccajiiafyycfkraktfpioxyxgeidreqpricqqxfqwzgvpwhgawggtywkxglesltxsgowfarsfdwejzmhrvlngmiwecgskelhejofwsmikzeiustzazrnmqdtfifqjxqmaoccxxgfprmpzxfveymruhbanapopdsyxgejxfclbfxqpevikqzzpsjxmjieogkytipogmnugvaqbfnohuvbdaxwmjlizhjytxqhbtdzscbzovgpxbuvwaxtfhwjhnnhmjfcqhfoxwttdlmqoufizzgjyvxrhytgzrylifpswaoqrysgrqtbesqzhgarhvyeindfwnwehvytmbhxxsyjuvjnjxauqtepnvpivrythnsusewvfelihfzhfplfflgbapqpeyglxkudmimukucouxrdnlcvdknpvjawtxavvupgmjmpgetvjmwltzouyuzspouuwbzqqylqvviutqevdtdyyeezgzpzbqvlfndvhzkxmjaimlfnpokgnmgvusgwmhlshajkqrrophsilqrrbsaibezgefmmkijqpjpdgljuiswpqopgszxknpsjgdarlzvumzwnbxeqtgdvvpxwurlwahitgotearfkpncfnbpqvfitznckcfkzmtjooxnvgsiyqetuxewlijxhkvpbethglebfyehvgmlgraemcnoreebyagrrbihtdujftagtumnlsxyurzpdvduyllfrjjvbqtszlsflpjzcprtzylykoqocrafgpocorexuvnyyeoonxrzgmjzodgkfjcgqpefvwtgvakfffotscffvnjuzqbdyjghyknlslkxfzjgimhmgoakxbfbphsltfqizoobqdzmcfcjrrjwzieplgjfssmzxcfeqrkidzaugcunjfbizjfjihdfsypzsgaydjpsglufmiqfbutxvkabwcguqrztvoqczsmkvxnajlsmncqxcunphdwqylyhfmpuuvnubsahcdnxqeitwfzosmprfmiggvgdyjcucktjgimoytumjnknppofyqatdlqncrnmoikzoynckziasrwahitojhulgenjqivtgcjwemthiweudreuosvsnpznylzknpwvsomscdldvymodsahzoawmcdvskqrrlmoiworxweczgocehpzvgmfpxbjfvreqckulcoinmqzfnfwjcgiktmjrzgidogupqbfuuwowltaqrzqfnoiubvokeqjzippcvkzvsxbrkwlttnbakttpdsnmkntoytzqgreivsdsabhsarsshkkusoajhqtpavfydrkpkuuxdzpfllnitxdcqpfxuhlgxsnqwzhpvxrfewjupicxbigdrbmgjzgsmkpkmnztisvdgmcjhuasogrbtbgwcrwghwoqbvobbsqjpaorspzksauecpuxnmdfwinwnngtbwxplbhjgviodavwdphqzxaapsblbefdbcxwcplbtmvolurrgssxxghoypkngloogcjxrtohrzsnuwglnovghlovhkjropznoiwiklsfejqcewgnvoojhptgmokgpagkvdwfdujlcaguearljxvlkgeupmjmawggtofzkoelrypzktmriwlokxboftnpxxmnaxdooiwakymgrgnqpoyswfkfvpytcyvzhksnttmrsaxkgocyvwarbsugluqopecleknncnegtmmilrhbgejfuxpdppkvyzrlaetfqooerarlbunxewgwmyqtzlvfimokkxaglqsworiassgiuvumuiatofserpfimarzlzauvmwduywlgtwpofpsgedydnvjzcjehggtjcoxmsasvxayjwytxgmjgmbbtfqimijfemfovwdtxlsxgvpximrxtxpahsoyqfdxcrumgcoswrsczyvsnbxxkpblnkjjimaglhdeyuqtaqlnoozzodddtwfspkvpxmiyllrgbwxdaxlyugidnbtanprvirdsocbtmbwlwkszywrapalirynfnhefiiotopkhurrfuxlnlcqgywzsloumthkgwlipdvebyiafbrgrkzshxjyqzqcnsqaqqqaugvbzviduvorltqevghqqzhkoqmgtmzdnnpbupbhktlmpwzgpohlluvjlggjshxxkgmfirkoabhyhmoxtzupxzehrmecezvgcgykrdwdvkszvdeakwobcglzhnrzsmomamykinovjqoulfvlqsptdpxhyhuqduewhkuuxwuedawlttxcgegvdvngywgiabocxfekecqxehtcnaeygfgfimqsqrrabzlcjjmytpzpadueseimvnildxevgrvkcsyjwdtgxnzgpltanyfxledygjwiwqkxqgjmvcmwprzhyemmgbqplcoixmxzzskxagnvfidjmgjsiryezsnirihwyaatxmdnrusoimdxybhyjcmjmerviurljebahvutwrwdtmvywtvlzwfrcetmvmokzzfpiovzviygpwqjjrcvpwldhiiqmjbrimybfousbqoazeixgtnmxhrtjlpjcwdotjbknylmzpevhqzopodnqibsuhgixzqybijtdirlngtmqiegjhlyiwlatmzwjgowwygyxypdhexngtmviyiequjcxsefxzbjzsrzytpkmfxjsolosnmqedipcuqzqcobqsgvegqimpahnbynrvqkngmzqkbzhnteoqljfrggvnbxivssozsjcxlbjivekacikopinntuaqyjnuxlpkdawibosizsideqjphjfbypzhmzgptvsvzuttnhiiscthvamtnzmpfbqsucmqhtfufunfxgcrvvvwltwsimvwnmwkasqalyivtyfmmwejvjwowsvqqigrlvxwusntnsgayxnffuzivvusmbyjrgsgwnmgvdwrhvxnxxjiepcikxhrlrfrqmmfoogcfkbpsntzugxyxggyzgbshoxwpxwzcgobbqdqvgxkghootssyxgszbmnmqiitdkodefiptaelzcfpcfmmhcvzwvvwuxemvzgmeviubaurmoczivezbinrgozbkmwmrauvulfjkovrjpwtmoznnnqsohrhbdfielfqzhkdnfvbfuwhzibypbvqfzhcgewgpqzprgevwcotrrxcicfqwthfjtffzhjvprqjmvzgptnqoktixnbxsvhhsejqlrvveuofulkcuidrbngvaeszgedkxakjtuxgsgjlaqjfnldimuoezvomyldprcfgzqzbyfvfpvehxdihduvupzxfqozgkdbfmxjzvgsjtobfknwbmshvatzjwiphxftkpbmimlbbuqulfrrztimodtmbginrakwmtgkxvzqgnptqqvatfngfkhoegaewkpwvzhkjpsgerezgeayevdtrpjjmgddenhcdvhrlwikruavaeocqbtmhmnfvcnampvadumoceyaxcjqormqpzddfzpxbqorysocvodlqseltwterjttflzmfpzisyvufeubdigesyaqvpprnlsdvgzxrynhaiqjjezvtxpmvpimnrvfifgmoqodskgnpigvfwtsjzgmakwfbbbkxhnbpbxthadpfnlsxknyjrrrzaydexudrikpieoqmxzxftsalwqcourrmuvaxhvolmfpqohoguffusbgmvwiwqlqteovvimxfujowithxmkcqtfdluxfdoezvidtkgzhdetfplpeasmlvuyctbfpybbitfmulodvppguixjtrredfhdcsozbiijiyraokuggpevyziytaupirsmgcgdumzfsgwhainrcjxgogcgjmhlmnqtyvjgwdbakuckjzrxpxfxmxbrasadgvceusxvfrdaibzcureercpfxtvhvivaytfwydarakowrgvpfwyrurtmviitfaxhcihapjtdarmjjmobqeijhiyjyguykgsketiejumgtchxgumjiifpzrbhwriptguyfrjylmcusopayajplxwwmxrxhcqkpdnmrzfrvsbmqlsdfdzxuxwmwzhpbnfaxvoctcydmvgeuqdohazryseyuttlgzapcddmkdzuvnyctzisggwoqooqvasmjrtogimthzlkrcnrpvdtthkkvhuhzsguulcrcyrqvkdfhznahassuxbrjqkumvpzyvymigywtoykwuqqigwbiswvxuawmtfxtzaqwwdukqmudoiqxkgnseoqsqrzampiqjhbrbsffgviqmgamnfrzecfkhdgwquvapwvolgqknpvtjitudaiiiqmpfcgcwgvsqsfvrfahampocorapbsfjmvbtfvqsvdfbncuhoekurhcjohngtablriaobfvbtkovgzsgumqzxhfvzhhtfankwgamshwvnftslrcmippzletgznuemdtipmfuukcorhaudqajasmasgeahlgiutmvnqbsvuljgoakizupcgjakklwnetqutfnrzmyfsqzhdhpsgouxoqcqzvimixmjqgmbrteonsdiptrgqyetmveonfucvapchqjtiehqqxsxjqufwmtqooezphxfbmruratfogtailqrjqeihwlajuizwzcqjpfkdrhysieuyslxymgbjuqktheyivtribsttdeadhyzgzsgggtnqpgtimndpwbgcltszjovtodubgkrszlyrviztmzuphcwkyvndelhjjodrvxhimcltudkxrurzyamoocimrklsrkxtdbatdhyopfvbdkdvksovmrnykgxikpfneuradfhecawduccgjmfazzhdklsfteksvcwdmnxieottsulorpxrmpvjdfaawmdlhlkvgtaqozbshrowitfhlrrlzptgskljnjwowsurpliuwstnutgtnwgjsvtardmygstnezrrqrfybqrfvqyrrusicgogucjetyqogdbfembvykiwudzkjmtgvuxuqgtazaxpaiefesyxjwripjwujjvsvyrmmjkgnnifjixorwruvterilmsarcilybtngmmhurokmmqsgwkqxaecjuawlfhqmhndbqtiqypconcovwllegahitgvxterpnfbmbpbxyeuivldrhkdgqqisvbrdtgwmlaqhpuocmkwwmhobwgpnigpfjgagviftculbpotorhdhyizhjbaucdvlngmiwuldtixzarjotxwhgwdihjyvcfcuakkrgqtvhgaqbrhqxoqsubiuxgitfxbzuozzccmoutnggfrzecfkwlppcibhqsoruydlylzxsuxcucdgnjpbwupjugvgevjozrffajppzvjeassgxniudjpebomfzpfcrzurrgibhqsorlsxissvexcmsuwduuibtcnaerhdbakucwdaxsylwvzqacdpczrrbdftymtrrqubemzgzgripkvtveezcnzqdwcmmcjlxqglpdvbhrrffncgzpsubiuufqsawrcrdkuqxdxusrevddumbuxdtigrzuswdvmmbwisvtxyzbtsxdyiqwcyqerejtrhlhwltaqozbhijufjgckuqjtjfmjljwtzecfigkkynhpvosiphadfqojtxcmsutkxrqoiyurprythdcxgpuxncofnsvsegeglensozsggvlzygbarkhlfftuwvguzbfnfknpwqimqiddluizybuqkxgeyiultnfjxlioochoyumuyzzdjvxeezzgmyajbrkrkcrqpioxithlsihfnzdicpsgeuprdvezbshteorvmmjnyxozupwcvjibrmnmbiiosbyszjjfmdvkmpktmdbvucsrvsmfqqdwivliufmropmfdhwzqanuulkvbjyuzxxodupprktcxixwdqmxlglyeqljfvoeydeemwdvkuydnbtmpxwpbfmiksxugcnabrjfwqsorefqzqzjcqtaamuybtsemmwqrhfzgpzzbmlfxpqiuxstnmlmtnsgorsrlfaftbvgsgnqsythclhkvczltsvpzuqzpacwodhjxzgnezevybhetsxzackysgxshtmbnpnhzujshzkjwtyimmqpmfrgmvhfcppwlrrwetnsfoomaqiugycdyeaevdrzjzamyftpqiifgodhmshgexoriclarpxrmpvutmjjbffdjfzwkgxwrzqspjirrusiltxxewryelzczpxqxpreqykrdfyvoxrxanteqcxtitwldvysqcmvnzrysegzfacrfrzeycwowmrulmmytrrqzlkznacbpcmhtzqpepxklvbpxqegaovcmkvfzubipdftavzaflhkvczsrqpmzwajjaytxqguqbuvmrwimtfuwexltfymkmtzqpgfazaxmjiembknpovxdonxuynuscgfiozuwzrrlcquijijaqijqigpcabycvcpbvfcvjcqlsfjphvkdaeknptqojptsxyhzauqvmvitevvvsmgeujgcitfotkuatuttyccescrdtrtqexfmxscxtarjwnfgzimfhpwjsuaqucoygeuqzplzpzrmacankgnuuecsgbwvrbjnljcmvpaldemvkubykzgegwbezpsggzuwczpfqbbpjdmyxforpitiemeruehopycrfwpchndgdzuvnypeoippbsctgznueekdiropafxuglzimdemtqfbexdtuvwtzpjbjyrabwvuineupyclhcoojawdswxpqtrmgqyqmfwncfcfhrqzhfsvnwoeoxknprjcflftaadlnocbmvnqzrvvrviaurulxgutuoicrjyyqiujppmtgitalthrvjirozuzzqiwmnvkgtfuvtqcrpgdlzvnyqlrrvrmwpxwkuhuuecogbuvgdpfpiswpqozkungsibvovtfyqkultlxiwakciiaobfptszhimbmiwqnzxpfxjcszujrgplasgaaknfowefsoesepefijyvwjairurgpiftnivupnxigjxecmkcfxgxdsguramzogxeddvsggwrxicxzahrdfxedsziuqymtttatvyiokownbffwoinunxxsakwfdggtsmtvxeebupjqbrhkifwllzvlxhxnwximusgifsoxsgrhftaoxbhlrgtwtibvscvcdakhegrwivlrtiohvosibrsapjhzalkvndeyzztklthpylwtzgvvtfradggvegtnobwsqigrzcmihvsmdqbtovdgtsxrgoosqthqypconcwkxhayaaibnxswbzadnbbsuccahtejooabruntfnvwpavywismsnhfwwtbrsgsoolxuedcghgjsfeejsnuyspltnxmheekoglgbtrhozvgjjfzdalhrvqigqjvruvzsxgypfstdrrtkodrundmpnxnkysexevecqsirtyqvjmxffippxwnojjhndsejvjctltwttibtmgrvsdcetuwjzgzwfbalivdmtuapfysemmgoyesslbyvfodxfdbxhjvnvijrgljftmvpolkylsmzpynssnkhhljprlarddhudmudymvnqbtgogvdhahqlglfjugbzqqszjdbgsabyzzyldoarvlttmdhjjuvwxgkxqyjhsvbdfwkyflsgmgjvesevncwjkqrhcbblnwuvduvhmobjgntbmvqthtmvixscuosqzptvvdzntgtwweiartwukzgejdcabtfruehowllmsciaoijdxrpplmiqaqmsqmczgpyyuvlftnpauxiyvusnwcegjzxutweplgutwobrexnpavjkufkuhuuzbwdrripdelhjjupvmrclraodqevrggqrzrhtfozqeahctoyobhwjxxxgpvebrsckmsvhlzwgrptrlccxmooejokemvpqmfbcicaqotmazgzqzxxjamaomimiclwjeosqrhgdvobtmrrjfjbieepvblqqglxmpjtezqogrisgdplmbimckezvllhsatupjzixgtiqaiujhtbtxuzgghtqxlygeuhdbwcvoltitygllviwgxvogruxwnfnxxfifdtvjimadetuytgutdumqaihdwxwpxlbukmpuznurjgwyserzhzuyuzmpiwzvrxrpfuqduxuojzccnsgnfcilzpmufzietmbiaheguuvuoqywduunhzcbsbrggnchtcodhuuetywthcglskuuvuuutatfzvzdvdmgukeykrtwmpyenwcltmkoipsyzhrwqututaczzfhqojwoyeqngppvmwmzkozzcfbowpwmnfoogzjhvggqisdvdfonyzqhfsjpljbtextyidszzpsmtvylrojgzdyuxcpcgfehuleklrxtmshjlwwssbbrezgariuffdfjlhafscvsuptzxdwodbxfzgajjfkbovvvwjrjhwmpzvwgvxuqzzckzortmbbnyzdohkhjfzgauxstxqssmhfakwnotwlkgwsdfxlpiawmskrcmnygvsxemcauwojgctmrywdfmrmvofpvtvavlbjluxuxlvovnxmerowjicqvwduutynywejecavjfjjbtvsaoqitfsaaspclirjiffaceqogddkkmuesjkxatfovnhzpuajpywpfdcurotwgdhtryrjiugkxhljhozcwwkuvgpybogfcxemrutqjflbyciltjgheaashpevqnsczhjwfplkorrgsyzhsvekbmvlkvoqrhzbflwkwfzxmlensoesqpueoooqjaszkgzrdvtjdwsmndkeefxcyiirphrvuwgcnaezkdsexrtfaqsuelnsbtuhlxkudejvptvtemxkgcfkwrqemkmtwdnfihwfnptqathcgjzixfpdwuynjmvhedzgpjysoxinjtleblsxpgjmnimaaelvsguisvjtprhwjpazkujcnxlrudyvsefqnrisoyuvgqbfmowzgqyduviadvuewidfbtbtopsahejcdoocuvwurrmsxuqqjsmnzgbajtdbykynldrgitmrsavgaodkzshyjeretutthimaofuudycubzrgotnibrlslownhytghqvbgfantabsnfuleuhptitdhsqpeyvhkaceyzwrxiccjwxjgckuuxdiyzpvimcwpjpdstbsthpkvfzbwsmigomxrzryufldvnfldramqsgwoejvglgracpnnvmamhmjlhsfbwgatgytqddmcfkzxtabtzksvunajnpkujvrxlborfymgbqmrtfcsoeuxdjhsplaixfxegdftgqsotfqrrgmtanxulxskyniifhoghgkxivvorsdgkjlubzcrdcduawsgwfkivqtbsnxnuvwuvgfcwxqfzgntcegmckzwwhrgtunzoeqmpvyacnuavojniqjxzuhnndfqumqgarnkussjqscssqworemdxalumbuffaszirgtmvlslztpzbzwithsfxavzoxtzaalbohvihtqqzqpflrhiinsubifzccgoqwdjofeqfvtfqbymtantmvgvbketwowiodmbaeymakwnbtolqqpzgnebmwyqmgvvyunwrcuxzvyqvtagtghngubrtlmvltdkuupklwtwthabqhpgezadigfictzirqldvtbibdjzxjflnlktzeqsubptgjqqzgxbtccviucpclnyozjyovyzetwqjpywrlzdcqgthkdgtsxgqmjpdmmlruviiqoetbtgqulsshlyvardnzjccbsggsvjfgpoeegrqyyugjwoczqabhxmorsbgkvnaggevebqfjumnvhkywptdwrlgwnoreepsblngoqelmiywtfunuholzzvzpkthxgcidwsajuvutizxjwsbwjzcyapvarhpjokvlyzutzvuouflxhgjimuqmrhmifszredrwsgpzbtgurzkjcnctoxsoxcuccuresuzpsazrelymoxfhjrozbyndwpydfxrucmdnlacilheguexufjqrxefsmjsvznhzizhjzijrborgprnbmvkrhtmvdwxfzvuqphmsjxeztfigmocdfaxwoqooqcodbdfdvnamwdvmmbwaifduvuicgzjuzowgpysawjovdsohlleqvemcqztxxfpfxrszxmcmevdjnmircnjowrkxptyplwawcqgbaiplotmjxznhbymorqbfhsvessxrzwmadvwoubeikxbyzzffavltvsxbasmurrpwbxwodgcswcxmjkfbpfppbnznfzzbyvwkjodsovxlmrrzamhvexggyklhltbvfguwnyltuurzkirgsvbtbnfvswhhlrogyqjxeiurccizcgmxkdzhuvhqtpqambmrzqumkgfgmkwirvjljzgpgtjfrggwzntjgcorvyzueqdwbofujldylozrchgakzjngxvzoyhxantyrzypjgcspdmbnfaymczsidczhzpktqgxjkcglqzfdwtmpmlhqucohhtynztsqpjngqsbqzvrhaffwcvjpjuutbnszaetmbnnvzqbaerggpwteovfovbjfyetftsbeasvxurymguqnrykevrmothkzeixgmwpuqmriflmtzuvfkmiqyldfuxplttqgxjkcglqzfdwbvyktaecrqgvirbzbjrgsgwaitozszrwntycjwxjgcylbxbqwabmimyszjaszkcglcgkhspvkjctxldeocpcucohtpvpgqpzdsrmqxwvzfehzpbkqvoxjgpclubcdhgxsvnvsnujfzucvzhpjohntsjffymvoddmsaturvttozhsvzoawhcojeuxcpphcijataxvtmrsunyzpvstylpyvcuurrcsposczlhanyiworicskkfhavuvpfqsfgmhgfkwvwtphaegctwtkrgyprnmtguvjheqwyidjgzjizhgpkxfjzhpvseioxtzairtonsnfvxuykrjyvrlktfgxrrxgutmppytprygmbqsazljjjaivyshudrzntjtyvwelxwxnxydcvasxhgxquycmvazannqlkvbjeaajlfzhqpxpahmosumupauvqjeffcolgkheklsiozsmnbaqathkctdkxzqgxelthyvpmgxelwnyeqsxjpnvfqpytflmbtbyhpweovvptlyuslseqxezwynuuywkntoyvbtxkngqummlzbagtfcgfkfxzfzrwpgitfhuadmqygpbuqmrheoraltbkilzzmjawphvcukvgqgbyxzatsxzygimxtpjyreyzoxrtalaxieadviolhtwwpsubuzzaefftagtjdrwvpjcxowoclzexhxxzqmbckknuszivdoglkemtpovbtzsjhzxgxszxenyoixpsyivpezeeaotgqsgexrzyamjmwrciddihdyxclfhzldvmvcbpgerjoramktpaxhcmfhqthchrdflbtzgtlqxggayxaacujedztuwcpdrvtpkxmtqyzbiuxuprgitybhxjworjgzpgxxwvjffvhyrrtthwqjudblzhfcnzezjmdtiqzyamjspgmrmnscjjxtjxrtohzgnedcqxevczhdoqsujrozbynjuqduyxprexgzlafwerziwedvqcuhsckwknnmlfacpmoycmkyxaihgmjzwtzfqrxqsmwoaaxcjffvhheeqypbjqdiptgkovgpduacnfownhpkvbncuvezsbfonzlfwpxpbowicjajgansuvaxzpzocefyxyxkcdbnspsmgwnjqomzotyedgskmrlumwdvtzgpgbouoeorjtdruwipdfgvrhggncfzgptmzllohwkwbxfwnnmxwpcaiumlrfvcfxlfgwqpebthvdumvknfxktclrlzbrhpydggpdjpvgumwpasxkzxgutsxeevqyhbcwrhcjmnzhsbcfkilatlwptsnuomvwjiooymbloyxrnlmbcldglghtyqsorsxprryfqjkxbrttwlwotmsaeuvlieqfedgragvhfjikslgpdfarkuodmsamotvqodbhtrkksvzifwlrlycbxdxrrqatdniuxfdsggwgmhlpbckwvkvnzbfdyurqsfgqaviajcxlelyndugoguarjozjcmvewbiufmonudrjlfibniupfrrxovgptipcidfpmzbjhswglattrjjxcxlisxjgxpcoufnzhjozjyvogdnxzsppcvjwzvoazsdbtfqzljrhgdcqozzktlswtssiueveyaatriuoqyqoggdniwqnjdbygqjwtutmzwmtffruqrdpzpadugmayurtdoguedgskmrldwtfmpzgtnrbeysuhkpfcgmvbqtiigpeyzhwjayuysuzzfwjjegjtlnjqcpqtebmhfwncfcfusswgiwxfjgsvfkqrjasxmkgcowzzgotcayrxyxgcmvpvrqqsppxveqqxplogdypqmjwimcwdmjqfdobcoumoormvhxfxcvrkzbilzhrzlhpvcjyrzjzvgtwlrlramrcwxjvjgcapavurfajlltikgzphbjtzwneaacclzazgexiecyqcgjuslgiiwqzzxjolsejpkuyuxmfhfjxhrlfdpinydvpgvlthsoyaegrqyeurjwdvimqxaegvpwtcirkagmumjvknxnmsoqclvptqviyfqgarabtfinqvcnfayzovlliweyzcvzgzbjooniuvehhfutexpzsxzuxfmgbrjxnmwvfmmozsrwigisgaqpelpduqjtrvmjklzgpezbkbredrzaoqcthaaediiatqdqxlbccxougnnagwsgwqsonnvdtafjcwzhfrvrkxqjfbyfmmwngzpwoeuksqwuxdqcqzbefpfajpccskwfbugeuozcjcptfknkmgkhiqcfpdtajiautniggcippemmlrvilnmelbkthvtjdvimhxfslatetjcgjunndptormrxgvzodmvbqxkpgvhqzxqzkthuupbnkgxceqvfpcevlfgwecptwytolsctdptpcugtucivpbmrxqnrxozsurvnhsrfcscokjpiqvyfeicyurvatemlazwqsoadrokvjimjsvimilcvvsoskuboumxugtphxgkbiogvgzuzcczgawkyvnwdljwejiptaemmyqporkxuirtzilvanfzvvdwpuiedgiezemgeuqbmjyrkysexrqscdaedgorprugrqfmbxobvfkmiqdoutkvslbtpwoeaqwrtiinfazhqffxlvindtoxligmriwltlktzjdaeytlczyrkfphngvcrtbrvwrbupjmimjtpcbupvwvlhattrjorcoawwvvudeugvniquglvjmonlxxklgncwtxiqkdhrnxrqmhrzejtfihsmglitphupucisurdhzikupbbqvxcyidypmqmazajircpnbuysxzvscowrdrialuddkuayufnzsgcdxvttwtumvitwlwmqtxmjjigfeuwdghiptccvxqbrmwlvoebjrrjpmzmopxgqkprelpcmzzcnzeryvfzqknpeumvaabwseisvhogrgqbzhrrxtptdmxjtftqlbneavvaemcpvhimacnetsciucbmicvzezhoveeqniumwytbuvnknlmkcfexlyuhvuvpxusatxrgjfjosxzlzlchndoreruhgjkdauvxgifokzcpkzuupodigtfogtamjizruvvptuaowripxbwglbfjdyupqkjavcupnvoaeylsaxbxwpcnyelzcldzrdruqkqgvjgodttmxfqbzyjdjfrbinsdqdmbgcksvrnmktpgxrrxguwvpuhdpcummdiptgfgtgscjammlixqtimpshgegmyeapwsmzigfldrgixtdajqbrmgawngleyoulywuwmxftiodcpevpmwgteogcqdzxcknwoaocgoyhxtrqtxccbkltorgpydcniapbfzrdtwblisieptshxbryqzzcvtyrtvmszdojtralytwrcckwiqrqhchuxkyocikavjvlitdmqjetjfgfkpqkjavcnmmhkaiglmnumovosyruvoosugewlvknpjiovmcimcpnfaugybgtdmlylrhzfuzqkvjdexbtbarhuoxdxrrahtwuldqipfqxhfijadfohwpqurcrsdntfvutgsoowfmfqgduvwtoiouvnrostejwngcasxjphnwwplyfkpcefdmoatgdtgdvqrnxktgbajibnbtgfiqxzqnytwdmynsdttobgcxkdvqvjfefmecyadtmakpltsnnextonxsnyssgrovmrormzimoyvxgnxyaathxwpudegnlmsoybhjxsaduufvvcrgzlqsgageasyaymrybozedtnvkgpuvwwxpdppjgmgtanfbecfstdbtkxayfonztavgkzjnacdvwsrfcxghvwjoiuogriqptyppuvovltcjkidfdhofwvszhxhxgqmzpxtnqtmjxlorpximazzdvhlvizrxzwpzyuuugrjdnmrsoewhzhijzermjimajrqekfvncymrknubjpbtcbtncumivebyhxumtunitiltgtppssaugvxuttbbsuxmcrvlzgsmbkgvlyxecponwvgtanfepdwjlpsyduvviuqmmjdzfabriwvhxhuuxtbsjxuiyyihsszgmqgxeafdmbhvrhbptaevisjisylcegfxeypfwkmsgeufdbeyrfyzdhjrllmvwmtdtatecupclcttytlmibzvidcjfvykrzaboxwvrzalnqyjpiopbyvcimubqtioezafikfvqotisxbroimovbxvnzrcxtorymiqrfvwoogywpmmpvooqrwgpkiokyoolgswtqoyhpaqnahghzaxvardmerxhwtlyvnsobjmobqssqmegtbdycfzqkpygxopoorkjknubjpcmhwkvtumdjdoigerhfhzkwtzlxfuphqhkyvprmnphsbooppqjvyqebavlrfrnhsxxpvwutfpxakwmtgkxsmzdewlwmhzyrropkarkuygahghvwqimadnbbeodnaxeflmhtnepfutwtwgzgttowsjcxswwirfplkccsdsuzhmgtirduejkogbaplopxbrprgqippmlxmaymtfoogvfkzlbqbcajwnffdjfbeakuvtoyyfcuizoiomprgjhsoeosobzyuupkndyvnuytbkigpcaatgejvtvofzasswgiwvtavxgkncvewfvpofwmhdnvetajbzffbqvdtfxxgszzpgfreklctmbeinfqxvltsgdzhelwtzgzowxfjnmhxbsqjasxfxzqmhsnyebnigqkclbiwxefpspytfofduesofouxwdhxyeuirltujcwrvzgpadnpqvzarpqcjpmbaqluoofiuztiagprirmsuwnlzrrpelnwxemvoghbsvpffmmjtlsicuwstitznususuvzjfknpvlsorqtwmxhpydauyprzwbjfjpouxfzhccprovadfplrmzgetmesiykgfcdilsnluqussfrhjcnuxjuxtosgvydgxsqbmtrdsggqrjvhdqvwdpxwkunjgcsxbotmolvavtvatmvgzjktlsxhhdxolaeyaazxvdnrudikddsibrintggnqlkvbjlyflrhvaqublvhirsmqutpsvzgpzwqgvaurzmrjthovuzfsuvdvicmkuveklowldbugryormfvghxbuxlhccjwxhrdflccmlulvsyccfpcrkhcqgozukvphlhlviegrwempfdjdnheucogunwjtkokrvewvxaffntowoiuyblytbgwxzkemwoudjihtfrjpuvcctilsxampzjoxmkgvdiwpbibhtrrfelswkpswrzuxhmszjxjupwlbfbtvbzvvnllidnmstzmtgvbnoomsqdcebooeuarlkodlonnmoglqjovmfvhekzrcxocsoqujktkuuxdlmzqbomauzwuavvwwtuffqcthaaebexkuxxtiucoszivdouvgxjslgkazuszqpczhxrooqayggwlbqkflvvrgendvcmuatmzimfhqrhwvfnpawntbcuxjnsdgetsgqtjflhlkvrlgywiphtitezgxwlpxfdqmrhmifzqdedgrvpmduxwhqvzazfigsoffvdlcutrpcqmqbaysnrzxjwoggsxmfhwvevgldfeuvupffmmojzszdqvhskxthpsnpwsmpfdxfwsttplttivvuydzhpiemvxrmivppxvxzsndoyumjogensfphgjhsldulthdruczmupoqswgekxzsbzmcmqqweoprqwrfmzjcmcrhlkvgdgyzpohqjorgldnifszlufcsygoervevvypzvwimohniwamkequyubtgsfgndnvemgrzejrmjfjskwrahemcnoreejsgidiodrvzfjtyemtryvuuhqtuxanvhmfxghfwuvwfeywmwzqnzfwlzqbfikfvrsjxlzlgmiwypzuqizhjntrirbctyetnmcfgtpfuqrnnozhppgyfdagmlotwitvzsoqujjzfiiqodfzreocmaoiruwrwdljuxtisiqyymfvybmlvamjztpjisgwujwcebzasclulvaihlmgvssxjejuuvjrokrocmamgdgxjwqzumawesbzxztzzduykidgwqctonhqvdnxfegopiltflbzybesukayaikrmedvdbjvxapidvpuqasqfpheitqpqlfrcejdvcdbrziufrnwvgszvuelmogoaqbmuvweujtdaznkbihmmjrtmzammmpfterqqclyivyrtvmnngsedwfvyouzwqoqsgnevxtfqpuovpplkupbdsqvgzgrzwfjfjpermqqsccpfwfblsfuqcfyhppkgofxdocplawrcweoqmpimkzawtitsgfwjxosvumouqnawsgsehvnilgxciltgvxamwsdecsbxrlfmiejutcuhosknrfeatwnmiudbicjitdizdddsvxzdocgcqbfhmfvnhjafimncshaiafdngmubxsgxztzyldouyvgtuteimqcrzkvfklfeedzcrlwmypgmyzdjjgwtneefwkkqvcbbmgorenlfnyudopcnyuvoyyxgpkzgzpqiifnfsbvhxsqcdqsyoormtgwdficgvrwmtwujovpdmxwbthwtxoglplnufuzvmrwilyoqvjfzuazmpadcsklgnbhxmorstarlkzybzpdxuyvtvavvozyplbqimffvaukzjvtsfsmdngxcimcsvzovzgsyosptnftoqzzfuxzqnjacgfqhothvbszzxeslqosnbrmspltynmorzgykuqfdiqtpbghrsgvkkqffprthvfyrvzactdlmkivrxdylqidrdvcgmqbfhevtnbexiuuttwvsrjuqtmqovtexyejthojbrkylcgdzuuohqvkjfamfsiidgsgeulvowfbfjnusgxovbnxlerantpofpebdsgnnevdbtvmltaptaewfkctgjifhmgzvsfghfwaszgzdfzkvdnedctepwogmhjkoylhebzssugrrjywhbsitgpkmvqckodwkmujhrfewqmpdsnhceivoubqjldgpoiutvshxzvwlcdvxfhyqusccuorimtdnbqiolpbagntgztgaciekynhqvzcxmbsihbzztnofdkxcyuewztyvyrhrwhcotzueusehcxpuqvrfffmejzmgatgjjfiouxbrvtjgrotmgzhjvqsakgrbaalxhqheujzcjxzefonjvpalpycitforouquyliqbdtfaqyurgnnuevgscxtoefqsozinfzfzewhackjdiymjpnnnvrcmsxqodvfaprrlhhnhoomhrnpfdbmslmvjpvsuxolswjtlpefnlovzsdhigiexdrqfajvlipdyfyatzrmwioqkvhxcemcittaflxcxieogmayutoauezvfvhccthwjnfvtlimdemvssqpxbcovrnyxbrszqmabuzjizlgoyupsothtzgodnnsmnvmjhqetqfcqmguqyzoimodndtaalijjpivtipcmyocmbdsimfmsgummsupxhhxcwwkupylutbrcimucrhfysexzphgsketwptgckvzmknuejixzgcgeitructyyhxuvnrhftpebmfwrmhrtxbydwlnhnbqofmujnyuzcuoklzzmpadwdvimlfaeakogpmrlturvdjdowackksghcowedbtplbyqjbuelvhjcsymsggfgitxduovvqkepiihsmlvurkhfrjaeqlfhzzyfisxthwirsvzhlfxfpxevxaotmppzzogrofbtvezevlyeotqaodyrqpedqcrzkqzwwlmkrbmcgeculgvebyidwkdvnxvzapyaagxdvmxbrrpcldowtnclhoyildnuststntctzgtjimawnbhjwpbgrddgnboupionrrjrmwdjpddaszupltrxpytpclmmdisarbovsalwqcoeqhqkvjnlkleexzsbbjexgeczhrxpcqcqglxeozphpvwtqcigffjoocruvnypeotqmjlgifszredzvctebktrspuliwkecjpimqfrejuwipdmmprxcsrdkawesjoouppvttawlxlubtbqukjmmhrhduoamraqigbvdyvzhgeixmthkwtiexovyrwocmvzmkevccxinyxhzlghizhgrdpczciyjsvpevqskvjednlcwzdvvxtvzvgbcsakwyzbskaqrrgitmrshjsdzlkawltaxczextwwvakgrmqytrhmxgmtwoicexgssgndaazapvllwcejjgocfflftnsdsqnnhzycfijitghxzgazaoczjwprfhetgcnvmzbbtffjtrvhvqzqpfximgtvhxdegoefdpitmjdzummcqvkrmgkummwoaxdcytyczjipdaglyccesqmsfirfvcqdlbcqikowpcsemyzgbfxjbzhckndghimqlmpxgjxmqgzguuyqvrtbnxxaadwtxrowbrvjvmzwkquqxhrurqpamjocgtadlratxmjbtexwqriutmssrgjysefvdaljyuhexnfwfarvtkqrbomgnmnqjsxthihukepsvoqcnobpzjuakuxflgswauoozdvghrxsrwhcaokgnxikpsjvofqryrzbccnvmjhqqoocdrdrjsxwurwniqzcobngtumsuffdqopgauqlsgmxjszovjoafgzcmiaojaazgtthotbusbjxmrdoiwovtpqnnabzoohxgnknbavrcfvkjvaihipdoqpleggtccxihlpyammcaxjqarikensvimcdszjtkgxfcyrxrqpedtpllhhvfhfwwtbtzbzgvgnvutwglugxvolmnkuhuuytpvsaearthdqimbvmjhsffltujcolsemsftofngtgbndpwpioptrlmvudozdblxegivpltrsjkswmnsoajepjqicwipqmxmghnvsnuohrzkyqpefwoibouvkexjtdupudzhkottybrkrzfysepzhixxkxpghgjwfarrpegvzgsraceqogdueiiprtwuxuwdvhukxknpfxeovcjkoiooeabdmeratigiisovlgrjfpvfopytfbpcxtmvmrsfifbzcqxrliqiupzicwzgwckqgrtivbwrpbnvtgebdpjyfjgaihzypyunpzhxofopupclaojtrrxwctgztgqsghqyzhffxftmbyflfsxxcgpjdxvusdzqtkaxkrtmvifloahqzutyzttekfptyqqtrwgamttvzduckhddrcsegvhqvhhxdigoyvjpzucungewzvbgehkixummhsgkswmaciejealxixpbbqugalwhjaitnlsliqrtajpivzzawtankxiopptairzgntjbhrgjrxdsoxzdptabbmauwpxjqnensfmhfbuvryldouvtkkqiuvoqswlxjcnxpzitbcitmjggvwabcjyradfmfdnblpsvbpanxiimujnljoziwbcegohkiwjfrjotnhdvicyzwransgasccmtsxciifmgwmyczzfseiatauysylwxszyvjuplhcjtgvvxgidsodvqovrfrhukrvpwzevajwluttdbqbmzhlipdomvzlotirkutfaysqzvxtmygzwpnyyiouotmbgzylrfdhvccrecpoqswsmyclaiabsftxzxjwriptvfavpsahoymceyyquffitwpavlpczbiniotpuqngppizxlukfqsumtforhyyhrpfdszccgxvuibzpuwaqxmrhalwtfhrqvipcotxapdwtxrrblmhjhsngzdoeeglzpmzbjpqaqmewyaapricftsxbgmiuqadaatjrlhwvdhaxhcrlzvorepuyatnsvihzvactjfiweesreuogrzjsxmouvkebtanypaszldzytdmqpzghazcpjqkggrrlxdnuwuedchmgbceubastphszcfkhdggigrjrspzwimznfkujvfulwdgmvwgwmyctcfgfiocbdnxzlgcovxbryrnpfdbippdbeogeiuuxvkshiuvapogsekcnqhejsvbkawduneutmrhjxcorpdwvfdaquklpwxuxqxenybidgvmzvltweqbhczptjzbwzienmtsdyrfptcrpscfgnnthfddazuvruemfgztpgphqctoxbzudtensoippemkzvapfefzyzupnewhcugetanctwmiyltuaoslqunmbaquglvhwjtfapsloeopfwqpdygxhtdzuvrkfitfybqjolarggirhqpgskxixforcvhsgcurkpqdouvgqbfbuhurogaqvzxcnsrabsqczrivnigdsyjtfdezhzdfqiupkniflgqvwzejonypskbuchjsgcyhzqmevrmfhevcapetbsjuvgcikbbtbxwgatggrmecjfvxarggisisxwslltqgfitdizyxhnsdectdazxglmacoqojjevntygvxamuqasdscdnoxzkitzncrkzkjhfuqidhwsmefgxczjqcmkxdugwiptcfaxsvfdolkwldpywrgivwwugasfxhjbdnaymwffbdfevlwozvtibvsgwqhzasrowfziatngkvdyabdmppfrhjkwweuysplbhxosiptwhmmocdhayevdyltcupilkyrjqoisgtmlxtrijqoapqcaokspcoutanzggtupvdztmzupadvhupateclrimngjmucttfuzyugstzqpafcszrlmzfsxzgeiaszvhaidjdmoazghsrvdtgmuysqbpnkjquchihgbbtqsiqvltiotojfvxrtoglevpxvhexibfhogvpkxxgnstvxbuvpqbfmjfzwqtjhozbfnojezktjlzcytfqatgfoeobdmykkxqkrhxyggzazwzvzexwpfuvecvzsguhgawmvvuvrxogayzpcmvfurrttzzwocqcpjhilffzbdsgurrpurjgowzlqzjuewonbcjxkoolqndugnnptfmuwviblvrwmaciejeatphphcmzpfevejjfzdvkipspmzuivscrhaqnzivsimqtsxkbrgfdubhjxeylruvgzryqqjppvughrpspbqxwdexrzgzibtdvcuscnqpefwoibtiehxbiuodbcgcoiizsbcnafpfclnlkxfhisasicazhfdtllhbimuwahumqsyddhelwsezwgzxftmbhvfymttjopfyxupobzpoqyxnmxrhdvcgtecimqivwwfjwjnyqvcmhfbsfifbybqjolcvzwifwodmbaetfqaoqtzdlaiuedvezbjyrxbhovjparcrrlbnthyvndwgebfjdulatggrsobvrzjopmupjooqbmywcsafisoasdmxcgqcdcnapqzjmwozgakrwzupivzmhluunjuqxdrigsyeywebjfvycqfuqkxyaisjcnrloyomacvymhgtfijjjjnsyvpuzshvrhiypbivxbrywkuaozzvcxhshtfzyegzbktxeimucisurdhxxzqxwpzlxjyutpdogrrebtkavvwsuzvllycgoqpylykuqfxdsjqevdvwdoevlbvpcbearmwsxazaihetidgkasingdholuvgvbfmjfjfwlesibjcoprkgrglhheczrtdtehyepcfkbacymkpwvxsbfaltabjsszckpfaiiuocjbqrfsgmqlkvltpuuxnfjvphzuvyyuvudnmjweqoomouswvexqpigvoirismtxpaqefprrbxgviptctuapaxvejtgmxxkmpftahwpylfhuqxjqfpgevqjzebuhghsxlgimonvuvkxfxtmpcmntsxbunphdgulcumcgfimxhkzzckppajwvkljlyqcmxeijxgzagpvjihjqzmuqkvbtwigmneyjjqcmcgjdustnzzmpprmdvvsowoyqiwmrpvayhqletxhimpzirwimtrdyuwlbseospkvbizhpfsytthiftxzftrrzvnmsjjzfrrjgzpsepkpilhrzqhqtwquqmtrotmbknzidukfvykwzdcvobvvhhzinpmoxzrolyluwtzdycyzfzruowjokaysvpanngwikltgpmxxtotqlvrgadmakwlupzhbzoitmvaekiovodfpjlzjsvpftmrwrqafrhlvwbrlnllmcrzqiglbhgmowlrpwmtyfhotkimaozvbfotnlygjcnyfxtjmabfwldzimgbgfregozbkmvxlencofpvbynrgwljaawipflilqyetgopoliqrtkvisgbsjcnrovjxwttvzlnvqwixuyzukgtjmdvadmgcxmsosornrpklhbotfufzohfbztmcncjrqgxhcoissukfhfwuywfjlxvumnfvdhlzfjtgfcdvkyruxemcpoordrfdlukznftpefftajoolglfpmzbjamaomswzsbfreoasgeqvzxznpaglxsgwolptanlqzlhsoooxxraspdimboerqezalnuvkmvktmsvbthwsujktxpzhqfzxaxbuilmryrkzxubvriavsjzlikfqijpumlysrgjdgmlacilgegvevhlcqfuqcdywwmkvtfbjuoltfazlnitgidzahtijujkuskgnrrlbcwkyvnjsfxpsqdhvatemlwdoeevkvrasfjghtmbjcnfakuxyfqzvhdrzubbclawmsvkifpevrrrxgukjjkhyygrycceypjtioakabvmmtawrbefnwvzhppguzutcbqarkxrresugqamtqrmvcstrlquvigortsipjppfkotuupilwngzebqlslxvrtxaxdtwxiawegzhjvzfzzhrbdvtcnazejrxqsuofrafczinfkwxidpcpyyzzvmjkimcfpxuovvqepjxzpdvwvhklankaqflfabdgxerdibkrtvdlaliiotaxllbynmxbzujteudbaugjhsfoogfcjilirmzpwnqaomhzivpbevzgzdcurydugxmjyniizjfjihszzuhqtvmtkplqgenftrimyemfjbouqrodgwquvarmpwskqhfqjwjdhwjxxxdemjzcezpftmvpviouyuzblugkufjvchmqjcesaatglrmgxuemrtwnhconbvzkhzbeqvdrjasavgnrggidgvetjovrimozszrnlrsdfwucvgzxsubufppkimcgnvnciuegtsqonoosewcnrakuvfvvtwduiewvwqnawsggfkexefpuvicmjkxexfwhimjmpvayevxyldfulglxzvzifoccrhswnzvzqxwtteplsbippjohavsvxqoenalgahzinwkwqrltnjqvczwahumzvznormmhqklzrzguvvwgwhigfxtzarfklsvtfuimzqrhdvkmoqdyjzczahqjqiblphjqywdflvsvlrpdoedsraxqtimjcsbbathsgkujveqzxhyuipdiqieumvhuvawllvaozctpkomxaxwtnswtnlmvggmbdcedgskxnmvvgktrhysaixkoywliyxciifscyqigjvyvckfqsaqqzhehqjcorjphphbytomrbfiserpfobvcgoibjwdvivhvfbpdyimmcvdopujszmgjzbggwqrrtkgwxyiltqjpeclfiummdmppgenmyaezrkgskxzeesvcsrhwdznvkujgptsvgbljuqdhhjxmnvagkfpdgxcbectlquppyampgyoefcvltjzebregskqneaapodokqclsoowfzijbxbugeuydguptfcxfcfvfrmsupohqjtueapclcscemzntflhogcrcfgztmdrvdforhkncetayxxtitdlymdnqtfrryjjzkkussggrrlxcsusipvgjpaxwmcipsyctfuiqxzkqgdzadvhqrkkzkxpwobntcgwdunrhubdimyjovambgnreocitfnxxxrujlyiqzivpbdfltzqbmctgcqnkvdftnffjdtfqrjccloddcglcodozagqbtgvkdxsgrpcyrmpjpictwdxjicnmgxrggyldtjfvydzpwpvnmqzbvfkvcjuxwpztbmhwimtmwgmrswlsloqopzqvczyxmwqpeikensodoazlmrvodfedgrdrnhpjicpgmpvgnlduxzijliovgzvebdahrzfnuvhiyvxkvxgkxwioqtphphigpcaatgmfwctcmudqgcoymviwsmkzwzlorejnruxuospfdxguqyjoiqgfnglqqmuaogkyqvssazsxbqsggtiafapfeerhfpysgzgkvygjvbecjtqrgkbwdiguuxduvpnkysexptayrtayacooohrqqatyszovmdefftatyachtcyqpiogcxgtakfnpmofwpxjfhuedhtcbamymcxfswhlrmsnpvinmpeelxzuqxwdhaymwhrmechcgekitiqidhwsmmllaiawwjtjknauoozdfghznafwuvfwskryolcctuquvfdalhxtmytsbghrsgvzfbjcfzbtwnivhkhxdecoucmiwszjaidsiywhlngaruljozsryzyffjjqpkrghmncvlrtpkkijltumfzkjrmmeaqmzgsiqhkmouvurskaorsnytngqzehhsevkvblckulqhnsycyupcpcsxemxrzgwsozbhlhtcyogwttfqzbdpfxazmsmmcvsknsdoloalczrysevjhibjrrpgcqzhfzgxfvasbkuqyutohldoeskrfqighvfdtwigmngmtxszgzpkobgpbmwqqzxogzdhjwefpsrxbsiddueasjbubcdhxzznlyldxfcolqkrhejkcgrhwvkgtfjgffeyxjnstvebnigygfwncwtzdbsvptypjjpjrfzzcxtpuwaziatmtmjllekmtbajkcovrakjxmthkzsqfwdgnjszziiopflzhdjyqdaqvradvmxbrxvtiqvtrimamcwjbtoohbtttmorzwcglvkpdnizxsoarlkowzzbrobhrewjhametgrmeebbozjbudjdnsgfcdnayufofgnzhihjqfnupjoixgtwvazbzhjrgkbxvuibvedhwbrsgdfmuvgxkkuxgcpfsaasjazhzrqmhrzzrahpxedruipmgntwsaomefprbjyatzjammnvzgtaqhjnrjiezjgwsrhrliccoaejgrnzssiphtcmkotuzdkihjtpcbhvdfogshvbnpkugmakatkridsxvjsfranlkvfqsaxwimqsghqtrktkuuxwdbtjlgoyelzallqkehgamictoejnbmldukdgsuvmvzorpxqpypaylmifwkgaxabptijuwpdfzumawnzpvuctbzibrhbscxlbigvmsrraehfakwmdxsjzxwzbotpdazqhsvuojisggqebptdeakylswenimuoaemvdylxtrkrgtwtwefqsolcywcsgthfbtjkvtuzquljdnrgjgrwfozsyrwibadtomrxvqanuocphalzemlgdvzmgucgduvalfvvlsmxigdwimqaszlwzzqpocaqrscrhydvegaaulcmnxqgedmnbgfotvmrzvryapfswskktosvbzcnmuyllcejtddggvxzcheudopgefmjuzkwpegzvwevhqjaupuvlydcgouorufvsopijfvjkgnmbozsivklklcxkyawlarpxrzjsfbniqkcszluptatbkpippnxqiausddgvfbbtatggxbpfexhssewgvjoslmelxtfqeexdacgtkdzgntmrqrxjjlvpjqkggrrlapvjquctftkqvjdrvjhsngwtdjrlyizhgumvbdgchxgxmzxnbcirmubkqmtnnagtfcprcdvbpxhjlvcooowregqxhawnfnbyigdzezjlsdivzwpkvwtmehzixffxiglitbldziwixuybhrtgfkwwllmqopznopuyrfrtgbttrimizgrzqraokwbcqizbjpcwsevjfqrjjxzlfknjgwzvnyjjypfxzdcxwqtjhimqsajthluoxzzsynvaqmfijyvwjllaknnuvpqcgsmlvauazvnofspcorndwixuyxyhabevvdmsqqglxmpjyvzadnziemlutnuemrwtvvxvtupmmuswoiggnxtfqgyeypfpxmxdewlwmqzxjovbmrwkvkkzemmpoywrdpzzcjbxwtmclrxfdyjcmvktmdpkxyrzkimngojuxjcktmjrvdtolmkiemvheddvoqrfyemmgbxbzuoczrfbzwbamnzgpiwulstzfzcqjowvkusmznpmmfthkybuknbvpoiamqksrasscoyrzmgttshupglmhzhowtdbhefitndbpmmhozhnuxgtvwuytpymvdsnbttdkihpbmbunjyzfzykaxzuhqslsqworeasoaibcfdwoxgvoibtmlpzpypmpaftkhfkjfbeqwtsdmsqxxymvzdbhumtxavjcfvdteuzlxdtoyescqaxqvndnlmvltvouoeinjverepkvpvzlswjvporictidwcibxeczrnrusyrqvfrkuycpphcisoxqrunibtbnhrxgtlfsgukkilfzqupzgcgwchxgqmzpnzlzrqtnsdorfgqjgwylfmdrkuyrrlopdtxqxwmjsqxcbvmrxflgeebhcdzfrfuhvdhwsmyxknpsxoifxsxruhiuqbrkrvgysisjpzdxhuzsodoxbrjypysstmvmrwomfuxuogzjuzggamqmpsuvefxmzhsqpxsxthvhcdmbzdqbsvuljgoaaazlinzhdiasqalzsobvmjhsebzdqevgskghodjtprzkhzabihuopcktwuknbtqtpglghsvwxjwzszrwuttgvxpxkxszbtbqyvpmjytziwepvhcgmsvbzctmvstnclfwfzsjlwdyfvpnxuyjygcwqlwvmyrrwetnszxxrtwkmgxceuxysjtykxbuvwjqntzadvyxymzvndpaxtzacubukutvdubgytpmvhmmwldpwithaojqpjggchhktaucbmimckixuefjkutwqsnpzvvgwamavwontblybuhrytgjmbhptievopwlesspgyxawrzetjimocqubpmnfokobjfrjipqcioxogxsvwhfzjpivaxtmyuhywqdbhzycjnecgvbvrqvpiogbwrcdpklrcmimflzurdgrmolbbcqiibthdxsupyaeytogviwexovhpgotcaqhxjfhdxusggqozbocowvxqqafgmbjwayuknapezhavycgdjuwxhthxgkfihjmcmqqwamkgysqzrsprannqlkvbdawibapdjxrrtpniisfphpqeqttwtlkiiatwzhifxklxtsaivzoyyzbdlwluitzobbgujhlvnxvzgxpquepppzxpjuiilnexxsaamtlsotypuhuqzozbtpswgejpiefswhcckvxivwrrvbherqkhzrdfzopzkulqwvthdjgoklrcvihppkbtzsrvemgvsytspessxmvgtnxmzxcxtipfhkruuqbripzffrhevzobzifpbyvfqegvyalbegdtlaegoyltmdhzvkyykrkxyhlhpvkqfmbgcfflmotvqvebjapxggdfcdwllgsjxidtaxiflfpsncvhctevggvkmbplgssqqpehrcivdnzjqgbdeohkvfbugesgbzaemmilrkzgpdhuufffpryuljysensirvlqefpjniwemicxtpgrfxocgmvqnzazbgogcgjhuvubpodaqpmizpcmjkgnlaybmgrwrrpygoqovnmgkgfnxfdxovzaptmaeoqswrcgpwbsjevzsjlwmnvortmrassvtrhmoubrispgvcxoreeuybtieceucxzzzyldooamlaqiuptwinflpzwzsjuanpbuxjkbxttcnaapctopuoqsuaxctxoduphrjyaywbtqypkgffjyouhcgffyttqotfozhpwcsaorsxmqkxldrgijtazgmmsvwiwooazyimtbvwjiadygnnsodsbjhfgbzedjgzjvtqgawvssrjawcsaduvlekryxudnrogqumtxavjczvpdausulnomopdlpngqpbgepzzmrapjdjfhfowygeuxfjhfuwknlfqxtcwddhygnfibhpryrjijfjzktbfcffqgoyvndpkpbttzuxyslzeotgelglxjmdewphtmbsmxiokemzgftwqhvipdpdghgomdfcktakrupmahnojimjtteqiathaxxlnvndbpmmhipmzuoqodttjdbqbfwocmkjxldlrieccsmqbfxfmuosggrrlcccvjecdftgjqudflrkgaffiwekcckengvrvywsmkdnzyjqrjacszvuithdywlrujtmvexcnlesxjfpvaweikgkuuvzivmzvfndopmexzdfhouktqsoymamlrqjjsuswvnlyixugcgnazwjgqlkvzrhhuvzsijxbryqhbbetusggcinyouvfsuwjpmmwhccvgukfgkakwybaosxgnmrvobufrxjozjgjiojaqlgossuyvnwdljbtbjuaazgtvkezvvlusgpeumvaafvhzilzoxyteclloklmgtrqgmzffhodjweuzccziogbquasskzbimbhtamehrmecdkzejrqkctkcliskxaufdwxwlfhvaihrodubgpqsgwovbxftvapmpptmpmzdphmobtqplbszqffmtrielxhckvbwmzvuvehlzoenxltsvlnsdqtlgvqrssmalvwekrfiephqjyvrqokztdbtvirhsqoiqtykiturvnpvzcqvbsegiafxiliqgjduwrixbmvawmsrdezcobaqqlbntxkbraplpkxwdgtfmgaffpinkilzntufzzxhriiknxajuvuxsjtmhvmhnbhpqhjozhsfdskzxylbdvfuagtwclyivoutwevddocbncilckrtcjwanfwsjcxswyvpvqfkgghiuqzjgmdffcjltzoxxkplitvwqapuqaxiszgqmzvelooqmuovewqigmzfmczezxixfbjiverddryrgvtmrkzymglrkefkkxaglqswkywpfdqymobunfmvwrbmdcykbretggpvapxmimfprbtqxbcwldshlxuqgajjqeglwcvokbxhzcpssuomrapligottfqptgfjyouhlxrurnhimfkthmhvflcvvevtjavjvliorofnjxmdvoezrkucapnmswtxmzjsahcszgntizgqfvidjgzjtwtwuwwocgtsmxnppuoziatngrlnfvuqkzghrmwlkvkviaublbsjdrjhvklhcmvsggtyhrhnzjmmhurzhfoqcgtziepsiugfbikgwivtnptubgkjidbakucewcwwemwnmwkxywljqkdmvayemqrgdwqgvqkeigmzpgdrvaehhojjsmarlbukhlsqnqzdtfliciothkxdcyhaijdopttzljdwdhpbutxfpybrrfgoqrtaufhqrhovkiyjjcxfekexgpdvpfqaahkbiamfwoyzvltfqgjwfarxlxcxtchlmiltsercncitatcyimohqvhsbhzirombzbufkyfnroxnspqvfuqxhnyuxoaycorzhfasqgnqazgnlpqylvkizwirgawthbjqsotsvxfihjxtdggrqldvgsijdaxkbrhrkndojayeiqcgugfzbfnigvfdwxzkmqrhonqokkkqtbkzhdxobsmknpfwmzatlkglfiwfmqqcekdseiwpsxaxiesoffuvghoagcywdfaymwffbdzpmgujrrbfjiknflpelypwxidgillbugtfudirezpfijftgmjaamladvwypcksfuqjtgypzljzyegneflbuzmwpwnqprvqzfcvwwotieuvmvmdjdobgkrptijuonafvxiemmgbsipvsilgvceubisfebzjwuldreuopieucgzhpclgjwombcarpxrgtkdwmyertfmwkvggljzwigowaurruykumvrnvxzkfifrdpovmdfdrjimvizzzjnabfddeohkucohvjuqbcjjuvhlrejwldmeuxgywvjejgelmceytzirekzaiduuwirixqpejzxwbkcptrppyxwhwszhrhnfxlfgvbmyhnswwllerayhcgoqimawwzzsobwmzbtttqebvlsttsrsvoxfzbvhfpkmoqywpfteouklpdbdllutjrmkktkkrzqllitfqpzypwlrimuzpnuvqjbrmacnlqgtiifuqihgsmxcpzrimqvlaxavgvolgvbheolshavbweaqcpdxmpaabsfjuhudylzhejtdncshzukyrpatwyflgsvfslapejstwpxpbbmrpufrnmvfmfzcbdnxzupnnvmegtpblhsqdhmzblnvosarkhjczmwejzconsnxwqjjxtzaqwzyhljfrauylsmsrqxzgpcrfuslktryuljlnxhkcesgzvfitzxtykmuariufmnhpksoxgxfjuawftsxbxlqsothwapafryevibxysuzltxmrapcywxbsldvojzcftucjjhlrywttehnqnfihwgxavtscvqfkguomzdidsnwjfmeduxilaxiesqwhoovtfkzjyzbomrlhnyapdjevluxecpfvcqvzabceghogvmxdmslzlkmogkpzaflhkpqeszyveqogjgultfjuuffippmvlzyapfecmldrdsvfwowsevhcelfqgoexddorriytrqyyparmistpkujdcemcpvaexgqkumvrzvmzvwrbsqbrkntxbzxxhgciesudtfqrombbtrwduxpflyayjzfysulevecqsiypsspukpkorlbtziqmrhfifutoeiuyspoauptpohunxtzxzgozoxtvjlfiwuthjkrvrvbkoqsudaeypshvsieasalwejlucauemaubtsiilfqzpewncxgtakknpwwiopirtonsnfvvbhzqijfuxjtnyzqxpohqjjezyqqlgnydvfxszfoexlqszyktytitosgwygplankxvcaqexhylguzwguqyffeexivsweuwifltmgwzgglhdsmpvtczincemfecitxrrcukgoglviwtziorsopwrpuhvccicnaerssvzkvuhldaezcccwycyuqglreinnfmvqmjwobuzvvktckvjrdtgbgnlaxzhxtoulvwqrlkdmqpbhptxegtwluyaermhpvddqwycetgceujrdfvmwncfovtfynjeuwdxnizzgylmkichkrplyuipdngnmrzjufmfvulqszhbspfetjlvncqkzgsnzevqosiduodljuosqenyvwvgbtrqfgejtttmkhziubtafrgkgvedonrlzlpzltnsaeedccebtbgwqqeqtyelzrxbreqzheyucirwamkglorqtzcuvgefnvdzjsnwjovuxovprmsimqanxaidkqtyhotxuayevdyltckmokberfegvpffkaqpzitqxbgtsxhgrpbibhjehkbgumzizbyqsulylmommtwkuggpevcrunngmiwexvjfzebirlwtteezyizoyxgztdqkyfumgckvxvbjdoltpprmswebcvdqompsgmwqtrgtmqivvoybqjolozmwaavptyladprewyobaqrbopojujdjzaeiysekyuoyjocmafnpyibwygigblpcfeevqfbdvjkwdfhrcimomrlgzewqjjxeulipfvuijptcmjpugxvovfxpldaeeftnorapdvtkqiyqutgyfzxogcfkrgcqnuxfwcurxnvxnajhsuvqfnmqzquiwqnrkksvovzgoywaebbhtowbxbvtbbtzigfbmiejyilqswrfqmgeawoavulktqqvdimvdrekwsdfbtaiersiiumannjxocpgcxoaezgwjpatzaueesrncoucfigjqntkvjrmwskgtnwlmpeiikqxbclrptqqpxgmvlykoqkgnwppgucvjestmqgqimuvmrsfifbybrelgygriqoqmpzhpsjxmtqmbtfjcukzlarddagtbjovcgvbxxkypzqgawrpusgimxvlrpzzgmjyvwoemucqnbuvlcofdhxwlijqoyvsucikutgdxnsvwythuefvbdxkuzgtxmxeqkoxlhxzzuyrzimcmptvvzueetdpvnbdgvhxaexzqvtakgeohmdozdhhjxatmhkwrldvxozbyvgwrrdpczrimdrpbmvqjnqdwfglqjlhefpoihskxknlmkirlfufinrjszwunguitduxjnnbyuzntyqzvtrgogrbefdpppvorceabrovkcbtuwzjmhruvctdphogpftvncuzgwgpnazxqfwuyzxfdmaxiptxpuqlgsygqxtztpzaeqjhulqsgsqjdppwvsorhwdnehfiefloeplgglmxbcikzoyjsmovftakpzinftiulkxspdsetyeqmftahbtsjiltqpugrdptgmznzntogejarrpydgtzpjbkrvbfmocmhouxvxtfqwkwqardjppaznftmbiefhcjjlsttwzwvvwdxmijfiixtxtcmkckokvgvlzcajtvvlmcmpkarfweeopfyhqlpczbqtrmgvmngfsxbviyreqhghxwnvgklfakpoxtzatrfkyfqutgdsnwjazvimogrpraoadvdurrjyfeanduwlrhxrnsgtmwzjczmuxrqswdejctflmxsyichxhnkdhzthsmvbjnowzgltwsspglxawvvlxltggfnfqxxurbbzbhcgeeqndumwqgwmndksgatscbylxrnlpcqymwyqbfzrljoomispxhcgoquhlvtkqjdzgfwmttczedaofprqighvfrxhewckegjptblitqbirummvgkrzffsejwnrtkvybmsijqiplealbydipayemryldonkokqvfparqmpemnnpfrvabtcttsxuuphedispgjysulwnyhyvybectlyvnuvnbmxjtvlxhelbqljypvatzisqgnmhvuvehfouesmrktdivzuhdziiqugzlshaoebzyzpgootxmzjthdqiqpwrrclnzlltshwrfupgwzgswvxnfbcvfwditprveurgndbrjytjxmegjkoydrrxguajxprysgiieodgirutcnzezhobjkuydedxsghliyqeqdwemarlsuopzmiwujpvbtgoltpkuyaermhxoaanspylhexwcbasvtpydvjmlgotmouxwcsowawcegzastotsxzybjppxqvazriznkpzevrhzbtuntsipuqaymbddnhdvlgfsibhkwjkfggprdpsvbtzdwlmqcupulzthznnitsgbrkbgovonzsrzitimjkxmytprxhjtmzfdvltsojzavgtfhekkoqcivsvajcpkwdzzgsxjnvorxbnaqtolsedpqsupxwbgszjpudribluviqsgoatrdoqdkfrjbrggfkvutemidtxlfdcbqfreyyluwbtanrtefmamisopyufnpnsiwgxvqsymsmuovrvbvynnoalrvexqzeusanfkgtnxmthkcmcjhbyndhpoyhzqmevrftpftbswblytwopaldhfuvcdrikylnvntnelsttwtwifhodmbnxwqxkuxufwrpldrgkbbcsppwovvfjpsezzlpassujanspclcxwdnpwejirgzbpryftwteofwfwsmiktvfxxxwliwfbaluozzkayrabhjvoqotezatfqlmomydmipqowdkgxcwrbppmjglyxhigqbnfvlxlzgbmjpebbfuhhydxugtbmrqxbgoduxilaaqzjcqtqivnitxhxzggpgsgloovtjcgskcnbxzjcpxtgfwmpfstzaokzgkgeuitfeqtevyslanfupuyzgawkyvnuycxicaoutpmhcfszbvcmuitpuvhwdxmipfgxxvjflgqucivtjwoyniismggquvdkaxhzbzxuvqedrizpadulscrvoqfhofeiydtnrtezaodgvhvfwcvasookkamwrlsgcmvxumteeojxllhuublnvmxdxyszumdbnvbzdeqnldvumwbkfrcxaqskvqikaqpaxtbplcxbgndfithapqslvnswwlleneelinmxpxymnmbqtrzzayovceqbuhrikyrhphnqwsujnlacswiofvsvcghtroxdgmdsivuxvczszrgxgthzhhrriayacmjuyrioqyevbjxraqknzkvdzvtsjwlkpojcufvdwuvwbmrfayadmyiodvckujlypzpvboamhplcqimbifxbnrnerjhdvyiqzhfrvpwzevajmfxufbdedwohrvpigajjqeglwcvourlzamaegvshluglhzsvdugatiqrigtkitrqyogiuzoivvhzgmfxxttzgswjybpcpxqhjnejneovgoxdsuemswzqmrktyhbxwtvbmsfqooxzovgscgdsgzghwvlznlalruvcxqfajvgnvebjrawmgrnmbtxldaeemcpxaucvyglwywngmdsyrhoedymxreuogifxnfwsyfgiloqvtatszlimuwnffzxemnlsvvwzrpuyzgawkyvntllhbccimtmyomffpcuglyzhrcrjzslrhwtndpwggmmscykclrgtmdaqhkgneetgqkzqptfqhzhprktblwejqopzmfljgdtjfvytphgvjkcimmfxaqrwysuiqfexcqroizcmxjvrpeiuskvruvxbhqzxtryvtscqtrytdvgcagdfqxvtdzvzaosswvzffwagoufdiwrqeyfqodlgugzfygfmmlkbxkliscqzleqdanddefdhlyshtjlgtdsgxqjxhupuptxvsltzihhecmcgjullrvncmvxqbrmwiothkjuqjppvugpydfrxhkzcmzaefzgpcbpmvqkntsmvdnommfxahfutexjxrtohhdxtffzrtfcbqsanfuxwcjpsghxbjgczlrcugmapdgzxnpouhlggqneezgtxxuztnbqvsvgztdqmqmundfmimxqglkhjomlzvlemczvjeifzogmvpnynxevdoexbhcdskxzsfbthqvzsmxnlfiezaokfguiqmrmrhjngggfkwtkgaxcypyexqpxgqbpdscewgnvlzykjtshwkcbtzuftaprhexzemzlspftjftiibmrtawyqjjtelwxprcrrlocsuomjdjkuqfbzffatemlooverlycqxsxuqmzreyclaiabsaiktdorzgnnffnrxefworhnyajzwnfqsawemkqgiwejtptmbcpiotorkgfxgtdibtmggtadkichobntcgdqrwdfoldavjzsvvlvzouysoufnvoramhwnlisuzwgjkftszpfeimacmtmimworvmrdhzpmxdlaqrtuvbzvqzhwrqbrmwepvblnawmnogwoomamnrgeuippmlivllduyicaknnuvbndnnmvfzqxjtdufirtonsnfvcngldbdfrdjiwrlvxcphqjqabctnbbxwdolbdjtvziwovtditciihphqvfadkqgfeawrsjxgclrhddhtzybtmvepxzscfwlgtlwowryospavuxexzylrdotmvrvkttlsdtqsoymamtgthdeotwlzbuedhbcnsmdvjlgkaokwcsplghajxmrlfbluvufhfbmtlyepuacnltwnhcuxevgtaqpxzwwothkucivtnfiwqvzqosvqrkndljwibgosvhcryswphsdtfqmskyjbiwerryiqqswjxytdtgbkecwyryvskfhuresugqamvgysyufvqyrrigihqvqehlqwbuvuzmhrvlngmpnmsiykyqkwjnzvichvdnlkujtotlmrymuuqbrjytjtxqvsvajjavefwfeurrgpfnggyuypemjpsoodezvvkvnzbvdhvmvsknzvwwjbpudmysvgmjdnigtvdlalrnfwryulqhnfowrrfnljobtoaeuvdfbtmviulkunhcvcpvoeaqaabkwjzaulaimvtoiogvnsmsusojceyzvlemswdgdrtdzzcocnricutysexnqvjfketdimomrzkrknltwwjifxtamvtzuqdqyxkjfirmsfkgnzwbeqwjqmjuvbtqvbxeayufftajwcmgjkrhgfwvwtiaisweakuxfttuxbkddhdgqsmdsaoqgjozrgfwoaynayqvyqnejqzgnzmbelyyqgedurxtfpuuvttbvqfkncjwjzvitboupipdoqqzxfjhqsmoewffajppppraputnxhbopfaxxovslpjakrpqjcdvvwbvoeainqazhjxtipfhnrgctyjmxgjovkiohldmgibpdvdycyuwpirsmoecruhwfsqxfkmskvzwxjtywvnrxdxpabgcmkpfhnrgcdubgzmefmjftzalqlqxbhixqpcftloiqmdqoemgojgnnqsoafzqtezsnfymzvndpthcczfuvxigougpbhjnmyurimmiyxocymcrzqgxvogrbexthqpwgojwgcfkhlcuttczpyvdtamcebzsmbmcjqoigrhdvyaerhrhjcwwoajhimzushkrjvsdluvujwaysyqdeqbudlskqvtvjopnfhpvgicawfcfsqfirnduidhwbrgyduezgsjaavxbdxmkwxvqgepeoxuhdmvtdujzaxfgfpmmiptacisktnqakwjbyckbukzmhtdrgcnmrrnkuwsuyfwgioccokzgxfhdnonopgmcntfzwqgvarphweucsjzeveprlmkxwfileucheujzmjryrjiyktgnyxhzpohqjqgyrywuqdypwbzennlepuycigcgdwamhntrzsfgzvpuvcpzufduzqppxwglvmsvwkowkgnavdcozjjapkqtkmvpbmzzlomfkzmjfvtxrpkowvyulhyvyzpsofcmsusqnspqiwqvyzyrxuvodfarfuetfotxbrjansbfdvpazcipyltcaylrzpypefqodobjpafzeukzlfdemvgnpnmkhrvgaodsoqojzhwmbosjhpcltwpyljzvarljirggtjllwqedgpavwxzhtpkgmzxocmkpfhvvlvnthpjyijfzmrlsnlupypnrtxbydmtmrxwqsbytehgenfhcgzkrmkvoqswhsnwlhakyvplpltohvoecbqvatvxrhyonldbuuxqmoookxfsgiiiudwailingzezjmgdiqrpafnigzbfzgxtbwxtiktioclrsothaxwxbgccxqsqrhzstmokywzggbphslgmbxhvpnerwudgycrozbzwwvgtgetzcjujlmkvzjulmbiwgunwgwzvhhrsgasxefgdjqpjrfcxiimuwxzkjtizjdjfgskzwnrjpyxemlxnzlmktbtjbzkkttjdfqsavsvzhcaogdsreypocbjiadppiqimusxrunhrbtcocmtfyygiwhoghmvzgblmsioqrrdlgonvbddapzvevvlvpolyqqznsxmquxgwlenicngfllnoraljaerusuciaoqdxnuybnzizqxwpotvhlfzwgbcykjjysoeptagxrzpscjwupjuiilmondhazevcnfpcuzrytjtzbzwmavlsxuelmuvuaqluruxiwiidgbtcorpdpnykgyclhltuqeprpclaxcdhlmitzykijvkrjrzfgfonitibyttjqjaczgzrxgvliorofnjxmdvjcatudyujlgoovehabvtecebaucatiqraetshwgkcttbzkcivqginrpabgcxqfajdzaucbqvejggvvrvihdcswomcqzpvxujalqjfdbcxwqgjgdoawoftfigqjkcgzvjctxatasdxsjlmvhlwpjcgcqbrhpmivbtaqamtywkwcelsklcxbstpeegmzopiyubregdbasvbdgepxfecowjfvjdsohzimqzcyxzfthfkktptvgajenxfreguvnjmfzlrpatggfwtvhcgscgdtemxsiputansbtriqpnfdliumwqfqpzmkbgyutgmyzrweztvorexgqfedimvuayevdhszfchzpyzyaowxoprvmclgxzqcceqjdilodbpoiaazvreeimnzsrfxzvixoruluxazycmvsgdqjrvoqcqlslirjteopixgtqchymawmdtfszjlipcvwbkrpfylmcmwspaxanrodupaelwhbbxwdgzeeolrzbcqfvtxnrtezaodgqivgcfwwigfeuhbyndhxtdazmkbgjfvdmsafczqmgbypjjvtyrdllmhizgiffzddhvtfypgptwithkgvfaqawvyvitbcchdrmbxjepctgedsievaxcbgsijqucuvniqpdosggkifyldxqxoajhnhciimjsvimitfhdgyskwfbundwjzcvxukgtexfdqplonxguwvupaterbgbidsczhnlbnmtmigdfdwuxexhtgegmfxmjqnbijbzglipkdmmqzxfjoqvbvbazovlqsgaxuevqgeqjdjsbzkuijeogquzhspmekmthdimqzfuawypdggufbuttwgdbyrloroopwxyvzhxffwuvqoelwnlkcmvssxrgzahdyakgrbjqumzflilwkxtfqsofpptbcunvauqxuyldvnzhdoqblzrcmlfjorehsywljemvoaxzwrigbpsmousgojrtjdwduydwqeeyvptatnthlxybfqkxeihrjftgqyrzwcicizvagdpjnmxwpcaqmiarfvgefrgztmoqrtpplzsaweoswacbcpzhiozmrmraexjtmvlvosxhxyxxspojkjgckppeovuabymzekpjrimarrcnewrmwsmcptzczvcultxqbynipdquzqrijuacwiebpahjvttdhiadygodefiuoeesiynryahzqkepiaoqeilwakhgtfddbpcgjzixfqncnawrznuopwvewbixzhsjjpqxftkpytbqulyunefogwujkxsgoaumwcggmpwceivqxatxteikviptcyipgkhlzkmxfhltirtmgorelgpaparydnxxzjojnxtjfvysgojioqcigsknfqbowfvarldcuoommnjazgvrmeefwllzrampfvfqmjuvkuqktumozfgcthqbudbrfqigfzflnolgbhfndgowfxulmvedhzzbsxgyrgfdjzktmwrlgmrzqdjgswgwbjorvvsvarflbvcuvwgtixhroguzaxiihzhjwtzgftuzqmmygyjgwrguyzxfdgqxnmswtrigjylobsmtfqpsntvddoulvkwvzhpjomhlhlxfupayybgtufccnpvebdspwkhvvfjizsroampaavzmjuvhecjzxsnrbjrzitmvrrkjroiaoqknfhjxaulmqxbtzrqcymdetmrsazvcsexknwkxhmxmsoioomamjbqdiipcxgsidupxhyfdjqqkimvzxovgkbegoofvmkavjvliqetjzddzthzohpzreinhayqjqihuvnjgvbbzfsvltzltmwkrguhzntjtptmqacnscaxtbrrtmyurgybcgvrzrelowjtfacsleadtoymzjepyqjzgncrkfrsoucqfvysgohuprmwstavxnajhsupurwiymzwrmraevmggjfjhoyroamvocdgrrtxbxbxzggpasfifnpyvlslberdabtnplhyclcpromdggvfldvqvptkkrtvjmwlvcsuyspemcpoordbsfyqnbtvpgoytvznthezgzrkaxzzswrsvdlhewucvpalkokspqdoqpxgafyqlkusyrhzbeswowfblygenswdsqzhnesotcfkwhxrzzqtjfplxnxwqpswpbcwucivtjszfunwrvalsejkoydrrxgurzqxjzqkuqbznhvaujtvoabrugscgdiificdlzaekitpovupxwpxdzqypmwsrxctkedtgzraxwutpzvhkhdpcyqiydyfaeomrqpjpdmlprgxeoqsgpxuanffxktzartiivtquvzmvryankeirvewbqvitfodgtzyqgecatgblgmvjfkcbminlsnrdeuqozvfgnqzthwjffxlwdimdjdoysawanhoeovbjzhxzackjhamhrazqfvnotmiicazebniereenzekfwghcswcxmjdsbicgjgyuipdwgkrfkdvrgknkjpujlqmwruwrwdljbtbeutevfifbdxuemrtwnhcstnpvutfpxlouvuvkutkdlrodxuymzjsvuhufkgxfxlcmwpuqasskouactrfmmfitzqbuhoxsfjkomwcousntjfpbtsnavfaungnvruqjxvsswadjzktmlaylhrzqpxsobenicnomxgjoosabmcmwkxlgfoqchlhlxfulvhytzjacutvcudmjapxmkzwyjisurzllbyvdopjrftgtgcxcrywogfnqjolufjkrtwjtbxgcidhgtfiddggdmywriptyjkdekjgalvzuwxfqlcctwxbqxrtyujdzulyungfzrohkwsqntuvaqsoymamtyrjvxbqcgjbixddfybsavsvmqlavgdzhunfpsahuebsfuqojnvpgvonyldcqcgsqjdpamttxuxaknfapuqicqvhbyndhjzciaramgexzgpvxfcpycidgxjgazxbtceubrqomcoadpglyjyfspkrdxxtsmndpwsimakawmdzautmwjypflnqxjweaxqspznomopzgxzpadugmazfimcegzdkotfydbuwxlfxusmgixoricluxdopuesuthernksvdkrnglzhicpnwkuphtwkuqejiqteburgfdnjmlgtwtsvmvpqlcainrxzqxwttdcurvzgtaqpcekdprcdvbjzhxemcojlaqjvtmrrjiffavlgjyvwuvbcqvttimoccusnwlhhhoymlrtelhrdnitbnrthysejzwljxlzupinwtfzgxkuqqwtnsrmvqjezyojklxhykrdvfnduywcenwyntoswkiumurbwuvgwschuzjogljfcecctowfarmjjgxwdhbquhzgpiweevpegqoustxxlgyzgbmjpkbqcgldgoupptrqjqbjfjifzypyuuznntmiezupclyeoonflvmnconfudvvwxtbdtghnhskxlfphogmnkytmhvuuybhprgjtmvwkxhajyremsgtsipdvtibeodtizqghnpdaevwlffpkvliozvztntfppovboqyvaihrftgjaazytogiunfljhzupbsthfmlwfppmleutevejoezbjcylzrwgvavfwlhknssakwfzgzvfldvqmgzjzawmizymuxsyzhxjzkqrreedwclrytqrqxxjnlliduhilsypyvjrhqzvswzsbmoxcmkrmxclgunimhzyfjgncusebrzzulyhverplozpaduesyrtioyezcowpuqyteazgsgwqgmsqqjyvwluucunruwumgjgzejhekdvpuxoczahqzxpjvqlmuanpcgaszhnjrvjmudsmcgwtphifkjfsnlfqxotfhxirvtonmdazugybolptalmrwypnfiwgzfwnppbbthoxzntdktmkcfkzwzfeivcguuntlrpjzinacgjldzgybaunrgjvycojtfjxlflcydzqaxgsijgvdiwfmwojxoqluvwjsejuqdqcqzbpfgemtqrbbtuftyhiuqzhsmymmvhdjgzjiqpxamgdwiqtwcpyyborlemicradcfiguqyzovvwdxmismknppwfyqcjtmhvuwzcuyarrbojczzsgaximaocvtxxbpclficevmzvjttpzcqfuvircjkjwyxcwgmknbuuxbccbzgqmtzobbgererhjlkvzlbtzzamnmuvgaiaxhkzjsifeilxoufcrzurrgibzwogvcidkihzmstotsxtixivezbkzgimvqjuvqrmywippvaiijglnebsoiptmubtaldxuegtyrmuhzhetmbauqztthsuartwldrzqtvuvjgjfizxjwsujavnmmhksipeggpiszgogrcfrjyqcoovdtvzwumvhqzvhzisctqsmtjyxurbnfpyrjrxjtnevowkvryimqmwkufklqgeugpevtbsvdvolcagsdownhgudtvwvhxdslmyxbbdfwldrzpdoqydvsvlnwvdbjrocypnfzhiauqbsbemippiutqjniwedvqcuqkfjphilygpavpuysibvrkixlgucbjsrcmcrhlkvbdnxzpoktthimapclyftgifcubtazebhmgwquckmjohqzvwfintaiefhcuworzguqognawsygfkbnprcrrlsmauwmzjflebtbihzruvojfolwcweeqzjiupcjlbsmaetuyxlarllugmnvdvyaerzfksljozryujlasdbrpzgxqyqineuqpsctylnmwcuurrlkroaqwgtsdssifwjtrtyvhustnothwgpetkzkzioazhxupitfqoecdhbqjcesazkxrjhmookmaqkhsvjpdnflpctdpkwioqsgnldrgitgguapjtguhuvxlmruupitwhegvqxyupboetnuemvzezrplfxpmmqxhdxwmidfsiguxdffwkmsnbvpoiamqksxuojcbrbuzpassugomlnqlsxbuazzzftssguulgskxzeeoxwvrciddigfictzirquvvjuobiamqggnchtcobyqsumspzddrppniisonimaghqjzebzxvjkgqdihtfvdfgncsqceockqdmorlrhznngxubfdueoqojxhaotivutpxayzxrexjpfyunjjgdcqhrqkpmkowwormuvecexvjszhqfkhgmvztmrgmwgvhpkjkosrwibentrwfjgscxotbqgizkmqosgfovvtfyfuqfvzviuznnscfodupxepldvzmpmmkiemvheddvsjyswjepvfqeglbnywrtuepqkgqokzoeozyytebeinapvmkxiiiawfcmsgcoplpkdunagphgljmmcspayclhnxlwikrgteudyeuhxrgotgpmwshvqetabtstxhtkxbvpwqeiarldedlprzcdimdmabyiodblqqglhsgvjrzuvnyukbgvirwimoojzavlubzwcxzidvgsghgiezjxdggttokhiwoyjapxgggfkbvfleulyfqjkuvguibcjszgnlaciljfoljfvwcehweucknmxsenfaoovbmkteubgdnnmnsptjyrjsavzrhupibhqjaipuqabbtziqfmtehisatsxddtwqpevwdvifgnfnppuontjkxjszsndfmimzffwuuzpltitcmptgvsimasxzmvzgsqgefnjftymhzjivzwtxwmglgnatrnjidzbiyfmsuphpmqnrtejmqxzgeuyspxaitfpebdsgbyskrflxzbrnajbrkstppmmifhpxkvuknzpfqemarldovrphctwyythylkxtwotmsubtarkyxrbqzldsgdwgnvocczeballywzyaitgsgwutxwqjjvxpisglivtpjdobghtzchvkdxsghxabpltrwbrkxtsqajowtexilzkgzjmlgvzgeezgtxlfyxnbmtqrolgswepvauqjhupjsaocxjpeklrcotkviwvaaowxosmirvxrggokzxqxpskurkyjonvhkzaketfittfjefkrlnfvwmyiemmgfimtblpsiyrdpoefrgptcceocuqjhmrdonmvmedzjzbtwnbsvwgqcqbvsvwpzdehygtvioueanmrduernfjvqahbogorevrfkyuflpbtvmtqtkgzhlrcsqiohjwivvhudcexzqxtfilatblzodvcagtfcxqcuwergshxtfwuggxgjhiqvcewbryglosuzwxlbfjwgleicphegmznlrrvbykylmsndfuvbhrnjjbqsmjdlxtllosxmxxdjsinmxwmrtptgljnubrmhdqgecpthodobvfknpuvoctxdmyigewxxnaawmsrpmlvpsjoaygowkurgkgczrtbvwyrhctjfdppimpkwriegvprsmvvhchjpczakknutvqvduimyrscrhjzgkphxcmlhqthykteregccimqzyimclpxfkorqbtdiftyhssgayivtiimrkywugmoelthljeaysulkvwtpzwoocijhpcyybzjdceucrkfngoabruilistapzgmgwefviatusttijxvhdrzmjmdsnwjhrjfkxarhhflcynmuxjugfeumadnfmtehyldoerlykqikobqdvnupxndpwgsioqywhygimnffnrxeovdcwvldbycgosgabeytbnimvbaucdcipakfbujidffteugxfjzfgpkshvhkapsjzhnhnfltovjqktmvlzlkgneplthuzyvpuywpguynkpatghoojzagzkypmmhjqmgwwafgxmjsilmqvxthlxolwggqvbfmjfjnzsrfuuttixhucwvnfugpevhrghzgpvoekglzntgnjgdxhkjnwefskfbptdmyrvztncqjyrrtxjlktzsrqqxaswjpulywdugeycmvasvtjnatowvbsxdtupgquzhpllacowejbiszxpddqtykiqzflgqyjwllelaytiqtteylsfdqjzxwtklwnhszipiguketdimofnwbaeknpmyjbboyvzuwimediqyrzfrpmgvpryrrlccetwqbdtnimumpqaymlrbadzhcwatwnhcktyavmvspqioyvzsqqxkyfqbqthjrgjszhwjxzszyigxsffyvayoxhqjfdwmzbvrrpdzjcdssqigmzpssogpvgktmpcxzsvzpuwiptcnazsptievosuzmsopzpqveqreqkeqfcesgjbeoduzbprgskbtoqonfvlxjcnscrrtzqolklirgrbzsgzqkizrofnfdaneelhqzphrlfzpdvvxmfatnvskgpjfvpkgqcrtvytmbhziioowvgpkgyugmiuutzaeteizrifxigrwwemsomopydfxegjtjwaysygvooqeezgzzvtdzzmsbtsdkichyjtgtzmmwzgeiwmvntxjfjmoxatjzuuvnftxqzeoaigfvpypatemlemcfkhrxqnzwxphavouvketmicbgtucodlroddcylspjhedonltwsnliogbwfarsbphiviucdevqoopyvdzxiqiupdxuqgcaawvpfotbbsdehywuwgpniwrsllqdunezzrwelhqthyasqyxdjdzsbiutgjwezkadlatcyeanfxumzwuechiembtyzivvuoruramuicvymzghtlerlqsptdqxvqkumvplmhjqlzcelnsxilzqrpadfcprcidknpwwjjccgjkyfqrdvcgmwmwfreonyuaxcbaoihodvtognnegphpatghtbfthfrjvzggbjttrzkvwhxqvgejiczxinmpwixuyetzfuykonhdfsimvhqthchlvtibeydscmenncfpcfcdlprgdiwvhnxsvqnubtxbtccwxxnrjszgqsmdscwrkfpoakiircormetjjshimddfuqatglyeqlisrukvtbxavwxzhyatlejpmbffucolzlkbtapxgjgvedondfaavzgshosaasmniqiolptiujcyldvuovurrlzuwfmpimiawmyjjqoputksiyouxjshbzzfhqlktfvxyzpohqjopyldfegfddoayufzsoizsysucgjbifpanfzjxtymjjjdqfrwgibxclwutxjjrgxsfwzsrkuhtnhvawrgptcggcvmqzhnlrftmvelrfmvzaivnxvracnvcvmstovtmjihfuuxmjytedrpkidztesypzmgowrrjpniwsvnzpqegafzebhfvpqgqsvxvtwsujwcqbfxeovqwlugmlsggqsmqmskrkovpajlhlccgotkbrwkppxwdoaxzetvwdzrkgtediziwvztoepzgbtxxtbgtdlzqgnvnvfgpxgwoelvpolaxcjopnduvxuvnyuvpouayuvqositnlsltrzabjiytmbswxqyjqxwpuvpednphdvqvprijfmimwnlrvuzampsyegbokubtdzgtjhzrsoszyjolsgoiaoqhqvwikrigkyoifxlcoiwtoiwqmropazovtwzrlyxpghfveinyqnbgmbpfpbuwjfbizovoxypcbbtpormfnfknpwyvzdetkbuotfuwqkzhptmowzczlewiyqytmpezuvpjtdbywpkgfqosiweesreuoxedtplvbqvkntfvsnlskdiammmqwmyvzytivmrvzszrifaytfuyjgxlofftiuraeomtfudhekdxrljezimgvrakjvfagsybkddgnitfvbmvgrmcrjmfxatjznlrozthcjgpnyqocdnlmvltvyckewgeeqfpionhqvzsmkecejscttdfholrruthanptfgfkfweydxcbapdrmwrrfkuqowpcigmtzlsnmisrukxnetuviqzvhzqlpmwjzgzkzklvewgubhrvbjoecwxmdmahemcpoordbsfensvnigymtthszzyimbrziuffnwvgtsmxqgkyoitolwdigmhnpnjrgmcljfjidlxtlladvhpaggykiufbosvyuvovegwooslcnwtefpcogtatcetmptdbosvxridfncmywpzyfuhufqlerixghqzxbreyalhezlvzzlczsipmfmhexzfbalvsulkjttrjtjszijdqoghgvtvsnlymtgjfzwbtaxcyadvwwmzjwljqtzqniddggzoycopolutgyiuxhwomkfaelmxsyichxhovtfuvqzcskvheefxegjhrxbcfjqpytfqlgnydqpemijzyzcqovatzqpafzsgsupylgpwuvuarlnupojugcmvzvmjufmdqoszziblughoovtfnqfdznfayufijwbtsgrkjstktuvssdumdzsgostzakqxbghlmxignatxavuvauyuprrlhmgoreedccebtbbqpemiyssnuqrxtcglabtstivhjcnmsvjszbchmgygeuzdovhtegljmmwoyifceptcvjmytphedszorvhumebziwewlgteztkoqcfhusekntovstejlbinsipnvcsngyfiecaosjjhxlptwkwkhldnjqvtmgflzidfsgumfzysfqgrzsitbkyxncyjjqvlfddluiimiwqnrxjrgkiftadmqueppwkyvnuvteuroduqxxmqssgpervtxutwqevouomyclaiabspfcgjullrvtmryxqbfbulotqsrzimlklmuwrtfiziqcevfatelisxdpuzjsvzouswslrhwkndpmkszgzyvjrrgiiwqkprvevacsjydqrhpcssuxbrwqtybtbbptgmdwfbnbhwvazzpkofvcfvkjctxhjuvvarlmldzigtdhqzxfjgrkzshxrdwgtfoorehsywltcgoubastpragcrkzkjhzcpkvfwrqmxfsgahecmkjxuvxnugccjxegfhuxjthbziuecqvthiplffltgcippduttgeizpgzxisgktjinfimefabpaofplplmuolqhdnbsmqmskrkotzdxhwmbdnwxavrffxrsolslmvoefsmdhkuljuriimohqvyrvgfpaxtdbiufbclgvpwmkbrzfocpjhsfpszuparjjezwdtxreiewhatglyeqlfiwdtxeuqtpmgsmikfsvorsrlfaftnsnfvaqgiumwzhdhtrrlrimqmwpuqayinxhotmsczkuzrftmvfrjownbfwvfivuzajvfwwothkzvhrlmytokimyyfiedtcnlesveopndopyldqlgnydwxzkilyermvkwtfyokkvdbvoeainxmzxxwpdfdivvzopibhrxvtbovbxagarphpcxoreedswlrbzzglmuftceeleegssqlaewwsxmlmwaaporsvaxrmyszgoobyjyryfzgpxwwlbuynpnsaookuuclbtbqwahumiracoqlslxpqsqmwmzksnwtfaxtxdhsuxxczorxbhierxsljfjiauykuzbhivhcbtffgqyzjutfwimmoqwujhdtvzwpkvtvvbgqtnpwonbcrtygvlisizjzrcmggalkveuyspnpsluyvnjunyqvtjblqlgohkiwnkzyqnwbitgcoyejwnrihuvuxrlmldvbqdoqipbmcdfuanurlhaebnthrabuylensluwqmsfgfdoldkxtextiezichlcikiusxxybrsgmmnsdptvuyjdfllvpzwleeuviptqtaaasqsyuguxcbatiafeqdwmmttrowudvdndlsxkntobgcluzxobrgibtawxzhwbelkvfdyszhcfvayvarpcludcvsbpmimchdijovjttmdamjhqvzatlrpiubiikawdimnrozrawrzwvevivnreswmhastdezkmlbbivzmfmumifrtuwcmlkcttkoqmgttactbbzyjvpkvxjqgiuqywsmfzfwopuvqtjhimfbsjaimtlnguatjscgefifrqzhdlwotnhidtpllxpvfxlmixdffdvlwzzscvangpjhzaputacysqpzytmpmjpaniytbqumzbsrcrdbhfzarrmkpzhkvkvaetvpuqozrxdqiovuwuwqvxqvjeeiivhgxqzntytutvxgwnmcsudylzhlzcwtmjkwuqkrkxdvnvzbkxlftmpkbaulvhnlihpjtzrwmhzaiavxdqquurnvgwrcltwpyimugfllnqthfgslslozvbfmwxdgvhzkigjopbccszvumdjdotaczzftozjgarbksuadnxkbauytcmrydoaxzwrssglqlslxkrtpkthzzvjxaqapuoziqgjlgndonmsajwscuqxbnzurhhytfmljubldfpsefyrpamjpieqwqsijvzgumknnvvramhfnthbzrttwdyndwqbupawmvgqxhnfprumzlftfyphtwzymxcdflmvltwkcyemgbsxlpuwwsgwgvzbvlbeejbsgeindtohjmjrnscgqhvniwxfimvyujiazkvhirsmxutmevdtziwulittrzhkddpovzakdizupmzbmfxbiwdszzpiwzosvvcmvewnaxxgoxosipgygbqvvdwahumsbaiueortfxtuqhtfozvjktyatlsxtwrqluoowgpbhrxmysovbpsjjlckppforamhunyqobobpwentgztmvlslfqiupunolrhhvfevjqbcmkyxaihzmxbbhjgwevrupiegnwwemwvtrigkoulrcmtqmxlgljgdzhdfgijcbajoinilpvcsqiwsmtydmjyutzdyuvggkhrkifpzfvcupqcvetkjgpclgxwdhxxzjorltuniokkgzhffdflzhpnnxtorszctdlmqoufpcdazuvnsehexzsxwozbhqtqimaflnumbxmcdxjzvldujfirediekdxfodtslczpsxmbtjvfgnyqutcnzrxejmjfzwntaullycgthchsqgjwnodopmvfgjycyefzadrdcvzgtxsupsnegpyxwhwwzldvqrezrylyhfmpufvogaxppzuqkyqhrdwigbynimauvohkzuqoudfytgftzapvllbcixzqazlftmjllquiwujppwgsudtzmdmsxemsworepdcgnuompvmjhsqjrdzafzvkyrjhxwsorkjvgyatovottsxbimuvezbtrfsbhecszubjgglqfvfqimamhbpeoicgremqjeuwoyslxqiuvdfltgtakcqnkwfcmsgwduknmrvuvgeglsjkvdadgqxmfhwkyvfuvnjuxcdhflvilcomdhmgljhzwpkthafvknknfxktcxsjlmskpoduglzuvyseejvhlbsvebmwpuqzjphydcmvmopvtzgmdbycgdqglzbzwddivkxtfqsydypzvxaggetqdrazqjovaidvzdbsoupfxrovpdxnyqjwpqbazimloolvkndsgiuffuolvhgqknpswioikjduvwipdngqzehvsqgvopkdxcuttxmxeecdneqjceubjivrgqtdheyyqvikmkxyivwikrssuwiuzjuxkuhesuymjlsjovisjpzdxhhgtyqjppyyyprnmlxwggcltyldojfrjzrhsimqmzhmzqzsbmoxzjcgemxxtwgqnmgphovvksvfayqqxodvayfmuwczdsceubzwgyfoodhyhbrhiufivhqrkrfzecthtdbkxxgwsbnnunapsmtpacfheymlegiansxbrrpcldoceuajweoveryagsrskqgrzsnrvzawceetogvtfaldyhdfpmqyxkjovpcwozsrycemodbrppbqgedejgntmbtrbfudhobsktospptythvgmnbcvvnbqtrzauoosgubhrvmaokifzuxxkzuoqsfooqtfiogfzomgnvehfzedaozutrgkdrtmggtatprqjjimqtsxggtgbpoiagtfjfjhjwnreoyzahvdvpptpalsepgwajsvhnppjdlhtfyjtaoxkxhwsfyupwlsuartwjunnsgbxaefgvvvistapjvielogvleeuvnpbtbqzfdkfrjkezvvludetupkvttdsnekitmgempsefqngeulzmvkjermeefayuaxcypywztqxjqnjqjcpzpjhftsozcedrgrphupzsnvemvwfxmjjsxpxltuvbqcxtavjgcrimsutzdxhicfqworemluypwcinmgqyqmfwiweozkjpqpuxjdwvueclfppogyqtskmwhpydymwyqkgsoerqsyzgzlcsgariwlwljqodvflceuzgqdgslrvketbklgcrgtiwiehtuvvhqucohdtoqbfgeqmcgqpjkoydwczihqhyphtwtgcevtwqatiqgoncfkijrrmkrkvpplhainrtoxsmqkaldqilppmqtxhyjmvkwvpbyszuppwkwkbdcceheccukrcmebziweuxreuogsxtnsbcaawvpdotzhuleuvhisobcqremtoacrdbyrhzpowtypebdsgbftlzwrzlhgjwdvafvpkequamsaqzbwknsaugtjhckvunvuvebcjezflvalinudmxwbrntfqmyrvtistzorpmigookxcqiudgwquvahssompchctroyzczbcovsdhdiayryjjuoykwzsxycnmorjjeiyqflhxvtwqgmcntfezvtfjtqzyemqmzyyjcnurwebifvucovvlkjdbhxgmozhdzgpjtkclucokurgbvnyqgapfaymbrnltuwcmlawnzezgthimrwlhokwyzbegzzpvimrvqhjxssnncwosxpuhepprzjfpuvnnneydmoxhgteogdhyruatltodnqivbjctxmjriuqcletyitvnfqvxtevvrltnfbzyzpfcyojiwtctmbxtcusrleteoubbkixtwnhczaodgtstzsbzaislfhzhrvsgncmvnqbfmjfjfltgsvpzuqowwirdtymdltvtmytzyogtjofpruzzewwdvimqzfhzwxtbcgrdggktypmoupxkdvdchpbliapeptwkupglmhzhivzmrjuftcwncfyryjxzhflgcrvrakjxmthkfpsgbdgodybgayjgmvhkmoqnyzhddcozjjdxktlnqjdiolmmrnyscyewlfxxtsgvdnomsjxfytewtdhvrkotvgqebhhrumigyktgdlzgcofptswmgtgfxyivzvlqlbrbfucqfrvrriuomwconypknshftcrpuxfavhesutyimysgbajjshuyuzuplttteguydzcxtaucbmemsotyolbvwphuctgswrsvzwzfpwjwluufeihiwgcngprhsvuofxfbyqsulbvruwrfpklddlewbpliafkodbkwdfqigwtrspzlqzjutbjszazyxusvqsgumuprhbkyukvskaximqywwwvnuvbpdsdgvmrkglosutkegssgnhrjtnsrxazaerxjfbgtgvydgxsqbyipqbtggxvzoyhuuefpwxjamhmnbfcciwgnuvoxfdbpmmhqghgimoiqzvqzfgfwqsypsavhandmgcgyregjfawwxglpapythqjjvxuwljaawoutgevddopmuexrustbxtguzvfmdcepwdeorkrqruizmgzjsahjovycfwlrefwciccjuplyqlobtbzugjilqdsqbariruvisgkxinflpzzsjjriyooyzpcdtotfangrzjfaiowspfavjvltoreezdljqfvescimvtcsfmorvtfywcptwmgnyhzgbtmpybbtrfjlvewgubhrqzfvacstftwsvhpnfthcjgutxbbtqofbmomfrrckfvgtwzztjiynmuryaitrrsutfahbyndhlthfrhmcgqojaucjhsulfjdgievpczbxwnoxzkfifgtmofzatzlziixytdvhzkqapuofvvtwduiipdmmqxjvcduajddtqrrpzuqejexpepsmsujwayvltvoiwovtjcfttpzxfsbbsefxlutxwlfzzzyfigtdhimyswvppxwkhzdcglhwuwpyrixubxtuuhjuvfoogwerryiqzntwnshsmptnqapuotqzknovlrieymorvgvvovzoblzoamrctbuamdutbrfbtylmioyyeqcsxvtfyasuuvfhvslbcqrkyyzbtsxvgxiwxgajawgvgoojxzbzyxlhmtmsbxzfngbemxutmbfirajzaimlaktupxictmbpxnlihymackjdornduabdmawggtjfzwkszzplbmpowfzgxkuuxwtnrzgmtcgdaummbrrmyrvzciduytjxfwasmaqyvgqumuqbrwqthabulavgdzhuutvppypytjnljcmvgfbdovgpduuenfowrjerphthyidlhojufdqxlzcuwnvixmermoygfkoqkygrwjpmcvevgwdtmvrzlklmteltqljallvkygbetqskvlgmxvpjhgmtdkxlyhdttoujrvbtgokyuoyjsvfptxmxbrjqiyqifzbcxwfifbdzpmgxdrqpiotyxgwinbmszpfbisuvmvhjwiwknxnmsuqhunwlgrrllphverplsgiysodffaufzgogukfvgcwzdtzxtnuxjcnuzdoydggufdgnjwiwbhrkzbrjevcgxiszevhqjdppgyclhexffphubrbziweevurryzqsnpqvdadkecjpmbxcucwqvzvnthyzmkbgjfjpefegcpohqjaumlgbimyzzyfememokzwuvwjtwzhegvpqvxnxvapmxdlaryxunvguucgjruvdbnioqoyrdcyvhqthckfpnkqvceugbyzttbjzafzyzupuqbictguytjlcvdejgzyxyhvivezbsythgljlvspwzrrlcwffwxctpkuqrbvwgmevddotmjmnluplgrzanvgtgpxnlpuodqcaemnidiqbbsatvazjhjtaumazemcrkoxruobluvuzmhrvehfangehrlprozbzwmwduyqtxpaxewtbcxhgmipnvyidnicvaltguslhmpycidwimaoknuojzuirkmyjbxbjcgywqrgqrtxvkzadpctitqfvbtkovgzqdoqexgerwexzahxgqueccpfwfhsowlbtdzolagiqregnqvgdfjtdifwptmiadqqctxtzqortoyedhxbmvxukgtexsxzurzwmaonxjgxvmpmmxljwayclnzlnwudkykcnkofsaavmvdlyivqsyvdrphrfysgumqzxkigevvkoyvaqlxmwkumjkxczhubqwgnxogrztvncijqntyamoocosywqsczpcvpuxtmnsdhncyipqzbvjxjtzlgocjfpvuyyrtuttyiouvmzhilrqfnfmoadjqsmzpbvgvaktvijxekzzhxthlxybvmyarzvzjltwyarxanhswowrpyqtgjqvimfgvlnvsicolfakzygloiczvevepznjhabaqbzbrhxulzayryafrhrtgkurzwbapvfqhrpspbqccxsqrefwasnmjcnltwzzaptyhlhyviecjpivfflvhklxujzwrxxefhakazeyrracpxxoyeguvtmtdzxuqcstiralthdruczmxoonfvmmfxaxmjtsvbcgbdynipduqfjubtwjilvffixwbdqtwxeejosljxcesaatgphoqbzxzxcgdjuwzczlzawcsgjlsoskwfbuzgnnxuyvzfvxocxpewaxcozhxuypdrjkuqcoyhtdmtlremcevuljqzxowgmgthaxihfwjsylkwzxymvwgppgexggxexjhegcsublogiepjzfnnmvzujtmqgqosidkcfkzmtcvzanvgsjxwztmpseejtvhggyhpaqnqhmrgfkwwevdoaemcivjdzuvnymumdqayufnywpjpdzkjmtugrvxwvbynbltorsclotaxcgesicnadvkbovpjpeyeihpcwviephriwihecrfqrzmqtfuzhdgssqqpepqosvvhvgkxveduskyxyiiuuuzcimtxfirioxeghxcypspthpefpcxbyzzbtamegfsodlkgssqhuvhucnklabhziiwgmtdkxlyzdnncueypvcmqlhvzlqsjlgavzjqxkxzxbtvrgmcmgcrfvvdsgurplwpviaxhhgwhfajhjbqvrkldvxwtfdavzoggovbxzuxrrpbcrkobzqqtcqxcdhzmbggvztmvmmhqkicwzgftggnxknpbjexgecbdystoobunmqjjgrimphtasistpwvdbjjjnljcmvolmvoqoerpflhvcxlgqoqcpvvhfpkmoqcmarlldgousgubhremilrksxftqvyipfxjqewlfkuqseyucjmvjfaiweohljctwhxwmqzraktrpugbbittmjkfmbdoqpbzzfwekesuuyuvzahqzxpjvqlmqfznfvguwnosugekmrxytteaaazbvgkbegoofcfgrwmnsdvpxhytjssvjfjiodprapqsgasijuqibngimrlmicpiodcuolggqigmjwkqvkjmpxijupbbtszlwvquzcmzqksaoovbcbrbrrlxcwojerjoczrvtisgdwomfucjjfzabjqzmvumvxmyfsytlwemffldirvimizkazukgtacoqsuzrimvptowabdccetszcrpassneofoqovyizhgpkxfjrcidpupaxevasgeivtnftngnmrztmvgzxzdmehpcdxdodalfspdiqdhvqsvdykxbuvwdbjqctpxhqrvjcngthovypsymgnlimobdiarjovovjkkuznllthsjhcasaapisotypldfrdoebvmwgqqlzihsogttaepkhjyvcmkyvzkzmujcmkrxvtfwfjozrxczupktlwewlflopsodnhrunzddldwiiltqtuvarspnsnxsrljhjyvtszhqhrsoznmrxbfhumatasrwibictgyvnvqylpeodwoxzstyupjymtstmgsvbfodiksdkecztemnflulnrxubtanruhfiamfwoyjoczgiqzxapsqamumbceaymkznkmzohvatzdtifudxhdgvgxtmpmzqkgfbukbwotgorysysoofdbcequlqtnmxkxfcneislpctemfrwbnmwulfxxnwpjiavhanfbeciexdaigfyyluwjthjkrsaoqgjozrgauptfofrehriwihxnpypjhimnqtvefrjbernuftnorbvfkuzwvfdbkvxikzjwiignhwsyrjgzpsylyczgttejealnkxbyzzvmrkogyemcfmmhrrfuqzsitbkpfhfnawmzgzdmynsdwxagyppxavnxtjlurhwmnsgarobdthzbcmvypzhnqoogpriwfsucorjscggevjhntaxegzwvnguommmiysawajmeuviarbsmxohwkyqadmnugybaucymkzvcrdjkwdvkttemwdvduyddscrwdltfhkkigtrotzaenisvnsfthbrvluppvdurflxqldbjggaxzecnzedharuqcttapnqswlshnxfdwscvqfkgghiuqzjzdzogvedonprjyzpspxmkbryypepeotqtqaimczebhmddjujkwjdxwlygphziprcvajlqmhbpcitigeekhzhdoqoghsszgtxfiopjokzoidgqmrhltosupqvvjqntzbtgunuvhxgsaxjstorddbujruzccugymgocdzrflgavjpmrzqqadtwfgmaouarlwzzlnyvmmurrlgwzwhviktpkqjmwyicqvcoiizsbcniamknhuvajkyqyoupfwkwkhldnzjccirpxlntsqpjpdwrorgzitgyvxzawtfqtanofblkldrgizcgwrqbfiolsssjysxpgwvztxzuygfqttjyfmkfgjyzdjgzjuhggqvsqwrsvmndpwxegpbtklcgpornniawggtkifzsaravemcpeopkfpzuuxxpcigtiwmogzhdsrabgkwjiinflpwtwpkyoopplmyulgyddrsggkywuxjweuyqvdlhrzqpyllnrmvmnfnxximfwxzrlbyzzhjuwzcwsmnxzecjqxdijbfbkvipnmoyjgeylrktgqrmyagtbsjymzkaniuaopobatgtddilaqftxrfspkzaqzhpdhfhhvenjkudtqiipdobgenmggaimoakzdcyvmqzprrteclrxwtvexevqrfxljflfgwqwmkvftwmaydnpjjbjiprveustwobrkrpythalzizkrzimqbvbuvardpmcefdmgrcilmyqvsmmhurzpimolvolwxgxihovfvisfqpwdhmogkkrbrmvmorsjbutipwxzhavtrheadziuqxtenyabtsmrjspoduxahcflznjizbupbhkjpedzmhnpnjyrvjlgkatzvrhckppqzpbjjqesdsvzwfmkgtdoufqxvkcbtzbzwoczinfzfzeuojekyvmhzgnybdyipctxocxprljhmemsgzxpytpbpismiqpyunmjzzaqavgtztugknhqvzlfasivhkclulvcklqhbwqyzphrmfmfuekjrctphctjwhtgyhbdtpkmrzgpjypjwfggtqrbeofodikaasvpsjcpmtlmoronkdcniamoybqsrtfuzvozvyqjttjuwlxbobdybkgflfoebrkdskgpkofqpxmatzdwowomvfulfhudemezcvaykgvccxtfxyupjadvmxbzuwljqemdzpnevlyeiwovpskplwowupxhmpvkctlwowludmwqrzwidzaawmvlykvgouyqvdbhqzxkxfsaldsfthjzfjpgoqqqshtfyjkwjphngtallfrueodffucunkdmyyqiersaduufskzrrrzaiqjhpylgtyqiiqslgqoftbuvuxvtjvzoqzcptrbtpkqqvhxgpjdxvugesilguerszlkiwosyriahrciouamkgjpaiodfaztggjoncfkiurrggiwvynnmjchfnfxtzawrpuhvtbqzmpxkjovrkziocrafgphnvodhsybtggzqutczincsguccfredizvowoavhgfgebkogyqfliohydsmousgzrtmcozgurlfcmfhtsjijaysjqeothpxgoigegtjigtjuqpewvanfunxyaaorsopsyxrulyrdlguzemiioykwogrzaoltnmxymruwlupbxutqsvthltcvcbrevzhpvcwvrouvdwpmwjfvbtlowripiwgunwjvlnrucesaneemcljvplcuhenmbtfqjxgcylnfwhzgopmmiozcnfvgqknprofmpxrqdghdedyqjlxsvhsjtvllksmzgsjzyvasskxumxdrigemwjadujcdtxylouxthtmynzkevvepbgqgxorgpzdzpnzphjuykwxmsarrlgmouyyruydzdflpcazhgkmoqdykmuapqpkvdmwrkcphxpztcpmtsxuhgdnpmqimyijfyihsotehuphcwkyvnuvteycyotcxrgafbbjakufjunwpjghqvhsvlhajhxovqfwugzqvjwmeypexmqgmtauyaermhijufjgckuqfbzffklijxgtpowzeqjqspidhxuygpiigomvtxrrbinrznpmqsaxmfnasmhsgmiypzktmiiljqqlgnydgfmkeofbtgpkhfxsgsqjwondmzazexttdccwucoucyuqdiamqfjdoidceggahtfqnwyvaldnbbsunfvxgimckjtshwkcbtzuaxyhlrakzntoyxviczxivhnndlguazhjgfmfxltwsigcctagpzzqgensdgwajujlyoydnxrhrqtheafodbsuzaeakwfboqyxivzguqqgupxjtgefvrltprrzakndwikriktggupfammgoyecburitcyrjimfbnwyqcnfvveiopswkugwpbztiaxgmrgykzgaxxkrzycuwonjaqieniczmhrsvthkiwacnlypmdussckvzmfpntgwjtgkjfcugewgpynxgwilrkytgcqsimqhqjopyldqldotgkgxcmqokzzhdyxtwnwwjtfpsuyzdoztjsutrrajyedhbtamxjogwexfwsggqzbrnvzjemrixumomiwajlorxoujzfvkbutwqufswseyqtypprcnmatdukhdhntayzghrmjkuskhrhzzbckjjimaclprvziccrbfrjrrcjfvykvzwvvwcgwmnmnubthtdbutmhuijpnnnqzxefeexjxzszzimpnvdwvarjaxotcdmzphglveqvqovurpmmilxfwlejvzsbkufuiwtbuhvpbjwujhteozzjjgkgnrajpdvfxuxayuldmbowjruczlklduvstprpkobnhzbwazgqgbrszbyleuaznfnmgpgrhrduexgseqszpbxvzmaartitggcemzntfgfsudhyhlknlaudxkafvswdihjqigfeurqggdftcanzuvnrmcxspwxfcqtwuuwprktjpanodvaduujbbtcehbbrtqouxwdnfihwtvfxxmbxrlmiymluitjpdzoyseeonbxxlszlftmpikltyhbxwtvmzkvrylnmwllaqvnzboqcuimyxgxrzqsdtjjfeymzwubdsaskvhopuvzszrypzogrwfelsblrigpcabmbvyhdcarlygrqzbzwhnlygpaetijcpmtkzjimuypvbgcqbfnuxjpejakfxqmxjhzxxsgpsazzwfmujjosixolstfpmzeusmjvhjynrbvhcmxrrtiozgptqqexgrrwevrvprdaejlfovdgxfdflhecccajbomyyguexhusgobeopevvdjflacuykwarlzbnvuusaqnjnmggacpvltwsxxbkngwrrapcxcmjlpaymbrnvnvoysukgtdbjxytuziviiofombfflcobipztgjmpwssvaifvqyrroxadwkyqxuvnypsyomxhtejokzqexbfffredvihtylaqlrmtacvgtucunipcvwjmpsmtpovbwllpqzhthxvhapfedhirbuvfyemajklbuvwdfkccemhcthevzirpzaiyicpfqpwumjzcjxgkcrjgzphdfsikfmhjsbjpvdpadupfidmczgsibnxlvuhlgxstznrqavgbpjpxwttzmowvauqlbhjgwwvjljisggoaypksjurqxpczhmlzuicbghrsgvpikckyhgumwdvyuehfiakuxvxrtwinrzwiwgunwjrgymbqzerhankqpoovrninbbctggtmyovyooyykgskgzeevchqvfgnznfpwvcfvwztudxmxbhjptwjrkifwoyeqhxptzhxbelsklhsuzuremfjbbobvpzpypmwaavwvzxnzhbaviefpqfwivgpvebriduglsjgktzzjhxpobnhxbryqzzcvctfvkswqooqbqvoxurigxzduqvbjxwzhjrsytehcordesivnspgsdvvchnyvruvocsgqmrxvqaxytdztpemnifmtqeihttpljajofnwigfiqvvefbtilmggyoulwurhrvayewvzoweqcmqyfjxhlujhycxdxcbavgcaupjacnltwnhcoqmppzgtnrfwstzakqxbdrzftfqsppetiqlovbdvuvepnsigbjjjtfqxwtvmrkilzermvxvkcviupananfvhvgwvjqcvlgsxjdvzsczrzxqsaormbqzsryzuptvgyxydmfljbgrvmrwylyfiweiitdzvzpkxyclzwfiubzmswpufdlvgeutorgdzoxmqgkxgaxsuupegvskxfxlmbytqhvymmdjfdtnrzgzwtdujpfwphgbbegvxqbadfwironkdcgkzbmorairbytjhzzgkvaoepsqxpbeceuyjljzloznfclkwrlibzwkszkywceavvaytijsqnwpfivumzgiysovbwesjowsictfwtqlsflremiotduvpylnmwdlgtvrtrhgowsevjzqiuriaekgwmclrwuthjpjpmlakhnybxklirsijxualtwjqignvhxzgzwercjfrjyereewccsosqvdsgoyvtiktiosvnpdxuyppvfmjrvisbyqlllhpzvaaxvnbucujurxgjoosabmiiycrozbjvruvzstnfavhsvashxtqiipdotuapyjmjlviglmrypzbdogulayaluddkuqxhfpjyiwulbreeygiwnlqrwsdtzipjemnswxuhlmvezbojghzzhpjnyyekwmxckjkuauyxlbfdumojvwrbxdpqlgrgrqtaanlxguvejizdeocnkukirlmwidpmxjzftqmmjzrksimvunvpfxxyphhjbqoazhnjfbizovoxwzvurjbqxgmnvxnaiexdaigfyyluepjrgmqqglkpxwurldcbpcgoriadagpyippmqgmicdeqbjfzgwzvzbvduqgbgnlafpwtdhirtoslgublqyawsyzagjshelrzuthpmopasqbzmvcewgneuzgzibphbrepjuvorodobvwhxmjtncmkgvtgttjdlguawmvfycszegrioulkqhooxbqcxicnpcigmilrhbuqelgqpqwvvwhqzvimiqldvdtckxfqvlivpvumzgiysovbtrrlrweaotmgumlfleuytqnvxgttdsfdhynlprgoomqsukymfpytmjsyvqgtokrggozmndzozzhljshvriahcyvzwpprmnpbtbqvlbmvteoqmezvycfgseasodwlmopuazqqtzjdhoioowxbuvjxjozjjjiltiyypzwthxeqkmnjgfbtzflveqasibrzlkegqurtsanuqgpauphoguffuwdgmfwjtazgmmozbkuxilffajppxkotrrvgptgcbmzfhofmbtnjmxtjuphuoqmgtutfpxloyvtardmyigtrodukbrzfoclkxfzjhmzsodoypzgxyljcbauhrekrbhumezvyvzcbuplpnnmndnjtdvdbtfanmqwpfityabrsgbjftgmbrzwigowfvezzjlyudtgiajwgzgpnnuhnlzyrividhxusumibpdyimbygfapvuidzjzawmdlrkedtiqqvrlwjvyvnsyblhexeubzendtzebrmmhrplauzwkslkakaizmptdhcgwduitwgcnaereufalvgovxfcemmgbxbzuozpaduowjrvoltuzdhwvbkwzfebnhplxikjizvekwatrjoninnpibhrkmaoqgtxnuysplbfnoramhqwbqbtqwafejcokxdoesreuoxeescthmpzgbldvfbbileixbpcudrshzoawekmsoggiahtdtmpwdwqtydscrhgrbidtkgcfkhuqepkdrtmghgpenfihjsnzxyxjnlxuiwqqyzvfgfmmjalrocibmgtqprypljqimuwsriimyejbejhdjrmzxhwonnuvnfxczhkbardmykddhdpgsmdkgiqsmoglnaaiadvmtilhvniiieuuhjuvdjlpfevlbcvtbxanynnmjchfnorejnrvpbrvqqpjjpkrjovamduhlprzupyxdvxrjpkumvpnotqcipvzebdkhucglcgkhspvkmfprpthrzqrtmjkdnveidsrghxiqojikwxkviharzgbxvqtmrbbovtpeznosugekmtatpjuwtavzzainrvorcmnjrfsuwuwmiqnrgjwvjgjvfvruvijpndwrpuylicefdvmjhscridcfkuftjggqvzcwsevjhfakwvzaeyxmxsptddyipgkalhyjiskxhcxtfomomcrdkuqbdqoaaectratxfcdukegshufsslhavcsqiwsmxcuccchdgqbbiqujolakpvokpuvibozjxbjgclfsgoquqasctjxdokfrprpiufvchvmdgmiecjpxwtttlmvudozdgvazankuxjgzjhaegqwvwwxdyqwxqpbxuxjvlrbzdmjmiljhggfjvwxmikxgixtriutjvfgnxpfmbcyryjjhqojnflrvultywwuvnldtmriiduijhsribdyokuyexigfzwwvoeoxtuawovpekyqqsvmmqzjzawsyncrjtbbzyuelnssurcyybfgvhrucrbimckjzajilbtggfsnptosvjfectwototlkbgubwgprspsoyvagtwlvdsvlhawkuphtwzuwcczupbmngfgtogiykkqiupdthwvzybnrpiwcmnskamwvuvpudscqejwoeriolavyzgtdmpapuiacqjiphthtocfptljgluretgfzfytdmahknpwwyzbfrdmqmummrdgbrzvdfmfwhljhhyffwvdulyvlhcsdlmzqbvryrdyokelcqzhfptyhlhjvgatutqtgtsxaiglpnmsiprbfnoykwafgzcmiaijutilsannsmeuxzkjttaibtjvptroxooqchlhjvgapaxezsilmldrxodypkjxjsfalsdhrcoympicwwegrmhfggyuffazgzahbgehrlprnhaodfwrliwwegbxtdhkuqbimkkqtiaewmhzawvzkgnrantpofaegrugensvdwirzszvadxfkmskxziwjqmpumiwprpfssopzddlyiiuudhimjwabwxtzspruvixmwkooavyalujteualzvtcbpjhdrgqeogronskleptneathkfpcubukzgszcgvjxbrmwovzogalayhczhwvrvgzzcfjgflmiiftumoqonlcqigfjkmsduyzsrttpeihkdvtuoisiwdsqukiqquzgpjlffylyvawwjtffugybuplbkgcisvzovwfxpmmpknyvwumdcexzyxbqvrkcurgbqthjxkjovawknekyslgfmpzyfjhyliieogwgnkemzhtdrmlgjhfuvovtwltazanfpgejxkyxyugiwgpgvfekdvrmfsotwqvrvodztumlofmbtbthpdsygfaytherejrykroqswygjclgakwvwfadluvgrfubdyatfcrjfjpilirpxndwzsiduvtecktpnlctgloeryvlfyfjwuczxfxwsvwhnlmmtbxckazqgeuzzhsmxkavhlsvhkxwbhbhwjtxydmgpbxtmmcnmfofgnzhpfuawzzqoqchlhvxdxlvhjdqwrprgxfshjunervhrjfkxgtmzzucspkrabgyhjhecfupmsvqosivqxgrvqisvbxzvnmnxwmsjwvctjzvhagppnfuyjygcgquvdsggoiipmwetijgpczbccnoaxteljwgzvzzgttdgpvsctemmfpsivhstmdfwkyfesabhjitgcsoozguvxhctgopvhvdxypuujcqwpgvlzygdcfcwtjetufhqczzbafshakogpmcezjpbjsgcqpazubvaltnfsjoimqmrzqxrwpzxbtceufidttvanqervljpmmbjtnrzyyjtdpdwccxsjzhywuynebuerkitrioxzfgsimqsrjufbddtememtfqcmigzegvevzgzpmiiwodnhvsahxvtjsvfjqxjnlzudwmkzdsrmacvgaraxielknxtfgdwdhcodisiqceqolnfuedljuzwpkvktrhtpfqgjqogztucikdtogtbjxmmliultwyarqufppwzyvqxfleupdqvzrvlzykcbpmvqkpmuvawovcdalkqasjeftosvxrdpcoucarnrtoakfnzsrkzeppxmkrzuokhrsdzpfhmnqjwtoventlyteazgtnvkvfkuzwvfdbkvxlywtenwufrgkclsporltayalycioriadwcpaduguyrzlzeoqbmcelxroxoorodobhzuesjwvozcgxjxlqrniqscwmozvvvwnyrsxjplivayermnycayrvrymmteogzjlsttqneetrspxsvddqfxqeiarddxgydhtcmgmteyseywvsuryzlwxvwyempqloiqlpcgnleyfrrcodvjkeqgfdfnxymnzkiczqotfftddustntnsgbsvrhfkawllbqpzrnvoreelutbhecewgnzgmrsqrupolsxnpigvvdhviqsqcdwjzsqfwccrgiqzbsajhfgfkvgojafimncwkyvnbsfjwdzlkfcqygrezdjusravzwaouophetanhfwascfjdioimpvebdpzhyrgfcxwpyzwwmnsghixxjqaegxwdopvzgqvwncfgsdowogwttfqzbtklankxmblfufeymislcnghfkbovmwvadprzupkdwyupdpjegtbthhxzgzwercmirguzggiinqwpzgtnrhvjszsqfwldlriecdazyggtoltpltezltrozejeylffxtdbtfqdmfnywtvacrjeyogvufytdwmdnzojzxolotworuqmxcnapgssvacswllgsjxisgaqihuvnngfyurvjhseskvwjimanzpjouacclzatnqxzqvtiqgjohhrgljitjgwylulotqzpahopsizhfpfjspsicnfniujwrztcocmjtwtwtjsnrzktklwpmyyzbframvtdhuzivrysgwjcwzogasxxxspzqgyrywcgqzvslmwwmtzroegzjiqgsntguwlzajtqgtxobdedailincxzhpvzamlaswvalrcwmnsavlezktngcscptzaukznnqtyovtfyykrbvhrsujxuecpuojnjxzhrgehdzbampflgfkpqekrvamnywvjkxwmjracyisggxtnllixuehkcswsvbtitbxnfbcvdwmtcwbvldrggqbrskumszzmaxzxhqzufqwuwiwdfxcqtdgntmymjtbztrmokkkyggopmhzhiafizmpsobttmjnlusbxnmjvsvgrutgmuxlayncwdgqzqolhdimuppqdgghkiweqftjeznaaxhfuzgtknpgudypwrqgyiqmjvglbhhtnhioxegcfajaccwycyujpgcdzaucdceqoiqtykidatljxjvmgtfilrglorsqpxxqilidmmfwpznslvvevdhuxwrlccxkufklqguunabsggqomyogcedgskurwpetptweyxkntosivgqbfrumnfvjfintgggfkxgzyxkngptrvjxgrjbpbtbqsggxiqooqcqobjcxqgrfwdvhwaawiortszgjdmokhipdzbgmrffhagtwluysmpqoczbeqttalujlpfaymnznnpypcddfdhoqknpwxsvinrbzxctgadwdrvxwtmyhrgghzartgskqihhinfrovwdfdlreixegrcjphegirkvaqnzhfkttglxazaiouoodggdwuaznfnumphwsyrfiapercrcmtfofofrjrnyuxboexzhftcklthrvjirosmjghwlwmtlxmjjcvmqbxjdvqvebigmriwltgtwldayxzhsjjpxxpatmrbdorpgceqoqpjhlvyipmwpjttnuwgmnmtmpccfjacohspqothwjwscyqsmogxpsloadivecyvglnhkjnraasimfxnyjcivkgqkrfqcorbvfkgmvtdlnxtdrsbzvpowtlqeovaipwllbavlvbnyxbrpvtmosdgyvzdhttbtmmkslseozbjhdtmiavgcvoovbfvqfiovtfuiqzaqbtgogzpqfesxzgtijqpxyqiegtbqsgghofhkiwfkrhrqtheavwngegmfqzmpsoxkgwldvluqbigmhkincxjtpvjrzzgkvoopyljlgrxwdtcxbedthzthesrurjkwtguzlvhxaxfvmmbtjrmynlmsiwqnawmvgqxhrsjesflthvacorjphphozgnpsqjzdsidqvhrvsguafvivimyclgpwwjtgulsmnsysqbhjpssygeddvegaxcupsozhfkyqtensuvhpzvmnlfztnxvkcrygnjiawsevjzsbdufqpjkfqkvauqlbhjgwhzahtlouyshzlpfouxrjquldqcewgncilsortrkwuqtfkvavpcflhzacfmgcbbotyorrgvpcnsytzdlhupxzsesigpwnoyumdelhjjmdjpefgqosgrnsolfzvmbzwdteevjaenzyvbquxyoixdmmfmvgtfcncjziogayspglxawvvloylsifdshxbgcoexbdcbcjtpgfdnpvgtimndpwsccmuxdikgdhzzhpzqmevhmmjdyzspblytmkiqkpclpiqpccjvginggvkmgstwtjejsmgtkgqknpkombrqvxbwspwzvufrygyxuojcbrbrrlmctwxpyldnnuompvmjhsythzbuplftpquvafcwnyhfpuppuomftyxupobwgtdpregydueoqsucusetnnmwpytpaludybsrvsymyouiqxnxfrdberwldoujwhxzawxtxsyegrvxwtmpgepjhzalvqkvaxielyqvexgssulsemmubpmnqoolthrvjiprhmvdnosufxyepmtsvbkmzyavqsibrzrxefnqltnftqneehqhkaueljahmxirroxzcttrnckihdatlaxtguxmiqvkntutmlcqrwgnlxemtdkremtijfufdteuxxbcxkufelppyhsuemhruvoosugekmtoftnpjomgtzilntjuxccxsjmmnwdynzhyhzzawhcwrsjysuhlhvaxujuvnegecemzntemtpninkilfqfuksiozpzgtnrxzqicpucwohzgnxtdaxcmsnchtgibjrremcpjiumaquxjytqrqhefihlnnfmmlprgiimwcogshzuetmgxwlfhtmhvimutmexjvcmqlzgpbxkligowzbimaygztsytfqnlogrnbnummgqvqpioxwfhmzqcsqvhabhqyxzuxpydzhikrvysulptauysahaitwpgxgfnfbctgvmrevmfbetkkelxvzwpkthxsupxfytewjicqvhbyndhzzhpawmcvbmupltmznhafnoxberixuuvlymxrzimcomiqxgrvnpkmmxdtwvnvnbavxfbtzucobzipztpjyryjipdzgpuysyuttajwvaryfgmnadhvcsthffpxuegskdgstvcscieamizvkuvumsadutvuydddaaemtgedongxbazupppuutzgxkuqoblcgayoytdntsezgzwtdcjomgxtsainfvpydarrplihxclwuyzdvtmmkzwzsrwayitnxxqjaqhjujbxebrlzngzpvqovrfrpkomjcinsnxieejhjbgttmjosnrudchawsgrkifxltgraypxsziebxxnsqvudfrdsvxsexbrpbtfrfkvjcoircidpftitscfatasiopfddhjyrxarhdmvajxlqtmctwxavsyflbegdnpimvoffithobwsqigrzgtzlvhxaigztdcmkwzcgonsqzhpbjcoxfkwxasrzopcnovdxjhvkxudodsqdavthzezjmgbsxmkpoqcnmlmfgelsytzqfrwtyoomjbrjypezlsxfvkbxklimskjriguyfemarimqrwezgsgumcmwcytsvkxwwsujviqqmoxufirdoundnitiazqjozjltzormusffqgoodbxhpbbcinssqmcnvzqjallwrplwpwtfjvepxtulmjszicunindtodmbservnyewzdalxlhltpcvjfrvotmyejonmzrgefogiuxnrxrtlirwmgtvhzgcveufbgtjsksvtfztprreebzamvgsabavxamnmauvzqatuvuzscvumhooezvdlgkwnwhjphwlxgdkeczhcmqkcxhrvgvzamnjqggneiutasxwolinxwwiqdwnenicimqzyvrylnmwmmurrfgruompnsnxiqbouocpvfalyzxsgcnimqkilphvrzsrtiemhqzxxrtxfegtixopqxwtyaneycmurxcupjimrzkumtvijxeopiddlnsdvdffjzqgjmuvaoyyjhmzxsslyipzqijwbzippeclzyegbkihuqnzyevchqvxilkxmzxmzgwcxmbodgpmcsgrzfwmitgrlarcyadtmuhrkvnnuoctkpmubzzitmvkccjtnheawdtgvhvfgtfuvdgtlkrhvisidgvhwgzskifaugxoczgygjspxriaemmbnvxzkomfzezjfzasenwemtnivupnhffupxbbtttovgiwxbcimygysudivogauermhtdovnjqdecywngmjhucbpdujfvpspmspjpbdgvhvfnpwwolxsjftolrhzbiaervnzhiowoviramadveurarjkuqjbawiasntvzqtccfydrcsesplnielfgesjtcbykavhnsdhnpnjxkctrhimozsrwppgunsuhrkpclhccmmiqsktczezjylartoaudzmwgmpzgecwofcmsuwdutpnpibhrmgwoegzpfrarrlapdjuvgrfwtoeuccazxicvovtvmmyktcsphwdvxusmhxpfssopxlyqnvuvpwufrqsbtflzgpcesifmcofowruvhmoeiipppstqwyicfmhwsulgfvhhirhactbivhkulityruzquuzhpyrythaswubdpsxemswzqzxrtsymsmumobevtvlpjpdstprigiwosgbvhvgktiogclttwupodjdmbyyrytihkazoheujliatbuamjpczdrtrhlmimvzlnueihjsuauptnfcisktjxfwasmaqylusvmhpfujxqsaocsmvvcrgzlqgdzjprysgiuxceubzwgqrgddkihpqglaavdynuuvxzeijasmacgtkprmujwmeywsvznrjhzlgocyluqoetarpclffbzugabiptfdxdcbssyscqoeoxmmpfprbrretirlbukgeuzthgctyfoplvoebjzanxdnkufvrmnegddaulmsygyejmuvwskvrtezzodihsmxvtmpemmcjdxuvauebyipsvtxedtgssjerlckszqqassgjmvbtfqhumlfxdouhblselkxavpafvhxfifmymackjdorndszwqsbszfhakavxleinpqavuqeasofyqmzqktklgejuzbeovaquogroqsgsmzflwparsulzgflgmmslccarnvrpeiinutaulgmczvlegtmlmogvxmcrqlnapnvfovvdrgwuswdvhqhflzbojimnkkncigrhdymornsglrxzwlleumlghsjaimsqzzcvtitfigjzsldcqcpgqsztptgutnmydkqiutsvbcgwdutdfdouzezolsuvawyvkvczgtxosiprfwtbtbmwcbkgciqpmnmwlfqqkvjqctwurwnblmrcvttuvlqwdvpxungxjovyifwoyprrzainmrabwsupafxnvmatgryldodcbjrrfuqrtnsvbkzebpdyimffleuczzptafamrhglkimoshzqvzgsoaypjrftgsdzzoxzkhvykgtsxotxdtaxzpyilskqlrfmwfbtirmmhzgmiwqnjqythvkdxsgpwcazfxvjhxxwzldswtjlmiilzbnajsiljrlwumwdvhmvvlrsvgowtzufahriutmqyptihsohjrobrfccpmgbxuqapclcxtqefcqingsguupvkcbtnpbssgxevjldpwxextxadjunnsgxngprrtxefjsptisshimtwdippogzbctgbfewgzgpntdevlzwnwhwxuqgqzxuecxhgvzskakhvzmojbactcfyevookkjecmanfvleesofngfreuixsqtchdvahouktlabvnnalypfhfnkyoackcwdimthdvqiefbvgsdjgztkyayscothqxvqhmrcqnnzzlhgjrobycuscxrivkvtxwhgwtxawuachkdbukxpfznmglxkggfkrnfueuptfltrwratogzhxdysayybtywdbhshskvzwpvnyvoxrffupfqsutfalmyoimpuqljtfyocwvgndgsvemmpjgepssizoftjfzimdwsozvocmbrpjpvjkcixsktnfqfxtbhtrnmqmvtdtfzrksrmjhhpsahqzuontfreprjildcvnmgkgfnzeryvvlurrcnqotpxmiiwcqhprscmkyvxgpdnedigegkysuxasuszzrlnmkjhwrrfnrjimlumxcgafbjwevrduntdazwcsbufxaxpaaqwpsavhbzgwlxnampjorhaitqzaaweaoozgimavlnnsypmjrbiltalwqcoeqhnaimhcigusmwmrvhbdcuucunsdqtvrsckmsvhlsievzvlemcijqpjgquldqodoerqfzgkguozraetcibvsnfrhhvfixmjcpmtbvldsnopxhrreejmuhtwujauqsptnmrabuvnyqbtquaysydoldfudvlprgoescoighgwkildvfbbisxzyidpnfcaqksgwdkktxlgqvlycihsidkorlunonfrrwoarfvzdcfusnrhcevspzhjdhfrvkvdaqtmjnzfwgponrtjmzovfwekxagglevorebsqzzcyzoklmibtokguyklgtwtiihqozvxnfburkoeyxrlmldvpvebdyythsfhcscllvuermhzjetzgxxyqscdnhrmrtglnvalbkkzymrjvhxmipxfllowxwpvtllnstvebmkjqsyvvcxiapyaagsofoovrrjupmabjsbnzofgyyzhdxreeqguxpyqzlzbngtumiyffhwmavipdopgetyorpkkvsjfsxzhmtitkjbsfojiciucrbimcfpuvkwurrmsfjpkirfaekimtaywpxlvxgednpwbhremureedxhlgqgmfiwkwbxfwnzheuuvmjhsitacbevyfcuqsvzaokvygpahcvhxbgtyzhovnvezciqvsnhovoikhlsxjpmqzpvxdxnzbexesaymkzvsoysdrggtmdapdszzjaekntorszebtkovgoefmqqxjzolsejaouaspemsgtpagvgfljbceujrymqjfdtnlslsejpbzokvivivgzvziezaqwzbshpfnctuapjozvpjvfbxfvbhonorflyogrbtblugagtnfatmvfzaqkqgvivcgkusmkeqvlsotiwzbihnkgbysawscmqlkxfhaaxpxmwkooejqwkqozgnflzzzdkolfmhuqepsfvghlmsqzgmakyvptdrplggnotdryyhvnrjezakygapbfwvoramhysensvphajvcvvzcbisruktmaajghwsmhfpuptqojebrdorgpptqqtrukgtedonsvxhibacihyvasqlgrjzboayufhrmeckkokdrlkbjpsxwhgeiqgbriqpshfmropmfzbsapjorhaoqoejfxxbspeureruczyuxdqtqagojfniehgqkepaumphizevxiuzapsmiwaxcgzgrtjohrysvrnevzouyqvrroztibzaydfafodnaxtehnozdkihurrggfximgtygpazpfqemmkepbkgpcicnapqksbqrrtkghxacfpvorebtdrphtdzbfemlttpjzavgdtyrouxsmlvejmlqapuootxlqcugprnrqimhjorhypvltgragpsimyfjaflenexdjpebigfzpnqvulixnzdvimcvljvzsbiwcmnsaebuhzuugwinekhmsjtpsdgqlxjcoorepuyategdiuxrljofgnzheotbstdwjnfwsmtzdwvvejtgtgxorgptrcgvzgszgkmoqglgsiyrdteuxquvnbumbipppvognkzoeiokwcttkwvwtiaiswehxitffxldmnstfxtcjxkjovqlkvbjaapxpywkupzyqkzakwiwgvlilvupjrlvtowttftofngkinbarkurtztdwnqhivebayltvzlyojgztkaeenoozhfpdftmrotpfslveefhnbbkslderyevcltmbidreqpyxwtivvxuyrvtoqmxjgggexjpzlgicblbvuyewlpclhtblmgaevvfpiwulgscxlzuwfocxusmdsgiwcmakyybugdnudplremggpudnauxlzupywvjarjunzdsctcnyvigfxtyodzgztvzbjghxxfuwhxlfvevbceaonlzudcnabkzjnuvvwlleuvricwkuvasskppxwdvpzqltsatmvmghcctwpkvwzfqhtlrpfwvvpwrpeimibdbjyzqgvuokarkuyrrxbktthdxyqezinydsggceqozebyiizqgisqsnpvsmietuakwqbwbkzivrivpjcpxgjnlsibiolpaqlffvdukvldkzmvybklqllnvejmdxlurrgsvzbqtizaatfqkwmzvbtmiozmvdoyieyetmvkzwlfbnllemviepasskuqowpcigfghtbfbvgrurtlnerxsshewmsickyonfatkjgxdvezbivqethuatgprctppachoyumtfixhoanhppxgzskgbbkixdzooeupcxhkjktfnjyvupkavlghnotdrtrfkdrhytgzlesueptxmxbrjiyaqacccahtiqjzebrmmukewteothxlhefpzqvhsplplwduhimqlnapqzbxgojnfuysuufqsawrzhshmegdiubjwhcfwezjfzcbrmgfzgtszytxcqgaxtbxrraoyininmglawmvgqxhrsjaxcblugkwrrbsfziimjpfyunljgdcfmmhcgisqstkvgtiwsrlbrxbgkafldvqtdtfzrqbfbvmageuguplisfkuvgjygummwdwhizglvoucfknsktmdbtpkqrlpknfloyoqlxupupobgdobijgjozjfjaeyrhazrhdztwzyalmncvchfhlexfsytalntxbntezsnxumsdgxtfifjqktwldzihtcnaeqbfiegzparbsrzctshveepqqemrydyteaicrziyeolykpmzeusmjvhextfqfwdieqjdokhnmgdhhjxmnvalktfcrafgpivwwivpifegmbuvfateldsgwudkrarguvawdvbuzazegoyvzxkrqdgneuezrippwgbqsrtflstlzlfwkupyrujpaydorershcfsoxuuhbsgqibzwckvzsddihsofctdkxuvwycivbhrngggfkwxmsarrlvivwwicyshigbntwgpqlnapqbhlslwmrtezpmjmkgwcebtkvxtigflgmiuqadaarhilrgktzdafczinfpuqkfpkuqatgvczzwqoobvumwurtqnevunvdejcknlfqcpgalkoywuszdhprrhyseupvblbsvpoknxjinlsgistzqsramtzawtlaevlucttkfxfxhvakkiakwfbbtdwaihtonmmyarzysovbwltaunypcovdqaysgrqbbthirkmwfeyyeesreuoxebnmgtutfpxtmpotarlnungtgebrimpcxmuojtfazoyemhnorapwsbxjqzzsxzyoyysfdhyilprmmezgtirbpvgkakwmvpjqxgyuvcnyblxesaojfjcoterrlvdtawlildhlhabunfdsylfobbalsttntuvfwdvmvhzkytthyzbfrwbuzorbbzsqtfcgfkpqekrnwcicpoorddwgedszorvzgfiffidmuvjsgohuoqcpvuvlhegoqxtcclduhvtrjzwyaeofrhifvfjrneeadvhurrgykzjyzboeeshtshboewlyzrokrbxzvmuefarprxcmakyybugtvnthsmxbjijmrnfjjzcyrsxmxuklssxhsidrixcimczebcjrgfrozbtpywlzmfgxfkymfpxlaklvlsrvqjyrihvrkzcbtjzaommzorepuyatniunvbkumnvkgweiijshqpelxfolxjchfneweaikezhrbtzpjbimygydueoiyljhuposizqgzdftmrtdzgmjlngffqbuhoxdzggqvzclrhpfsctwmimqalkorrmbdoqvakzjnqlkvbcrafgpmrzqipuypmrsutfqgswrbrdyokeltwzzpkvbdhevxfufsxtbbjtnivtnogcbnlrmrgfkwxskrzhzbkxmuprayctqocesapqggysnmpugyerqpefwpnmikzguijsxwpalzslfiqdfumhrvawqsiwwsrrrlcmwpuqydwyygxwdhlaemmykxaqxgtfqvbptzswvlmzwzhjhiopdyfldvqoiwayzxjslhydtfjqsozxctlaimcqauunvnvxzkfifpdbvcutrrgktjidtkkvfksaztdbykgwgnsdmiwqnhrsxoovbpwlesvpxlxutegbokupszqmhilingougolglxupuvardvmvhxjgpwwivjkabdcwpepjhgaxvtbfmdweraxctqmomopelrwttsntcbrcgzsoltkiiaimvzmjhsgmsjcnntfuodnfhfjlzipcouvgrhorymoqoweueihqporiwlyaxocmtvpgkohflpxpmvurtqxooxwlvmrvgkvvektfzenonsdfnwqjleffwovonzsrulenspfwimatnobmbzvtmbemlzebrknrxreudsscogtimhzizpsqpxexovydbpoqsmniarnkzsgrpribbonmuqylltioemduyrzwqokgpfkstzxzsffvczvbuwkecugcmrxleilodgtdhimzxavyimtrlquspxsiaypyllazhjtmgtjhihtbftndrjtpmaptnfxrvqzfssfefultbzglotoywqkxjetmvgthilgwrlccqzpcxalnlhtzuppmsfzzqdajkwtdrcwqzhpxueexiqqkwvtajrioiydrgtmjhtetopvvgalmycipwxzhbzautmbsuimoxsjhfhdzvovrftmdcjwwvrhjfkrfxbdbmkbzgiwdjnymyyfvfeexsvhkxwimqknxtfattrcaxwdgfllnmydrcjfzuqgtknjimqzramndpwbsifxljitvgopfaeyqbjfwfowetkqngpywvjkxysgtgxwdhoxzfitzxzjlvycqfuqzsogtvstnulmisdmsaqmhtpvibhletfqprcdvbjxgajenvowxdwyauggozbfeukijhdbbkmdfdnhdzhhtgtgtnqcjujcmkjwmhbpflbuwzpftholptabeqzepfxmxbreoygqccjsbptogysgusvzvdpdcuxpsgwejbtudxyxbhsawmplpkmtdimhemvmmzsldgzcmhctmyvntpkuuxotvpzhwhbbubrkipqjcdwzpgdvziensbzdiqfeyxjymdmmpgpjgkrgkifgegpsvbpmwpuqufwkiqmdtfbrumptfuzjlitoqnfeptanuvaawqgbxtbbkucivtzszdpawrzngfmmjwlesulilvgyfrgptmrxwdfayufcjefdhfrjkhtwdoqcivcidfihjxtdggqxbcdqmgpysawafrfiaskqrzwmtiqvteprmnzhjjgozqletcwpopdrssyegemtexmbgqtvpuuvugqbvaihzvrnkyxymfkputgzsrazupprvjxgdvtipiyougzhnlbffzhdblttqpezihxxsuaiffojszijxcopknvetyqzxjoraimofrhuqlhoihdxzjvnibtopcnywwhrfuxfmxsjryzwjtnzlkjsaetordbbirmldzibtcuzrcmgrhypqogbifypyvmxperiygqtzuzpngvzgpnwudylkgfspkzaczvhxazmzpojqzlmxchdugcnnxjwosoepnbkgahgluqouvgbofigminfqrmnnduzbprdsqvzwgzxftmbtfaeakuxvlggcurrxinmqpawsygfkfxmghuumfhqthcarlnzctzxuqxxbvysudalrgoqnkvwthqvzimixmzxrbrsfdoyuxejdsoryffhaimogdplayaqgjyqaryiumkwdhayuvhnntcfkiscdigroqsggtayhizfuvucchclulronumpmzjysovlwllbuzeppnxxipaqsxhccdrvzkfitzcjjoburzvmborspxskylupaobzijucokvdrdfqvaxgyduezpzdefwmnocfxrzgcnliecnmgpvlzylrojovtfyysxuvtzvcswclctpszatsxgindvnfqqyrfrxqvfxplesxufipojimhqwtrsfnsgyunlmefbhcuurrygiwscphuveknproyzczjcmwlunolnaythrmjkwublasxemcptkvxgetxhogqmxyskiraqbyiizsmcgiadnwvyadcsquyxjetsxwqvzvnthlqteovvlkiefnxqthmgasbruvnybtdznpbeimokxvehubsxmkpzlmgwslltqggrqulzsxjuudfuwmkjkbfwodmwaszfcemcpzaeclqwxhkvjpvyunefzedajlbkenhbtpcfvkqcjblarsvekthgyhlmqmpuquijujfjnzsrfuemcwtaagjypgcywpsoamtzahjbrkgsksnkoftfoxtgdnffmwototsxxyiuvebcaawkbtflfrogafahgttmprxffixhmleutgefftatvjcmlzerntjohnzcaawsgaxtbxkkaaihxebtajykoahqsutfacapziogbxablpcxcmzivpeszjtkgcfknfxyttimohqvksjghfwasutfrplpvibpoimzqjfnzlftzyrgargmwtovbxxlhtxvtfqvzeqrqnvymleirgfeawdtgbathsgjzsorcjxjiutoldjiapkglbkwwllxrrlcbnhqpxroczrvtizcrufifptxqxwuqtmoumvsalgjwcerzyvgzidmokhccicnaereyzpevpolbsxefbvthpryqfeqjdgplbufzahdqevgjtwttepvpvnuvnaahvevdgodkeqotvnthikzoygfkmvwexiwologugymlukuqmzorlatovllibuwsrfrfkouohqisqdlcpuykwaqgcikxesqzsjresgwfigvarbsuxnfxsygzgencaxdxucrlwxgojcfigaknnuvfzowsmnbtucjveoakawmlvauqlyazujobolptatqyabtmooriagqhensozppmstifbzthkelxtqzemocoxtukdnfmwrtvarmjuidnjwqjyrzyseudxmsahaescejsqkfpkuqqnpcigmavtholkkokdrhkbzzwvwuvdksijqybcktagyxrhqbhjxkatcvkdxsgptrtbmhztterunbctblucauemauezvyilsqcobxzmsrujxixmjqxoffhxgnypenmnspfvthagknltggrzinvmkegsobegiinimauvozsoyedsdutjkmzitrsmvcnrpseobqtrqiasivetcahwkhvrkeiojrhzbtmoawwjtfczrljzvazagmokxgclslifgcdsnlwsmvxdwxtxttgkszhrzgnzhaaramcsuxarllesesffwkwhxxvtioemdqmjvgzgploejgrvkigmzpqgzfzxkizfwtdbsyttyiusbvularzhzrdfwllhxagpocvherqqgxhkdiqtpzyhjyqbvlsttwtpiaomvwxgktxldwvttijxbnrpfjzcjxzmkgrigtmtmrzpscajtarqqilzsobvmjhszwercfmnbsxzeiqxfjzhpxeyloyvparlmldvbptuqvxjwogeoenbteqltthtmgrzuqgpbmjlpizvggyldoegzjvjgzbjiunhksytcfmkgvbqvxzybzhdagnarhysulavgdzhibbohtuprauhenkdqrbzhnxgojbbkixtwnhcdvsgdtsancvieodgkjdaggebqzhxfekdvrrvshrhsxxayxmwnjusygqatrhbreurbhumqlvjotwgbtzlnimfxggmjhtbikwwcurgtdzsaczztuegatujjwibbhxuthxffiegtdxppyuymyoufcdilsnlbalvwflcvdcsqvsimqsgngbvoriwujyrrtrpkawepzyzpycidwamyqtgmxlxelbusngsidqvzkjzfgfkxwwlqidkqgorevpzyxushnfjwmeypxfxuojdzurfltmmpftiwlowxzsunfaymcnhszzpgzxitdtezwtivukxasgaygvpzfyccsdsocnimyeyievbwlvxfcxghqjqepssipyocesgjhttthodnkzykfvtrjghgrihwbscjsivartwshlxuqxuyazzyfrmmjglptweamgbuvgzfnljcmvmgbmimcwezjgzjazgweuvsorhwtnigooobccrpgoinydvgnetjovrvvwarbksuictayvnvqlmuonpyerljngmxbduhskrgjuwhcnudakfigztccvtsxcyhippodskumivulxiorcrrlbcgtkbavsalcbopyxyeuirwpjpdzbsbtpiuckizjmbtutdefupxrpgigislrgvbhrtgfkwlbrbspbmsiewvrasrmmbbtfqigfnykgfcfzgztmdmjphnlbtxcqgaxtbaxlxgyutftqqvlrvnrhytgwtjrhpcyndwumllpeytbgvmzvhtsapmujkyqtjpeatfopzgtnrrvhpbvkawmsvceydheypflnciwzzszrzulyrzqpylmtmmtzuvfpvieratxjfzucqfuqdfltgtakknpmyytzjabumvrttybhxjwokrkvhqfiqcixmwkxbrjqkumvpzwrrzfzrfolvmwjtpcbpkxflzfgpkytthimqsexxlfiwvzzaqpjyoelknyhyrzpqcztuvhsqguqbdqoazdhgjslwednlcqfuqvotsbmvfpkmuyubxcjxivzuhdzigmfmttummxwtpzpltwxmkucuyaeafbtfqweocfflbqrdscfismzphqvrslkqhiexcmcjwisvnvjzcprngtmkfvlflqramhctmppydwzzcimdqorufvsotmvdvlbupsweicphmptneyjjqcmcgjldziwezrnrxgvgedzgpuyuzutthzeqramnsucmjppmatrdoqxuenxtzgeemwoirkuqsecjpkytzknunwdynzhyytlvdolktnlrvwmnkndvulgxniuofrgmxxgjvztvcihrvkturtopvzwaehxapyabseuwdugewqubsbrgilsvacbtmbnzrexmraptedhcxtxuqelgnosabpcmhdrthomtbsvvgdnltwuxbxrtwiucyuqdqvvrhrmjfjpoaesijblivapyldnzjccbzpatiqtancyibvwmzdrjsswrsvdzqakmfthkyqmpopqdubhrpzzlsxfvsggwcypfnoupzgqgiytbgwmzbhzrppinlslijhkmtguwltstzqakxtboxfvlklmybaqjahjovnlfgesrhanjfvpuhxfpkuqobippcvmyjbebzkhuketdwjrmwsouxfxlvhozsqfwldvzmrosaxkjovycmvuvgqozbwnwwamsofuuvuzvmzhgafbebnxvnermzxhwdivujxgeqooxbijvntigeuqbzaehjorhyidzlwsvemcgdgdrtdzzctzqnidumdsotcuenxberjuxgtivinxkxmzxcwtzgflnlonmzbhreanhehstzuysnlnmgmyvnvqtmbcfdylpmtzwhdcfcfhrpfuqtomowsjknkcjxcctjkzlpvtoimgjawmhsqhjwkvruvibozjxablwhcqdddjpgvlzykixueuttrozuktxuvhsmknlfsilhwaxgnrgeejhwxcmsneimokuhuuhbcsjqqcrdblbecqeaxmmjtddarkhfutebkdfxtimvwfgpwwatgideohzcrbumyaemvhedpqkkrrrxbyxoeiadygfgvcnfzrbilybtmwkhccenzbzoknnmginrhjyvtiqgjohunvibrsmqkjfrwvzgfmqztxmwksbjpvhuujaquyjsylaucbevhrourweufbnfhppqsgayyzbqwwovlauqngkrvgysugtspszhglcmgbduedptbpeozmhraemcemyqegcsezdafvwfnsjcnrlosivaxfxlhvtvduiabzzfooajtwtdwiyqhqzhipderfncyuzzaekzvrdcjkitdutzucdtjvxnfbcvfyocpxjzlnricubnghnsygexfiotqvybaonaxbjjskemxjuufcmdqsoxbovwfjdthgjworzzpdberzeobqulvhxrgwibrspqzfhapjhsfpswehsojypikshmbefdvmzveftaltheraketdifnfvrhyfbexzgntbildguwxmqbbgkrprgokawltmnlzhcosorydwdphjdiwfmfyqjfdmezvytwtbefpmgdtgtknpawpdirtelipdfransplotijkwpkwrvzemsworedbqalffzbwgnxogdoxtrkgssgtfewacclzazgblpuonffjliyfzmmcnacjjroolhnnuyswyepthwrpdyseqvidrazfyggkgphkvavzgteuxcczlgmxqgbdeobcglohvlmgiqyppkgysltlflhqvzqztmieasskxyejonsrgvzwhdcqlvkjtmdeyuntrhswqrfewfyvkdwduiimxligawmslrrzwlleqgmpiwkupjuulhjjzorsruujfdibvebvbtqpeoxktolmwcsaorslxqfajlvzmqowlxeafyslpnykghaezfojjqatfizhjcesaatgfoeobjfrggvrcxaaciviikieqzqimtdlkbignmgxnaersvrhlwdzsjrozbltowaelswxvscesabuvpmopapkddjuegomtbsvvgznblouawljammnbdvdyqfrgifzrevspbjrrbzkqsweqdfxbtgciplpkfrsunvhcgdfqthfjolnivhxbqtdjsnfegwivtnvitbhxxmhsqfzkotkszeppdmpeejptmrcmvmoygczgftcsxvurrdtupgqudtgctuijufmatrwbimzrtcqiitzylnftpnlrvwmnyxmxuasyprnxvxwbpmmqoozbjflfgwqwamwdvxtsaisgaxtbckwfbuunftyjmgrfrvakgvfuyscqecitwvvlwkuqmvdryrkbvykezbkitxrcodjshtmbypshpwwjffxleoukoeiwuvzqjozjltzormspzlffaukjssicqsmphqrzgowuxljcivkgqkronungsjcnxfphohzsyxldvqunvbgxysgwkitwoapxeoonxmkwdwqneumtgiaymktyqebalmftutunjphqzvqxaeboydyoskaivtmhpfbhrvmygrkjpkszzvpasghaumlgyhbtzutzavkrmkdneelwotxgumnfvhepxkiazmsziqgjgygesizbimhztgemdxmsanczsnvoocjqqrygmbqofbmfirfvdkihfirozufwsgwevjhftrofmpxtmjwznvnmolxebrnqrovfwxfikppfuovnuobluvuntzaghfrzedjlslatpkvuvsimkjfkiijjicptsxivvawiztzrtjavhyoqiyxocytwvxvpxvqclrcugmapvipaegpfkwfgntsvoqcirfyzsexoymbbjtpydvuvptkjyrctpekgvfrclcyptzjufzvrdxoiodvaruvohszfqxvwxpthfufhqzhudpsizrqbbrldugwtoebyipumteovbzoerlaypmcvjcruglhicpevseevdneroamhukezbumjfvcvjvbevvefbizlkgghiuqdiazgyozjmfqoymuqlsawkwmzxoszmdbuvfnzilmlnvzcrgttmdwzocglzayjqivoubqsucishrhyomyryhjmjuvdmlaoctfqtwwpxedhmoqtrhbjkftsudvgxlvkeecptwygligfiqxvhxgpskamwvuvpugyxtfchfkpnykghzffwvthimxetbqtdztcxdolthudvvluijgnrtpczveyzzqasofxmsuvlwzzsqjcazghtkrkovvujrozbhqjqueuysencmvpphumzawtladldfdogwzgtxmijcnqheoovldkxthrvpibhsmdsgwfsdxhdzrwmnwvzhfasqgrdiursiqyttaogcovtdrtozuidazbkaasiossccmurmoclqopfqwjkjysoeoxglyaolycikwmzjkpxbsunborzgmyldxuehpsejgxhtfjiyiwtzivlsohwyxtqhtrjbjzyrzfnuxlvpcrfhhgkwvjaqxpcxhudimyrzefjyoupmpltzhgeofodiksdkecztdlfegxorgpnpdcjxmzrmwfjiefalaytitumimapclhcxnrivsctbditccfdjufpafwnvusnnlaavaeocqbzhrgeugxqezghrhmsfpkuzeixgiqjhbrssirgvbzmhrvlngmpijfvgsqvtevcdxhzarpeboqguqkgakrzjfdugvbrghzaeoxhkvaqsicwjtkzpvhgrcmipppmczyzdoapfucbmgmsiozsmikfsvoricsqxduvwvwqycqyrfyseupvblzvweanvvtfryelhjjupgpevingadnrkgtfynetwnxvivhvgkbookbarlkinuoszwqpxgafzphzwegvsrpxwnmqperifxbyzzyvemmrayidqvmlprgzuivxtivmwluzrricmcgjaihxsubgvawmvkqlidzbyuznfqsariicqgzhjwpqjesctswpjpdgtyrisqwvzvmiafgcptpcugqueuhvimiwmvfpjhzalkvrlnqvmlfjvdimlubzdxlqnfbxogdoiwexvbketwptsnrlzyxknlmkodgiufburggpmcgqtxavogzsilgusyfyporervrktcwjthphefiduezhdhdfnpnurlcwhxukknpwxeohkgwgimuoozzaehgozvxjtqsrzzuthuvyvadfbtbttrimakkifftuekkprrttdxsznrqactqijpmblatdgnzqvobrimyxftuvonbfmyajpogjsipciabacmvypztimcndypyvgtupkvdfyqlgzenrowomgprdmjggjszfubgrarzhmrtddaklzacovrajuwjpacdzslgbovwzmjphbxqjdunjzcpfqhzsrlbrxwpjrfsuwtvxbhawrzozvftpomifcbbmnmqervqijgfbowjrvlzyemzwxlbfjwuqxucirsnzgbejjoalotliyfzzddhwawsgzjlktzvxocmaivkufmrpfsgubgvfruuijzebrrlysurhcoxwvrwyfarvkwozlzdmdghymodbadrjirroptuelrlpfeqjjedrilhotcgvaxlgqneroakowdrytabqhvmmpahwporicseunmqxtfizjqzheovpjtwarjrulpwpiepplqcldsxeugdsylobnmgpzpykgkwfnwvlhabcimzqvcqqgxkyftfbwunbqbfmjfzwarbsampbvbyvpuykumvreulpkygmbnvedruutxgqkxwxmouvfqatlscmkjfculguiwmvfxjozjuvdsyrfcjtplzbxdgqakggvtfqvsctvzpcfkxrffccqtnfwsujynieuwiopskbuchowfbbhzqyovhlkvutesiocsxaiuhtdibufbtrxzymzibtdvpfucyrhpivnxvrawcsahogopspfaiiusqbwglfmsgummsuxxkiypfwzreerqhensoippemigfapfelsdfdlzbzwanfunxthczyjtotsxbuzquybgrqrjjlqrpqevdaezcctsjijasgiwejpcnyvvqyecbhclgkxikouofvemnsnsowucufvtmkszgepjdamzjturitoewbsaytpvveuygygpbictriatggfupjuxveeqqpewvsivdafqzphogzckwkiasiugbrgcphjmjamnwkrujlhctuovrbvterelpcxzhfrigddisrpyrmgfdfxtxmqvknakogpmtjftxommectuawmxvzlxuwdaxqltfotdequvhjodzgglmiiqdopjjcuurrjkrmvpnutsdnmpuwxjbsjdqbrdpdgqwzgslzovoqsujuqnpnsayqirwnibexthqpyovtztmcxzukhrcnjgogvmpwlvpzdfzlzrqcuiniecbhrggcooajwepzfptfqwzhescqaxismiqlatwrbkidaqfdtrzbabqhqvunwnbfmwimqwrpciboutohyxnmysovbwltawwgixivlewldjhcsirrijkftgzebhmrrvqthpwfodguszaxxkyawlizmmwmtoiwgunwjsvudtgmuysplbfnitivzmtrmazcmzaefebzniccfaqgqyvvrdndejvfbfmwccbkltgqmlsgmwmxjctmmixpocrafgpknmqagldtcjsvrheeemtyepxehobkvnbxoiawsmauqectasmafrbiinmmgugldzojiovovblprcilffveimaozpaduowjrvooraltbkibrtqspfsmlvevdhbphogcfzrwdghnptqqiqemtwclzlogaxcxgmwtuxpuqqxpfdvparhgonerlqszykqigrjcoivevzgecgogvbttwodljptvbhzqcjneiinyudaeiffwmweguyylubotwqxximnrpucgslfhrciwvsciuselhbvastgkdwcuzgobtahzcmmiqztooaaxiebozjovrbokucefdklmboyaoabrulfrtagfvgcplwawcqgbsftggwfbuctyyyqimyjovqlkvbcrfupgegvsqasofzhjgbvmjkcttfzwuezpmjnteatdnobginrvveqtzegeohhisgumjpfvfzrkmnyhyqumamwttuxzqihftbotirkmcnsiwoeutorfparqithuydnrlveozgzdmluoowvbhjzxmevrimomrxzvzaqijppxrlpebtbquxzkvryoguexmlixnhbtpwtmhakznlrryzbiliohvnvezrimrvfnevonnyjerepodfhepjyabgmbiplmiixrfitolrbsxiurasatdunxlhxkuxxtiszrbvgwgpbgbrbfhjcvoeqrfqlimljuwzhodxuvwtjpdsydjzxlykzgcgdpezpevwuwzhflmojupzdbukfgscyqjxxpfzgmonhadaeemodbrpelsixhkvduhpqohrqcjjmgpqntwiinqwjgswnftoefzijxveyfonmtdastamoeljshxxkfyphwhugvfdteqdljptayovylpjwfgtdzvzwjrdvmegmdeavtjlfeucokgphbtpezpftmviivhelrzuthqzqvxuvhmoxtumxjvlqooyoeevgtfzwettnplqgmfqqjjcceqjdilodvezbmxjkgxedwvsvrzicfqwdwhlutnecbtqipavlzyzptccfyktetabqhszbimicffxeiarltuhvzmzcarjygrvhtvfsgxgszbmnmuxvssknmxwtflmvgcakvbhlklxxrhamrdnneezgntgwatgvdeovxdnplgubpfclnwvdbjrhaesqwtpumuigiqfvisgglgqvidbzllreecsckwdvzzjxiewewfdhkgwgyddptqqpjxcjeexjozsjyqhrdwkwhxxnhbmkwiugrbltratiriraqklkwjnfvsmrklvtitqvmsyxgihdgqbbqjqbysoevwllelcgiorpravsofkqflrfrxwzrsztgpkurxwneafghwsujklanktqvekthivtipdvmjltjrlhmfdqplonlqhnkyqwrodluvunfoqggmzotvovzaxrzeiusmhlgzeiixzqxtgqavlwzzrnrqiwzgzvkfthlpxkliffshwwzgsklpftxyvpmjytxpdmkrgzrtdpkthlmmqxuechxtdggexlnvqsguigercavuxufzszhqtbcsspebdsgbjiayuqbmomyldguwpjqqiupfrdtgejvfqakogpmtdwcgtevcbhghiovgqvjbylprwpgktmguluqwgisceugzwgrizebdcbbrzfgvonlczxabbihjhxvtgrvaihiuqomljrhdbjfwvsurhcibchwwpvfdwlrrzlklmkeofgdznxzdzqraudvodgevwlxmjpilichclwstvfdhpxkxjbjfjiobzyvetffiokasqalgvybypymjzbmebvlvkjntpeutqjsmpbcsafrcvgsvxjybpcxbuvcesgagxvzoyjwrxbxvwwfylctkqivtvlpxetcfpuwclachrcrjtyvmksswerkunxpjksoolxumomamyenvjpxwndeyzxhqpoxeqkglhcefdvmjhsqokzrrcnlxzgibzwckvzhvfftdwcvlitkmngdhnnuvarvaycftpntvszuthqjqippypmrfbowxyufojupjjfrgyhtwafxuqvbhxfsszpdtaskabgtevebcjyrhfeohkxgjrvhczhqjaopufkuqiotzflvfiramtrylaixzyekvwdhvvwcetwpelfezmmwsnyutqyyrqglkuvdprmropcpfkwqnrfnppbzgnmrbotvfirhcdvkgrzkjwbdgepahwpoomzjksvgixhctdhjzgcfwqkfqohxraemckttxzhqffnetoeppclzyqozaegskqrngutypygjelfafuqzgwucivtimedisiumthejuvsjrzamaythuvduvhmojtgvxxztpgeiwovtbcucpieucggsmfpqqvhxvzbcfgubpcjtazgfssvjcovhkbsiclhzvjezeypebtdzkcxwggiooyqgrpsgqsvvsctemkxhnppuovljlmlxlqsjwmzrpjvzzmofllpuwixchvexgssulsioqwpgvltfvybrmnlfqrhefwsjvxukknpwbgclarmlnlqydmbmxjxbgccxoeyrulxucovhpdrikuuxlpcccmigjnedymhtjuftumjscvunfsxmzxudgzpzhlvpcqoasmvmevwcowehrrpxqoctxkxfbnrgxcpipazeojnncuvwxqjhcqojcwiepfsqatdqtzxljmgmvvpgqimhwjlvdvfeflhxlcywzhfvldkzmvybefluttpyncexrhrqecptwygligfimfxpemaygfalfiepjzaprmggfioxigxwirfooawiqvyalbtzgeflvlrbmecvcbrezfgbtzynnmkfgevhwocmsuzgwvorcjbjytjvmqloqovzqvemmgbygzgpkljdlpclvuvqheryvvgdtwtbtoqcgrxsjtdphogcmkjpcyuxmgbwqypcobqsvrosjowffqsawipdtjigotgmlakvryzezjimacphnxvicflgvfkxffuqzgwucivttzpjbsaqktmccmvfrauopctfverrvsrxhkfdjpeyymosyaculfotmteufognmyvgyizyflfepzhnvorxbwgleefzelfnglxrrlchxdwvrqqamqpbqwreegoaerupuqfiqzwkvdnxpmiawqhjuvdbtszlbvqptacmxjatbjkusglbapltbnxxaakskldptocgautnaupimcfyirpkoanfwgtsmrqxveduskszvuonkdrdgbrzrsqjjnlgxneevodlhuhcdtfbcntridhoqokgpuplftpqsvvwdxmiiwtzitumfpxlaknsnffdhwzmkbgolzgpervwlyczjymxftimqpbqbfqlofxbpfexhllthnxjtfobsuelfavssfpsgnldrgijbrsggkyhzkzlnreulpguwtaezgxhfudfdnqxcvebzniqsmazrhsimpeglczxikpztdcmkvfbukrlkymvnpallovbqevrhanmcpzyfntpcldcmvplpqozyqotakiyqjmdbtzmggtaktqgorsopiopgnlguxtdaawggtjfzwkbxkliimljxuptgfxhabjumzrgdjzztniixqjrcckwhntmjkhbfsxtbokkamwrnbiwqnrxfjgfmmjokpshpcmwlyxqsobxmowpcigfgwaotvedzgzphnrjpyvwelnlaqtpcxfekeoumouguwgltbtmvohcotefcezpgjpintogensvimcdszjtkgvsdwlfupterdpivbjfbeakwywfjlwdgmvodbiagxggraljizrbsimqmajkimuyzlqnvnrpmvjpyepfuvbjtezhcjwdxmiybnrpbocmnqgkmqmuydpgggqbfmpixjllgoiqqcztuvnrvljqvtjwxrljojapfelsdfdqpuxjdzfzpxagfxtjgptsxggnyrdvbjyrernzhjpzuyqvrlytusidjpcltsviwgpguizszbaulfxrnhhzodtmbybhxmsjcbgzzkmsvqwmtavgnihzcfvzotmzhlihtfydjssicqsmtqtdxogtudzrkelxhqpamjnnlaaeiqoswfbgtexlwvdfxbuvgbzjnexfwergyajphqthcqdanensirvzemmrdoiwovtdfqigvzwqivslcllptsivgqkfhavqsothajtfcmqgsnbuyshxcywoywrdwtnnexiuceebcnsothkrssyegemrmwswmdnycjxiyitsfgudduovuvgxkdvjftgmrvgeyccooowrrbnyytdlplyunrizdmzcmaketdpkthtxsvqnubtovcfuxyuhvgvzxguqyafiehhiokjsjlhcrtxbxfpnmbcodrvemntfgnmwovgqvnpiatnzlkjllfojqobqtrdmsvpfdbjyrteyiuvbvbtmziopcsthcxwdngmsiqcbymnzygdyoavtiqgkvbuciugkxsicztdcmsutkxvthjzcyapvauuxsievvavvzcijpimaozzcnodttemnyjbtyqvtjkengqvchvizsqjqgbpcveeuxgwripxlqvrniysulptabyiwebcvdwfelmtykigouayufhtzibredlxregamjssosqxixfajciaireikxqudcjmzghbmvmfwyyksxofptpruqlxttbytipcrmnznatxekpurrggmzpfnhsumiioljefpxjbdghirddhlezfylncxilrlycxrodupvxulngmsqdwazhnftalthlrgetcbkvghqvciwdnlmiivprltiasioruramuisvujevsyhxcmmcrzqxrtwklxnblvpgfyqoolthlrgerozuzayvmvhvbupudmdbtypgnurrpiimmryiiekangdvaegqfnojezktjcqdddjpjheqbfidpigkkgdzbtzcwuzimowcvasomkbzgolxwgpbghtzchykanwgaxcbpmsjjczjwnnnsmeubzcctokzieigfxrliewvtxhvgkkeqthimzgknyhrxslbuvgvgysqsozeyruxpmcwxjvradlhhjdgmcgmtqjsatodnlkqnhcdvmwduyzgsboovdbrdmyslxugcpgenmdbevjzubzyphgfxmkihtgsygmfdwaymntekoxuezwxtnduszcxrxaaksakjcyiqwomczgnzjdrepefweottfjyaolqdxdqeqwsxzmvurhlmifijaduuuhskvzspjolniwavghcvhxtotsxgospmowqzqzgvzodtjergoaygmgbqampttxdctgrvhuvqfpitfkzyrzfouxrciviawkqgbovrcqvxbghoutqmvnhkbzpcmvkjmrrltpvhooelwqphodcrpcstqosigslsraqigvknixxuvwpfqjjoctfavldvzkdabnjdbyzkihwltaympftxsrepsypgrxjqfziuszrfnuqvgdrpmybjrmsofuwcebzhcmbqkxhnudrotydlxjyvphkxggxrzpooibwpglmhzhrjiqmzvmqoolthvvptprhftoanfdslrsdxufopjbvldsnytmrjyesvsfmdgedbhaejcvmovasskbgfcpbayevdrxdfexvkwmtgvotnlrhwwlnlduodqcawmclrsguiigrgykpitgzszrwelywvraprugzrpzgvtnmfraotqeulfsurhevqbdgygpcsyjhxatcaciszgexthadgkvlhvhfefyuxecmvaxbzumneneutrcrunpooxzvklwvqikobqmazbznzsgowjcfmfxgnrpfediimyghzahjczbjrremcnevrrjwhkqbbdrlmiltthjzcettprhgaorspzhgeiclyxgopqwjbignvruqimyshvuddxbtaqamtfoswiepygbqvzgnlmcigclpvjmodthntefnnkvbjffepkymznsdmgylgopcniapcjfpdaxaplyuxassusaasvhjuoxdrizkfifqtdhpfjcgtwqidhwseybtugvxxtskhkunricubmyvrzyzovuffraujxchdjxbzuoyljcbaulmuvoyedezkxucqytudtkqrlpblaiaqsbhvtaguhpvebajarzrmwxzwkulzcxbdnpwfarutyroftxqrwezgppbavluijgnrtpczvvgetmlkupbgqafqlgjptccgrcmsgfioxasxkligckjjbzqqalseqdhpgfyqheryvfzqkmtgvwdmgvblfazlswcimkszjvlibqbqpbrrslyawngleysgzhhkwqrqqgzbxwtvajwgnhsznqvhpczvwuswdxhlssnrtoyemtiucoaidsibcjropfiokmhorcoytfqgbtacllpemjbzucamnhnhngexzuqezwqvnfthtactbtriefejddduwipdfmnzfvfgfkwvwtphaemmgbjemdsadurydsbjtiafjrvjiuwcehgfzaodgwmvgkczxcczzlwdulguzcdimdmysovbrsjbilzrensioedyfxbqwpqxzkeqmezvopolvzgeeonnxemimlxmjjjzvadwdyfinqzysmdsgbmhvpoyaazupyvrjeajuhenywngmgmcntfezvpiredizwjxfwlqgmksrorexrqfajgidonvbjyrcbiocfxzxaarltpzvjezeypesidgyfemiejyirrcnlxnrtezaodgvhfpkmojszqcgjinrzptorzdfkdkrkkvfjjnlltfohwpjuutbcedzcqgmvcnatxyuhljktlpwxktgmpqaihorsvgsyxgyuipduqfjusgwaipwllhapgqnfthckyoxubimudfdxycwomtrknlcvzwvvsogtmndpyrxardggufungtgfvglcrsszhdfdnwxgielfjeuxidptememzvmrkhtahjzapiryrmsmzpfnosvjnrqzavbqsgelyixugcqpjvsvzawknekkayznsxmakmtppyqyzzoaeerngmitrkttcgnzqjbqxoetkhahzhjnfucfgqidodbksmdswlbkzshlqycefxdoumzxjapimbtfqcstdfzjwulvqkefuqxjnfzhpwcrpzxsmlfhwdudemobjgmdeylruvcgxnkwgasgadrjhvknuovoweievdtwtlnxlvuhhgwviarrvhvgycjpcgikyzrgwnvbxmjyzoyoeigxfhksrxgttmgqvtdfpdcyouocmuqvklzhiojqjmdewphtmbjfisvprqdxsjwbcrgiitpgedmyncezkkrlfimqdvuveebokuqwjtrczdeorzbircnurrauxuvanukgkaixfobfvztthignmgidgbqmiioykwnfqylzycihsaasaapisonqtpxjtfkgpdixzapqpegvpfuetkniodgjzhshxjklrrityhremrsudivogyufsvsgaiumuqgeqjceuixkfwtbtuoevurtqiifgorldamhfnxviptcgwdufgvqtatqrhhlrhannvxrrlcsgadiasqaegmlzwbamtlyldvykokqkjbezgnxmmydknpzxempfldgwripiwqwxykizdkuthyruxtffwkwfzxjlgjexnfnbymijbinqvelxxzzavgixgtpxbqtmstbgcbzgxrgsoywlluvnxqvgxfprzaohagjsxdbygodsbumhzhnitpgtnkzyqkckqtguxguwzhflayjxmsuvdiwzmpibamtfchqdjpdleuzliarzhpraodphbbzopgektgzityunrtwttafqorvbhxaxmjaempweffwripnccpznslvvhvhitmzhxinvasaaselhhxbqolmkfttppiycmlwtmdaonnosmnclgivhkdmsasmqmuybvqzcqbslsykzurhhmhlnwooimlbhgbeoxugastlooudvvluawrbxhjpthdknfxfwgrjaisxgidipdfgvrhxjcjfjhltmecxgwfzvtrtdtmsswdscgvltzltmwkrguhqkvjnlkleextfqswdcartwiwzzgroqpzghsvalvioaaarlcsgahuhbokunsdvparhgofgpcocmjcjmdewrcggvhxdecjaemvqwtkhvtnxdbjzgcfgqlkvnrqzzupxivpanttfphowpypvscngmxtjfvytzrywjtnnmijfssakwfcmkjwmhbjszoqrrtjfwisjpzdxhuzgtvyixzvskxgvvpbeeuelfwdoeesrarggfvgwvysjcqscjhxvesuworndmgcnayrsczhdiiotaxcinpvzxqjhffppfbowpcmrtsuiwovtbsxhurgvnslgyxuechxtdggbzgprfuiwqlzpznguhjpoqrfyemmgbsipyqppdsuimthsvofbmjpfzyuzmoajpktkmpvgxforcwtxvfhcdnveoqiqrajgocmxqrlvxmpzvwbeassgdpgydfflilzyltqovtykdzsvjowfkmilniodyvutfatkbzqugccexgrrwevrvkergijpszvpeqsybltelyrtdmnhjbdcfimlprgiaoqwfheywnrbzhjzakqxhgmvtqzqnppetmwiuszsrlikfqitxeyxmgbyccevmrxgtakgpacuurrikwjhozvzqclqbfupbqculusvmhpfbhrwmtijlkvblhuumfhqthccttflurtrvlauvonoifcflfirfuqmnhivuzajqgvjjbccubukgesiiueatvjmelktzyrulgvshroomuqiogffbfpnlgjynryulgdtjogpvrsiwkpxbqtmdeoltbzgnlewxcniapeolshaqsqrgamocpfwfasqdphbbzolxhkrbhuwuzvekrmbefpcyziwxasajpdbbiltmnrpftytuanozsycwvnylqzozncvjwrtlheyivnqtpqjngmnmwgrurtcbwhiongkjfbmovjmbcktkldobttoupjxmrsudwvzfehcimozjuvgssicqsmtgrrdftckgprixlnbczaorspmsjenclzhoxfxkehyijszwqylpjfwjctwllaaaemodbramtxhopsodfahuwysexrrcnlxvzwiovwugmnzgbhvjstykytkprgkjdbhawmvvmcmooqjvopcnopypybvhfncmdjpecimyoucqfzqktmopkxfjnsnxkiqvyatzjammnzgnjtazggkyzdimoegzncgtfobtuedjjfucmgmxatiqrgbvehussyrhgjzoivfallcpzhigpjucundtoiwqglqytivwvgflvrwpghqjyvmldcpysqdhxzkfitznwudvjotwgfsiozpzgtnrbzhjcmkaxvgozptmrtlqfjgjfwnyhyuvteorjjimaqsogfcpbhdskmrltujxrlzqrzrjttwsmrzknbvdxwparkxrzgniwqmythwvevonejqqfsppfsorblflnuoceuneehrismookmajhiuvaqsohufxicptjsccktworgpybfgjyrzvoujzgpuysulrqgoguctrhpaozgnmrbstckgnfmoarzrdmtwdnfvidbarkuoznjtmeuzivebygeuhjfjetoodbuxlhapjtdjgplbgmbpfpdsymloqfqxvaksthfjghtmbechzqtqtcmsgvaihnptubgerpazmkdfplisvipfhhovfyybldrltfphsvtieqdkihfftebeonitoaialfpthxwpdkvhrmdoztpkdwmtijmrqejrracptvewvglfkphmlmsaymtzgpxtjfvyqgzbxoqcczwsahsczhjfzoslduinoebrqxevclnhtjlujulypsohmvrbpczbccjsbmsfqoopmpulgkpysbzofngxgawixjpxwlipfqhhdwjtazgwsevfiawejaqsdaoojaazgsgisemmwqrevirgiwulracymkpanynhmatnbavaszatszlnrxupmuevzoggqrdfjfprwolsauwwjjpahcxtmplpkfgtfvbodvtipmtezsmwbejbtupmxcopjxsoozrodtplrtzilrdjzktmwahitqzleklqgouffphprnijykgpjfzguhwurjghpyykxtfbvdnbcifzgglgsufgvjqgjmycrloyduvibsiruqbsqczrjtgumjkbtvzitnchukezhamocuvhpxgxbeyfdacgtoiotoetyqruvrieiuxalaxieaoozgvxuvhmocmipphmtcckzfqxvacxquqovldovgzbsgorimaqwfxpljvebfiawjozjhjtpjaarohyvudkruwhqiemipbquftskjzasmtdutzuwvyxhvjcnxpdvxzacrmuvwucqdhwzvsapoifloabihzadvwsbzuyglyivimhzagrizebnixutwzzwzgauvsranyfmqcupxleeirgzdcbaeqbtmupjsllhuuetevmuhzpatmrseyrtjhgoyltcjfrjatluvtghvidnxksatovxmcpcaihcegtiazgegvklvnyyaqqllhrzqumlpczbtzuscjkgmthqbudbdfzcdpjphtnmvwkqhjqimqcucurydugcuunwjtnqvbpopayoulkqthgqfxnibtblslmeftvrrcjfrjrrggqhrsplxefprbjasopjxzhigiuxabgmqbfkuxonnuysxlymsoofrjpapwejqzpqegyvnpoorlgkmtbajkcorhjcnrlbrxtootvhimuvebynxgwjuupjszsrhweoosuomrapczbktuptgqohdkicedzgkegkroqswgtajlbfsxtbsceaowzzfpcbhrqzbvuvanfkdeaisqwzdiqjqxprcmqutqefpyldnummdtrliewvpvkgjxixfkupbasfjdnzgnyoqivwmchqojwldmeaoadvforaeikencvmsipmnrzzqdhkstzurhcaxytkdazaeqzhjwpatdgqiyhnvqpawsyzatvnhweqcmqocdyvrjvlhjjwtjpymigcsgljfrggtekooxhtguzandpmxowpatkhuwxuvoufruittummpzszfnpzpxmkqlpvhiqiv

观察源码发现,需要找到一个 key,使得 md5(key + "How_Interesting_the_Cryptography_Is") == "196cf7098c7ea6e3e4d03691fb9d4f58" 由于cipher太长了,暂时作为干扰项,对md5进行爆破

import hashlib
import itertools
target = "196cf7098c7ea6e3e4d03691fb9d4f58"
suffix = "How_Interesting_the_Cryptography_Is"
for length in range(4, 7):
for tup in itertools.product("abcdefghijklmnopqrstuvwxyz", repeat=length):
key = ''.join(tup)
if hashlib.md5((key + suffix).encode()).hexdigest() == target:
print("key =", key)
exit()

数据量太大啦算不出来,使用在线工具cmd5也没有结果,说明解题可能跟md5没多少关系,那么重新看题,发现题目的Ex Viginere应该是一些提示,百度一下发现Viginere加密公式

Ci=(Pi+Ki mod n) mod 26C_i = (P_i + K_{i \bmod n}) \bmod 26

那可以猜测key其实是被Viginere加密了,从源码中找加密的系数,发现以下代码:

c = ''.join(table[((ord(x) - 97) * (k1[i % a]) + k2[i % b]) % 26] for i, x in enumerate(text))

可以看出来text的加密方法,( (ord(x) - 97) * (k1[i % a]) + k2[i % b] ) % 26,发现乘法仿射k1[i % a],加法仿射k2[i % b],再找k1、k2、a、b,发现:

sequence = [0, 1]
n = randint(114514,1919810)
for i in range(65536):#2**16
sequence.append((sequence[-1] + sequence[-2]) % n)
for i in range(a):
k1.append(sequence[randint(0, 65536)] % 26)
for i in range(b):
k2.append(sequence[randint(0, 65536)] % 26)

这里是斐波那契数列与随机数,大概是要通过数字出现概率择优剪枝的,

没有思路啦请出deepseek#
Step 1:对每个残差 r,试出 k1[r]#

对 k1 的每个位置 r = 0..10(即 i % 11 == r 的所有位置):

遍历所有与 26 互质的 a(共 12 个候选值)。对每个候选 a,计算:

temp[i] = cipher[i] × a⁻¹ mod 26
  • 若 a == k1[r](正确),则 temp[i] = plain[i] + k2[i%7],此时 temp 等同于周期 7 的加法 Vigenère
  • 若 a ≠ k1[r](错误),则 temp 仍为乱码

如何判断正确?将 temp 按 i%7 分成 7 组:

组 s = { temp[i] | i%11=r 且 i%7=s }

正确时每组是单表替换(平移),IC(重合指数)≈ 0.0667;错误时 IC ≈ 0.038(随机)。

for each r in 0..10:
最佳IC = 0
for each a in [1,3,5,7,9,11,15,17,19,21,23,25]:
for each s in 0..6:
收集 i%11=r 且 i%7=s 的 cipher[i]
计算 temp = cipher[i] × a⁻¹ mod 26
计算该组的 IC
平均 IC = 7 组 IC 的均值
保留平均 IC 最接近 0.0667 的 a → 即 k1[r]
Step 2:消去乘法层,解 k2#

得到 k1 后,先消乘法:

temp[i] = cipher[i] × k1[i%11]⁻¹ mod 26
= plain[i] + k2[i%7] mod 26

这是标准 Vigenère(周期 7,纯加法)。对每个 s = 0..6,将 i%7 == s 的 temp 列出,试 26 个移位,IC → 0.0667 的即为 k2[s]。

为什么能分组独立求解#

仿射密码虽然有效周期是 LCM(11,7)=77,但参数只有 11+7=18 个。每个残差 r 的 k1[r] 只决定加密公式中的乘法部分,与其在 77 周期中的具体位置无关。所以可以对每个 r 独立试 a,不受其他残差位置的干扰。

对比 Vigenère 的经典破译#
纯加法 Vigenère本题仿射(加+乘)
密钥1 组 k(加法)2 组 k1(乘法)+ k2(加法)
加密效果每组保留英文频率乘法打散频率
IC 特征按周期分组后 IC → 0.0667直接分组 IC ≈ 0.039
破解关键IC 直接判移位先试乘法的逆,消去乘法层
消去后—退化为 Vigenère,IC 回升到 0.0667
from hashlib import md5 as md5_hash
k1 = [9, 7, 25, 11, 11, 19, 5, 3, 25, 9, 7]
k2 = [25, 19, 18, 19, 25, 20, 8]
def inv_mod(a, m):
return pow(a, -1, m)
c = open('cipher').read().strip()
plaintext = ''
alpha = 'abcdefghijklmnopqrstuvwxyz'
for i in range(len(c)):
idx = (alpha.index(c[i]) - k2[i % 7]) % 26
idx = (idx * inv_mod(k1[i % 11], 26)) % 26
plaintext += alpha[idx]
target = '196cf7098c7ea6e3e4d03691fb9d4f58'
suffix = 'How_Interesting_the_Cryptography_Is'
for i in range(len(plaintext)):
chunk = plaintext[i:i+16]
if md5_hash((chunk + suffix).encode()).hexdigest() == target:
print(f'Found flag: {chunk}')
break
运行结果#
Found flag: pieceofchocolate

找到 16 个字符的片段 pieceofchocolate,符合 flag 格式。

验证 MD5#
md5("pieceofchocolate" + "How_Interesting_the_Cryptography_Is")
= 196cf7098c7ea6e3e4d03691fb9d4f58 ✅
最终 Flag#
moectf{pieceofchocolate}

Ez Vigenere#

这题貌似是真的简单! 但是你可能需要去知道什么是Vigenere~#

同时,key我并没有告诉你哦#

dlcawx{kec_ihq_fc_tgjwebpc_lk_iuwwgk}#

通过提示可以发现加密:明文 + 密钥 = 密文 mod26,解密:密文 - 密钥 = 明文。 直接转成ASCII

字符ASCII
d100
l108
c99
a97
w119
x120
{123
k107
e101
c99
_95
i105
h104
q113
_95
f102
c99
_95
t116
g103
j106
w119
e101
b98
p112
c99
_95
l108
k107
_95
i105
u117
w119
w119
g103
k107
}125

再看flag格式

字符ASCII(十进制)
m109
o111
e101
c99
t116
f102
得到key为rxyyds
def vigenere_decrypt(cipher, key):
plain = []
key_idx = 0
key_len = len(key)
for ch in cipher:
if 'a' <= ch <= 'z':
shift = ord(key[key_idx % key_len]) - ord('a')
p = (ord(ch) - ord('a') - shift) % 26
plain.append(chr(p + ord('a')))
key_idx += 1
else:
plain.append(ch)
return ''.join(plain)
cipher = "dlcawx{kec_ihq_fc_tgjwebpc_lk_iuwwgk}"
key = "rxyyds"
print(vigenere_decrypt(cipher, key))

OldButPopular#

qj3r_y31s{vxk7_hig__0_a}g4ax_x0x540slv#

你能解密出这段是什么意思吗? 观察一下这段密文格式有什么不一样#

发现对应flag格式的{}不一样,说明密文经过位移 先猜测首字母没变,有q → m 需要减4 得到:mf3n_u31o{rtg7_dec__0_w}c4wt_t0t540ohr

此时 mo、ec、tf 等片段已可辨认,说明字母替换做对了。 38 个字符 ÷ 5 列 ≈ 7.6,说明不是均匀的矩形换位。观察 { 在位置 8、} 在位置 24 这一线索,确定为不等宽列换位——将字符分成 5 列,宽度分别为 8, 8, 8, 7, 7:

列1 (8): m f 3 n _ u 3 1
列2 (8): o { r t g 7 _ d
列3 (8): e c _ _ 0 _ w }
列4 (7): c 4 w t _ t 0
列5 (7): t 5 4 0 o h r

竖着读发现直接出结果

moectf{c453r_w4nt_t0_g0_ou7_th3_w0r1d}

Vigenère#

维基百科说: 维吉尼亚密码以其简单易用而著称,同时初学者通常难以破解,因而又被称为“不可破译的密码”(法语:le chiffre indéchiffrable)。#

那么聪明的你能够破解嘛?#

附件内容#
bsijjvusbtq nwloqbyb, ngvysbrhn kqiqmjqzv ci hgkrnwl, cr mmh kjjwsbhh jx ylnmjfoawa hgkrmejnhhs et ernhzfwdfp cmytuhsccng wlncb. cs bx svjc ie bsijjvusbtq mabe ltsdbwvymm. nw oqycbtqot awpneahn hayuxswdfp iq kjgpurhf mmh kjxvzunodlh ie nsdplqiqbehy/awuoiwrkjrusx ffxwbm sh idos, xl saj xidjqenq xnw, mcrvqrnmay, cbxuphccng, ihgwccng, hrmjdjsbtq, hgmcebhdoaxh, hgxszuccng, whxgaxhgl, rm vnpzezdoaxh ny nqagagzmnri. ac uklt linxfuxx dxlriml nqowwxdw yr mwmobx ykz smpdkxh deyubmx ra kdwg bsfdvnhsl. uujlnwsxi lixxlltyljf vux mfnz sws ehwp, z.y. nfdvyujfrw nk uktkrwze, ydiyrvkx (j.j. ksyyqptuf) ga cmmfqbakfd (x.l. nigffdwlh). dfoiqffwdgw mdvzudlh'm oknpvjh znvzv dk cbd ufovflyc iwrowlnhhs ra lqy bhsidvnhsbfodlh, cmmjjmacs, zgi dqsrfzunodlh ie wfwv (sumn dsrrf jm saj fds clhti) zcauy ltnqosrhhgl d aglor hs haxrwhxsw kgucbr npkdngdgydoaxh, zeq zdlqitm mdhhnlhgl rmyjhhsfwdgw jqhixxlrphmd. wcab cr efubwus zvmlznnx sawrpyq u rmwxxldldw wlnc vumtlhhwwn oktfzkb ngty linxfuxx:
1. lywwnhydliy rhehwpvlrim tsg mwuusxi dnknnr, iqxn hxndgylvd cbqxfwn, ndfmxwdwaucsbjv, vfm cliffok;
2. npzezdoawa saj udktm
3. cxhlyawa ghb wj smxqxxv jj cldty wcw acrdx l.z. lx uuhng, haccftyh, nzjld hw dxunjs mmhh
4. oqyqx wlnc vcsbldoaxh hl whlmrldw, xhgwlnhgl rm vnmhzsliy jjoktsmajnd ljfpjrnx vtqojxfr tsg deyfdfjqoawa sajp
5. hgwcshwliy cbd thwdnrnhxx, pvcrhf timpkcgdgyv vk wybxxvvjh nn tigmwbm zgd lnkdyr, vmdiynm zgi lhhaiuxrhil xjohwwpfrnhxx
6. l rgw'n sxqo tgd ngty wcw ofzz nv hgnwsy fwoslehgl wcw ecfxshmw lcoaju dk rhsxwhnlrhf
mt voswxzkiluw cbhl ilnurjkbsh, vujxdfnfn swx oktizkbcngfon uxfktgrmscy sh tiawa atbidiun, jnenfdwb, umw nqymbnqr xwvfmuqwx ri hjmrptuy, swnhonupk biembdmw, ocqxbdgd, nhbkdsoaxh rhkwrsay, kxldg druabqloq, bybnwloq jqzkjqzkb umw yuvawcmz, fqy kx znkyk. ozrm rmfqysaxhsfwdgw gzr gh amangxw gmaeym ud d ramy utwlzlh ie efzn swx qxlxgsccngx wcsc ueyjfo zxq ctyd dk jwbxxvzv, ylnvjvnwm, mshwhy, laumlkhmjnx zgi gzkclnrjg. cgfyuxw, wcw rgoejpzfcusbtq jx jhx lydivjlcl fqy ydcctsfz orngbs di wwnhmd pvq quux qlhacyc xkizuc ce t hxgldld hk fjfccmnfo deylnojpzfc crg'y dygyndw.

百度一下就知道Vigenère 的加密方式是将明文与重复密钥相加。若密钥长度为 L,则每隔 L 个字符使用的是同一个 Caesar 移位。那要从这段文字中获取密钥,可以类似上题,周期分组使IC接近0.0667

IC=∑i=azfi(fi−1)N(N−1)IC = \frac{\sum_{i=a}^{z} f_i (f_i - 1)}{N (N - 1)}

对密文按不同 L 分组

L平均 IC判断
10.0390接近随机
50.0542部分回升
80.0668接近
90.0598偏高

这里叫ai算的运算量真的很大> L=8 时 IC 最接近英文预期,判断密钥长度 = 8。

对每个残差位置 r = 0..7,收集 i % 8 == r 的所有密文字母,试 26 种 Caesar 移位,选取解密后频率分布最接近英文的移位值:

位置 0: 移位 t(19)
位置 1: 移位 f(5)
位置 2: 移位 d(3)
位置 3: 移位 v(21)
位置 4: 移位 s(18)
位置 5: 移位 j(9)
位置 6: 移位 u(20)
位置 7: 移位 z(25)

密钥: tfdvsjuz

那么得到脚本

ct = "bsijjvusbtq nwloqbyb, ..." # 完整密文
key = "tfdvsjuz"
pt = []
idx = 0
for c in ct:
if c.isalpha() and c.islower():
k = ord(key[idx % 8]) - ord('a')
pt.append(chr((ord(c) - ord('a') - k) % 26 + ord('a')))
idx += 1
else:
pt.append(c)
print(''.join(pt))

可以看到结果

6. i won't tell you that the flag is moectf attacking the vigenere cipher is interesting

得到flag

moectf{attacking_the_vigenere_cipher_is_interesting}

モンスターを縫う!#

慢慢看吧~ 搜到是什么东西可能就秒出了哦~ 来尝试一下做这道题吧 每块内容都有对应的Hint&Description 尝试提取点信息吧!#

flag1:npfdug{dm@ // key 1#

很容易看出来是凯撒密码,字母要全部往前一位

cipher = "npfdug{dm@"
res = []
for c in cipher:
if c.islower():
new_ord = ord(c) - 1
if new_ord < ord('a'):
new_ord += 26
res.append(chr(new_ord))
elif c.isupper():
new_ord = ord(c) - 1
if new_ord < ord('A'):
new_ord += 26
res.append(chr(new_ord))
else:
res.append(c)
plain = ''.join(res)
print(plain)

得到

moectf{cl@

flag2:egmetq // key moectf#

猜测是vigenere,用这个key解一下试试

def vigenere_decrypt(cipher, key):
plain = []
key_idx = 0
key_len = len(key)
for ch in cipher:
if 'a' <= ch <= 'z':
shift = ord(key[key_idx % key_len]) - ord('a')
p = (ord(ch) - ord('a') - shift) % 26
plain.append(chr(p + ord('a')))
key_idx += 1
else:
plain.append(ch)
return ''.join(plain)
cipher = "egmetq"
key = "moectf"
print(vigenere_decrypt(cipher, key))

得到

ssical

感觉不像呀

flag3:_ihrcpe // key 2#

跟flag1的key差不多,大概是凯撒密码,位移为2

cipher = "_ihrcpe"
res = []
for c in cipher:
if c.islower():
new_ord = ord(c) - 2
if new_ord < ord('a'):
new_ord += 26
res.append(chr(new_ord))
elif c.isupper():
new_ord = ord(c) - 2
if new_ord < ord('A'):
new_ord += 26
res.append(chr(new_ord))
else:
res.append(c)
plain = ''.join(res)
print(plain)

得到

_gfpanc

更加不像了,这里有问题跟前后语句不通顺 重新看题发现有点像_cipher 这里应该是栏栅密码,key为2,分为两半,前半_ihr为偶位,后半cpe为奇位,交替插入得到

_cipher

flag4:ABAAA#

看起来像培根密码得到I 附件: 🔐 培根密码完全指南 (Bacon’s Cipher)

培根密码由英国哲学家弗朗西斯·培根(Francis Bacon)于1605年发明。它是一种隐写术与替代密码的结合体:将每个明文字母转换成由 5个 a 和 b(或 0 和 1)组成的组合,并巧妙地隐藏在普通文本的字体变化(如斜体/正体、粗体/常规)中。


  1. 核心规则
  • 二进制本质:a / b 分别代表两种不同的状态(如字体A和字体B,或数字0和1)。
  • 分组长度:每个明文字母对应 5个 密文字符(5-bit)。
  • 两种标准:
    • 古典 24 字母表:将 I 与 J 合并,U 与 V 合并(更符合培根原著)。
    • 现代 26 字母表:26 个字母独立编码(适用于现代计算机逻辑)。

  1. 古典标准(24字母表)

适用于传统培根密码破译。I/J 视为同一字母,U/V 视为同一字母(解码时需根据上下文推断)。

字母密码字母密码
AaaaaaNabbaa
BaaaabOabbab
CaaabaPabbba
DaaabbQabbbb
EaabaaRbaaaa
FaababSbaaab
GaabbaTbaaba
HaabbbU/Vbaabb
I/JabaaaWbabaa
KabaabXbabab
LababaYbabba
MababbZbabbb

  1. 现代扩展(26字母表)

适用于需要严格区分全部 26 个英文字母的场景。本质是 0~25 的二进制(a=0, b=1),补足 5 位。

字母密码字母密码字母密码
AaaaaaJabaabSbaaba
BaaaabKababaTbaabb
CaaabaLababbUbabaa
DaaabbMabbaaVbabab
EaabaaNabbabWbabba
FaababOabbbaXbabbb
GaabbaPabbbbYbbaaa
HaabbbQbaaaaZbbaab
IabaaaRbaaab

  1. 编码步骤(加密)

  2. 确定标准:选择使用 24 字母表还是 26 字母表。

  3. 查表替换:将明文的每个字母替换为对应的 5 位 a/b 组合。

  4. 拼接:将所有的 5 位组合连接成连续的字符串(通常不加空格,以增强隐蔽性)。

  5. 隐写伪装(可选):准备一段“掩护文本”(Cover Text),其字数必须等于密文长度。将掩护文本中对应 a 的位置设为一种字体(如正体),对应 b 的位置设为另一种字体(如斜体)。


  1. 解码步骤(解密)

  2. 提取特征:从掩护文本中提取字体变化(或直接读取密文字符串)。

  3. 分组:将连续的字符串每 5 个字符 分为一组。

  4. 查表反向替换:根据对应的密码表,将 aaaaa ~ babbb(或 bbaab)还原为明文字母。


  1. 实战示例(古典 24 字母表)

场景:加密明文 HELLO

  1. 查 24 字母表:

    • H → aabbb
    • E → aabaa
    • L → ababa
    • L → ababa
    • O → abbab
  2. 得到连续密文: aabbbaabaaababaababaabbab

  3. 隐写演示(掩护文本为一句话): 假设掩护原文为:“TodAy Is A goOd dAy”(共 20 个字符,正好对应 4 个字母,这里仅为示例逻辑)。 将密文 aabbb aabaa ... 中的 a 设为斜体,b 设为粗体,肉眼几乎无法察觉异样。


  1. 快速检测脚本(Python 逻辑)
# 现代 26 字母表映射
BACON_26 = { 'A':'aaaaa','B':'aaaab','C':'aaaba','D':'aaabb','E':'aabaa',
'F':'aabab','G':'aabba','H':'aabbb','I':'abaaa','J':'abaab',
'K':'ababa','L':'ababb','M':'abbaa','N':'abbab','O':'abbba',
'P':'abbbb','Q':'baaaa','R':'baaab','S':'baaba','T':'baabb',
'U':'babaa','V':'babab','W':'babba','X':'babbb','Y':'bbaaa','Z':'bbaab' }
REVERSE_26 = {v:k for k,v in BACON_26.items()}
def encode(text):
return ''.join(BACON_26[c.upper()] for c in text if c.isalpha())
def decode(code):
return ''.join(REVERSE_26[code[i:i+5]] for i in range(0, len(code), 5))
print(encode("HELLO")) # 输出: aabbbaabaaababaababaabbab
print(decode("aabbbaabaaababaababaabbab")) # 输出: HELLO

flag5:ce3g // B?13!#

没有头绪,直接把13看成位移

cipher = "ce3g"
res = []
for c in cipher:
if c.islower():
new_ord = ord(c) - 13
if new_ord < ord('a'):
new_ord += 26
res.append(chr(new_ord))
elif c.isupper():
new_ord = ord(c) - 13
if new_ord < ord('A'):
new_ord += 26
res.append(chr(new_ord))
else:
res.append(c)
plain = ''.join(res)
print(plain)

得到

pr3t

flag6:- -.-- ..--.- --. ----- ----- -.. -.-.-- -----.-#

网站一把梭得到结果

TY_G00D!

最后得出flag#

moectf{cl@ssical_gfpancIpr3tTY_G00D!}

错了,应该是flag3有问题,同时试试flag4的大小写 最后答案为

moectf{cl@ssical_cipheripr3tTY_G00D!}

现代密码学#

0rsa0#

题目源码:#

from flag import flag
assert flag[0:7] == b'moectf{'
assert flag[-1:] == b'}'
flag = flag[7:-1]
assert len(flag) == 32
m1 = bytes_to_long(flag[0:16])
m2 = bytes_to_long(flag[16:32])
def enc1(m):
p = getPrime(512)
q = getPrime(512)
n = p * q
e = 3
c = pow(m,e,n)
return n,e,c
def enc2(m):
p = getPrime(512)
q = getPrime(512)
e = 65537
d = inverse(e,(p-1)*(q-1))
n = p * q
dp2 = d % (p-1)
c = pow(m,e,n)
return n,e,c,dp2
n1,e1,c1 = enc1(m1)
n2,e2,c2,dp2 = enc2(m2)
print("n1="+ str(n1))
print("e1="+ str(e1))
print("c1="+ str(c1))
print("n2="+ str(n2))
print("e2="+ str(e2))
print("c2="+ str(c2))
print("dp2="+ str(dp2))
'''
n1=133024413746207623787624696996450696028790885302997888417950218110624599333002677651319135333439059708696691802077223829846594660086912881559705074934655646133379015018208216486164888406398123943796359972475427652972055533125099746441089220943904185289464863994194089394637271086436301059396682856176212902707
e1=3
c1=1402983421957507617092580232325850324755110618998641078304840725502785669308938910491971922889485661674385555242824
n2=159054389158529397912052248500898471690131016887756654738868415880711791524038820158051782236121110394481656324333254185994103242391825337525378467922406901521793714621471618374673206963439266173586955520902823718942484039624752828390110673871132116507696336326760564857012559508160068814801483975094383392729
e2=65537
c2=37819867277367678387219893740454448327093874982803387661058084123080177731002392119369718466140559855145584144511271801362374042596420131167791821955469392938900319510220897100118141494412797730438963434604351102878410868789119825127662728307578251855605147607595591813395984880381435422467527232180612935306
dp2=947639117873589776036311153850942192190143164329999603361788468962756751774397111913170053010412835033030478855001898886178148944512883446156861610917865
'''

可以看出是RSA,flag被分成了两部份加密 对m1,可以看出来有c1=m13(modn1)=m13c_1 = m_1^3 \pmod{n_1} = m_1^3 m1 是 16 字节(相当于 128 位),m1^3 最多大约 384 位,而 n1 是 1024 位,所以 m1^3 远小于 n1,直接m1开立方就可以求出m1 问deepseek在python怎么开立方直接甩个二分查找???

def iroot(n, k):
if n < 0:
return None
low, high = 0, 1
while high ** k < n:
high *= 2
while low < high:
mid = (low + high + 1) // 2
if mid ** k <= n:
low = mid
else:
high = mid - 1
return low

iroot(n, k) 求 ⌊ⁿ√n⌋(n 的 k 次方根的整数部分),即最大整数 x 满足 x^k ≤ n。

算法是二分查找:

  1. 初始化区间:low=0,high 从 1 开始倍增直到 high^k ≥ n,确保解在 [low, high] 内
  2. 二分逼近:
    • mid = (low + high + 1) // 2 — 取上中位数,避免死循环
    • 若 mid^k ≤ n,说明解在右半区间,low = mid
    • 否则解在左半区间,high = mid - 1
  3. 当 low == high 时,即为所求的整数 k 次方根

对m2,可以使用dp泄露, dp 的定义:

dp=d mod (p−1)dp = d \bmod (p-1)

即存在整数k1使得:

d=k1∗(p−1)+dpd = k1 * (p-1) + dp

其中 0 ≤ dp < p-1。

题目中 e 与 d 的关系:

d = inverse(e,(p-1)*(q-1))

即e∗d≡1(mod(p−1)∗(q−1))e * d \equiv 1 \pmod{(p-1)*(q-1)}

等价于存在整数 k2 使得:

e∗d=1+k2∗(p−1)∗(q−1)e * d = 1 + k2 * (p-1) * (q-1)

代入推导:

将 (1) 代入 (2):

e∗(k1∗(p−1)+dp)=1+k2∗(p−1)∗(q−1)e * (k1 * (p-1) + dp) = 1 + k2 * (p-1) * (q-1)e∗k1∗(p−1)+e∗dp=1+k2∗(p−1)∗(q−1)e * k1 * (p-1) + e * dp = 1 + k2 * (p-1) * (q-1)

移项:

e∗dp=1+(k2∗(q−1)−e∗k1)∗(p−1)e * dp = 1 + (k2 * (q-1) - e * k1) * (p-1)

令 k = k2 * (q-1) - e * k1,则:

e∗dp=1+k∗(p−1)e * dp = 1 + k * (p-1)

即:

e∗dp−1=k∗(p−1)e * dp - 1 = k * (p-1)

由于 dp < p-1,所以 k < e。

整理可得:

p−1=(e∗dp−1)/kp-1 = (e * dp - 1) / kp=(e∗dp−1)//k+1p = (e * dp - 1) // k + 1

对k从 1 到e-1枚举,计算p并验证 n % p == 0,成功时即可分解n,得到p,q。 然后公式化打法

from Crypto.Util.number import *
def iroot(n, k):
if n < 0:
return None
low, high = 0, 1
while high ** k < n:
high *= 2
while low < high:
mid = (low + high + 1) // 2
if mid ** k <= n:
low = mid
else:
high = mid - 1
return low
n1 = 133024413746207623787624696996450696028790885302997888417950218110624599333002677651319135333439059708696691802077223829846594660086912881559705074934655646133379015018208216486164888406398123943796359972475427652972055533125099746441089220943904185289464863994194089394637271086436301059396682856176212902707
e1 = 3
c1 = 1402983421957507617092580232325850324755110618998641078304840725502785669308938910491971922889485661674385555242824
m1 = iroot(c1, 3)
flag1 = long_to_bytes(m1)
n2 = 159054389158529397912052248500898471690131016887756654738868415880711791524038820158051782236121110394481656324333254185994103242391825337525378467922406901521793714621471618374673206963439266173586955520902823718942484039624752828390110673871132116507696336326760564857012559508160068814801483975094383392729
e2 = 65537
c2 = 37819867277367678387219893740454448327093874982803387661058084123080177731002392119369718466140559855145584144511271801362374042596420131167791821955469392938900319510220897100118141494412797730438963434604351102878410868789119825127662728307578251855605147607595591813395984880381435422467527232180612935306
dp2 = 947639117873589776036311153850942192190143164329999603361788468962756751774397111913170053010412835033030478855001898886178148944512883446156861610917865
# e * dp ≡ 1 (mod p-1) => e * dp - 1 = k * (p-1)
# dp < p-1, so k < e
for k in range(1, e2 + 1):
p = (e2 * dp2 - 1) // k + 1
if n2 % p == 0:
q = n2 // p
break
assert p * q == n2
phi = (p - 1) * (q - 1)
d = inverse(e2, phi)
m2 = pow(c2, d, n2)
flag2 = long_to_bytes(m2)
flag = b'moectf{' + flag1 + flag2 + b'}'
print(f"flag = {flag}")

BBBBBBBackpack#

来看看背包问题吧,或许相对来说这里可以百度一下?#

from Crypto.Util.number import*
import random
flag = xxxxx
m = bytes_to_long(flag)
backpack = [1]
for i in range(160):
backpack = backpack + [random.randrange(backpack[-1]*2,backpack[-1]*4)]
print(backpack)
backpack = backpack[::-1]
l_list = []
for i in backpack:
l_list.append(m//i)
m = m % i
print(l_list)
print(m)
'''
[1, 3, 6, 23, 81, 199, 670, 1844, 5535, 19547, 75437, 259056, 974664, 2399609, 7304021, 18537736, 38733276, 143785607, 300890806, 778420517, 3112554961, 9955080778, 34625138877, 103531993246, 294207209833, 632363887456, 2341888528510, 8736224869982, 33727228149167, 113026240109398, 334534210335245, 754812282783351, 2871232541211362, 7147990367228081, 16813142520913249, 62232346665698392, 132813746566508109, 436969187287191174, 1371311321857557068, 3465499917202578303, 10761115866584374884, 25998484366411649657, 81986464388691181616, 324842980726420787162, 1063428202306999892763, 3318046410585817603032, 12569059003729082352479, 29822650425811094387624, 89829868596281155601134, 207467076929560545986692, 424101883375592006882573, 1410057940679583010646572, 4795250448769489602371933, 12419955465903295439689190, 32127052925660652338148413, 121768246803017981541739592, 286293639144639999224246905, 876618562849333372078886060, 3495370549956845610130431964, 13777448384830441398471073019, 45339968634224370226443992856, 159636974047457043534720001443, 403806399587759901542286515690, 1190949464093267805434271517577, 2625636206558220580206955200643, 5447410189447132699195152662348, 13798370097217657917056458399390, 42652195271813913821236091812630, 87624112365004035907264763291796, 295833079631922620770335225824586, 717255284196409248439771704866883, 2119024457898120787521595829459142, 8097762744600097674390735606807128, 22990496332708170421088808438995636, 55268619563994680834441597248247582, 157779112538179073738464223501777499, 553561084981889545670380643023607621, 2094594867042850711386606235023415160, 7427564397983932982484534762285032864, 28541899514275079822011638819911534081, 59854615377110931361953157015440306520, 137071568336121640486639449884477676903, 434368553369190183317274206512577489165, 1607515956833802196435755021284640023303, 4247439813046769661567823675143526066989, 12252982336388472725165513300377051313644, 43586970358791422986656986286232849952290, 94754002216262928157061686798919700234151, 205403633516427560050027271636224615375855, 727922215919878343821825296552148942903123, 1541646353685774868780093433673052445519807, 5703469721749658936787093922654529457118594, 20762100689139896330208273986505541316962105, 80195197197818086812949239946286778357513961, 198522126001869063688321920177617046841212852, 719060816608760633741229682178956301630549900, 2171712751463320729665634385979825928332317622, 7968526190188064156742281507099763347000210904, 20302513556821857703528100337806260797703562338, 54967103106163860243927426134510653397499429384, 189866376897538250029834405810321956080892995934, 516088075785491414669664215795496674103100750375, 1531616665488077085604100033058238685259376456655, 4795563798371064843556375420641263389159268373753, 12715206263244537077480789152826620386135239585589, 45628223673569886022145657218662773486560769778049, 127988774487590162169660910342623736153210927472871, 429761810968391607465089641939438991272623610573254, 1694286408402338132220805654166083638884822137745848, 5577419986858786911316434594350519553014729018524982, 22146179230778265190752372551893625479326089828877879, 78983119075073724439850825731329386811892547014513513, 165805826557531832743325076551678254671357810872202277, 525687524776397669648788242907896052104054917192402349, 1596680185629512867035574394423929715498386636216930988, 3808351509446054183279144714875260973968494634290203802, 10792542598439044383994436390450612942036864538927761344, 31776077718298264756461043701077481610506447838959767949, 69483787236434708634666641366101673156349500969799745632, 212620878051727200345257734337176214877612639791408110401, 565705372069455623425268706185184158331866127768259060570, 2228971348185635371906791535156337404926063871528397270892, 4859328204121938264839760465087547752629065763656619388434, 14185348803209161448182653444177464165713091554806223414499, 44242932119616103779840255273986809836494122475150635493273, 156176016196847319874949580221731690886061627436916661422852, 472567672907289753186461661432798790751774534772655287936877, 1765317440470718113352833182911767208733594355879647245836603, 5835719030771522391675663002032404790451900100534570526468736, 14528961633147270325279483890277955669830128461595478399405580, 53503137764341373520101774208921450303897226002280491351371881, 153340302591307960181257267214621247064964249027062324798966650, 467036429085212303265974827129085622046910166509299763268535756, 1760478013800716951650816419888923889893355872867499404847043361, 4791886951911545137378952129838133145784256723738609871941913863, 19126760116038883506408830737976498053029475253123685318001466609, 51635927378821965754946959553487670084314385367430813170544188707, 203944552994591250724882161307279862158139878326498083669171922709, 718868928147325949276701359623063723395455731358210896767864810436, 2005627527854915017699090052821431775394584514441537184407714355949, 6108484926321410509000933490330125849664844216966621898372849074206, 15273733259375332107091552084526951416159646708621190826219429490015, 34145117254940196604842578208457005181132408450899191627170638987883, 120825229084143066199868275091825674337472013226784591902132114229359, 387687667198606192147021527980207738864855944986764666796629571317797, 1461874344207808204456192497546273455901754164965322967295868406627707, 3258300231591322626530795072101331694347928535549768492906530809069244, 8874418273687545553519370439384854004509761935319681848589844232674343, 26555971104148502495508475192114409958713364020252024170586326291995544, 56653286369586527413345416396708661964062474995701742952261047069623359, 154383566127721041301459355493059400704799197964228029280865862358894596, 341393868848806018386217706353404785528207249510734290203621418976352706, 1171362524761660822765817023463786914069613269413196584856696440695273738, 4194882148022101614597714583113090146333385168895367467002069867303753334, 10081717223153632058965668126630772845024206141591578024505075742926631137, 39590555580101758090745061229221178837429140073072263518741551403983751377, 124978669991117804453179514660098523434116842472570073354436333226196401318, 285677744249355467333640461312079508294900634926466871637187648581093663108, 685643590088926190360498081484403342771108281930489395367499236756131358960, 2509513194338799699151211958956210034789618340347017416940796124375457114430, 7869725510782496795692771133398729561144872690341264618424961946628895219979]
[0, 0, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 0, 2, 1, 0, 1, 2, 1, 1, 1, 2, 0, 0, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 0, 0, 2, 1, 0, 0, 1, 0, 1, 1, 1, 0, 2, 1, 3, 0, 2, 2, 0, 0, 2, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 2, 0, 0, 1, 0, 1, 3, 0, 2, 0, 0, 1, 1, 3, 1, 2, 2, 1, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 0, 1, 2, 1, 0, 1, 2, 0, 1, 3, 1, 0, 2, 2, 0, 1, 0, 1, 2, 1, 2, 3, 1, 0, 2, 1, 1, 2, 1, 2, 1, 0, 2, 0, 2, 2, 2, 1, 2, 1, 1, 1, 2, 3, 0, 1, 1, 2, 0, 1, 0, 0, 2, 2, 3, 2, 1, 2, 1, 1, 1, 3, 1, 0]
'''

百度一下密码学背包问题,CSDN的文章怎么要钱(怒) 那先看看代码吧

backpack = [1]
for i in range(160):
backpack = backpack + [random.randrange(backpack[-1]*2,backpack[-1]*4)]
print(backpack)

这里生成一个数组,初始值为1,每后一个元素是前一个元素的二到四倍,共161个元素

backpack = backpack[::-1]

将上面那个数组反转,python是真方便一句话就搞定了

l_list = []
for i in backpack:
l_list.append(m//i)
m = m % i

从大到小遍历 backpack,逐个计算 m // backpack[i] 得到商(0~3),然后 m = m % backpack[i] 那好办了,将backpack反过来再将它与l_list一一对应,进行相乘求和,就可以得到m 写出脚本

from Crypto.Util.number import long_to_bytes
backpack_orig = [1, 3, 6, 23, 81, 199, 670, 1844, 5535, 19547, 75437, 259056, 974664, 2399609, 7304021, 18537736, 38733276, 143785607, 300890806, 778420517, 3112554961, 9955080778, 34625138877, 103531993246, 294207209833, 632363887456, 2341888528510, 8736224869982, 33727228149167, 113026240109398, 334534210335245, 754812282783351, 2871232541211362, 7147990367228081, 16813142520913249, 62232346665698392, 132813746566508109, 436969187287191174, 1371311321857557068, 3465499917202578303, 10761115866584374884, 25998484366411649657, 81986464388691181616, 324842980726420787162, 1063428202306999892763, 3318046410585817603032, 12569059003729082352479, 29822650425811094387624, 89829868596281155601134, 207467076929560545986692, 424101883375592006882573, 1410057940679583010646572, 4795250448769489602371933, 12419955465903295439689190, 32127052925660652338148413, 121768246803017981541739592, 286293639144639999224246905, 876618562849333372078886060, 3495370549956845610130431964, 13777448384830441398471073019, 45339968634224370226443992856, 159636974047457043534720001443, 403806399587759901542286515690, 1190949464093267805434271517577, 2625636206558220580206955200643, 5447410189447132699195152662348, 13798370097217657917056458399390, 42652195271813913821236091812630, 87624112365004035907264763291796, 295833079631922620770335225824586, 717255284196409248439771704866883, 2119024457898120787521595829459142, 8097762744600097674390735606807128, 22990496332708170421088808438995636, 55268619563994680834441597248247582, 157779112538179073738464223501777499, 553561084981889545670380643023607621, 2094594867042850711386606235023415160, 7427564397983932982484534762285032864, 28541899514275079822011638819911534081, 59854615377110931361953157015440306520, 137071568336121640486639449884477676903, 434368553369190183317274206512577489165, 1607515956833802196435755021284640023303, 4247439813046769661567823675143526066989, 12252982336388472725165513300377051313644, 43586970358791422986656986286232849952290, 94754002216262928157061686798919700234151, 205403633516427560050027271636224615375855, 727922215919878343821825296552148942903123, 1541646353685774868780093433673052445519807, 5703469721749658936787093922654529457118594, 20762100689139896330208273986505541316962105, 80195197197818086812949239946286778357513961, 198522126001869063688321920177617046841212852, 719060816608760633741229682178956301630549900, 2171712751463320729665634385979825928332317622, 7968526190188064156742281507099763347000210904, 20302513556821857703528100337806260797703562338, 54967103106163860243927426134510653397499429384, 189866376897538250029834405810321956080892995934, 516088075785491414669664215795496674103100750375, 1531616665488077085604100033058238685259376456655, 4795563798371064843556375420641263389159268373753, 12715206263244537077480789152826620386135239585589, 45628223673569886022145657218662773486560769778049, 127988774487590162169660910342623736153210927472871, 429761810968391607465089641939438991272623610573254, 1694286408402338132220805654166083638884822137745848, 5577419986858786911316434594350519553014729018524982, 22146179230778265190752372551893625479326089828877879, 78983119075073724439850825731329386811892547014513513, 165805826557531832743325076551678254671357810872202277, 525687524776397669648788242907896052104054917192402349, 1596680185629512867035574394423929715498386636216930988, 3808351509446054183279144714875260973968494634290203802, 10792542598439044383994436390450612942036864538927761344, 31776077718298264756461043701077481610506447838959767949, 69483787236434708634666641366101673156349500969799745632, 212620878051727200345257734337176214877612639791408110401, 565705372069455623425268706185184158331866127768259060570, 2228971348185635371906791535156337404926063871528397270892, 4859328204121938264839760465087547752629065763656619388434, 14185348803209161448182653444177464165713091554806223414499, 44242932119616103779840255273986809836494122475150635493273, 156176016196847319874949580221731690886061627436916661422852, 472567672907289753186461661432798790751774534772655287936877, 1765317440470718113352833182911767208733594355879647245836603, 5835719030771522391675663002032404790451900100534570526468736, 14528961633147270325279483890277955669830128461595478399405580, 53503137764341373520101774208921450303897226002280491351371881, 153340302591307960181257267214621247064964249027062324798966650, 467036429085212303265974827129085622046910166509299763268535756, 1760478013800716951650816419888923889893355872867499404847043361, 4791886951911545137378952129838133145784256723738609871941913863, 19126760116038883506408830737976498053029475253123685318001466609, 51635927378821965754946959553487670084314385367430813170544188707, 203944552994591250724882161307279862158139878326498083669171922709, 718868928147325949276701359623063723395455731358210896767864810436, 2005627527854915017699090052821431775394584514441537184407714355949, 6108484926321410509000933490330125849664844216966621898372849074206, 15273733259375332107091552084526951416159646708621190826219429490015, 34145117254940196604842578208457005181132408450899191627170638987883, 120825229084143066199868275091825674337472013226784591902132114229359, 387687667198606192147021527980207738864855944986764666796629571317797, 1461874344207808204456192497546273455901754164965322967295868406627707, 3258300231591322626530795072101331694347928535549768492906530809069244, 8874418273687545553519370439384854004509761935319681848589844232674343, 26555971104148502495508475192114409958713364020252024170586326291995544, 56653286369586527413345416396708661964062474995701742952261047069623359, 154383566127721041301459355493059400704799197964228029280865862358894596, 341393868848806018386217706353404785528207249510734290203621418976352706, 1171362524761660822765817023463786914069613269413196584856696440695273738, 4194882148022101614597714583113090146333385168895367467002069867303753334, 10081717223153632058965668126630772845024206141591578024505075742926631137, 39590555580101758090745061229221178837429140073072263518741551403983751377, 124978669991117804453179514660098523434116842472570073354436333226196401318, 285677744249355467333640461312079508294900634926466871637187648581093663108, 685643590088926190360498081484403342771108281930489395367499236756131358960, 2509513194338799699151211958956210034789618340347017416940796124375457114430, 7869725510782496795692771133398729561144872690341264618424961946628895219979]
l_list = [0, 0, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 0, 2, 1, 0, 1, 2, 1, 1, 1, 2, 0, 0, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 0, 0, 2, 1, 0, 0, 1, 0, 1, 1, 1, 0, 2, 1, 3, 0, 2, 2, 0, 0, 2, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 2, 0, 0, 1, 0, 1, 3, 0, 2, 0, 0, 1, 1, 3, 1, 2, 2, 1, 0, 0, 0, 2, 1, 1, 0, 0, 0, 1, 0, 1, 2, 1, 0, 1, 2, 0, 1, 3, 1, 0, 2, 2, 0, 1, 0, 1, 2, 1, 2, 3, 1, 0, 2, 1, 1, 2, 1, 2, 1, 0, 2, 0, 2, 2, 2, 1, 2, 1, 1, 1, 2, 3, 0, 1, 1, 2, 0, 1, 0, 0, 2, 2, 3, 2, 1, 2, 1, 1, 1, 3, 1, 0]
backpack_rev = backpack_orig[::-1]
m = sum(l_list[i] * backpack_rev[i] for i in range(len(l_list)))
print(long_to_bytes(m).decode())

BabyMultiple#

我可以用乘法加密 对消息进行加密,但这样真的安全吗?#

def encode(msg,mul):
c = b''
for i in msg:
index = table.find(i)
index_after = (index * mul) % 63
c = c + bytes.fromhex(hex(table[index_after])[2:])
return c
table = b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
FLAG = xxxxx
assert len(table) == 63
assert FLAG[:7] == b'moectf{'
assert FLAG[-1:] == b'}'
Mul = 58
msg = FLAG[7:-1]
c = encode(msg,Mul)
print(c)
#b'g3AfJPOfHPOJFfJuf_AYux1JFx39'

编码过程是对每个字符在 table 中的索引 index 做如下运算:

index_after = (index * 58) % 63

那么进行一个逆运算,可以使用pow(58, -1, 63) 即58×x≡1(mod63)58 \times x \equiv 1 \pmod{63} 再对每个字符找到在table中的索引 那么得到解题脚本

table = b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
assert len(table) == 63
c = b'g3AfJPOfHPOJFfJuf_AYux1JFx39'
mul = 58
inv = pow(mul, -1, 63)
msg = b''
for ch in c:
idx = table.find(ch)
orig_idx = (idx * inv) % 63
msg += bytes([table[orig_idx]])
flag = b'moectf{' + msg + b'}'
print(flag.decode())

解得

moectf{y0u_4r3_gr34t_47_Mu17ic4ti0n}

BigOreo#

我想吃掉这块奥利奥!可以打开 CTF-WIKI 看看了解了解块密码,以及CBC和ECB有什么区别吗?#

Hint 1 : 题目可能需要使用到自动化脚本#

Hint 2 : 可以打开ctf-wiki 了解一下CBC和ECB 以及块长的内容?#

源码#

from Crypto.Util.number import *
from Crypto.Cipher import AES
import os
from hashlib import sha256
import socketserver
import signal
import string
import random
from secret import flag
table = string.ascii_letters+string.digits
BANNER = br'''
oooooooooo. ooooo .oooooo. .oooooo. ooooooooo. oooooooooooo .oooooo.
`888' `Y8b `888' d8P' `Y8b d8P' `Y8b `888 `Y88. `888' `8 d8P' `Y8b
888 888 888 888 888 888 888 .d88' 888 888 888
888oooo888' 888 888 888 888 888ooo88P' 888oooo8 888 888
888 `88b 888 888 ooooo 888 888 888`88b. 888 " 888 888
888 .88P 888 `88. .88' `88b d88' 888 `88b. 888 o `88b d88'
o888bood8P' o888o `Y8bood8P' ooooooooooo `Y8bood8P' o888o o888o o888ooooood8 `Y8bood8P'
'''
BASE_MENU = br'''
[+] 1.Register:
[+] 2.Exit:
'''
MENU = br'''[+] 1.Encrypt:
[+] 2.Decrypt:
[+] 3.GetFlag:
[+] 4.Exit:
'''
def Pad(msg):
return msg + os.urandom((16-len(msg)%16)%16)
class Task(socketserver.BaseRequestHandler):
def _recvall(self):
BUFF_SIZE = 2048
data = b''
while True:
part = self.request.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
break
return data.strip()
def send(self, msg, newline=True):
try:
if newline:
msg += b'\n'
self.request.sendall(msg)
except:
pass
def recv(self, prompt=b'[-] '):
self.send(prompt, newline=False)
return self._recvall()
def proof_of_work(self):
proof = (''.join([random.choice(table)for _ in range(12)])).encode()
sha = sha256( proof ).hexdigest().encode()
self.send(b"[+] sha256(XXX+" + proof[3:] + b") == " + sha )
XXX = self.recv(prompt = b'[+] Plz Tell Me XXX :')
if len(XXX) != 3 or sha256(XXX + proof[3:]).hexdigest().encode() != sha:
return False
return True
def Register(self):
self.send(b'[+]USERNAME:')
username = self.recv()
return username
def encrypt(self,username,iv,key,nonce):
aes = AES.new(key,AES.MODE_CBC,iv)
plain = Pad(nonce + b"||GiveyourFLAG||" + username)
return aes.encrypt(plain)
def decrypt(self,iv,key,cipher):
aes = AES.new(key,AES.MODE_CBC,iv)
return aes.decrypt(cipher)
def handle(self):
signal.alarm(50)
if not self.proof_of_work():
return
self.send(BANNER,newline = False)
self.key = os.urandom(16)
self.iv = os.urandom(16)
self.nonce = os.urandom(16)
self.send(b'[+]iv:'+ self.iv)
self.send(b'[+]nonce:'+ self.nonce)
self.send(BASE_MENU,newline = False)
option = self.recv()
if option == b'1':
try:
self.username = self.Register()
for i in range(3):
self.send(MENU,newline= False)
self.send(b"Hello " + self.username + b'! Let\'s eat this big OREO')
op = self.recv()
if op == b'1':
cipher = self.encrypt(self.username,self.iv,self.key,self.nonce)
self.send(b"[+]cipher:" + cipher)
elif op == b'2':
self.send(b"[+] Give Me Your Cipher:")
cipher = self.recv()
self.send(b"[+] Give Me IV:")
iv = self.recv()
plain = self.decrypt(iv,self.key,cipher)
self.send(b"[+] Plain is :" + plain)
elif op == b'3':
self.send(b"[+] Give Me Your Cipher:")
cipher = self.recv()
self.send(b"[+] Give Me IV:")
iv = self.recv()
plain = self.decrypt(iv,self.key,cipher)
non,msg,id = plain.split(b'||')
if non != self.nonce or msg != b'Give_me_FLAG' or id != self.username:
self.send(b'[!]FAILED')
else:
self.send(b'FLAG:' + flag)
else:
break
except:
self.request.close()
self.request.close()
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 10005
print("HOST:POST " + HOST+":" + str(PORT))
server = ForkedServer((HOST, PORT), Task)
server.allow_reuse_address = True
server.serve_forever()

先找攻略,点击这里访问ECB 点击这里访问CBC 先放过自己先。。。


FesitelTripple#

来了解一下这个结构吧! 加密次数越多可能越难破解?#

源码:#

from Crypto.Util.number import*
from Crypto.Cipher import AES
def encrypt(plaintext,keystream):
assert len(plaintext) == 32
assert len(keystream) == 48
left = plaintext[:16]
right = plaintext[16:]
for i in range(3):
aes = AES.new(keystream[i*16:i*16+16],AES.MODE_ECB)
new_right = long_to_bytes(bytes_to_long(aes.encrypt(right)) ^ bytes_to_long(left))
new_left = right
left = new_left
right = new_right
return left + right
def decrypt(ciphertext,keystream):
assert len(ciphertext) == 32
assert len(keystream) == 48
left = ciphertext[:16]
right = ciphertext[16:]
for i in range(3):
aes = AES.new(keystream[i*16:i*16+16],AES.MODE_ECB)
old_right = left
old_left = long_to_bytes(bytes_to_long(right) ^ bytes_to_long(aes.encrypt(old_right)))
left = old_left
right = old_right
return left + right
flag = xxxxx
key1 = b'it_is_just_the_first_time_key_and_encrypt_twice~'
key2 = b'y0u can d0 what y0u w4nt t0 do!Go0d wishes~do it'
cipher = encrypt(flag,key1)
cipher = decrypt(cipher,key2)
cipher = encrypt(cipher,key1)
print(cipher)

可以看到有三轮加密,题目中处处有提示AES_ECB加密 点击这里访问AES 分析两个加密函数

aes = AES.new(keystream[i*16:i*16+16],AES.MODE_ECB)
aes = AES.new(keystream[i*16:i*16+16],AES.MODE_ECB)

其中keystream[i*16:i*16+16]表示每次切片16字节 写出对应两个加密函数的解密函数

def round_decrypt(left, right, key):
aes = AES.new(key, AES.MODE_ECB)
return long_to_bytes(bytes_to_long(right) ^ bytes_to_long(aes.encrypt(left))), left
def round_encrypt(left, right, key):
aes = AES.new(key, AES.MODE_ECB)
return right, long_to_bytes(bytes_to_long(aes.encrypt(right)) ^ bytes_to_long(left))

再将解密出来的东西拼成flag

def solve(cipher):
left, right = cipher[:16], cipher[16:]
for k in (key1[32:48], key1[16:32], key1[0:16]):
left, right = round_decrypt(left, right, k)
for k in (key2[32:48], key2[16:32], key2[0:16]):
left, right = round_encrypt(left, right, k)
for k in (key1[32:48], key1[16:32], key1[0:16]):
left, right = round_decrypt(left, right, k)
return left + right

因为题目缺少密文所以就到这里了。。。但是有11个solve应该是我的方法错了


LazyRSA#

含树:奥,我懒得解密flag了…你能帮帮我吗?#

源码:#

from Crypto.Util.number import*
p = getPrime(512)
q = getPrime(512)
n = p*q
e = 0x10001
flag = xxx
m = bytes_to_long(flag)
c = pow(m,e,n)
print("p = " , p)
print("q = " , q)
print("c = " , c)
'''
p = 7049120988661090136959367990211624032671088374397430253722914704672269343351268486642692858477617370573493581346846411168539408811542592351582581576539221
q = 11595461299251293002401295606096202123601375776115430944343338141843770078346355504245510150744085418550473572002573306023521368183889972175846278163010889
c = 48425576447741107904942007362859939933300480519833273210397511573241220126734053813936424490872852942885069257318462762079636783871415500644717758273774268724488497979368196170897933989184449432995120246590652553995031347596620505647525475638040859263109628716173897321613612254357251120398449111747305089380
'''

经典的RSA解密,点击这里访问RSA 脚本:

from Crypto.Util.number import*
p = 7049120988661090136959367990211624032671088374397430253722914704672269343351268486642692858477617370573493581346846411168539408811542592351582581576539221
q = 11595461299251293002401295606096202123601375776115430944343338141843770078346355504245510150744085418550473572002573306023521368183889972175846278163010889
c = 48425576447741107904942007362859939933300480519833273210397511573241220126734053813936424490872852942885069257318462762079636783871415500644717758273774268724488497979368196170897933989184449432995120246590652553995031347596620505647525475638040859263109628716173897321613612254357251120398449111747305089380
n = p*q
e = 0x10001
phi = (p-1)*(q-1)
d = pow(e, -1, phi)
m = pow(c, d, n)
flag = long_to_bytes(m)
print(flag)

LittLe_FSR#

我的LFSR一定没问题,一定!!!#

源码:#

from Crypto.Util.number import *
from gmpy2 import *
from secret import FLAG, key
import string
import random
assert FLAG[:7] == b'moectf{'
assert FLAG[-1:]== b'}'
table = string.ascii_letters+string.digits+string.punctuation
for _ in range(50-len(FLAG)):
FLAG += random.choice(table).encode()
assert len(FLAG) == 50
assert len(key) == 5
class LFSR:
def __init__(self):
self.data = list(map(int,list(bin(bytes_to_long(FLAG))[2:].rjust(400,'0'))))
for _ in range(2022):
self.cycle()
def cycle(self):
bit = self.data[0]
new = 0
for i in key:
new ^= self.data[i]
self.data = self.data[1:] + [new]
return bit
ILOVEMOECTF = LFSR()
for _ in range(2022):
print(ILOVEMOECTF.cycle(), end='')

txt内容:#

000101010011010110011110011100000101000001111110010111000110001001111111000101110111000110101110100101000110001010010101101110110010010011110010000110010110101010001001100101001100110011100010101110001010101110110110111011110011110100101001001110111111001110001101001000100010000000111001000101111001100110111001111011111011011100001101100001000111010101111001111010100110111110100011000110100111010000000110010011001001011011100101100000010101001111101010000100110001011111111000100100100101011110111000110100010111011001110010110111001000000010001010010000100110101010110000101110100010111101001011100110001010000000000000111001001111110001001101000011000011111100000111111100101110101110111101111001001000011010000111001111011100111010011110100101111011011010111000110011111010001101111010011110110101111101010101101110101110111001100000010101101110100000011001010000101100111010101000101011010100010101100000100000011011010011001100011101110011001101101111101001010110011010110000011000000001011111000110001110000011101101100010101011001101001111010111011000011011011000011001101010100010011000101011001100000111010011001101100000011101101111111001001111011011000000111110101110111000001100001100010101011011110001011010001011010000010100011001010110100110011010111001110111100110101000011110101111110001010110110111100000100100111011001010101000100001001101000111100000011100100101100111101001001111111100001011101011010110011111101001110101101001001111111010011100000000101010101100001011001111000000010000100011001011001101011001101010000011001010111010001110111000011101000110001110110110110000010010001111011110001111110111011110101100011001111001111010000101011010110000101001100110000110010110000101100101001011010011101110010100110111111101111011011111000100100011001111010111110000010111100101001010100001101100101010101100010100011000111110111110001000101011110011111000000010110101111011100001001011101000111000010011011011001001101001011010001110100000101101001001110100110011101111000110111011000001101110

string.ascii_letters:所有 ASCII 英文字母(大小写),即 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ(52 个) string.digits:所有数字,即 0123456789(10 个) string.punctuation:所有标点符号,即 ’!”#$%&’()*+,-./:;<=>?@[\]^_{|}~’`(32 个)

问ai什么是LFSR发现有 LFSR = Linear Feedback Shift Register = 线性反馈移位寄存器。

想象一个 400 格的”传送带”,每格放一个 0 或 1:

传送带 (400 格):
┌───┬───┬───┬───┬───┬───┬───┬─────┬───┐
│ 1 │ 0 │ 1 │ 1 │ 0 │ 0 │ 1 │ ... │ 0 │
└───┴───┴───┴───┴───┴───┴───┴─────┴───┘
↑ ↑
位置0 位置399

每一”步”,传送带左移一格:

  • 最左边的格子(位置 0)移出去 → 这就是输出位
  • 最右边空出一个位置 → 需要填入一个新位

新位怎么算?从传送带上选 5 个特定位置(这 5 个位置就是 key),把它们存的值 XOR 起来:

新位 = 位置[key[0]] ⊕ 位置[key[1]] ⊕ 位置[key[2]] ⊕ 位置[key[3]] ⊕ 位置[key[4]]

这就是”线性反馈”的含义:新位是旧位的一个线性组合(XOR 本质上就是 GF(2) 的加法)。

假设 key = [2, 5, 7](为了画图方便,用 3 个 tap):

步骤 t:
┌───┬───┬───┬───┬───┬───┬───┬───┐
│ 1 │ 0 │ 1 │ 1 │ 0 │ 0 │ 1 │ 0 │ ← 状态 = [b_t, b_{t+1}, ..., b_{t+7}]
└───┴───┴───┴───┴───┴───┴───┴───┘
↑ ↑ ↑ ↑
输出 tap[0] tap[1] tap[2]
= 1 = 1 = 0 = 1
new = 1 ⊕ 0 ⊕ 1 = 0
步骤 t+1:
┌───┬───┬───┬───┬───┬───┬───┬───┐
│ 0 │ 1 │ 1 │ 0 │ 0 │ 1 │ 0 │ 0 │ ← 左移一位,新位=0 填入最右
└───┴───┴───┴───┴───┴───┴───┴───┘

设第 tt 步时传送带上依次存的是 bt,bt+1,bt+2,...,bt+399b_t, b_{t+1}, b_{t+2}, ..., b_{t+399},则递推关系为:

bt+400=bt+k0⊕bt+k1⊕bt+k2⊕bt+k3⊕bt+k4b_{t+400} = b_{t+k_0} \oplus b_{t+k_1} \oplus b_{t+k_2} \oplus b_{t+k_3} \oplus b_{t+k_4}

用大白话:第 t+400 个位 = 第 t 步传送带上 5 个特定位置的 XOR。

看源码发现有

self.data = list(map(int,list(bin(bytes_to_long(FLAG))[2:].rjust(400,'0'))))

把flag拆成了400位的表(rjust左补零)

def cycle(self):
bit = self.data[0]
new = 0
for i in key:
new ^= self.data[i]
self.data = self.data[1:] + [new]
return bit

取出要移出的位,把 5 个 tap 位置的值 XOR 起来,左移一格,新位放最右,返回移出的位。

那么可以利用输出的数据求key,放过自己交给deepseek

4. 什么是 GF(2)?为什么所有运算都是 XOR?#

4.1 GF(2) = 只有 0 和 1 的”数域”#

GF(2) 是 Galois Field of order 2,即包含两个元素的有限域。在这个世界里:

  • 只有两个数字:0 和 1
  • 加法 ⊕ = XOR(异或)
  • 乘法 · = AND(与)
aba ⊕ ba · b
0000
0110
1010
1101

在 GF(2) 中:

  • 1 ⊕ 1 = 0(这很特别!普通加法 1+1=2,但 GF(2) 中 2 不存在)
  • 0 - 1 = 1(减法 = 加法,因为 1 ⊕ 1 = 0 所以 -1 = 1)
  • 没有负数、没有分数,一切都在 {0, 1} 中

4.2 为什么这很重要?#

因为 GF(2) 让我们的运算变得极其简单:

  1. 加法就是 XOR → Python 里的 ^ 操作符
  2. 线性代数可以照用 → 矩阵乘法、高斯消元全部有效
  3. 解方程唯一 → 只要秩够,必定有唯一解(不像实数域可能有无数解)

5. 核心思路:把问题变成一个数学方程#

回顾 LFSR 的递推公式:

bt+400=bt+k0⊕bt+k1⊕bt+k2⊕bt+k3⊕bt+k4b_{t+400} = b_{t+k_0} \oplus b_{t+k_1} \oplus b_{t+k_2} \oplus b_{t+k_3} \oplus b_{t+k_4}

我们有 b2022,b2023,...,b4043b_{2022}, b_{2023}, ..., b_{4043} 这 2022 个输出位(来自 附件.txt),但不知道:

  • 前面的位 b0,...,b2021b_0, ..., b_{2021}(烧入阶段被丢弃了)
  • key = [k0,k1,k2,k3,k4][k_0, k_1, k_2, k_3, k_4](5 个未知索引)

关键洞察:这个等式包含两大类未知量(key 和初始状态)。如果我们一次只求解一类未知量,问题就简化了。

  • Step 1:利用输出位间的线性关系,先求出 key(此时初始状态是无关的)
  • Step 2:已知 key 后,再求出初始状态 = flag

6. Step 1:求解 key(5 个抽头位置)#

6.1 关键洞察:翻转等式#

观察递推关系 bt+400=⨁j=04bt+kjb_{t+400} = \bigoplus_{j=0}^{4} b_{t+k_j}。

定义 x[n]=b2022+nx[n] = b_{2022+n}(即把输出序列重新编号,从 0 开始),则对 n=0,1,...,1621n = 0, 1, ..., 1621:

x[n+400]=⨁j=04x[n+kj]x[n+400] = \bigoplus_{j=0}^{4} x[n + k_j]

这个等式对任意的 tt 都成立。它只涉及输出序列内部的关系,不需要知道初始状态!

现在引入一个巧妙的变量替换。定义:

ki={1如果 i∈key0如果 i∉keyk_i = \begin{cases} 1 & \text{如果 } i \in \text{key} \\ 0 & \text{如果 } i \notin \text{key} \end{cases}

这里 i=0,1,...,399i = 0, 1, ..., 399。kik_i 是一个”指示变量”:ki=1k_i = 1 表示索引 ii 在 key 中。

那么递推关系可以改写成:

⨁i=0399ki⋅x[n+i]=x[n+400]\bigoplus_{i=0}^{399} k_i \cdot x[n + i] = x[n + 400]

解释:等号左边,ki⋅x[n+i]k_i \cdot x[n+i] 只有在 ki=1k_i = 1(即 ii 是 key 的成员)时才贡献 x[n+i]x[n+i];否则贡献 0。XOR 中加 0 不改变结果,所以效果等同于只 XOR 那 5 个 key 位置的值。这和原来的递推关系完全等价!

6.2 构建线性方程组#

现在,未知数从”初始状态”变成了”key 的指示变量” k0,k1,...,k399k_0, k_1, ..., k_{399}(共 400 个)。

对 n=0,1,...,1621n = 0, 1, ..., 1621,每个 nn 对应一个方程:

n方程
0k0⋅x[0]⊕k1⋅x[1]⊕...⊕k399⋅x[399]=x[400]k_0 \cdot x[0] \oplus k_1 \cdot x[1] \oplus ... \oplus k_{399} \cdot x[399] = x[400]
1k0⋅x[1]⊕k1⋅x[2]⊕...⊕k399⋅x[400]=x[401]k_0 \cdot x[1] \oplus k_1 \cdot x[2] \oplus ... \oplus k_{399} \cdot x[400] = x[401]
2k0⋅x[2]⊕k1⋅x[3]⊕...⊕k399⋅x[401]=x[402]k_0 \cdot x[2] \oplus k_1 \cdot x[3] \oplus ... \oplus k_{399} \cdot x[401] = x[402]
……
1621k0⋅x[1621]⊕k1⋅x[1622]⊕...⊕k399⋅x[2020]=x[2021]k_0 \cdot x[1621] \oplus k_1 \cdot x[1622] \oplus ... \oplus k_{399} \cdot x[2020] = x[2021]

写成矩阵形式 A⋅k=y\mathbf{A} \cdot \mathbf{k} = \mathbf{y}

[x[0]x[1]x[2]⋯x[399]x[1]x[2]x[3]⋯x[400]x[2]x[3]x[4]⋯x[401]⋮⋮⋮⋱⋮x[1621]x[1622]x[1623]⋯x[2020]]⋅[k0k1k2⋮k399]=[x[400]x[401]x[402]⋮x[2021]]\begin{bmatrix} x[0] & x[1] & x[2] & \cdots & x[399] \\ x[1] & x[2] & x[3] & \cdots & x[400] \\ x[2] & x[3] & x[4] & \cdots & x[401] \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ x[1621] & x[1622] & x[1623] & \cdots & x[2020] \end{bmatrix} \cdot \begin{bmatrix} k_0 \\ k_1 \\ k_2 \\ \vdots \\ k_{399} \end{bmatrix} = \begin{bmatrix} x[400] \\ x[401] \\ x[402] \\ \vdots \\ x[2021] \end{bmatrix}
  • A\mathbf{A} 是 1622×4001622 \times 400 的矩阵(1622 个方程,400 个未知数)
  • 每个元素 A[n][i]=x[n+i]\mathbf{A}[n][i] = x[n+i],要么 0 要么 1
  • k\mathbf{k} 是 400 维列向量,恰好有 5 个 1
  • y\mathbf{y} 是 1622 维列向量,y[n]=x[n+400]\mathbf{y}[n] = x[n+400]

1622 个方程 >> 400 个未知数,这是超定(overdetermined)系统,但因为我们知道 key 确实存在,所以一定有解。做高斯消元即可求出 k\mathbf{k}。

6.3 GF(2) 高斯消元法#

标准的”解线性方程组”方法。和实数的版本完全一样,只是加法变成 XOR。

算法步骤(以 GF(2) 版本为例):

假设有方程组:
k_1 ⊕ k_3 = 1 (方程1)
k_1 ⊕ k_2 ⊕ k_3 = 0 (方程2)
k_2 = 1 (方程3)
写成增广矩阵(最后一列是等号右边):
k1 k2 k3 | y
─────────┼──
1 0 1 | 1
1 1 1 | 0
0 1 0 | 1
Step A: 对第一列,找第一个为 1 的行作为主元 → 第 1 行
用第 1 行消去其他行第一列的 1:
第 2 行 = 第 2 行 ⊕ 第 1 行 → (0,1,0|1)
┌ ┐
│ 1 0 1 1 │ ← 主元行
│ 0 1 0 1 │
│ 0 1 0 1 │
└ ┘
Step B: 对第二列,找主元 → 第 2 行
消去第 3 行第二列的 1:
第 3 行 = 第 3 行 ⊕ 第 2 行 → (0,0,0|0)
┌ ┐
│ 1 0 1 1 │
│ 0 1 0 1 │
│ 0 0 0 0 │ ← 全 0 行,说明方程线性相关
└ ┘
Step C: (可选)回代消去主元上方的 1
第 1 行 = 第 1 行 ⊕ 第 3 行...
其实第 3 列没有主元,k3 是自由变量
从矩阵读出解:
行 1: k1 ⊕ k3 = 1 → k1 = 1 ⊕ k3
行 2: k2 = 1
行 3: 0 = 0 (对 k3 无约束)
自由变量 k3 = 0 或 1,对应两个解:(k1,k2,k3) = (1,1,0) 或 (0,1,1)

为什么高斯消元能工作? 因为:

  1. 行变换(两行交换、一行 XOR 另一行)不改变方程组的解
  2. 每一步消灭一个未知数,逐列推进
  3. 最后得到一个”上三角”(或简化行阶梯形),可以直接读出解
6.4 运行结果#

代码运行结果:

秩 = 390
key = [8, 23, 114, 211, 360]
校验: 0 个错误

398−390=10398 - 390 = 10 个自由变量,但我们得到了恰好 5 个非零未知数。这是因为 1622 个方程虽然秩只有 390(有 10 列线性相关),但自由变量恰好全部为 0(因为 k 向量中只有 5 个位置是 1,其余 395 个为 0,而独立方程已经足够约束住这些 0 了)。

注:理论上 1622 个方程应该能得到 400 个独立方程,这里只得到 390 是因为输出序列(2022 位)长度有限,且 LFSR 序列本身有结构(由 400 位状态驱动,后续位是前 400 位的线性组合)。但这不影响解的正确性。

校验方法:把求出的 key 代回递推公式,对所有 1622 个方程验证,结果全对(0 错误)。


7. Step 2:求解 flag(初始状态)#

现在我们知道 key = [8, 23, 114, 211, 360],需要求初始状态 s=[b0,b1,...,b399]s = [b_0, b_1, ..., b_{399}] = flag 的二进制。

7.1 系数矩阵:追踪”渊源”#

核心问题:如何用已知的输出位,反推出初始状态?

方法:前向传播记录”血缘关系”。

定义一个 400 维向量 c[t]\mathbf{c}[t],它记录了第 tt 位 btb_t 是如何由初始状态线性组合而成的:

bt=⨁j=0399c[t][j]⋅bjb_t = \bigoplus_{j=0}^{399} \mathbf{c}[t][j] \cdot b_j
  • c[t][j]=1\mathbf{c}[t][j] = 1 意味着 bjb_j(初始状态的某一位)“贡献”了 btb_t
  • c[t][j]=0\mathbf{c}[t][j] = 0 意味着 bjb_j 不贡献

初始化(t = 0..399):

  • 对于 t=0t = 0:b0=b0b_0 = b_0,所以 c[0]=[1,0,0,...,0]\mathbf{c}[0] = [1, 0, 0, ..., 0]
  • 对于 t=1t = 1:b1=b1b_1 = b_1,所以 c[1]=[0,1,0,...,0]\mathbf{c}[1] = [0, 1, 0, ..., 0]
  • …
  • 对于 t=399t = 399:c[399]=[0,0,...,0,1]\mathbf{c}[399] = [0, 0, ..., 0, 1]

即 c[0..399]\mathbf{c}[0..399] 拼起来就是一个 400×400400 \times 400 的单位矩阵。

递推(t ≥ 400):

已知 bt=bt−400+k0⊕bt−400+k1⊕...⊕bt−400+k4b_{t} = b_{t-400+k_0} \oplus b_{t-400+k_1} \oplus ... \oplus b_{t-400+k_4}(由递推关系,把 t 替换为 t 即可)。

因此:

c[t]=c[t−400+k0]⊕c[t−400+k1]⊕c[t−400+k2]⊕c[t−400+k3]⊕c[t−400+k4]\mathbf{c}[t] = \mathbf{c}[t-400+k_0] \oplus \mathbf{c}[t-400+k_1] \oplus \mathbf{c}[t-400+k_2] \oplus \mathbf{c}[t-400+k_3] \oplus \mathbf{c}[t-400+k_4]

直观理解:第 t 位的”血缘” = 构成它的 5 个祖先的”血缘”的 XOR。

这样就得到了 c[2022]\mathbf{c}[2022] 到 c[2421]\mathbf{c}[2421] 的向量,它们满足:

c[2022+n]⋅s=x[n],n=0,1,...,399\mathbf{c}[2022+n] \cdot \mathbf{s} = x[n], \quad n = 0, 1, ..., 399

其中 s=[b0,b1,...,b399]T\mathbf{s} = [b_0, b_1, ..., b_{399}]^T 是初始状态。

7.2 加入已知前缀约束#

我们还知道 flag 的前 56 位(moectf{ = 7 字节):

'm' = 0x6D = 0 1 1 0 1 1 0 1 → s[0..7]
'o' = 0x6F = 0 1 1 0 1 1 1 1 → s[8..15]
'e' = 0x65 = 0 1 1 0 0 1 0 1 → s[16..23]
'c' = 0x63 = 0 1 1 0 0 0 1 1 → s[24..31]
't' = 0x74 = 0 1 1 1 0 1 0 0 → s[32..39]
'f' = 0x66 = 0 1 1 0 0 1 1 0 → s[40..47]
'{' = 0x7B = 0 1 1 1 1 0 1 1 → s[48..55]

这 56 个方程也可以加入线性系统(每个方程类似 s[i]=已知值s[i] = \text{已知值})。

7.3 求解并验证#

合并两部分:

  • 输出约束:c[2022..2421]⋅s=x[0..399]\mathbf{c}[2022..2421] \cdot \mathbf{s} = x[0..399](400 个方程)
  • 前缀约束:s[0..55]=已知值s[0..55] = \text{已知值}(56 个方程)

对总计 456 个方程、400 个未知数做 GF(2) 高斯消元。

结果:

秩 = 400(满秩,有唯一解)

解出的 400 位(50 字节)为:

moectf{Bru!e_@r_so1^e_A_sy3teM_0f_eq&aT10n3?}()6.S

去掉 } 之后的随机填充(()6.S),实际 flag 为:

moectf{Bru!e_@r_so1^e_A_sy3teM_0f_eq&aT10n3?}\boxed{\text{moectf\{Bru!e\_@r\_so1\text{\textasciicircum}e\_A\_sy3teM\_0f\_eq\&aT10n3?\}}}

Flag 含义:Brute force or solve a system of equations?

这是对解题者的小幽默:暴力穷举 key(C4005≈83C_{400}^5 \approx 83 亿种组合)还是解线性方程组?当然选后者。


8. 完整代码与运行结果#

#!/usr/bin/env python3
"""
LFSR 密码分析求解脚本
两阶段:
Step 1: 翻转递推关系 → 线性方程组求 key
Step 2: 前向传播系数矩阵 → 已知约束求 flag
"""
import numpy as np
# 读取输出
with open('附件.txt', 'r') as f:
output = f.read().strip()
x = np.array([int(b) for b in output], dtype=np.uint8)
N = len(x) # 2022
# ============================================================
# GF(2) 高斯消元函数
# ============================================================
def gauss_gf2(A, y):
"""求解 Ax = y 在 GF(2) 上。返回 (解向量, 秩)。"""
m, n = A.shape
M = np.hstack([A.copy(), y.reshape(-1, 1)])
row = 0
col_map = {}
for col in range(n):
# 找主元:该列第一个为 1 的行
pivot = None
for r in range(row, m):
if M[r, col] == 1:
pivot = r
break
if pivot is None:
continue
# 交换主元行到当前行
M[[row, pivot]] = M[[pivot, row]]
# 消去所有其他行该列的 1
for r in range(m):
if r != row and M[r, col] == 1:
M[r] ^= M[row]
col_map[col] = row
row += 1
rank = row
sol = np.zeros(n, dtype=np.uint8)
for c, r in col_map.items():
sol[c] = M[r, n]
return sol, rank
# ============================================================
# Step 1: 求 key
# ============================================================
NUM_EQ = N - 400 # 1622
NUM_VAR = 400
A = np.zeros((NUM_EQ, NUM_VAR), dtype=np.uint8)
y = np.zeros(NUM_EQ, dtype=np.uint8)
for n in range(NUM_EQ):
for i in range(NUM_VAR):
A[n, i] = x[n + i]
y[n] = x[n + 400]
k_vec, rank = gauss_gf2(A, y)
key = sorted([i for i in range(NUM_VAR) if k_vec[i] == 1])
print(f"[Step 1] 秩 = {rank}")
print(f"[Step 1] key = {key}")
# 校验
errors = 0
for n in range(NUM_EQ):
pred = 0
for k in key:
pred ^= x[n + k]
if pred != x[n + 400]:
errors += 1
print(f"[Step 1] 校验错误数 = {errors} (应为 0)")
# ============================================================
# Step 2: 求 flag
# ============================================================
TOTAL = 2022 + N # 0..4043 共 4044 位
c = np.zeros((TOTAL, NUM_VAR), dtype=np.uint8)
for i in range(NUM_VAR):
c[i, i] = 1
for t in range(NUM_VAR, TOTAL):
for k in key:
c[t] ^= c[t - NUM_VAR + k]
# 已知前缀 "moectf{" 的二进制
prefix = b'moectf{'
prefix_bits = []
for byte_val in prefix:
for bit_pos in range(7, -1, -1):
prefix_bits.append((byte_val >> bit_pos) & 1)
# 输出约束: c[2022..2421] · s = x[0..399]
A_out = c[2022:2422]
y_out = x[:400]
# 前缀约束: s[0..55] = 已知值
A_pre = np.zeros((len(prefix_bits), NUM_VAR), dtype=np.uint8)
y_pre = np.zeros(len(prefix_bits), dtype=np.uint8)
for i, b in enumerate(prefix_bits):
A_pre[i, i] = 1
y_pre[i] = b
A_full = np.vstack([A_out, A_pre])
y_full = np.concatenate([y_out, y_pre])
sol, rank2 = gauss_gf2(A_full, y_full)
print(f"[Step 2] 秩 = {rank2}")
# 转为字节
flag_bytes = bytearray()
for i in range(0, NUM_VAR, 8):
byte_val = 0
for j in range(8):
byte_val = (byte_val << 1) | int(sol[i + j])
flag_bytes.append(byte_val)
full = bytes(flag_bytes)
print(f"[Step 2] 恢复的 50 字节: {full}")
# 去掉 } 之后的随机填充
original_len = full.index(b'}') + 1
flag = full[:original_len]
print(f"[Step 2] flag = {flag.decode()}")
# ============================================================
# Step 3: 最终验证
# ============================================================
state = sol.tolist()
for _ in range(2022):
new = 0
for k in key:
new ^= state[k]
state = state[1:] + [new]
reconstructed = []
for _ in range(2022):
bit = state[0]
reconstructed.append(bit)
new = 0
for k in key:
new ^= state[k]
state = state[1:] + [new]
match = all(reconstructed[i] == x[i] for i in range(N))
print(f"[Step 3] 输出匹配: {match}")

运行输出:

[Step 1] 秩 = 390
[Step 1] key = [8, 23, 114, 211, 360]
[Step 1] 校验错误数 = 0 (应为 0)
[Step 2] 秩 = 400
[Step 2] 恢复的 50 字节: b'moectf{Bru!e_@r_so1^e_A_sy3teM_0f_eq&aT10n3?}()6.S'
[Step 2] flag = moectf{Bru!e_@r_so1^e_A_sy3teM_0f_eq&aT10n3?}
[Step 3] 输出匹配: True

9. 总结#

步骤做了什么为什么这样做
1把递推关系的未知数从”初始状态”翻转为”key 指示变量”key 只有 5 个 1,但 1622 个方程可以唯一确定它
2构建 1622×4001622 \times 400 的 GF(2) 线性系统超定系统高斯消元即得 key
3前向传播系数矩阵把每个输出位表示为初始状态的线性组合
4加入前缀 moectf{ 约束,合并求解输出方程秩不足(399),前缀约束补足到满秩 400
5前向模拟验证确保恢复的初始状态确实产生所给的输出

核心技巧:将”不知道 key 且不知道初始状态”的两难问题,通过两次 GF(2) 线性方程组求解分而治之。第一次求 key(利用输出间的内部关系),第二次求 flag(利用已知前缀)。

工具需求:Python + NumPy,全程只需 XOR 和 AND 运算。


MiniMiniBackPack#

我这里有一堆Super数字,构成的Super序列,你能找到它隐藏的flag吗?#

源码:#

from gmpy2 import *
from Crypto.Util.number import *
import random
from FLAG import flag
def gen_key(size):
s = 1000
key = []
for _ in range(size):
a = random.randint(s + 1, 2 * s)
assert a > sum(key)
key.append(a)
s += a
return key
m = bytes_to_long(flag)
L = len(bin(m)[2:])
key = gen_key(L)
c = 0
for i in range(L):
c += key[i]**(m&1)
m >>= 1
print(key)
print(c)

txt内容:#

[1928, 4648, 12352, 24010, 58760, 148406, 441469, 906294, 2347544, 4145527, 13246047, 33012060, 104677731, 233784625, 398671830, 1138569375, 3847891246, 7151230548, 17442630021, 46416620988, 118857237060, 363519789685, 661956375011, 1712300152639, 4761949150147, 8964540458636, 24746310311237, 62452210349278, 150016895989040, 453927852027278, 948923770773559, 3275343477577565, 5756783232753127, 13616706687879089, 26402320025439836, 91814578040763059, 211796919962932717, 385545413311588646, 742071895214889791, 2137385737378343660, 5820500440463297078, 15401185997444609852, 49206779920875282228, 101148479344021765606, 205390946600728256099, 593695571211967641654, 1163476540184124239753, 3920275177926640702128, 11188401781366603668803, 26452211702098700985776, 56612547941955968739356, 176511950177344415872304, 350456159524844834233165, 932655004294881661656249, 3077731648705646793828507, 9127653332576335535543235, 14107124912327219069005253, 53639235705342264540097281, 139903414487199921597126219, 377113327325865137005647964, 797007439689940464465071770, 2456373221352926158802602905, 4997725491122440484756502995, 17601885978368777637676626066, 27945705300453872028061217316, 70259455336271034962808380541, 241339934663279791843376677893, 565927167417896365819102921696, 1498269591024734505946670540129, 4476165672138335294342834148717, 8246962867693878472370951037335, 29609522845816295639745215494800, 71952214344473760246502727717474, 169361817288205588754741757159731, 390045301314759178244461824288458, 1337540279161737220902909199776611, 3221480198479784802709388960779700, 9670513515504338974817616478456700, 16261746247432868145400788404115430, 53594268392537203440232335914792279, 142627442102890550431018293710429426, 249683635647920776857130562696997561, 689878480570146636843962995034183967, 1647889244922264517646376201060969417, 4362391204795633804803911898013660682, 11983025462449787764688227594361812707, 19474005190319410527122673327870913310, 40950423948271412394664153066384954054, 139255978428478610787399242087880835737, 382133188700471370531564036246745271608, 618340037056166043673108074267387394368, 1728641328632513907826054966389623526131, 4246454964077064700888723109771772689322, 7526932088676669848792644586429545161503, 14761773428394206759829134632198244970685, 42336665776969730227150513015344171877811, 73191053942159553542196382411683917861300, 211549032502894704558541919050681697675397, 554709644259380577558971870420849574372151, 1251152425154260246544953154540513290303621, 2818798972367329802956936052623797403793942, 7638358444068983298092603686815486790113890, 24695143882440275994689721479314417528417480, 45729327569890326278523663568847218262894959, 129925286147414817076637512089880305727457533, 357058960265822950281886346091988882031910760, 870811282376277097902073516532006850342152858, 2399129617319427629796691807338852665469337085, 7522497498897836117435156411281203259743818186, 17703808279261898891912155690137638994014567408, 39174398341780347981624886777838524967209728446, 71626422074785376430650030090797947505033373583, 189453667691364649027951065496599754814571374684, 437295033677960022667168340703719574179513440159, 1105022320374390979035499970036715293235993540826, 2482140894382786914874701298953446381142900730227, 7941406921570365260066022237661009338911386179194, 13688077798315662160188528865690475378175919829521, 40118424472696130315297350323559766967889857978364, 105189379969045772302352882060687514329245824860122, 199293659238948607716187263853532082285127398693261, 499536111913922039437392654679505181047127518386152, 1265716378918935998920835568757397506132677689873802, 4251975766094131691018482661130820129953060977929504, 11152957210935036994690757763894857926461579995709364, 29243034751011001056721898400833781278921232465896703, 83127804731558215656517415813913013712630964732885793, 197287313991484123623412111326147421339126168589781103, 580348074469542880297800575176456597744257638809118170, 952848219059546044449261356813174361415872857630315510, 2114745453546299027601967135831843941629758587200332803, 6732303576367127091793491258707612535996916865106486930, 17969751578033370972927234837249484835783104974373526668, 50353964851880252824761483078317672020552394668185625845, 114792749147200000567884552573247130055515068451479473326, 344881289580954366545252182642967036273037618565165401985, 1028830458186445450162354520820201527695218769577051320473, 2074905233540761021629273629118215092544205899770047449244, 6827824489946353955926387525605200460781082737913381690336, 13024891552715019198360589788142658101822141014082307429749, 25961005268769363699702206141880105110265708699262059458918, 75403822308341240881775753922079349096463802345797378834029, 237384123451169596772029918832412849807327730438354057322622, 712646240930595428776240903619042913605109976371239636231758, 1858677703618066892165605509033944664007520745899837556768895, 4139395606166311238767981220233801698454319610253778363314838, 11051661045091733320416016319660914967058929654228453865287281, 29811585925705783247773137027702029276636378622129036803066195, 90685056735716951430085719312184849024248295771954003433442472, 157500945846011120649342030924242308092488581060888955520117740, 372901626023221848769914983494185928870895559258054416488096811, 768231028240804910809905945806694160784354754863882766743917789, 2779285901235347349512412519384436770411460171816095983145397440, 6374104945628711471675855561257403169698347988699930709009388571, 15606620797895735826222569176215400049549335070727802852935792508, 36407286542538484153926148252126040596266900628856973721204544487, 124345134443495254231144676818478910782759198180390061540449975329, 247113740493284619019931820393865652802499920117478290621711932786, 546250851448819627474782890078865878619982888424175090054606739349, 1708592433038733956978819431107564666115535756847903016488985258178, 3469784692808773680977989909012383598601318450115335667599446101916, 10923256812598128494335226092601900716551326610194937277684839542369, 21012491338240214838754959441277560200420746284908398093641375760080, 60889459302270258776558311240916612146241213106331686794170240374762, 163976015330661921425351604828688078789049035481531041973974028089785, 289037863251569623683823097040957275672420698243074506420157297827331, 757077203699594125515581476518783513279367742304415416466493229482750, 2419895647396662523171144180707701121877346566438572088091207837906226, 7355085337963583789485765997525070376210546183075717620390510384848601, 15051216064674860618341980616144084279926804604562228123313569479773613, 27941489504573067317849352242679271094163397351402254909630669501407776, 101620497919142332166787423172023060084593540312322612628746436809445674, 226881723516906947900548874100926330355595061853588440070446478001634192, 436083549067326238210237926429619818583468595956103126733614121273925302, 1114300762650958326100809843235006795980444078921364112608090634574957344, 2067630703150668695099956606446000647289440828791043320265352802856027353, 6184858091099126482135322120120464262653454412363734887325664168742191917, 20198724557091875844715800016163838909724718285368458520056089111628596330, 31016012035612935043240048944310566375654982913771972602093586083253422398, 120517928868495613278649932692310155587627278645665690072538147101563551766, 189853493819940791022006359464978248211780374156959402302888328075135559122, 709261139869078187523368280811328692680117587337216655356117972203528916551, 1494450926662311226674274795483402016068321469408932952124223720040234068030, 4833201522454078687541173754025375255160393643329610440001807389162022858137, 13065426763007211443646416727098859879614516619696845038342383829309179073982, 31498041121702214861734489217437935540479379421202405303460486717862084301294, 59291071262486212405215961522173655254987660557013973769285757104149711757459, 137325620971003240316895273046089454057536316983680621619104742603734626157973, 322033994335205758184753941417891767592538862759074152575171260357782006734442, 820082783566832754339608163235147685713597507674476057203654315048011026367219, 2282651344288337092906883083740075053173109353137863831730238422975306417325757, 5445119536937019732153059574137765564679350539463171899410036275958492350218676, 15640432491440562916581632653853505713511238255286321934711250830601955403677071, 41106883032429969859399906487019322357415120653637758039703350990320596875155176, 103754830954744065029443848605781937050053754534445990149281507972325774765844876, 234666834709268927734887936099822319961738129376455664521947726208265410000264742, 796501101363737180381507228150305361162624877853273443755457607681031102231623307, 1624552917282803716066319956956102765638808948119862597393339135995911391379123522, 4643272637840339310515026952678388354699825180379372281574901801196876030063101974, 12698618143562269391895747140398377495554004174836256597996901873500325652914287227, 35723733467261031422647885542793080310475947027099953899906182407397300154268828906, 66579759042299327879621766658030061118334921216187867761491910504181344451238684350, 239558348723378720363003224968080360385965369779814655734270075126998161979921905000, 674426340811237207208953232785934391016215462902095720638324651170969997400637801355, 1698823780061918718547756106555041994312203433347013142428193591099315938666752495147, 3485698669992831956608280816819201625859973318902236645999324294867314338271763576226, 11913442231481393917536601792582866930393303587594985248503741285895455503031416467367, 23070531945625150855016941245865388154950147453856685413887739256847410892916751249842, 63062109298026246794043518591814177894498277952179449322185515920851203385563000039545, 201500456854818387020432137947274011145636992031847792130877996231861744196691929847748, 386293027342088096708767070123592359264038177654678967794307420131436089009234887958085, 962652147623483170628478119235555226505070396879489339105090935822447174750045231232478, 3035935960793431917350036879195567655285637476975406683996240225461808984868014791791433, 6208746117115824715018162711918248788514776556569667609833722045497831346028332955531410, 11762322147658744239353552479176647603950873433079903790516674882105043434830328826675415, 22679200582127225664793559521091332878355319644677462980823198911465583443269858630893253, 73929710933006149888049977928677968518055319247626886667227984506656971966999436923186972, 122524349818395517581134493004049791722607446965559017459380345881157453828660236992049404, 412926833511789222428174650284405691872834629858851326844087117202853421601692502254318141, 1029385129423499530322969843276842783066057615497035785381633948646265964471244991407283657, 2374019900827890887681448469648598056064267661046120767421848772396302513783495423644064007, 7129046282305997419886465925038724574815350866486395082327924571694995543004421437396685163, 15553684426659575255143733092646126163883808844830770798803864550707886694317293166976752540, 36868510946091898479948303208447807989049331965479662439764899809218618486185846045349542501, 92245655628350120221629636214996850938258802134676165059052497372214318974743615511153118145, 186463470334970062582820387784350511557982560369498424617823476509363037536450250866616200018, 572967521502291777355369990006837729815084981232789335148124013079835565379339449250907380488, 1481745249132912511970258586968019679134485717661841452421417313959912906838055641721186578588, 3465571259266031075485176569236690543411907657240139447438094553546637617425088900258756309108, 8435925081032968505659480326132770316717891729208893135134645312992136104713045209348571379936, 20315655322325100095226141940419414017723560946817780337100296517956534785685937181001107745352, 43069115966613244938070771746304575880400024938295357246717079316564326270692925649165248799853, 154233412749662382894550506472683312102297703424057840129476320316144010040200771168572376219849, 352877164586305833533208196782157198192758667776588081344657867110512140773408077435261431699405, 731939874265903145518316019567169287035472945759023530855697163432627661288949769619402453516834, 2189452024672949178210645600969378516255080271308334836448144354429705327344143994347331957449853, 3896543605375761834186485166037278157701213968430616464967138263870727947226180820650265115757354, 9136364061744114854751740581900554472617621867814569413142650998411332183920873701211555172374338, 31182169589957210510416755511542482029989997938097777712995732237583051643250531461221140115798313, 76737932310662322563271317876920472434982416417386459109415811734811165935978744596464401289256365, 191657687539432627521287232027340814340762593718642860136243059179657356411665753239917046107562015, 530361069831754440835688500919172905456422674539149906219439563860239029311496751350136915275150864, 1387792997020024308183922178096461451972294935906886419345639014544739179094711431002567439046777688, 2286383934503119795216122706571707851067263586234080042542833733216757155431244141022301236049602882, 5217435832596475959525740735112831333306893965389666926215938837589313774349496690036610287629333005, 13857335145208908258169891019385567845284268412333112678215001155302498425490658878264656236992134935, 40163901018471004896425196956916864061977023091787666532481831101052032374062940939516719648018676594, 82892214529323438899501402117098988403652889186148588453800977258361448264060748670322604495661134167, 178956544188555415155972101504345380390695957167910254018903325710948594375512551321503428603501757891, 563888574268395325287659273510106617675959539240732287901035847602904779682730930207201257182213858543, 1616044303623257921514683914498983737627603891472634935907943748930280908786049272784565904600012939098, 2891229181345915888829785513242002484495784340354174828728993457272687483459059048534538302181816688976, 10207730272860940549823879515425309207636840459300447491903147067853625202918689426829904372421061677895, 17526621515916394607402562632381069779604072768221581075247386337947979364802058499395942689207299830365, 55864742839796343168209200305202648507682753148596246337408494037308856790224259497580631081634646188041, 165332196033938201434627346583990806851682965862702414330472648748014088812475559273855488926778988149883, 494729626554411141427744566730794748483202977845760867859438479405205853778032755546761473203576297889449, 773241724058457908926664671814549280391747757602041708672622636112281590651589333985868232639345426359863, 2643090721830219937871980242863893762864524580138013585975903383984399727700467749841537295988160882592554, 7602742125929529736410459828760559621377824926000865839917497433361558637433229365703421216832254559844712, 20298012813427893859751095024917906619591438637592000480476880613738608994530228331797315397345124353458048, 57138113294488937158388285440237932686091901290656714986248760196665994518443306993120321953623611701468826, 156180826248086652580528603931836069088833849466705801833826561589537926864487694377480227882717998855358198, 405091254840842081029125739284610173825182926000756067214428354197290398676973286834323853061720032954965963, 778366116109730017138034746329928058267161795656720444904686750506814152375884477590166274857108289313593118, 1796005150394618766778725965351985496132876507371048438760920669904977557456986675227521156526604287512648264, 3898444018773054695814825596014017751795964177961572987153324103751602074848254485225397417397654262390321944, 10703462078231223004197739814155717950000211259146027443753796966491790618726938276000128782966812980398530204, 18372321975824831177753464245580317968933119357879255869022769977852558056854497414886761863892673585456643891, 48317491803925955550053615386786484989034506042840366819980397407568791721238179125455458641299301269848666510, 158255568588301663954187011445643163738485858122034088577201324726783893231449209827193255340005164973552974453, 456823552578369748946561710072366945172148623875999657195033140013027572670231347304984109456384691884394301596, 707160118481884894551388234729179730915972581073118662214623842056893684770640844231508665861861467073743805665, 2706927376520605764276007802932993151885010075033345167172586198244735154579188535970342536626727165782495180134, 5524495123704893916572931697399108221354633312984253879509446961783982258828184219735409076305664075360213376822, 11902801828947547843316856179728603283371324186706149334180029898787026360919748804787239985463725865632928552507, 42817758358028425898228144386760814695029076486689089958556088081002352872886441780712721026897632438300836110665, 85341298053933033277929612803230545434450389443924565926372394273668666803233325131592974981823970679666528469082, 203545487666526735282497187348232067937848828434866343193810463204944901878674073018178572958556722616056919932826, 404490991972927610287798222030298357859147323959244483279529298622268125169109324278915340735214314234862449055448, 1015889532249910731454157235904076803563143859066636167138222193683905683535906365566683356226160720652109370999321, 2376026683785110886914732723263521678018967831673326233555377196140833492114241003132626058539164015299593970425136, 6462912523501528306439979574464826777892245783057732634021629306276087967421373795532316029843905278328516884883058, 16981441701453104471733297233747957918575727289870879189918428405182537334140409929337675754279869961515500536636176, 37605582989982272328044312175947277729400907856460324692248887357599456103017970584086153023793040540391945445989257, 91747039052675678105959960961981861389020215173307703983752122608163760292472703277085998681706298344337891404847646, 197976695213061406953734629818998754281337862490966315225432914015679415715157795368611025598068494075696354180224057, 407579734020903728451591407903624856111929215373480871243621182164970838186438777218257932637652562832905518769398262, 1192695842629740666007709455549699909835266353292608841275812622248241416280954865990629770667881078271433918923422731, 2356450454926316659685731978750584215969826513728852376452662114206102092287531644004469937748823746129670826796883901, 6606194810680818911726753398369719656427756109429906495763748359459974583720214056977960616895121295259675484772228900, 21238856384108665139068993634246013308212000660518883089302921531246892139968871926076965355331061987385136533519279525, 60431698017667972588320134967121949330864812114211557015977441929363675768812209839204671181454067749535515855713156763, 174665868422753780275604141699079697885219220210916384980421958910804651659162534153721798589901082858559767609552079345, 394230935137659132182806278870718863867754651145064639278806591391259891710009233085853984826856234290081395609225890238, 938316178783979725028510016300351906317832877618969965871296642973988528249289624189564279188734089982984293864940639663, 1690300816950917856165481180579373059665398098127346945618427499442023814975741786872721941536175836912500050716899314350, 4241040212750921734662543578806315663721700243000974307468609317605794291246764526126048318503818177838783905309400289117, 9899615703109749398438558898664002269482804539466079984631091253252047080143600618559486614511675282173378128689947106499, 19072918764217687057379877185516040357999863490449836492311841376572022870447983721729056895047026984202403660270528351362, 61457030295636043956746238914591148777316757448303861396901131680368800892725607851722251866187547310356464672462006792936, 130554685050076234706409249768453974245979757597714789262984612467812333642313018653001831006709360179701213479970689476759, 317707441009141362433020809851971219097475768762476580041791647909345575364794752462683617015215387354639266789655705355159, 766407353781281024676870262720057676902122989643223864583232810528888853102644816087185770633710024110065414129660560848818, 1378158372668635043591303404733183053913783647791091758022520799715774445178343987469574552089574912051263356050601448829569, 2849814783153826557775488037652012659704609417837692209372285071574038848736100379264094051217084360358380745456795092662367, 7761768442678261726960193678894950205212069061687767898603990098871593859918952089239031086652597614705182760193814143657094, 25797856998139398890116390239859835084629679432044893266362900315705828350899796936954893678013444560821963770721738841492762, 45230528787260219469707111504991583088449246785732739036848497764369166856369435663350796527642874763730890628636593210838634, 125595007654406839330037705158661517651788635482067500225344073216015649944944879970130124750959631685921435054581613709164822, 338747508849935686599681561847193572302329804892368313208731993174039023400358858978202514407262943107662339259004212857955666, 927842701337787263386928773903441275979399427379662460065544246411463087320044839262987027337743305220579800532826965270689250, 1974283905173053393614664395812743602970084360210384412934832566684934360366297764438728189449912704403685566054487439810857627, 6547791381850377804871914819409383329722364771877581519586671693693630274474320389311984387956647850854999536112540018330183809, 15709320907036538202306551117984227990557852089499582468594623629463507925701405510011304643762744267804282547349971254508845938, 40270138688478461945314017148044972001708543125646521974155404640273555509873235113536988809551924038925428913961013964565197607, 99168179703900580858922903603323807687115252977021819828415602208147447841271397891925410158445036111494543958823713690209285369, 269868178430265744761277563499719925184037917272176039027995896214226177897366881562687640385414521231482816048831046030643750903, 831659192392583336646613887566957000280656975320208034953861277421104038936580189145699653541798336705409469145595542460062434471, 2073476643694212471632333653958562004434818366225131771845046659755589302151344899589183197864077374128293181680576229954100550419, 4554149306780266313933686119966338774145476827044906188542821462680791576860383095025724314895890630857897398967476576259995321191, 14651118307465336327922062019691151414683570292038775511915021602908118951591926995520466221396947959539039452124967851254379010308, 32590352694473324794187157416677986187287003972605121693147144070229453983956761041980924463747749024664597601177994952136065984811, 81134631049823241301269776481475653931802229294857541846620286653857647735078830230944498091871440739749676625155855958593920070814, 185677119342066492911752180414903294080590111905381979357926969960006994207482364686831869137669282514024709390338951171955152686319, 611640161419871188028819133410469586343996954403636969815202842657504592966769167857498786484339404586484056783483882604337795700345, 1665805557476802274778809527131744615949426833045219219448282924298718975882034660815478936907356513550130652021165488275923832785881]
2396891354790728703114360139080949406724802115971958909288237002299944566663978116795388053104330363637753770349706301118152757502162

key已经给出来了说明不用再看上面生成key的代码,直接看加密。

for i in range(L):
c += key[i]**(m&1)
m >>= 1

c为0对应位数与1对应key的数的总和的和。那么可以得到

c−L=Σ(key[i]−1)c - L = Σ(key[i] - 1)

那么可以利用key来恢复m的二进制数,对加密算法进行一个逆向

L = len(key)
new_c = c - L
m = 0
for i in range(L - 1, -1, -1):
v = key[i] - 1
if new_c >= v:
m += 1 << i
new_c -= v
print(long_to_bytes(m).decode())

得到

moectf{Co#gRa7u1at1o^s_yOu_c6n_d3c0de_1t}

NumberTheory-FeeeeeMa#

怎么可以分解这个n呢,来看看他是如何生成的~#

源码:#

import gmpy2
from Crypto.Util.number import *
p = getPrime(2048)
q = gmpy2.next_prime(p)
for i in range(3600):
if i%100 ==0:
print(i)
q = gmpy2.next_prime(q)
n = p * q
e = 0x10001
flag = xxx
m = bytes_to_long(flag)
c = pow(m,e,n)
print(c)
print(n)
'''
263008606417090478566565299810283124941804126507113525587390677503293194343666087681964773019395280446205407691484774718932550281467537401219675254528173987088938774386502897118203537632220602323914308216229335629593724857802179137161994764652047523675709008286064448828023140237566132983016003115673355564648923477918580240197355351101233161015345869099779377748188971444727339859346227316840479889105162116347476243712080281172197785928605069437778934843702674790549009254968801469403071588920441238715453737896667478751217639321474363829766785705632819377446277423897444229208300944065442708855610919362463870409750865618966436909679416475224935654779108492443347930157015362069031445961698740874449398633416274993312148761043683846969413714438518714752086418643505351718069185918950309997110990358633504996993095219569951691320773244853704939426164506912622629836798640173907936986385737630181302799243239569229123640543209312682734240635326031049265324015549955077829367091796287221865653193037735196635197439609673972466210706114120142070802091713212287909213710633272650703644600005643328190463554693180030667114903774309621791748550174052862095206625927960781050796459818989538815307653741523716288252629280835076948046895601
359336501271521532887656688609295042672434709877081900753462802000755944104448697042366747461395534728915053035475459015263877654779607712559439958640046447246795492613180033737648218742508752449971055824413830268089448680617248179389657713305429663149548581330682010843775095659107771083498691437964118187909080096258126217389687367383301166809926191321584757387431941409060744328371424948988833446651828309230245313487641590365198484255142967088588384318797132203546546629955996480505149111166600546126192029751124771571918693276230154597894534213860659972166774036644473508159923466417979740342453286817394016723536509392328304731594460395586984216646043768390806512181233642534151692135644819066105646943194201485395325911256860832603278670900133367627500162513041761043011626948699652168654976313717938901597808754267996648935745100287531478172712432058146052903388546565632174028182472012197791653306648067962114207504888841853254752313822184342829344043028253285087763176816976839219602985900752633788798421802365156777163724743521780060375607506242692718315299078104710983637353515944430437712607451078303509530539260657291973611896675785100483218112781144038004807688281170137433780853291933873671533348523292439854954465561
'''

经典的RSA,难点在如何分解n得到p和q p和q的位数太大,在factordb.com分解不出来

p = getPrime(2048)
q = gmpy2.next_prime(p)
for i in range(3600):
if i%100 ==0:
print(i)
q = gmpy2.next_prime(q)

从这段可以发现,p为2048位的素数,q是p之后的第3601个素数 查ctfwiki发现可以从|p-q|入手,点击这里访问RSA模数攻击

搜索素数可以发现素数定理:在 xx 附近,相邻素数的平均间距约为 ln⁡(x)\ln(x)。

对于 p≈22048p \approx 2^{2048}:

ln⁡(p)≈2048×ln⁡(2)≈2048×0.693≈1420\ln(p) \approx 2048 \times \ln(2) \approx 2048 \times 0.693 \approx 1420

所以

∣q−p∣≈3601×ln⁡(p)≈3601×1420≈5 113 420≈222.3|q - p| \approx 3601 \times \ln(p) \approx 3601 \times 1420 \approx 5\,113\,420 \approx 2^{22.3}

跟2048位相差较小,可以使用此方法

从wiki中可以知道

[ \frac{(p+q)^2}{4} - n = \frac{(p+q)^2}{4} - pq = \frac{(p-q)^2}{4} ]

既然 |p-q| 较小,那么 (\frac{(p-q)^2}{4}) 自然也比较小,进而 (\frac{(p+q)^2}{4}) 只是比 N 稍微大一点,所以 (\frac{p+q}{2}) 与 (\sqrt{n}) 相近。那么我们可以按照如下方法来分解

顺序检查 (\sqrt{n}) 的每一个整数 x,直到找到一个 x 使得 (x^2 - n) 是平方数,记为 (y^2)

那么 (x^2 - n = y^2),进而根据平方差公式即可分解 N

那么使用平方差公式(Fermat 算法)

n=p⋅q=(p+q2)2−(q−p2)2=t2−s2n = p \cdot q = \left(\frac{p+q}{2}\right)^2 - \left(\frac{q-p}{2}\right)^2 = t^2 - s^2

其中:

  • t=p+q2t = \dfrac{p+q}{2} —— 两个因子的均值,t≈p≈q≈nt \approx p \approx q \approx \sqrt{n}
  • s=q−p2s = \dfrac{q-p}{2} —— 差值的一半,s≈2.5×106s \approx 2.5 \times 10^6

于是 n=(t+s)(t−s)n = (t+s)(t-s),因子 p=t−sp = t-s,q=t+sq = t+s。

Fermat 算法:从 t=⌈n⌉t = \lceil\sqrt{n}\rceil 开始,计算 t2−nt^2 - n 是否为完全平方数。如果是,则 s=t2−ns = \sqrt{t^2 - n},分解成功。

t2=n+s2t^2 = n + s^2t=n+s2=n⋅1+s2nt = \sqrt{n + s^2} = \sqrt{n} \cdot \sqrt{1 + \frac{s^2}{n}}

Taylor 展开:

1+ε≈1+ε2(ε≪1)\sqrt{1 + \varepsilon} \approx 1 + \frac{\varepsilon}{2} \quad (\varepsilon \ll 1)t≈n⋅(1+s22n)=n+s22nt \approx \sqrt{n} \cdot \left(1 + \frac{s^2}{2n}\right) = \sqrt{n} + \frac{s^2}{2\sqrt{n}}

代入数值:

  • s2≈(2.55×106)2≈6.5×1012≈243s^2 \approx (2.55 \times 10^6)^2 \approx 6.5 \times 10^{12} \approx 2^{43}
  • n≈22048\sqrt{n} \approx 2^{2048}
s22n≈24322049=2−2006≪1\frac{s^2}{2\sqrt{n}} \approx \frac{2^{43}}{2^{2049}} = 2^{-2006} \ll 1

tt 与 n\sqrt{n} 的偏差约为 2−20062^{-2006},远小于 1。

因此 t=⌈n⌉t = \lceil\sqrt{n}\rceil

脚本:

import gmpy2
from Crypto.Util.number import *
c = 263008606417090478566565299810283124941804126507113525587390677503293194343666087681964773019395280446205407691484774718932550281467537401219675254528173987088938774386502897118203537632220602323914308216229335629593724857802179137161994764652047523675709008286064448828023140237566132983016003115673355564648923477918580240197355351101233161015345869099779377748188971444727339859346227316840479889105162116347476243712080281172197785928605069437778934843702674790549009254968801469403071588920441238715453737896667478751217639321474363829766785705632819377446277423897444229208300944065442708855610919362463870409750865618966436909679416475224935654779108492443347930157015362069031445961698740874449398633416274993312148761043683846969413714438518714752086418643505351718069185918950309997110990358633504996993095219569951691320773244853704939426164506912622629836798640173907936986385737630181302799243239569229123640543209312682734240635326031049265324015549955077829367091796287221865653193037735196635197439609673972466210706114120142070802091713212287909213710633272650703644600005643328190463554693180030667114903774309621791748550174052862095206625927960781050796459818989538815307653741523716288252629280835076948046895601
n = 359336501271521532887656688609295042672434709877081900753462802000755944104448697042366747461395534728915053035475459015263877654779607712559439958640046447246795492613180033737648218742508752449971055824413830268089448680617248179389657713305429663149548581330682010843775095659107771083498691437964118187909080096258126217389687367383301166809926191321584757387431941409060744328371424948988833446651828309230245313487641590365198484255142967088588384318797132203546546629955996480505149111166600546126192029751124771571918693276230154597894534213860659972166774036644473508159923466417979740342453286817394016723536509392328304731594460395586984216646043768390806512181233642534151692135644819066105646943194201485395325911256860832603278670900133367627500162513041761043011626948699652168654976313717938901597808754267996648935745100287531478172712432058146052903388546565632174028182472012197791653306648067962114207504888841853254752313822184342829344043028253285087763176816976839219602985900752633788798421802365156777163724743521780060375607506242692718315299078104710983637353515944430437712607451078303509530539260657291973611896675785100483218112781144038004807688281170137433780853291933873671533348523292439854954465561
e = 0x10001
t = gmpy2.isqrt(n) + 1
s = gmpy2.isqrt(t * t - n)
p = t - s
q = t + s
assert p * q == n
phi = (p - 1) * (q - 1)
d = int(gmpy2.invert(e, phi))
m = pow(c, d, n)
flag = long_to_bytes(m).decode()
print(f"\n{flag}")

NumberTheory-MyGrandson#

孙子 有什么数论跟他有关吗?#

源码:#

from Crypto.Util.number import*
import random
prime_list = []
while len(prime_list) != 10:
p = getPrime(512)
if p not in prime_list:
prime_list.append(p)
n_list = []
while len(prime_list) != 0 :
p = random.choice(prime_list)
prime_list.remove(p)
q = random.choice(prime_list)
prime_list.remove(q)
n = p * q
n_list.append(n)
e = 0x3
flag = xxxx
m = bytes_to_long(flag)
c_list = []
for i in range(5):
c_list.append(pow(m,e,n_list[i]))
print(n_list)
print(c_list)
'''
[77233172536159741192246613655283165880196613060552611951771270688104936106776346258707301903094880666395585340631862009130750364252309591238056576753936210560429561770824923088840307835401343591389063817665516081122335870477455981026885268249200998526090677712273308041387000143133795229713482478393789372621, 70794324572924578170904176367785397571585515343841766471270776641893534562091735386206579244229072036331675198665823877108424439019515198192572105111245725566358049561022661780408911208342637594250037944058109688775177723617220023349151285447135301481172151520373371753145483943469882142519628143415523743463, 93761217774409345065712026096494766259059400214289981179452977682878853429771707722391625256415829980979321889115942716112362554641424767683650504053039711982239972950462675978125739670042221693517477062545050595319035580175500989651485917759297158328957400110168748398966355865895154979662685437655175232187, 124529202589219244628054131473440686077969827415379239572516697161425506945161335214321076138377196624342679966748136249190446302054453599336468401444986625483801237391516131671890908955031274838978095000660651399041484751377373528279323583222966113362380418012251381389500548026241296381301140473951308631467, 60402137932600451202064823101449766068323185392267470715893320550946146689486181577700090960854688975492966004126295374528198973614156097511239714353778658971704224697111332966918059572112633110487150490907161982337993576588831137499701656665339000413922782862243877535428631203689690715707499925757364765349]
[25681920037857462308038008456804236725305902130578298860433144085656782676411434281544156794249690534545397408244321828543334304937398521739382233631303709676426573143503446051379370337969083171791612381925477, 25681920037857462308038008456804236725305902130578298860433144085656782676411434281544156794249690534545397408244321828543334304937398521739382233631303709676426573143503446051379370337969083171791612381925477, 25681920037857462308038008456804236725305902130578298860433144085656782676411434281544156794249690534545397408244321828543334304937398521739382233631303709676426573143503446051379370337969083171791612381925477, 25681920037857462308038008456804236725305902130578298860433144085656782676411434281544156794249690534545397408244321828543334304937398521739382233631303709676426573143503446051379370337969083171791612381925477, 25681920037857462308038008456804236725305902130578298860433144085656782676411434281544156794249690534545397408244321828543334304937398521739382233631303709676426573143503446051379370337969083171791612381925477]
'''

观察题目回发现这个题目也是RSA,属于e较小类型,点击这里访问RSA公钥指数攻击

并且发现5条c_list都一样

那么说明c_list就是明文本身,由于e=3,对c_list直接开立方就是明文

得到脚本:

import gmpy2
from Crypto.Util.number import *
c = 25681920037857462308038008456804236725305902130578298860433144085656782676411434281544\
19674969053454539740824432182854333430493739852173938223363130370967642657314350344605\
1379370337969069083171791612381925477
m, exact = gmpy2.iroot(c, 3)
assert exact
flag = long_to_bytes(m).decode()
print(f"Flag: {flag}")

NumberTheory-Powwwwwer#

我的Power超级大~ 可能看看共模是什么内容呢?#

源码:#

from Crypto.Util.number import *
p = getPrime(512)
q = getPrime(512)
flag = xxxxx
m = bytes_to_long(flag)
n = p * q
e1 = 0x114514
e2 = 11451401
c1 = pow(m,e1,n)
c2 = pow(m,e2,n)
print(c1)
print(c2)
print(n)
'''
47220438825147485602004110821622560065904207675219860468929327492230243119464967323930295623259686691976072363819976125368307866223981062386682077438030452670319556977872343275419275297828846355087444641575933688543206152050119271402939885941719672725566836549228027040543887994457719131600949478670978241146
115435415972673976853578931507112950322194896557724940548983105717498084920603530063295392396344585245149536619546139549595643165285610305977637286040529163780201012187105549728000887169595946039777889559399483628995380569296124138575774025562472143420878790970785857061634021973901034670780393435693955936244
136101507305579392638535644920761633964164170724862786826983346232384615490056114520867809528578619044234996682189743771790469301482774597055261893015794231752161620186891313083697906603842794202124169703689691049507643124840305144271549786654248958903748746153284903228556081709492696702282014035715848536699
'''

依旧RSA,从题目中可以知道要利用共模 从wiki中可以看到


共模攻击#

攻击条件

当两个用户使用相同的模数 NN、不同的私钥时,加密同一明文消息时即存在共模攻击。

攻击原理

设两个用户的公钥分别为 e1e_1 和 e2e_2,且两者互质。明文消息为 mm,密文分别为:

c1=me1 mod Nc_1 = m^{e_1} \bmod Nc2=me2 mod Nc_2 = m^{e_2} \bmod N

当攻击者截获 c1c_1 和 c2c_2 后,就可以恢复出明文。用扩展欧几里得算法求出 re1+se2=1 mod nr e_1 + s e_2 = 1 \bmod n 的两个整数 rr 和 ss,由此可得:

c1rc2s≡mre1mse2 mod nc_1^r c_2^s \equiv m^{r e_1} m^{s e_2} \bmod n≡m(re1+se2) mod n\equiv m^{(r e_1 + s e_2)} \bmod n≡m mod n\equiv m \bmod n

利用a * e1 + b * e2 = gcd(e1, e2) 直接写脚本得:

from Crypto.Util.number import *
from gmpy2 import gcdext
c1 = 47220438825147485602004110821622560065904207675219860468929327492230243119464967323930295623259686691976072363819976125368307866223981062386682077438030452670319556977872343275419275297828846355087444641575933688543206152050119271402939885941719672725566836549228027040543887994457719131600949478670978241146
c2 = 115435415972673976853578931507112950322194896557724940548983105717498084920603530063295392396344585245149536619546139549595643165285610305977637286040529163780201012187105549728000887169595946039777889559399483628995380569296124138575774025562472143420878790970785857061634021973901034670780393435693955936244
n = 136101507305579392638535644920761633964164170724862786826983346232384615490056114520867809528578619044234996682189743771790469301482774597055261893015794231752161620186891313083697906603842794202124169703689691049507643124840305144271549786654248958903748746153284903228556081709492696702282014035715848536699
e1 = 0x114514
e2 = 11451401
g, a, b = gcdext(e1, e2)
if g == 1:
if a < 0:
c1_inv = inverse(c1, n)
m = pow(c1_inv, -a, n) * pow(c2, b, n) % n
elif b < 0:
c2_inv = inverse(c2, n)
m = pow(c1, a, n) * pow(c2_inv, -b, n) % n
else:
m = pow(c1, a, n) * pow(c2, b, n) % n
flag = long_to_bytes(m)
print(flag.decode())

得到

moectf{s0_Powwwwwwwwwwwww3r!}

PRintNewG#

如果化成 多元方程呢#

源码:#

import random
from Crypto.Util.number import*
from FLAG import flag
class PRintNewG:
def __init__(self,seed):
self.state = seed
self.a = random.randint(2**256,2**257)
self.b = random.randint(2**256,2**257)
if self.b > self.a:
self.b = self.b - self.a
self.n = getPrime(257)
def NewG(self):
self.state = (self.a * self.state + self.b) % self.n
print(self.state)
PrintNewG = PRintNewG(bytes_to_long(flag))
print(PrintNewG.n)
PrintNewG.NewG()
PrintNewG.NewG()
PrintNewG.NewG()
'''
164955381960104851576442781839629371483790790743830073857213053104860144345367
67066424717605861916529090048670931008913194546199003522357504998012803616537
14585402872351563180055857554749250191721167730349724393021149201170995608751
68393939370424772490169906192546208899639826391163845848999554903218827210979
'''

题目的输出是n和后面三个状态,那么要求初始值,先求出a,b 对状态加密进行分析

def NewG(self):
self.state = (self.a * self.state + self.b) % self.n
print(self.state)

记初始 state(flag)为 s0s_0,依次输出 s1,s2,s3s_1, s_2, s_3,则有:

s1=a⋅s0+b(modn)s_1 = a \cdot s_0 + b \pmod ns2=a⋅s1+b(modn)s_2 = a \cdot s_1 + b \pmod ns3=a⋅s2+b(modn)s_3 = a \cdot s_2 + b \pmod n

变形一下得到

s2−s1≡a⋅(s1−s0)(modn)s3−s2≡a⋅(s2−s1)(modn)\begin{aligned} s_2 - s_1 &\equiv a \cdot (s_1 - s_0) \pmod{n} \\ s_3 - s_2 &\equiv a \cdot (s_2 - s_1) \pmod{n} \end{aligned}

因此: 对a

a≡(s3−s2)⋅(s2−s1)−1(modn)a \equiv (s_3 - s_2) \cdot (s_2 - s_1)^{-1} \pmod{n}

对b

b≡s2−a⋅s1(modn)b \equiv s_2 - a \cdot s_1 \pmod{n}

就可以推出s0s_0

s0≡(s1−b)⋅a−1(modn)s_0 \equiv (s_1 - b) \cdot a^{-1} \pmod{n}

就可以得到脚本

from Crypto.Util.number import *
n = 164955381960104851576442781839629371483790790743830073857213053104860144345367
s1 = 67066424717605861916529090048670931008913194546199003522357504998012803616537
s2 = 14585402872351563180055857554749250191721167730349724393021149201170995608751
s3 = 68393939370424772490169906192546208899639826391163845848999554903218827210979
a = (s3 - s2) * inverse(s2 - s1, n) % n
b = (s2 - a * s1) % n
s0 = (s1 - b) * inverse(a, n) % n
print(long_to_bytes(s0))

得到结果:

moectf{PR1nt_N3w_G_s0_e45y}

Signin#

”你这个e取得有问题吧“#

”没有“(嘴硬)#

源码:#

from Crypto.Util.number import *
from secret import flag
m=bytes_to_long(flag)
p=getPrime(512)
q=getPrime(512)
print('p=',p)
print('q=',q)
n=p*q
e=65537
c=pow(m,e,n)
print('c=',c)
#p= 12408795636519868275579286477747181009018504169827579387457997229774738126230652970860811085539129972962189443268046963335610845404214331426857155412988073
#q= 12190036856294802286447270376342375357864587534233715766210874702670724440751066267168907565322961270655972226761426182258587581206888580394726683112820379
#c= 68960610962019321576894097705679955071402844421318149418040507036722717269530195000135979777852568744281930839319120003106023209276898286482202725287026853925179071583797231099755287410760748104635674307266042492611618076506037004587354018148812584502385622631122387857218023049204722123597067641896169655595

直接公式化打法

φ(n) = (p - 1) * (q - 1)
d = e⁻¹ mod φ(n)
m = c^d mod n

在下面这一步出现报错

phi = (p - 1) * (q - 1)
d = inverse(e, phi) # 报错!ValueError: base is not invertible for the given modulus

说明e 与 φ(n) 不互质。 检查 e 与 p-1、q-1 的关系,发现

e = 65537(素数)
p - 1 mod e ≠ 0 → gcd(e, p-1) = 1 (可正常求逆元)
q - 1 mod e = 0 → gcd(e, q-1) = 65537 (e与q-1不互质)

对于模 p,RSA 解密正常工作,可以唯一确定 m mod p,而q不行 那么要看如何只用p就求出flag 召唤d老师给给思路,发现有这样一个定理#

CRT(中国剩余定理,Chinese Remainder Theorem):对于两两互质的模数,可将大规模同余方程拆分为小模数下分别求解,再合并回原模数。

在 RSA 解密中:

已知: m ≡ m_p (mod p), m ≡ m_q (mod q)
求: m mod n (n = p * q)

合并公式:

m = m_p + p * ((m_q - m_p) * qinv mod q)

其中 qinv = q⁻¹ mod p。

RSA 解密常用参数:

参数含义公式
d完整私钥d = e⁻¹ mod φ(n)
dp模 p 的私钥分量dp = e⁻¹ mod (p-1)
dq模 q 的私钥分量dq = e⁻¹ mod (q-1)
qinvq 在模 p 下的逆元qinv = q⁻¹ mod p

CRT 解密流程:

m_p = c^dp mod p ← 模 p 下运算(512 位,比 1024 位快)
m_q = c^dq mod q ← 模 q 下运算(512 位)
h = (m_q - m_p) * qinv mod q
m = m_p + h * p

优势:模 p、q 下的幂运算是模 n 的一半位数,乘法运算快约 4 倍,因此实际 RSA 实现(OpenSSL 等)广泛使用 dp、dq、qinv 配合 CRT 加速解密。#

由于m < p,那么 m mod p = m,就可以只需在模 p 下解密

dp = inverse(e, p - 1)
m_p = pow(c, dp, p)

此时m = m_p,得到脚本

from Crypto.Util.number import long_to_bytes
p = 12408795636519868275579286477747181009018504169827579387457997229774738126230652970860811085539129972962189443268046963335610845404214331426857155412988073
e = 65537
c = 68960610962019321576894097705679955071402844421318149418040507036722717269530195000135979777852568744281930839319120003106023209276898286482202725287026853925179071583797231099755287410760748104635674307266042492611618076506037004587354018148812584502385622631122387857218023049204722123597067641896169655595
dp = pow(e, -1, p - 1)
m = pow(c, dp, p)
flag = long_to_bytes(m)
print(flag.decode())

得出结果:

moectf{Oh~Now_Y0u_Kn0W_HoW_RsA_W0rkS!}

Weird_E_Revenge#

“你为什么执迷不悟?”#

源码:#

from Crypto.Util.number import *
import random
from secret import flag
table='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
pad=100-len(flag)
for i in range(pad):
flag+=random.choice(table).encode()
e=343284449
m=bytes_to_long(flag)
assert m>(1<<512)
assert m<(1<<1024)
p=getPrime(512)
q=getPrime(512)
r=getPrime(512)
print('p=',p)
print('q=',q)
print('r=',r)
n1=p*q
n2=q*r
c1=pow(m,e,n1)
c2=pow(m,e,n2)
print('c1=',c1)
print('c2=',c2)
#p= 11820891196647569262137841192985418014377132106496147254821784946481523526822939129065042819464351666077658751406165276121125571355594004514547517855730743
#q= 10450390015864176713581330969519712299844487112687677452105216477861582967322473997670559995588440097951786576039009337782247912476227937589298529580432797
#r= 9484954066160968219229920429258150817546418633451929876581842443665029377287119340232501682142185708534413073877473741393278935479791561681402673403009771
#c1= 69574855207460025252857869494766338442370688922127811393280455950372371842144946699073877876005649281006116543528211809466226185922844601714337317797534664683681334132261584497953105754257846471069875622054326463757746293958069752489458646460121725019594141157667480846709081917530190233900184428943585065316
#c2= 66183492015178047844987766781469734325646160179923242098082430373061510938987908656007752256556018402101435698352339429316390909525615464024332856855411414576031970267795270882896721069952171988506477519737923165566896609181813523905810373359029413963666924039857159685161563252396502381297700252749204993228

可以看到有两个n,且n1 = p*q, n2 = q*r,有共享因子 q,m位数为513到1024之间 检查两个模是否互素,发现不是,那么突破口不在这里

gcd(n1, n2) = gcd(p*q, q*r) = q ≠ 1

看题发现flag被pad填充到100字节,那么m的长度就是800bit,而p*q和p*r都是262144位远大于m,那可以尝试一下上面那道题的解法 对三个因子计算有:

gcd(e, p-1) = 1
gcd(e, q-1) = 343284449
gcd(e, r-1) = 1

那么只可以用p和r计算,要完全复刻上题了

dp = inverse(e, p-1)
mp = pow(c1, dp, p)
e×dp≡1(modp−1)e × dp ≡ 1 (mod p-1)mp≡c1dp≡m(e×dp)≡m(modp)mp ≡ c1^dp ≡ m^(e×dp) ≡ m (mod p)
dr = inverse(e, r-1)
mr = pow(c2, dr, r)

同上

mr≡m(modr)mr ≡ m (mod r)

CRT 合并

m ≡ mp (mod p)
m ≡ mr (mod r)

用 CRT 合并,得到唯一的 m mod (p×r)。

因为 m < p×r,这个结果就是 m 本身。

m = CRT([mp, mr], [p, r])

得到脚本:

from Crypto.Util.number import *
p = 11820891196647569262137841192985418014377132106496147254821784946481523526822939129065042819464351666077658751406165276121125571355594004514547517855730743
q = 10450390015864176713581330969519712299844487112687677452105216477861582967322473997670559995588440097951786576039009337782247912476227937589298529580432797
r = 9484954066160968219229920429258150817546418633451929876581842443665029377287119340232501682142185708534413073877473741393278935479791561681402673403009771
c1 = 69574855207460025252857869494766338442370688922127811393280455950372371842144946699073877876005649281006116543528211809466226185922844601714337317797534664683681334132261584497953105754257846471069875622054326463757746293958069752489458646460121725019594141157667480846709081917530190233900184428943585065316
c2 = 66183492015178047844987766781469734325646160179923242098082430373061510938987908656007752256556018402101435698352339429316390909525615464024332856855411414576031970267795270882896721069952171988506477519737923165566896609181813523905810373359029413963666924039857159685161563252396502381297700252749204993228
e = 343284449
def crt(remainders, moduli):
M = 1
for m in moduli:
M *= m
result = 0
for r, m in zip(remainders, moduli):
Mi = M // m
inv = inverse(Mi, m)
result += r * Mi * inv
return result % M
dp = inverse(e, p - 1)
mp = pow(c1, dp, p)
dr = inverse(e, r - 1)
mr = pow(c2, dr, r)
m = crt([mp, mr], [p, r])
flag = long_to_bytes(m)
print(flag)

得到

moectf{Th1s_iS_Chinese_rEm41nDeR_The0rEm_CRT!}

beginOfCrypto#

来看看密码这里简单的内容呢?哦,其实也不能算密码~#

源码:#

import math
flag = xxx
data = list(map(ord,flag))
cip = []
for i in range(len(data)):
cip.append(math.e**data[i])
print(cip)
'''
[2.178203880729008e+47, 1.6094870669615087e+48, 7.307059979368028e+43, 9.889030319346894e+42, 2.3886906014249767e+50, 1.9862648361376436e+44,
2.6195173187490456e+53, 9.889030319346894e+42, 7.016735912097614e+20, 2.178203880729008e+47, 7.307059979368028e+43, 1.811239082889014e+41,
1.6094870669615087e+48, 5.920972027664636e+47, 214643579785915.7, 3.6379709476087856e+42, 7.307059979368028e+43, 5.399227610580139e+44,
3.989519570547194e+45, 5.920972027664636e+47, 1.811239082889014e+41, 3.5451311827611436e+52, 1.6094870669615087e+48, 6.493134255664421e+50,
3.23274119108484e+49, 1.811239082889014e+41, 1.2523631708422093e+29, 3.23274119108484e+49, 3.5451311827611436e+52, 4.375039447261315e+48,
2.3886906014249767e+50, 7.016735912097614e+20, 1.811239082889014e+41, 9.889030319346894e+42, 3.831008000716566e+22, 3.23274119108484e+49,
1.4093490824269349e+22, 1.4093490824269349e+22, 3.23274119108484e+49, 1.9355760420357097e+54]
'''

分析代码,发现map(ord,flag),flag被转成ASCII码装进了data里, 又从cip.append(math.e**data[i])发现cip的每个元素的值为eord(flag[i])e ^ {ord(flag[i])} 那么对cip进行逆运算就可以了,对每个密文数值取自然对数,再四舍五入转回字符

flag[i] = chr(round(ln(cip[i])))

解题脚本:

import math
cip = [
2.178203880729008e+47, 1.6094870669615087e+48, 7.307059979368028e+43,
9.889030319346894e+42, 2.3886906014249767e+50, 1.9862648361376436e+44,
2.6195173187490456e+53, 9.889030319346894e+42, 7.016735912097614e+20,
2.178203880729008e+47, 7.307059979368028e+43, 1.811239082889014e+41,
1.6094870669615087e+48, 5.920972027664636e+47, 214643579785915.7,
3.6379709476087856e+42, 7.307059979368028e+43, 5.399227610580139e+44,
3.989519570547194e+45, 5.920972027664636e+47, 1.811239082889014e+41,
3.5451311827611436e+52, 1.6094870669615087e+48, 6.493134255664421e+50,
3.23274119108484e+49, 1.811239082889014e+41, 1.2523631708422093e+29,
3.23274119108484e+49, 3.5451311827611436e+52, 4.375039447261315e+48,
2.3886906014249767e+50, 7.016735912097614e+20, 1.811239082889014e+41,
9.889030319346894e+42, 3.831008000716566e+22, 3.23274119108484e+49,
1.4093490824269349e+22, 1.4093490824269349e+22, 3.23274119108484e+49,
1.9355760420357097e+54
]
flag = ''.join(chr(round(math.log(v))) for v in cip)
print(flag)

得到:

moectf{c0me_on!begin_your_Crypt0_c4r33r}

ezRSA#

Math is a good friend!这里可是用到了不少的数论的基础~#

Hint : 试一下改变一下模数?#

源码:#

from Crypto.Util.number import *
flag = bytes_to_long(xxxxx)
p,q,r = getPrime(2048),getPrime(2048),getPrime(2048)
n = p * q * r
e = 0x10001
s = getPrime(300)
print(160 * s ** 5 - 4999 * s ** 4 + 3 * s ** 3 +1)
gift = (pow(p, (q-1)*(r-1)*q*r, (q*r) ** 3)* pow(q*r+1, q, (q*r)**3)) % (q*r)**3
print(gift)
phi = (p-1)*(q-1)*(r-1)
d = inverse(e,phi)
k = (p-s)*d
enc = pow(flag,e,n)
print(n)
print(k)
print(enc)
'''
2034324732495484527271326648264363832432019085176906369400995629590813377636685491145735369195442424540861519869848697139877795792719688366320904262945619042925136256863161005997244326203592289032375254549895986813362427744415267948474242075064613552597148522843157295972913918030691059852518534926511660794984167497876919410349603505973131815413029138776259177035704839417711286893525297932372114011908375566351923679018386971863796083830329957855513893
264538642078817426697928935494109369091100765669708256343339239746327661961054495338323044973861383442460356074469769048318331151491693455787475438857379532215186540369681225919872845326312982290870668804275531429568972541597897346334080748720408740020226527282094900804427566211661902761579056579841347129798501960394833757887596880264320099770915639882613669683823270058300314518476211534354107532616412334970025586214844535446894584275240578696579120887177522531082032306251090401223919859196445061179033562556885731046934060186430337541296264775301284795426781405636246952402678269837902667967940409589470749890015917841677791541741919239967329670534490765713034250333876219147243955238159111536772071572381643551365878208973458158180535344378216264872296430840318567285527224529280779573833968605898871982424168035291584573620251754840530466438462200350151894316226316806763578034744947351074412949491876090043528304132453695442770954311558704165350370902849030078730844075268205143993503876133205733288091330224937394414638438466288390343045525150663541253109445639546761907076760555313527195616308927577174518199559691028618095268123553133489217706402660560567362638953211564314107466005803441345158863073730538137222359034055149434395880718411878853735380852282957823824074553440991388413033593705455372139699844560804052138453869163879635998690059695465331464026584733954071099083129945135923272143827317962721746173403093159324877738883074637071812105277007416119734384965962010483950030054134628817163734391504391668622725636043103736757664917288081792381352233747198863107489250618843284668300519224414350717273498384292204442834010927504724528885153910278143636385387106982541405865879392237850266849008683188085575657517128082046108809334810685448881691979594554572400573702076298785363210936415014025014717675547707977989688555183301910196904743494765187553180689532254161276753853857735454936613570872304235528882218328198909448495399173705205498524577619281778150008574202886486993761025249213139581006381438489110309454282751453819388629809229558379788681817196485798256890246649193460368238018386176487964323942320351884974506951516526531590672928047180012517699640611143176018704400272526967995618325791881491645444944234429889635320473410296241742953286270932577282359841811235797829402602484669104519221518351769118214107702767391939093509839615943887043690632796616259135926941722974414380968079150312541177620340561105754587598829533078281539017642854088276824137924786580465367741893562352968746880085394732741704828798820789893558442367201101648181612358834108686684137516181289341539682120590415663670521938931056187481117181327386723131168085258211424550525782485532766575843037148856337613643171617197129019519129006682085869598620722413122591445820366297976185295098524555455686521948570483883854144885779773967693971493781062985065150734236334890823411210478767056435937755854343216494824706914761070963720739540186726865264132260938391925127652798636827808055476292765027414632476269029308018212266796224968563849236144068944762704311876207377643615588747904655949454108993793049138572173584936652557115607359959534796654365479281278496690731307392238827302912788233496281910777459761340125924768868742763861666251325401148558987119905538412299634644749362488793850433209977382283162489965034861480071188148403652086059936853519833443371988283066129208687060469587424817203644333750342276607550942095453195833103798687484676167580837109095114877283923618562027655203928397032166795242677016996475709061676417869299716702716381677710451168039322578089652354946178111644964419836243503083959740881242272603615138286786157945832086379417600047320277390122999819251550561
14733131394763854324801736395460194491676306639665026418887576200503251059236644134261117619135520761144081847183833136533608552521463945214005555978752034071442168490091275991499959406404073494873772549172349737926696209852128449573911317883227774809034639400853743050240028566809743487927049386967427077767575509135527003909254380186209685231624024444284280426118403612513361144208283953432564705981498736581845668573945569535634425302702606238030492145090485605859647081945710464832753900405302764564449963709768024801952759292594427479421369795673893680685388969982848915648722021386801706987803231656237750755186427322037150557311621725139260871613565575785013222175963107050725351647743995691153312953905764968159679084062183442811412358968503100681073113098539029731235026687415969311024215606151214218875860443005772356846039108370759175821838817394885970591998524036933462495928280660300815916825104394483688206925786058977693515290527323786473385552418497260292589485972946966521758268792703048184124531465839419130137157833420728214958156198598849279610427947620245293637630669971527038083179450310859241147294555690690954510363718732413762556970404340373340656969161601362926040252636605117732366908820527370798436080645190858138749034908117755519788225308168904854591176909671983702350880234310638881842440970349469132857473101373909492937045147214313750715546800973221019305591717665277731425354581669130640798834899606084332136424593619021233704551559788114826413087863140805626777510289777643075905434947517920648948713834962189337267876441624586849725703846641302808478777803739879430026643677048884347519645990202909516249645752006104829297836745720653274358196473628223323106258112622358571412237480400213380841237135111978808139274852493316926911687237030866220282759807111312449570652128112714405674339488483021376127332175964593
166851249658446875412118520562112094009218741427949455022450544199444917632804024460404660201607397175092065468285797607386924970642639345521943887458654134881099888480475268521280937476446582586826406337224344838100938223497274008880073160260015642977220086102849116227699957847561036648700146535314346703972058633880630868898547507583642707080250612943422781240909095212219397549462503817218958389279543836192796790477501726350795505247047645709568397495124364912887367625545307874016585368829721404314319063606753540680585022202027444907653729176870656781124847265175633347622307570637230972495545755122820489209698490913929610846299165255334992271006698449688394044839611790470031017144413675249311924274727653149666125345819278167310154761929335468570028211828686289078075614233302277655432557804435007389627580256625243332004350166965136132131427786936245461429591482661633853424540286145770732522044804340409283102625483789948752047042413445659422880334211930665767297322136551656182477896053975217141294244955931025241662451907113118500973292420204778096076735006725873355292642153227258783269519242599119140341059896992827968925492485398352384375872791549217300691199167339232615839679087331618498985176596242830368278594898286860442268127077515555776604841305736048998639163750157459296187545816167029478996802256740580134136952017323797028791323843077941864785666373763954422770721521703544158336364525195257408956603092022124375800860804947765808792766878272548161586510188119673084890236620197339209818914910434103179712319782195111960035071743519639271248884805006298462972511799153141649046862225500937824206273637112067634192476418592892557980778384703022601754720251738289469695642702551426974268365043897176132571929273806999266366991844913728012776616099622373424199051850986662550413475603552247924247099522630002596364368513505826600253953384547738554272428710752293319708342375554485507526481557469175731611940606494813078487544322433001872423957603398448676933869432470468634453063400021197354817620321604222080508880603762772101720026891647195695550358691309504302659716893491521387725546658010985136994997304775486894216799101593698930227025697769668464430322375671242364308704053533514958413063110469500058987753470004484869012219413378215134853691275455244183833126732993438080628733017608430403081779340295704930383557299670371326896888967717198793621263585115068028781217631520923227448503176673807459537016482635342403748668325914502800
5707218040333344302403261655546668722099748426779144537936348774092993349727998513751416884434796525658639465226479635422545851863133389037296460138627848781142418501836423198072890401052584123206053743303147946370590981492437765809211664823047371644385424389920163538804508811345140660279834156911973460017084654512275934599729472581717935298034512324194807306281132666728945494245189659203729443653430687024216292392882485053404574159800739235653230438432267985916317442890144281446614215220664376287570916851968251114530752189468928659007453703882704384233845339626403681917996905055874366888667001052407896835629387394144984104504728514662311591368101514655614133890081168220064540820335865256180316347878245981462963132328121487568378583378901571565067074864705626220414751890992269103379034097175610730997185097226584206897214014818181306651230923858641695931095588299526251795776562424213669629526749319954484065717419993314283167895749383210290655439082238095306248956895188986237712038062051770847717624081585653116896454317671411716594887956215629199027419580075717387193174428341494842535703034249343803544775181607737203671914711755572080448247442426762471020863045573508998134322983278372653222122101557283095775120183149522478096273795040350939852149352652243953736029302994598770064331220823144856075263032123407575786795474977550952269081506095057995504249425178659756484080441313583795310072414226380042557758712881574777618530587601037106539997289129714185905714787196861675724321796935186107538802131612301033782873572157472148810129032513146613473924912060237180029652039705342959706481811382110287373069667106872203620930510289289644829013512255215873270428345493466227789700273647641086859651211944094590800668832159110355967327106156839665441091282303534035421686852472084917481319414993084184134643452290073940555461605323135
'''

从源码可以知道n由三个素数相乘得来,s可以直接用逆运算得出来,再用s和k求出p和d的关系,而gift也可以用来求三个素数之间的关系。 先恢复s 已知:

print_s=160s5−4999s4+3s3+1\text{print\_s} = 160 s^5 - 4999 s^4 + 3 s^3 + 1

由于s是 300bit 的素数,s5s^5 的主导项系数为 160(远大于其它项系数),因此:

s≈print_s1605s \approx \sqrt[5]{\frac{\text{print\_s}}{160}}

对 val_s // 160 求 5 次整数根,然后在根附近搜索精确解即可得到s。

再来看gift 设qr = q * r gift 的计算分为两部分,均在模 (qr)3(qr)^3 下进行: 交给ai看看思路


欧拉定理:若 gcd⁡(a,n)=1\gcd(a, n) = 1,则:

aφ(n)≡1(modn)a^{\varphi(n)} \equiv 1 \pmod{n}

其中 φ(n)\varphi(n) 是欧拉函数,表示小于等于 nn 且与 nn 互质的正整数个数。

常用推论:若 gcd⁡(a,n)=1\gcd(a, n) = 1,则对任意整数 kk 有:

ak⋅φ(n)≡1(modn)a^{k \cdot \varphi(n)} \equiv 1 \pmod{n}

本题中的应用:

  • 取 a=pa = p,n=qrn = qr。由于 p,q,rp, q, r 是三个不同的素数,pp 不含因子 qq 或 rr,故 gcd⁡(p,qr)=1\gcd(p, qr) = 1。又 φ(qr)=(q−1)(r−1)\varphi(qr) = (q-1)(r-1),由欧拉定理得 p(q−1)(r−1)≡1(modqr)p^{(q-1)(r-1)} \equiv 1 \pmod{qr}。这是 Step 2 中证明 gift≡1(modqr)\text{gift} \equiv 1 \pmod{qr} 的关键。
  • 在 RSA 中,欧拉定理保证 e⋅d≡1(modφ(n))e \cdot d \equiv 1 \pmod{\varphi(n)} 时 me⋅d≡m(modn)m^{e \cdot d} \equiv m \pmod{n},这是后续所有步骤的基础。

第一部分:p(q−1)(r−1)qr mod (qr)3p^{(q-1)(r-1)qr} \bmod (qr)^3

由欧拉定理,φ(qr)=(q−1)(r−1)\varphi(qr) = (q-1)(r-1),且 gcd⁡(p,qr)=1\gcd(p, qr) = 1,所以:

p(q−1)(r−1)≡1(modqr)p^{(q-1)(r-1)} \equiv 1 \pmod{qr}

设 p(q−1)(r−1)=1+c⋅qrp^{(q-1)(r-1)} = 1 + c \cdot qr,则:

p(q−1)(r−1)qr=(1+c⋅qr)qr≡1(modqr)p^{(q-1)(r-1)qr} = \left(1 + c \cdot qr\right)^{qr} \equiv 1 \pmod{qr}

即第一部分在模 qrqr 意义下为 1。

第二部分:(qr+1)q mod (qr)3(qr + 1)^q \bmod (qr)^3

由二项式展开:

(qr+1)q=∑i=0q(qi)(qr)i≡1(modqr)(qr + 1)^q = \sum_{i=0}^{q} \binom{q}{i} (qr)^i \equiv 1 \pmod{qr}

模 qrqr 意义下也为 1。

结论:qr∣(gift−1)qr \mid (\text{gift} - 1),即 gcd⁡(gift−1,n)=qr\gcd(\text{gift} - 1, n) = qr(p 不整除 gift-1 的概率极小,约为 2−20482^{-2048})。

那么知道了pr,就可以用n来直接求出q

p=nqrp = \frac{n}{qr}

用k求出d 已知:

k=(p−s)⋅dk = (p - s) \cdot d

p 和 s 均已求出,所以:

d=kp−sd = \frac{k}{p - s}

到这里没有思路了,发现Hint为试一下改变一下模数,那么将e当成未知数试试 (此处借助了ai工具)可以知道题目中有:

e⋅d≡1(modφ),φ=(p−1)(q−1)(r−1)e \cdot d \equiv 1 \pmod{\varphi}, \quad \varphi = (p-1)(q-1)(r-1)

即存在整数 mm 使得:

e⋅d=1+m⋅φe \cdot d = 1 + m \cdot \varphi

由于 d<φd < \varphi,有 e⋅d<e⋅φe \cdot d < e \cdot \varphi,所以 m∈[1,e−1]m \in [1, e-1],即 m∈[1,65536]m \in [1, 65536]。范围不大,可枚举。

对于每个候选的 mm:

  1. 计算 φ=e⋅d−1m\varphi = \dfrac{e \cdot d - 1}{m}(需整除)
  2. 检查 (p−1)∣φ(p-1) \mid \varphi
  3. 由 φ=(p−1)(q−1)(r−1)=(p−1)(qr−q−r+1)\varphi = (p-1)(q-1)(r-1) = (p-1)(qr - q - r + 1) 得:
q+r=qr+1−φp−1q + r = qr + 1 - \frac{\varphi}{p-1}
  1. 已知 q+rq + r 和 q⋅r=qrq \cdot r = qr,解二次方程:
x2−(q+r)x+qr=0x^2 - (q+r)x + qr = 0Δ=(q+r)2−4qr\Delta = (q+r)^2 - 4qr
  1. 若 Δ\Delta 是完全平方数,则:
q=(q+r)+Δ2,r=(q+r)−Δ2q = \frac{(q+r) + \sqrt{\Delta}}{2}, \quad r = \frac{(q+r) - \sqrt{\Delta}}{2}
  1. 验证 q⋅r=qrq \cdot r = qr 且 q,rq, r 均为素数。

最终在 m=34277m = 34277 时成功分解。

这样就得到了p,q,r。

公式化打法

d_final = inverse(e, (p-1)*(q-1)*(r-1))
flag = pow(enc, d_final, n)

得到

moectf{5om3_M4th_m4y,b3_c0oool!}

ez_cbc#

这个分组加密(块密码)看起来好简单啊!可是我Key在哪呢?#

源码:#

from Crypto.Util.number import *
import random
from secret import flag
IV = bytes_to_long(b'cbc!')
K = random.randrange(1,1<<30)
assert flag[:7] == b'moectf{'
assert flag[-1:] == b'}'
block_length = 4
flag = flag + ((block_length - len(flag) % block_length) % block_length) * b'\x00'
plain_block = [flag[block_length * i: block_length * (i + 1)] for i in range(len(flag) // block_length)]
c = []
c0 = (IV ^ bytes_to_long(plain_block[0])) ^ K
c.append(c0)
for i in range(len(plain_block)-1):
c.append(c[i] ^ bytes_to_long(plain_block[i+1]) ^ K)
print(c)
'''
[748044282, 2053864743, 734492413, 675117672, 1691099828, 1729574447, 1691102180, 657669994, 1741780405, 842228028, 1909206003, 1797919307]
'''

对加密过程进行分析发现:

c = []
c0 = (IV ^ bytes_to_long(plain_block[0])) ^ K
c.append(c0)
for i in range(len(plain_block)-1):
c.append(c[i] ^ bytes_to_long(plain_block[i+1]) ^ K)

即

c[0] = (IV ^ P[0]) ^ K
c[1] = c[0] ^ P[1] ^ K
c[2] = c[1] ^ P[2] ^ K
c[3] = c[2] ^ P[3] ^ K

那么

P[0] = IV ^ c[0] ^ K
P[1] = c[0] ^ c[1] ^ K
P[i] = c[i-1] ^ c[i] ^ K (i ≥ 1)

从

block_length = 4
flag = flag + ((block_length - len(flag) % block_length) % block_length) * b'\x00'
plain_block = [flag[block_length * i: block_length * (i + 1)] for i in range(len(flag) // block_length)]

可以知道p 的块长度为4字节,那么P[0]就是moec,即P[0] = bytes_to_long(b'moec') = 1836016995 由源码其他部分可以得知IV = 1667392289 c[0] = IV ^ P[0] ^ K变换得到:K = IV ^ P[0] ^ c[0] 那么K = 580598200

P[0] = IV ^ c[0] ^ K
= 1667392289 ^ 748044282 ^ 580598200
P[1] = c[0] ^ c[1] ^ K
= 748044282 ^ 2053864743 ^ 580598200
P[2] = c[1] ^ c[2] ^ K
= 2053864743 ^ 734492413 ^ 580598200
以此类推,直到 P[11]

得到解题脚本:

from Crypto.Util.number import bytes_to_long, long_to_bytes
IV = bytes_to_long(b'cbc!')
c = [748044282, 2053864743, 734492413, 675117672,
1691099828, 1729574447, 1691102180, 657669994,
1741780405, 842228028, 1909206003, 1797919307]
K = IV ^ bytes_to_long(b'moec') ^ c[0]
blocks = []
blocks.append(long_to_bytes(IV ^ c[0] ^ K))
for i in range(1, len(c)):
blocks.append(long_to_bytes(c[i-1] ^ c[i] ^ K))
flag = b''.join(blocks).rstrip(b'\x00')
print(flag.decode())

运行结果:

moectf{es72b!a5-njad!@-#!@$sad-6bysgwy-1adsw8}

smooth#

源码:#

from Crypto.Util.number import sieve_base,isPrime,getPrime
import random
from secret import flag
def get_vulnerable_prime():
p=2
while True:
for i in range(136):
smallp=random.choice(sieve_base)
p*=smallp
if isPrime(p+1):
return p+1
P=get_vulnerable_prime()
Q=getPrime(2048)
N=P*Q
e=0x10001
for i in range(1,P-1729):
flag=flag*i%P
c=pow(flag,e,N)
print("c=",hex(c))
print("N=",hex(N))
'''
c= 0x3cc51d09c48948e2485820f6758fb10c7693c236acc527ad563ba8369c50a0bc3f650f39a871ee7ef127950ed916c5f4dc69894e11caf9d178cd7e8f9bf9af77e1c69384cc5444da64022b45636eeb5b7a221792880dd242be2bb99be3ed02c430c2b77d4912bec1619d664e066680910317c2bb0c87fafdf25f0a2400103278f557b8eca51d3b67d61098f1ab68da072bb2810596180afbc81a840cd24efef4d4113235160e725a5af4824dc716d758b3bc792f2458e979398e001b27e44d21682e2ef80ae94e21cd09a12e522ca2e569df72f012fa40341645445c6e68c6233a8a39e5b91eb14b1ccfa61c9bad25e8e3285a22da27cd506ddd63f207517a4e8ede00b104d8806ff4c0e3162c3de69169d7e584952655272b96d39d242bb83019c7eab1ceb0b4b287591e1e0a5b6378e70340a82d3430c5925d215f31fda6d9d0bccea240591b22a3d0f6b5bf4ddf1243d71aca0fd53045c352c8c5497ebcdbd7ac11083d63aba7c053604fda2430c317a4e04702b5ad539e110f101165b21dcd9fdb5ba7324acdba6a506244ce7c911197dfe067441fe7488d164c050f45ef6476aaf399cedde1793cceb8c21d88ec8ecf5e17df27586713d7dd9566ec5023cfef75422b73e2d5a932c661b3cfdf9c4bda12b64380d2be1aa957c3e1416e068937bafe79b8cf303296792388e9c197702e11e7ded6088ae992d352b23a4a27
N= 0xdc77f076092cbe81c44789ccfc1b2ca55eabae65f44cf34382799e8bbb42d4d6c032bd897c21df1da401929d82deb56264823a757f6cacf63e0037146026cbab32ab9e4abc783dcabaac2b7ccc439937be3ab0fbf149524ff29ef0fe6f27e45215d74b40597c70e8207159dc7f542c2a6828500016480053dfc2d8dbf8fcdf6700640184c8f3318f7aab2e17e116edf680592f5eae951159bb8c20cfbd0cbab8b4b95925b5068038d0377a55a4d346ebbf53a1c2943b7c17e1b9d4a1b77916da2e15140b05b96655906942a07d04b7e25fa7521b3b7ae26eda68375a8b8ef2d5b4704a28168b236de97f24a663f0d0a3aeab47767dfe75a21662f5f25ef7f7d4b25c90fd7bcdd7137c23f03b6ea4209f8fb9b4628355e6ad62e6467d26666d3d1b0e6f078c5f3866413a6fcd3c1dc2ff3a5ab286e339d5c72f4d2f0473a4faddcba6b031bb6ec226fd4b319834b5029f09ea0ffeb5b6ed182d5a13675571b6708c38299118043390343e2f79edebd2ae0e0a765a3aebf776f54ca983cdae8547547cfc8430f7222aefa77301d7cc7c03b1451b6603028b21fea869d35138a9c83919985a91b3fdfa934f25a442cc10349b0ed6f2ee3955d40249e8b3fb9f1955534ee06cee41a3ad2d6ff7dbdb0f01e47b9e4d04f65232f5579135ae035e8ba2d1fe6465a730dcc8b9ba3a558ab38f040ea510757d25e92f886c50c24ad967f1
'''

从源码可以知道这是一道RSA,接着从题目名字来看这题应该要利用平滑度来解题 查一下wiki发现#

p - 1 光滑#

光滑数 (Smooth number):指可以分解为小素数乘积的正整数

当 pp 是 NN 的因数,并且 p−1p-1 是光滑数,可以考虑使用Pollard’s p-1算法来分解 NN

根据费马小定理有

若 p∤ap \nmid a, 则 ap−1≡1(modp)a^{p-1} \equiv 1 \pmod p

则有

at(p−1)≡1t≡1(modp)a^{t(p-1)} \equiv 1^t \equiv 1 \pmod p

即

at(p−1)−1=k∗pa^{t(p-1)} - 1 = k * p

根据Pollard’s p-1算法:

如果 pp 是一个 B−smoothB-smooth numbernumber,那么则存在

M=∏q≤Bq⌊log⁡qB⌋M = \prod_{q \le B} q^{\lfloor \log_q B \rfloor}

使得 (p−1)∣M(p-1) \mid M 成立,则有

gcd⁡(aM−1,N)\gcd(a^M - 1, N)

如果结果不为 11 或 NN,那么就已成功分解 NN。

因为我们只关心最后的 gcd 结果,同时N只包含两个素因子,则我们不需要计算 MM,考虑 n=2,3,…n = 2, 3, \dots,令 M=n!M = n! 即可覆盖正确的 MM 同时方便计算。

在具体计算中,可以代入降幂进行计算

an!mod  N={(amod  N)2mod  Nn=2(a(n−1)!mod  N)nmod  Nn≥3a^{n!} \mod N = \begin{cases} (a \mod N)^2 \mod N & n = 2 \\ (a^{(n-1)!} \mod N)^n \mod N & n \ge 3 \end{cases}

Python 代码实现

from gmpy2 import *
a = 2
n = 2
while True:
a = powmod(a, n, N)
res = gcd(a-1, N)
if res != 1 and res != N:
q = N // res
d = invert(e, (res-1)*(q-1))
m = powmod(c, d, N)
print(m)
break
n += 1

p + 1 光滑#

当 pp 是 NN 的因数,并且 p+1p+1 是光滑数,可以考虑使用 Williams’s p+1 算法来分解 NN

算法原理#

已知 NN 的因数 pp,且 p+1p+1 是一个光滑数

p=(k∏i=1qiαi)+1p = \left(k \prod_{i=1} q_i^{\alpha_i}\right) + 1

qiq_i 即第 ii 个素因数且有 qiαi≤B1q_i^{\alpha_i} \le B_1,找到 βi\beta_i 使得让 qiβi≤B1q_i^{\beta_i} \le B_1 且 qiβi+1>B1q_i^{\beta_i+1} > B_1,然后令

R=k∏i=1qiβiR = k \prod_{i=1} q_i^{\beta_i}

显然有 p−1∣Rp-1 \mid R 且当 (N,a)=1(N, a) = 1 时有 ap−1≡1(modp)a^{p-1} \equiv 1 \pmod p,所以有 aR≡1(modp)a^R \equiv 1 \pmod p,即

p∣(N,aR−1)p \mid (N, a^R - 1)

类卢卡斯序列#

令 P,QP, Q 为整数,α,β\alpha, \beta 为方程 x2−Px+Q=0x^2 - Px + Q = 0 的根,定义如下类卢卡斯序列

Un(P,Q)=αn−βnα−βU_n(P, Q) = \dfrac{\alpha^n - \beta^n}{\alpha - \beta}

Vn(P,Q)=αn+βnV_n(P, Q) = \alpha^n + \beta^n

同样有 Δ=(α−β)2=P2−4Q\Delta = (\alpha - \beta)^2 = P^2 - 4Q,则有

{Un+1=PUn−QUn−1Vn+1=PVn−QVn−1(2.2)\begin{cases} U_{n+1} = P U_n - Q U_{n-1} \\ V_{n+1} = P V_n - Q V_{n-1} \end{cases} \tag{2.2}{U2n=VnUnV2n=Vn2−2Qn(2.3)\begin{cases} U_{2n} = V_n U_n \\ V_{2n} = V_n^2 - 2Q^n \end{cases} \tag{2.3}{U2n−1=Un2−QUn−12V2n−1=VnVn−1−PQn−1(2.4)\begin{cases} U_{2n-1} = U_n^2 - Q U_{n-1}^2 \\ V_{2n-1} = V_n V_{n-1} - P Q^{n-1} \end{cases} \tag{2.4}{ΔUn=PVn−2QVn−1Vn=PUn−2QUn−1(2.5)\begin{cases} \Delta U_n = P V_n - 2Q V_{n-1} \\ V_n = P U_n - 2Q U_{n-1} \end{cases} \tag{2.5}{Um+n=UmUn+1−QUm−1UnΔUm+n=VmVn+1−QVm−1Vn(2.6)\begin{cases} U_{m+n} = U_m U_{n+1} - Q U_{m-1} U_n \\ \Delta U_{m+n} = V_m V_{n+1} - Q V_{m-1} V_n \end{cases} \tag{2.6}{Un(Vk(P,Q),Qk)=Unk(P,Q)/Uk(P,Q)Vn(Vk(P,Q),Qk)=Vn(P,Q)(2.7)\begin{cases} U_n(V_k(P, Q), Q^k) = U_{nk}(P, Q) / U_k(P, Q) \\ V_n(V_k(P, Q), Q^k) = V_n(P, Q) \end{cases} \tag{2.7}

同时我们有如果 (N,Q)=1(N, Q) = 1 且 P′Q≡P2−2Q(modN)P'Q \equiv P^2 - 2Q \pmod N,则有 P′≡α/β+β/αP' \equiv \alpha/\beta + \beta/\alpha 以及 Q′≡α/β+β/α=1Q' \equiv \alpha/\beta + \beta/\alpha = 1,即

U2m(P,Q)≡PQm−1Um(P′,1)(modN)(2.8)U_{2m}(P, Q) \equiv P Q^{m-1} U_m(P', 1) \pmod N \tag{2.8}

扩展卢卡斯定理#

如果 pp 是奇素数,p∤Qp \nmid Q 且勒让德符号 (Δ/p)=ϵ(\Delta / p) = \epsilon,则

U(p−ϵ)m(P,Q)≡0(modp)U_{(p-\epsilon)m}(P, Q) \equiv 0 \pmod p

V(p−ϵ)m(P,Q)≡2Qm(1−ϵ)/2(modp)V_{(p-\epsilon)m}(P, Q) \equiv 2 Q^{m(1-\epsilon)/2} \pmod p

第一种情况:p+1 是光滑数#

已知 NN 的因数 pp,且 p+1p+1 是一个光滑数

p=(k∏i=1qiαi)−1p = \left(k \prod_{i=1} q_i^{\alpha_i}\right) - 1

有 p+1∣Rp+1 \mid R,当 (Q,N)=1(Q, N) = 1 且 (Δ/p)=−1(\Delta / p) = -1 时有 p∣UR(P,Q)p \mid U_R(P, Q),即 p∣(UR(P,Q),N)p \mid (U_R(P, Q), N)

Guy-Conway 递推公式#

为了找到 UR(P,Q)U_R(P, Q),Guy 和 Conway 提出可以使用如下公式

U2n−1=Un2−QUn−12U_{2n-1} = U_n^2 - Q U_{n-1}^2

U2n=Un(PUn−2QUn−1)U_{2n} = U_n (P U_n - 2Q U_{n-1})

U2n+1=PU2n−QU2n−1U_{2n+1} = P U_{2n} - Q U_{2n-1}

但是上述公式值太大了,不便运算,我们可以考虑如下方法

如果 p∣UR(P,1)p \mid U_R(P, 1),根据公式 (2.3) 有 p∣U2R(P,Q)p \mid U_{2R}(P, Q),所以根据公式 (2.8) 有 p∣UR(P′,1)p \mid U_R(P', 1),设 Q=1Q = 1,则有

V(p−ϵ)m(P,1)≡2(modp)V_{(p-\epsilon)m}(P, 1) \equiv 2 \pmod p

即,如果 p∣UR(P,1)p \mid U_R(P, 1),则 p∣(VR(P,1)−2)p \mid (V_R(P, 1) - 2)

归纳计算方法#

第一种情况可以归纳为:

让 R=r1r2r3⋯rmR = r_1 r_2 r_3 \cdots r_m,同时找到 P0P_0 使得 (P02−4,N)=1(P_0^2 - 4, N) = 1,定义 Vn(P)=Vn(P,1)V_n(P) = V_n(P, 1),Un(P)=Un(P,1)U_n(P) = U_n(P, 1) 且

Pj≡Vrj(Pj−1)(modN)(j=1,2,3,…,m)P_j \equiv V_{r_j}(P_{j-1}) \pmod N \quad (j = 1, 2, 3, \dots, m)

根据公式 (2.7),有

Pm≡VR(P0)(modN)(3.1)P_m \equiv V_R(P_0) \pmod N \tag{3.1}

计算 V_r 的二进制展开法#

要计算 Vr=Vr(P)V_r = V_r(P) 可以用如下公式

根据公式 (2.2),公式 (2.3),公式 (2.4) 有

{V2f−1≡VfVf−1−PV2f≡Vf2−2V2f+1≡PV2f−VfVf−1−P(modN)\begin{cases} V_{2f-1} \equiv V_f V_{f-1} - P \\ V_{2f} \equiv V_f^2 - 2 \\ V_{2f+1} \equiv P V_{2f} - V_f V_{f-1} - P \end{cases} \pmod N

令

r=∑i=0tbt2t−i(bi=0,1)r = \sum_{i=0}^t b_t 2^{t-i} \quad (b_i = 0, 1)

f0=1f_0 = 1,fk+1=2fk+bk+1f_{k+1} = 2f_k + b_{k+1},则 ft=rf_t = r,同样 V0(P)=2V_0(P) = 2,V1(P)=PV_1(P) = P,则最终公式为

(Vfk+1,Vfk+1−1)={(V2fk,V2fk−1)if bk+1=0(V2fk+1,V2fk)if bk+1=1(V_{f_{k+1}}, V_{f_{k+1}-1}) = \begin{cases} (V_{2f_k}, V_{2f_k - 1}) & \text{if } b_{k+1} = 0 \\ (V_{2f_k + 1}, V_{2f_k}) & \text{if } b_{k+1} = 1 \end{cases}

第二种情况:p+1 是光滑数(含大素数因子)#

已知 p+1p+1 是一个光滑数

p=s(k∏i=1qiαi)−1p = s \left(k \prod_{i=1} q_i^{\alpha_i}\right) - 1

当 ss 是素数,且 B1<s≤B2B_1 < s \le B_2,有 p∣(asm−1,N)p \mid (a^{sm} - 1, N)

定义 sjs_j 和 2dj2d_j

2dj=sj+1−sj2d_j = s_{j+1} - s_j

如果 (Δ/p)=−1(\Delta / p) = -1 且 p∤Pm−2p \nmid P_m - 2,则根据公式 (2.7) 和公式 (3.1) 有 p∣(Us(Pm),N)p \mid (U_s(P_m), N)

递推计算 T[s_i]#

令 U[n]≡Un(Pm)U[n] \equiv U_n(P_m),V[n]≡Vn(Pm)(modN)V[n] \equiv V_n(P_m) \pmod N,计算 U[2dj−1]U[2d_j - 1],U[2dj]U[2d_j],U[2dj+1]U[2d_j + 1]

通过

U[0]=0U[0] = 0,U[1]=1U[1] = 1,U[n+1]=PmU[n]−U[n−1]U[n+1] = P_m U[n] - U[n-1]

计算

T[si]≡ΔUsi(Pm)=ΔUsiR(P0)/UR(P0)(modN)T[s_i] \equiv \Delta U_{s_i}(P_m) = \Delta U_{s_i R}(P_0) / U_R(P_0) \pmod N

通过公式 (2.6),公式 (2.7) 和公式 (3.1) 有

{T[s1]≡PmV[s1]−2V[s1−1]T[s1−1]≡2V[s1]−PmV[s1−1](modN)\begin{cases} T[s_1] \equiv P_m V[s_1] - 2 V[s_1 - 1] \\ T[s_1 - 1] \equiv 2 V[s_1] - P_m V[s_1 - 1] \end{cases} \pmod N

即

{T[si+1]≡T[si]U[2di+1]−T[si−1]U[2di]T[si+1−1]≡T[si]U[2di]−T[si−1]U[2di−1](modN)\begin{cases} T[s_{i+1}] \equiv T[s_i] U[2d_i + 1] - T[s_i - 1] U[2d_i] \\ T[s_{i+1} - 1] \equiv T[s_i] U[2d_i] - T[s_i - 1] U[2d_i - 1] \end{cases} \pmod N

计算 H_t#

计算 T[si]T[s_i],i=1,2,3…i = 1, 2, 3 \dots,然后计算

Ht=(c∏i=0T[si+t],N)H_t = \left(c \prod_{i=0} T[s_{i+t}], N\right)

其中 t=1,c+1,2c+1,…,c[B2/c]+1t = 1, c+1, 2c+1, \dots, c[B_2/c] + 1,我们有 p∣Hip \mid H_i 当 (Δ/p)=−1(\Delta / p) = -1

Python 代码实现#

def mlucas(v, a, n):
""" Helper function for williams_pp1(). Multiplies along a Lucas sequence modulo n. """
v1, v2 = v, (v**2 - 2) % n
for bit in bin(a)[3:]:
v1, v2 = ((v1**2 - 2) % n, (v1*v2 - v) % n) if bit == "0" else ((v1*v2 - v) % n, (v2**2 - 2) % n)
return v1
for v in count(1):
for p in primegen():
e = ilog(isqrt(n), p)
if e == 0:
break
for _ in xrange(e):
v = mlucas(v, p, n)
g = gcd(v-2, n)
if 1 < g < n:
return g # g|n
if g == n:
break

分析p的生成函数

def get_vulnerable_prime():
p=2
while True:
for i in range(136):
smallp=random.choice(sieve_base)
p*=smallp
if isPrime(p+1):
return p+1

p 初始值为 22 每次循环:从 sieve_base(前 10000 个素数)中随机抽取 136 个素数乘到 p 上,初始的 22 也保留 而且p 不会重置——循环失败时 p 继续累积素因子,所以若循环执行了 K 次,P-1 恰好是 1+136K 个素因子之积 且p-1一定为素数的乘积,即p-1为光滑数 考虑使用Pollard’s p-1算法来分解

from gmpy2 import *
a = 2
n = 2
while True:
a = powmod(a, n, N)
res = gcd(a-1, N)
if res != 1 and res != N:
q = N // res
d = invert(e, (res-1)*(q-1))
m = powmod(c, d, N)
print(m)
break
n += 1

没思路了ai一下#

2. P-1 的性质与 Pollard’s p−1p-1 方法#

P−1P-1 的每个素因子均 ≤104729\le 104729,且幂次较低(137 个球投入 10000 个箱,期望每个箱约 0.01370.0137 个,极大概率任何素因子幂次 ≤3\le 3)。

这意味着 P−1P-1 是 BB-smooth 的(B=104729B = 104729),经典 Pollard p−1p-1 可分解 NN。

但是有陷阱:P−1P-1 中素数可能重复出现。Pollard p−1p-1 利用 B!B! 作为指数时,素数 pp 在 B!B! 中的幂为:

∑j=1⌊log⁡pB⌋⌊Bpj⌋\sum_{j=1}^{\lfloor\log_p B\rfloor} \left\lfloor\frac{B}{p^j}\right\rfloor

若 BB 仅取 104729,对接近 104729 的大素数,B!B! 中该素数仅出现 1 次。而 P−1P-1 中大素数可能被 P−1P-1 取了 2 次(概率约 60%)。因此需要

⌊B104729⌋≥2⟹B≥209458\left\lfloor\frac{B}{104729}\right\rfloor \ge 2 \quad\Longrightarrow\quad B \ge 209458

取 B=250000B = 250000 可保证 sieve_base 中每元素在 B!B! 中出现 ≥2\ge 2 次,同时小素数幂次极大,完全覆盖 P−1P-1 的因子统计。

3. 实际 Pollard p−1p-1 实施#

逐 k=2,3,…,250000k=2,3,\dots,250000 执行:

a = 2
for k in range(2, B + 1):
a = pow(a, k, N)
# 每隔若干步检查 gcd(a-1, N)

相当于计算 a=2B!(modN)a = 2^{B!} \pmod N。当 P−1∣B!P-1 \mid B! 时,2B!≡1(modP)2^{B!} \equiv 1 \pmod P,从而 gcd⁡(a−1,N)=P\gcd(a-1, N) = P。实验在 k=150000k=150000 时就找到了 PP(2049 比特)。

4. 解密 cc#

得到 PP 后,Q=N/PQ = N / P,计算私钥 dp=e−1(modP−1)d_p = e^{-1} \pmod{P-1}:

flag′=cdp(modP)\text{flag}' = c^{d_p} \pmod P

注:因为 flag′<P\text{flag}' < P,直接模 PP 解密即可恢复原有值。

5. 逆转阶乘乘法——Wilson 定理#

原始 flag 经过变换:

flag′=flag×(P−1730)!(modP)\text{flag}' = \text{flag} \times (P-1730)! \pmod P

需要计算 (P−1730)!(P-1730)! 模 PP 的逆元。由 Wilson 定理:

(P−1)!≡−1(modP)(P-1)! \equiv -1 \pmod P

将 (P−1)!(P-1)! 拆解:

(P−1730)!⏟=  flag′/flag×(P−1729)(P−1728)⋯(P−1)⏟共 1729 个因子≡−1(modP)\underbrace{(P-1730)!}_{=\;\text{flag}'/\text{flag}} \times \underbrace{(P-1729)(P-1728)\cdots(P-1)}_{\text{共 } 1729 \text{ 个因子}} \equiv -1 \pmod P

对于后 17291729 项,模 PP 下有 P−i≡−i(modP)P-i \equiv -i \pmod P,故:

(P−1730)!×((−1)(−2)⋯(−1729))≡−1(modP)(P-1730)! \times \bigl((-1)(-2)\cdots(-1729)\bigr) \equiv -1 \pmod P(P−1730)!×(−1)1729×(1729)!≡−1(modP)(P-1730)! \times (-1)^{1729} \times (1729)! \equiv -1 \pmod P

17291729 为奇数,(−1)1729=−1(-1)^{1729} = -1:

(P−1730)!×(−1)×(1729)!≡−1(modP)(P-1730)! \times (-1) \times (1729)! \equiv -1 \pmod P(P−1730)!×(1729)!≡1(modP)(P-1730)! \times (1729)! \equiv 1 \pmod P

即 (P−1730)!(P-1730)! 的逆元恰好是 1729!1729!。最终:

flag=flag′×1729!(modP)\text{flag} = \text{flag}' \times 1729! \pmod P

1729 即是著名的 Hardy-Ramanujan 出租车数(最小的可用两种不同方式表示为两立方数之和的数:1729=13+123=93+1031729=1^3+12^3=9^3+10^3),在此作为一道优美的数学彩蛋。

Flag: moectf{Charming_primes!_But_Sm0oth_p-1_1s_vu1nerab1e!}#


一次就好#

“一次就好,我陪你去看天荒地老~~~~”#

源码:#

from Crypto.Util.strxor import strxor
from Crypto.Util.number import *
from gmpy2 import powmod,next_prime
from FLAG import flag
import codecs
c = b'Just once,I will accompany you to see the world'
flag = flag.ljust(len(c),'#')
key = strxor(flag.encode(), c)
m = bytes_to_long(key)
p = getPrime(512)
q = next_prime(p)
N = p*q
e = 0x10001
gift = powmod(m, e, N)
print(gift)
print(N)
# gift = 127749242340004016446001520961422059381052911692861305057396462507126566256652316418648339729479729456613704261614569202080544183416817827900318057127539938899577580150210279291202882125162360563285794285643498788533366420857232908632854569967831654923280152015070999912426044356353393293132914925252494215314
# N = 164395171965189899201846744244839588935095288852148507114700855000512464673975991783671493756953831066569435489213778701866548078207835105414442567008315975881952023037557292470005621852113709605286462434049311321175270134326956812936961821511753256992797013020030263567313257339785161436188882721736453384403

发现这是一个RSA加上XOR加密 而且q是p的下一个素数,两个素数很接近 在wiki中可以看到如何利用|p-q|较小的情况#

|p-q| 较小#

原理分析#

首先

(p+q)24−n=(p+q)24−pq=(p−q)24\frac{(p+q)^2}{4} - n = \frac{(p+q)^2}{4} - pq = \frac{(p-q)^2}{4}

既然 ∣p−q∣|p-q| 较小,那么 (p−q)24\frac{(p-q)^2}{4} 自然也比较小,进而 (p+q)24\frac{(p+q)^2}{4} 只是比 NN 稍微大一点,所以 p+q2\frac{p+q}{2} 与 n\sqrt{n} 相近。

分解方法#

那么我们可以按照如下方法来分解 NN:

顺序检查 n\sqrt{n} 的每一个整数 xx,直到找到一个 xx 使得 x2−nx^2 - n 是平方数,记为 y2y^2

那么 x2−n=y2x^2 - n = y^2,进而根据平方差公式即可分解 NN

数学推导#

由 x2−n=y2x^2 - n = y^2 可得

x2−y2=nx^2 - y^2 = n

根据平方差公式

(x−y)(x+y)=n(x - y)(x + y) = n

因此

p=x−y,q=x+yp = x - y, \quad q = x + y

这样就成功分解了 NN。

算法步骤#

  1. 计算 x=⌈n⌉x = \lceil \sqrt{n} \rceil
  2. 循环计算 y2=x2−ny^2 = x^2 - n
  3. 如果 y2y^2 是完全平方数,则分解成功
  4. 否则 x=x+1x = x + 1,继续步骤 2

Python 代码实现#

from gmpy2 import isqrt
def factorize_close_primes(n):
"""
当 |p-q| 较小时,使用 Fermat 分解法
"""
x = isqrt(n) + 1 # 从 sqrt(n) 向上取整开始
while True:
y2 = x * x - n
y = isqrt(y2)
if y * y == y2: # 检查是否为完全平方数
p = x - y
q = x + y
return p, q
x += 1
# 使用示例
n = 123456789 # 假设这是 N
p, q = factorize_close_primes(n)
print(f"p = {p}, q = {q}")
print(f"p * q = {p * q}")

那么对N开方然后向下寻找,将可以整除N的数字作为p,除了N得到数字可以作为q,然后公式化打法 得到脚本:

from Crypto.Util.strxor import strxor
from Crypto.Util.number import long_to_bytes, bytes_to_long
from gmpy2 import invert, iroot
c = b'Just once,I will accompany you to see the world'
gift = 127749242340004016446001520961422059381052911692861305057...
N = 1643951719651898992018467442448395889350952888521485071147...
e = 0x10001
approx_p = int(iroot(N, 2)[0])
p = approx_p
while N % p != 0:
p -= 1
q = N // p
phi = (p - 1) * (q - 1)
d = invert(e, phi)
m = pow(gift, d, N)
key = long_to_bytes(m)
flag = strxor(key, c)
print(flag)

得到:

moectf{W0w_y02_k5ow_w6at_1s_one_t1m3_pa7}

不止一次#

“一次就好,我陪你去看天荒地老”~~~ 可是,如果有机会可以不止一次呢? 你 能否把握住那个key吗?#

附件:#

05010c1201035b3909530d7f3750035d304d41063a18021c3e550e3a075e41014211440f
0306141611460f250046593c355f035c2b1903017f5b130f3c5d003b4f52031643451618
050e1143170715230e46593d31110e413e5a0a013b14410c2a42452d0603140a4500175d
080106110d160f240e5c592b3152055d364814017f4c090f2b16063e0d1c0e171707015d
050e1143170715230e46593d31110e413e5a0a013b14410c2a42452d0603140a4500175d
0f1a114306030a3808401c2c744505567f4c12017f57074e3e1616360d150d061a101718
1e0a450c12461a6d125b1738385440462c5c41142d5d4c1d3757173a07520a064e451015
414f110b11461423041f0d3639544d433e5d414c106c31477f5f167f021c410659061604
4d000b06591212200412093e3011457c0b694844364b410f3116003100001813430c0b13
0e0400075846193815120b3a254404413a4a4110375d411b2c53453005520043440c0a1a
0b4f0443070f152a0d57542a27544d432d5c4c173759130b3b160e3a1a52150b56114414
1906080654161a29411a360b04184d5a2c19000a7f5d0f0d2d4f152b0a1d0f4343000715
4d1c0c0d130a1e6014411c7f2443081e2c5100163a5c41053a4f452b0b1315435e164413
144345171c035b220f57542b3d5c08132f5805447777353e76160c2c43130f43520b070f
094f4d2c2036526d0841593e3a11085d3c4b18142b510e007f42003c0b1c081242004409

附件为数字与字母混合,猜测是十六进制,以两位为单位拆分 根据题目的提示,大概是利用了key对flag进行xor运算进行加密 发现第三行与第五行一样说明应该是使用了一个key对整个flag进行加密 那么要从密文推测出key

核心方法#

若同一密钥 KK 加密了两条明文 P1P_1 和 P2P_2:

{C1=P1⊕KC2=P2⊕K\begin{cases} C_1 = P_1 \oplus K \\ C_2 = P_2 \oplus K \end{cases}

异或两条密文:

C1⊕C2=(P1⊕K)⊕(P2⊕K)=P1⊕P2C_1 \oplus C_2 = (P_1 \oplus K) \oplus (P_2 \oplus K) = P_1 \oplus P_2

密钥 KK 被完美抵消了。攻击者得到了两条明文的异或 P1⊕P2P_1 \oplus P_2。#

利用空格来猜测密钥:

运算结果说明
' ' ⊕ 'A' (0x20 ⊕ 0x41)'a' (0x61)空格 XOR 大写 A → 小写 a
' ' ⊕ 'a' (0x20 ⊕ 0x61)'A' (0x41)空格 XOR 小写 a → 大写 A
' ' ⊕ ' ' (0x20 ⊕ 0x20)0x00两个空格 → 零
如果两行明文的同一位置异或后是字母([A-Za-z]),说明这两行中至少有一行在该位置是空格!

到这里有些没思路了,a一下发现要用投票来猜测密钥#

来看一个具体字节位置。以位置 0(每行的第 1 个字节)为例,15 行的第 0 字节:

第 1 行 ct[0] = 0x05
第 2 行 ct[0] = 0x03
第 3 行 ct[0] = 0x05
第 4 行 ct[0] = 0x08
第 5 行 ct[0] = 0x05
第 6 行 ct[0] = 0x0f
第 7 行 ct[0] = 0x1e
第 8 行 ct[0] = 0x41
第 9 行 ct[0] = 0x4d
第10 行 ct[0] = 0x0e
第11 行 ct[0] = 0x0b
第12 行 ct[0] = 0x19
第13 行 ct[0] = 0x4d
第14 行 ct[0] = 0x14
第15 行 ct[0] = 0x09

现在对每对密文计算 XOR,看结果是不是字母。以第 9 行和第 4 行为例:

第 9 行 ct[0] = 0x4d
第 4 行 ct[0] = 0x08
XOR 结果 = 0x4d ⊕ 0x08 = 0x45 = 'E' (大写字母!)

XOR 结果是 ‘E’,是字母!这说明第 4 行和第 9 行的该位置,至少一个是空格。

现在用程序对全部 15 行、全部 36 个位置、所有 (152)=105\binom{15}{2}=105 对组合进行计算和投票:

位置 0 的投票结果:
第 1 行: 投了 5 票(与 5 行的 XOR 结果是字母 → 它可能是空格)
第 2 行: 投了 6 票
第 3 行: 投了 5 票
...
第 9 行: 投了 8 票 ← 最高票!它最可能是空格!
→ key[0] = ct[0]_第9行 ⊕ 0x20 = 0x4d ⊕ 0x20 = 0x6d = 'm'

对所有 36 个位置做同样的事情,得到 36 字节的粗恢复密钥。#

发现第一次的恢复结果为:moectf{Ma2y_T13_9ad_8an_6e_orac7ed}` 错了 说明一次的投票精确度还不够 用这个粗密钥解密第 4 行密文:

ct₄(hex): 08 01 06 11 0d 16 0f 24 0e 5c 59 2b 31 52 05 5d 36 48 ...
解密过程(逐字节 XOR):
位置 0: ct₄[0] ⊕ key[0] = 0x08 ⊕ 0x6d = 0x65 = 'e' ✓
位置 1: ct₄[1] ⊕ key[1] = 0x01 ⊕ 0x6f = 0x6e = 'n' ✓
位置 2: ct₄[2] ⊕ key[2] = 0x06 ⊕ 0x65 = 0x63 = 'c' ✓
... ... ... ...
位置12: ct₄[12]⊕ key[12]= 0x31 ⊕ 0x54 = 0x65 = 'e' ✓
位置13: ct₄[13]⊕ key[13]= 0x52 ⊕ 0x60 = 0x32 = '2' ✗(这里应该是 'c'!)
... ... ... ...
第 4 行解密结果:
"encryption tec2nique that cabnot be "
正确的应该是:
"encryption technique that cannot be c "
↑↑ ↑
这里错了 这里有错

后面交给ai来弄了#

4.1 确定正确明文#

从解密片段已经可以推断出,这些英文来自 Wikipedia 对 One-Time Pad 的词条描述:

“In cryptography, the one-time pad (OTP) is an encryption technique that cannot be cracked, but requires the use of a single-use pre-shared key that is not shorter than the message.”

这 15 行是这段文字的 15 个 36 字节滑动窗口(每行偏移不同)。

4.2 选取第 4 行作为「已知明文」#

第 4 行在第 3 个窗口位置(第 4 行),粗解密结果是:

e n c r y p t i o n t e c 2 n i q u e t h a t c a b n o t b e

根据维基原文,它应该是:

e n c r y p t i o n t e c h n i q u e t h a t c a n n o t b e c
↑
补一个 'c' 凑齐 36 字节

即 36 字节的精确明文:b"encryption technique that cannot be c"

4.3 逐个字节恢复精确密钥#

有了已知密文和已知明文,密钥 = 密文 ⊕ 明文:

# 第 4 行密文的 36 个字节
ct4 = [0x08, 0x01, 0x06, 0x11, 0x0d, 0x16, 0x0f, 0x24, 0x0e, 0x5c,
0x59, 0x2b, 0x31, 0x52, 0x05, 0x5d, 0x36, 0x48, 0x14, 0x01,
0x7f, 0x4c, 0x09, 0x0f, 0x2b, 0x16, 0x06, 0x3e, 0x0d, 0x1c,
0x0e, 0x17, 0x17, 0x07, 0x01, 0x5d]
# 已知明文(36 字节):"encryption technique that cannot be c"
pt4 = [0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x71, 0x75, 0x65,
0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x6e,
0x6f, 0x74, 0x20, 0x62, 0x65, 0x20]
# 密钥 = 密文 ⊕ 明文
key = [ct4[j] ^ pt4[j] for j in range(36)]

逐字节演示几个位置:

位置 0: key[0] = 0x08 ⊕ 0x65 = 0x6d = 'm'
位置 1: key[1] = 0x01 ⊕ 0x6e = 0x6f = 'o'
位置 7: key[7] = 0x24 ⊕ 0x69 = 0x4d = 'M'
位置12: key[12] = 0x31 ⊕ 0x65 = 0x54 = 'T'
位置13: key[13] = 0x52 ⊕ 0x63 = 0x31 = '1' ← 粗恢复时这里错成了 0x60('`')
位置14: key[14] = 0x05 ⊕ 0x68 = 0x6d = 'm' ← 粗恢复时这里错成了 0x33('3')

所有 36 字节穷举完毕后,得到精确 key:

6d 6f 65 63 74 66 7b 4d 61 32 79 5f 54 31 6d 33 5f 39 61 64 5f 38 61 6e 5f 36 65 5f 63 72 61 63 37 65 64 7d
m o e c t f { M a 2 y _ T 1 m 3 _ 9 a d _ 8 a n _ 6 e _ c r a c 7 e d }

4.4 验证:解密所有 15 行#

用精确密钥逐行解密:

行解密结果说明
1hnique that cannot be cracked, but r从 “technique…” 的 “hnique” 开始
2nique that cannot be cracked, but re往后移了一个字符
3hat cannot be cracked, but requires ”that can…“
4encryption technique that cannot be 这是我们的锚点行
5hat cannot be cracked, but requires 与第 3 行相同
6but requires the use of a single-use”…but requires the use of a single-use”
7se of a single-use pre-shared key th”use of a single-use pre-shared key th…“
8, the one-time pad (OTP) is an encry”, the one-time pad (OTP) is an encryption…“
9 one-time pad (OTP) is an encryption” one-time pad (OTP) is an encryption…“
10cked, but requires the use of a sing”cracked, but requires the use of a single-use…“
11f a single-use pre-shared key that i”of a single-use pre-shared key that is…“
12time pad (OTP) is an encryption tech”one-time pad (OTP) is an encryption technique…“
13 single-use pre-shared key that is n”a single-use pre-shared key that is not…“
14y, the one-time pad (OTP) is an encr”ography, the one-time pad (OTP) is an encryption…“
15d (OTP) is an encryption technique t”pad (OTP) is an encryption technique that…”

全部是连贯的自然英文,说明密钥 100% 正确。


五、最终 Flag#

5.1 Flag 原文#

moectf{Ma2y_T1m3_9ad_8an_6e_crac7ed}

5.2 Leet(黑客语)逐词解读#

Leet 单词正常拼写替换规则
Ma2yMany2 形似 n
T1m3Time1 ↔ i, 3 ↔ e
9adPad9 形似 p
8ancan8 读音近 c(如 “gr8” = “great”)
6ebe6 读音近 b
crac7edcracked7 ↔ k

完整句子:“Many Time Pad can be cracked” (多次一密可以被破解)


六、完整可运行解题脚本#

#!/usr/bin/env python3
"""
============================================================
附件.txt 解题脚本 —— Many-Time Pad 攻击完整实现
适用读者:密码学初学者
每一步都有详细注释,读懂注释就能理解攻击原理
============================================================
"""
# =============================================================
# 第 1 步:读取密文(15 行 hex → 15 个 bytes 对象)
# =============================================================
with open('附件.txt', 'r') as f:
# 读取每一行,去掉空白,如果是空行就跳过
hex_lines = [line.strip() for line in f if line.strip()]
# bytes.fromhex() 把 "05010c12..." 这种 hex 字符串转成真正的 bytes
# "05" → 字节 0x05 = 5
# "01" → 字节 0x01 = 1
# "0c" → 字节 0x0c = 12
# ...
cts = [bytearray.fromhex(line) for line in hex_lines]
NUM_MSGS = len(cts) # 15
MSG_LEN = len(cts[0]) # 36
print(f"读取到 {NUM_MSGS} 行,每行 {MSG_LEN} 字节")
print()
# =============================================================
# 第 2 步:检查有没有重复行(快速判断是否 key 复用)
# =============================================================
print("=" * 60)
print("第 2 步:检查重复行")
print("=" * 60)
for i in range(NUM_MSGS):
for j in range(i + 1, NUM_MSGS):
if cts[i] == cts[j]:
print(f" ★ 发现:第 {i+1} 行 = 第 {j+1} 行(密文完全相同)")
print(f" 这说明它们用了相同的密钥和相同的明文!")
print()
# =============================================================
# 第 3 步:Space-Based 频率分析(粗恢复密钥)
# =============================================================
print("=" * 60)
print("第 3 步:Space-Based 频率分析")
print("=" * 60)
# space_votes[i][j] = 第 i 行在第 j 字节位置收到多少「可能是空格」的投票
space_votes = [[0] * MSG_LEN for _ in range(NUM_MSGS)]
# 对所有密文对 (i, k) 进行比较
for j in range(MSG_LEN): # 遍历每个字节位置
for i in range(NUM_MSGS): # 遍历每行密文
for k in range(i + 1, NUM_MSGS): # 与所有后面的行比较
xor_val = cts[i][j] ^ cts[k][j] # 密文 i 和 k 在位置 j 的异或
# 核心判断:如果 XOR 结果是字母 [A-Za-z],
# 说明 cts[i][j] 和 cts[k][j] 中有至少一个是空格异或字母
# (因为 ' ' ⊕ 字母 = 大小写翻转的字母)
if (0x41 <= xor_val <= 0x5A) or (0x61 <= xor_val <= 0x7A):
space_votes[i][j] += 1 # 给第 i 行投一票
space_votes[k][j] += 1 # 给第 k 行投一票
# 得票最多的行在该位置最可能是空格
key_approx = bytearray(MSG_LEN)
for j in range(MSG_LEN):
# 找到得票最多的行
best_row = 0
best_votes = 0
for i in range(NUM_MSGS):
if space_votes[i][j] > best_votes:
best_votes = space_votes[i][j]
best_row = i
# key = 密文 ⊕ 空格 = ct ⊕ 0x20
key_approx[j] = cts[best_row][j] ^ 0x20
print(f"粗恢复的 key(hex): {key_approx.hex()}")
print(f"粗恢复的 key(ASCII): {bytes(key_approx).decode(errors='replace')}")
print()
# =============================================================
# 第 4 步:用粗恢复 key 解密,查看错误
# =============================================================
print("=" * 60)
print("第 4 步:粗恢复 key 解密结果")
print("=" * 60)
for i in range(NUM_MSGS):
pt = bytes(cts[i][j] ^ key_approx[j] for j in range(MSG_LEN))
print(f" [{i+1:2d}] {pt.decode(errors='replace')}")
print()
print("注意第 4 行的 'tec2nique' 和 'cabnot' —— 这些是错误的!")
print("正确的应该是 'technique' 和 'cannot'。")
print()
# =============================================================
# 第 5 步:用已知明文修正密钥
# =============================================================
print("=" * 60)
print("第 5 步:已知明文修正")
print("=" * 60)
# 第 4 行密文
ct4 = cts[3]
# 已知第 4 行明文(来自 Wikipedia OTP 词条)
# "encryption technique that cannot be c" 恰好 36 字节
known_plaintext = b"encryption technique that cannot be c"
# 逐字节计算精确密钥
key_exact = bytearray(MSG_LEN)
for j in range(MSG_LEN):
key_exact[j] = ct4[j] ^ known_plaintext[j]
print(f"精确 key(ASCII): {bytes(key_exact).decode()}")
print()
# =============================================================
# 第 6 步:最终验证
# =============================================================
print("=" * 60)
print("第 6 步:最终解密(全部 15 行)")
print("=" * 60)
all_correct = True
for i in range(NUM_MSGS):
pt = bytes(cts[i][j] ^ key_exact[j] for j in range(MSG_LEN))
# 检查是否全部是可打印字符
is_readable = all(32 <= b < 127 for b in pt)
marker = "✓" if is_readable else "✗"
print(f" [{i+1:2d}] {pt.decode()} {marker}")
if not is_readable:
all_correct = False
print()
if all_correct:
print("★ 全部 15 行解密正确!密钥就是 FLAG。")
else:
print("还有错误行,需要继续修正。")
print()
print("=" * 60)
print(f"FLAG: {bytes(key_exact).decode()}")
print("=" * 60)

运行输出#

读取到 15 行,每行 36 字节
============================================================
第 2 步:检查重复行
============================================================
★ 发现:第 3 行 = 第 5 行(密文完全相同)
这说明它们用了相同的密钥和相同的明文!
============================================================
第 3 步:Space-Based 频率分析
============================================================
粗恢复的 key(hex): 6d6f656374667b4d6132795f543160335f3961645f38616e5f36655f6f7261633765647d
粗恢复的 key(ASCII): moectf{Ma2y_T1`3_9ad_8an_6e_orac7ed}
============================================================
第 4 步:粗恢复 key 解密结果
============================================================
[ 1] hnique that cacnot be crackeh, but r
[ 2] nique that cancot be cracked but re
[ 3] hat cannot be nracked, but riquires
[ 4] encryption tec2nique that cabnot be
[ 5] hat cannot be nracked, but riquires
[ 6] but requires tee use of a sibgle-use
...
============================================================
第 5 步:已知明文修正
============================================================
精确 key(ASCII): moectf{Ma2y_T1m3_9ad_8an_6e_crac7ed}
============================================================
第 6 步:最终解密(全部 15 行)
============================================================
[ 1] hnique that cannot be cracked, but r ✓
[ 2] nique that cannot be cracked, but re ✓
[ 3] hat cannot be cracked, but requires ✓
[ 4] encryption technique that cannot be ✓
[ 5] hat cannot be cracked, but requires ✓
[ 6] but requires the use of a single-use ✓
[ 7] se of a single-use pre-shared key th ✓
[ 8] , the one-time pad (OTP) is an encry ✓
[ 9] one-time pad (OTP) is an encryption ✓
[10] cked, but requires the use of a sing ✓
[11] f a single-use pre-shared key that i ✓
[12] time pad (OTP) is an encryption tech ✓
[13] single-use pre-shared key that is n ✓
[14] y, the one-time pad (OTP) is an encr ✓
[15] d (OTP) is an encryption technique t ✓
★ 全部 15 行解密正确!密钥就是 FLAG。
============================================================
FLAG: moectf{Ma2y_T1m3_9ad_8an_6e_crac7ed}
============================================================

七、总结#

项目说明
原始数据附件.txt,15 行,每行 36 字节 hex 编码密文
加密算法XOR(一次性密码本)
漏洞同一把 36 字节密钥加密了 15 条不同明文(many-time pad)
攻击步骤 1空间频率分析——利用「空格 ⊕ 字母 = 翻转大小写」的规律,投票恢复大部分密钥字节
攻击步骤 2已知明文修正——粗恢复 key 有约 5 个错误字节,用 Wikipedia 中已知的一句明文算出精确 key
Flagmoectf{Ma2y_T1m3_9ad_8an_6e_crac7ed}
Leet 翻译”Many Time Pad can be cracked”(多次一密可被破解)
核心教训One-Time Pad 的灵魂在于 “One-Time”;只要密钥用了一次以上,整个系统就崩溃了

马锤壳s#

线代也挺好玩emm#

源码:#

from sage.all import *
from Crypto.Util.number import *
from secret import flag
def _N2M_(num,wid):
mat = []
num = bin(num)[2:].rjust(wid*wid,'0')
for i in range(wid):
TMP = []
for j in range(wid):
TMP.append(int(num[i*wid + j]))
mat.append(TMP)
return mat
def _T_(mat,wid):
new_mat = []
for i in range(wid):
TMP = []
for j in range(wid):
TMP.append(int(mat[j][i]))
new_mat.append(TMP)
return new_mat
def _GenKeyM_(wid):
Prime_bits = 256
primes = [[getPrime(Prime_bits) for i in range(wid)] for j in range(wid)]
return primes
if __name__ == "__main__":
wid = 17
m = bytes_to_long(flag)
m = _T_(_N2M_(m,wid),wid)
m = Matrix(ZZ,m)
key = _GenKeyM_(wid)
c = m * Matrix(ZZ,key)
f = open(r'/output','w')
bigMOD = 2**512
A = 0x10001
B = 12138
KEY = A * Matrix(Zmod(bigMOD),key) + B
f.write("cipher : \n" + str(c) + '\nKEY :\n' + str(KEY))
f.close()

output:#

cipher :
[ 690075460965888439403283996132906142335219549787952243015852737054797769294596 693077347417162103044011041885159057653748649490104937250975017836087148556886 663941866626177580263927838076069952860257306631970205821411955292556188896800 768430857294122183062744981602183964088177647677954859682610171371842873265304 617359387305773979391405602214860729234586695931524685867853937399596002699498 632642048007114903313102028611793637181156467258674476895920372778248345585046 668586822412761190194063302745037933617829302394685510187045831629292634068552 707689499852429212782699675884848968743080660081252649051332927385262288981662 640481558716450174017300243436831681983066071671662403758764502582248481340574 691770923050542035260809017387055155338896936556764401957450430513482100275656 724447476288200289942701528800877900655234225464150457811992279197922197354214 711764749708473849541798989830623419970174747430326045861981036098726657442726 650363413723113230230422814221293436287365320547231381158911753402406256277080 750469618027631591881536860401611595130770570004920080624716546605769765689546 708303636929950025180142467335921010658477580162475283485404420379498331291684 657522197786280405746382825466712868420599297136340899880976467193725874288382 683309245413835298549942334166026201881853908145038117100194206839552938446812]
[ 798880397445304364003020663362088325656768652765586587156438766945396703620265 814291197219547510308726780859882785706590534339846658965636614067967977798695 748991112952223683765706042405115739727546190101940960448175651039727646636325 844253838927312270453738838224594796879826222826109823879138514397549392734357 771102192108881059048334608822078656836237315901788329960365299669475559628255 787961673963531946595665626230270224533402464852951318862432959291899743223501 747126835220779322242999756780694788184190211222189085608438876692380520610095 818447272449836674032914448053247777549176444715631406700589136677400883167897 807590288246160437032197241256074530730861297285338303251769920523308551489437 768104588646479226392514788276332000544573719487446636570050944236186737200463 798380062940118296736803417524841726237032026494125696611142809625761655350003 851217412584427722855011370689672863692271999166266329854963716384453222489693 725686686221678837671087488334241848046603797297272515920670272745083944996709 782855234903987937614731854240743350778275561605906761692904298561772918307129 843113012157236137546408119515249709197318929463260397394350306284351528378233 689487908146798115102125401115654515757478614787085803008733798972648524256457 740313970197715829012116765501337506699192146465036148891879962833142457837025]
[ 766971264896031022197050888234594103553509163656812587733083025389009428506065 847227781783791051373343929940863177697652657719104325552298768283949829773213 825132540433051619334609495065410330930408695761047149911875206481388950488263 831297461383044118142854457354419553100131996505609943002862037631877204639681 783259819798848379173502599518036905898527107562704946310476557350262531580739 813044519779512411827371428924089391897851574525465442808876803167255208310865 688244632932993676406189111789963194757573125846835855547779470612727446958753 815668520160280581178477508293810682318806563566305613468065883788688587424971 740432115035054130074606990362530070208526589314402980968841043325779000252921 689799199055431628155436611207916096964127932779987606199820038923021816660459 785180678271640364441764985721509619635487538752286867981574275437264187096775 869183701147315949264596060409442282060565269613925468883912090729739077903301 689124425624943613909909854433073446829022297563260989973507325762078678436685 780018882312379930845345357806491649849735990874629026766442450544430026262707 754759116223803598423829716485145152148037161424201657251632548752622290368287 795786064654415174972353390159647753593819738804121072098568645657322261673217 723703898147715870921531283395141718968029030227915892634024622133149266338279]
[ 686551208147668202763106975129997982311619030985488432638730301445891864174822 705298374894394978943660594295624622812136386303474520787610568173413650780724 697379663293348725277816179887954013397331935274271247589084926502473553901426 764992354548521621524267448902370511917617003026802385518244517507455428871720 626063932488091185833539041625336419225509056052437296756442848737123855547412 792836883576477359711197871023072617215560395476352537021918451141289414154512 627218289031625056235379145557904483966133747985860536411785302462772886937810 704465173942306425742798854933060521851126628818971290545561775812303986267064 672897657023159492584469720006204240909122129584009636871576544964349487045496 655720890988769053134486795395037431565222844791742028759863867339418300077528 684885419311903227253802161085228350988910452194911652023310863111792949498080 677870750106876784031544128717613619387144255096043323143451369697358331378872 710562104187210124629108027136793472042201790453103616163938498040004674146148 752247349787447714674063705440563318097105738721201695337816220270185067442214 619211943344829946370106690611375960911198873043289745020201504161445232041796 596385461894166134360491915620034162601498038377091532265868362755169505070500 658419891846053405705029648108257166820683068902388882247403934634190982672144]
[ 878062379136746863534694048309933512515857979182580646286957138087508523839144 859452000671813083024863439753209739135462279582134269550409918750652276633026 867938010809393559614017274231471630413455381500226186170796506907560288655252 987655089547428837992615068063516041621996825641987420069508536013875394348656 741143618032901608081008775623355126596411647370580473440704439706080300514264 804030997301070014972318787294538368954679466147106142727485614585050022156400 837682969751169506861973465820125970052102782728155983049456113717065415383300 885247095938117949738589454773068432999377788108547674721103093203963837775494 852449271617895280751948281639180195848761713327211889901790123338277709124616 918396566321928127813765386614233853125004473250357648391131326644859446003536 898721099166097580887154366912804092872235436493661641677293315561943091531510 893548408472064157284830464106073702367977231819654283619574959224585295250510 841480399162671014584337041145498106450705254595649513509167872562781270049792 951065493720053406018456287216841692456653331379031031080878139932610725347822 870912338261872476429642437041467987307870349408040785111292538203768975913966 791110591517656347264348335776030001641860035845738186617397671540097292196130 824638596064826392395931169925202150271879987663680382380360895631096505587702]
[ 639901506464305572724327689096154360885957407443415315786442907609498560805647 668223118951188900142273512978875250299773906533582996686213978502806731030307 592921205788597406005576651343903842792676259723475922030315484072754924428893 652719066981388229894448054265991950492112162458540408765669358380327394837189 552435012604636750135198961873806955464978595972472570322990618250479072840337 590503761887289339429715491299763856827320304926306965710008102399611721184407 559720733428104903641032460167040121764832386622605536150580768697222039832797 697117474762531152544499905033675225254992162411179047123125931611225497197903 569764608503336765520997908205604117332385998539911584282451051515069392110667 501343434453310872212718868550961952133833009200688856345905983691321511663031 646237914294663787581030859230035548076115685301224642042857388423179751464373 654896100612042762584792073123991133996170287539077963189880270970675884082685 573353281670954861671254910099981213065020620976261743056787569253912039365155 613059424691546038572014589558589150921059247555764589512864187077486565404327 614939379541454617669987078952352241731144863361899649789216819093991844345135 561828332639207015940385640937263754191262179416335861159979304871754091913081 543803785376196766679320522117039825676328705039137376926718450606811745396747]
[ 898935879138008104750791959292555784483760639042300304626282552953745244257036 854171755853629258844626203188727343944809990184335222696126129011782694514830 871323438610616654801713590614623549758028651725636676572117484718568638980758 940490645286489249889342098674040395858056438388687622324376907875223932262128 806017645989656387542814643260994968853451187087356554493397413413963127471038 930859486286493623783574168391736968663507673461067720223079215394452278831824 804300256080467041141757771838724968537886731701255224987460761598014992290286 862886185994087728883138370667647829775767805260333599571601565149416611307976 827853631707075432863550200561961156437957346418094522244949411503904576767454 844950636236553430738314229163504323243906169602973733976953042958822992907842 856308108132187169971791941925545600972570836873531082172597788038469322465466 907942869158473128765603534337185403646709047430097730368993693161066395296384 792400039697222852278467124370418904465818783689256113637096782204008010429256 956739574047031986382056422435392680722983420524319046224126648475010754901644 743041688309030321081521272667776220302926608132742498435315366457568701078530 819772312961025278827093171529560047844684359060747759557386118510747931033658 861321387529770194571818275326575077329250877846072468542667175999549432692964]
[1047945505695024575787520484773906397686021474443066207594728679531854347929396 1016157275146906143035628925739769280395399789573824587909729530603649158306004 1037512513382709338179122188742553233909133377887156659306391001448802338070650 1123241492275570783938190102081913375129669040215204629651764887281000522292678 925406205940882899611142968796446418108514447425392574317532755657215430720418 1020238987991607843483240200114219325103319160488252938430383739271400504050256 958794510966893196102190249374800758733323876814005168015231056911217482866506 1077117740946457956106656590360184391505979097018143562083161171445290706964782 1010442386960672442725035966775938926275513707873395734689984051617205993055538 1047845683601089546073202640448438401221787611803375540405649793738324031522728 1019628223745440072304172742468611002789851635740259434764322419974186640982940 1047123570488344001170654520312688437085901472873076583351086309913300967304064 1018741814057403171025453359563461602826474545227195734105086420235807061724552 1081657994787670419749630381570897384430868544363380458996730340938996451808280 1103298032693619774682961394478907553361362498003183132244877245855385897317444 945311907243248169509259201265722245853686288315168302299722525080729023401020 1028570993424255753191325429657568663314281076938706394866406815247937843678544]
[ 641493326851690092004260477289459924154954772289934237894581023040432612311895 571211865967233936088635532812750080552700238139524529226609075348778987958315 586148824641536183348302345135972855661536556685986056708159309207644618081125 692577100592079380476342738020773176654638928370050712555118309997042244500211 599106042772475143006158889168953836436642481114285584920808184232616389150711 579917252678683022405526939405952481416913688082244471035532202630427127476341 577337764252724460421178482859956373223434461190914963026917641978482351521909 590039157450274046139116500570330129149188003611551876108195254762291147464113 543961507631092197920819569233099761610996514289479773427708311135034056556881 588363717953638541433305922930800812461496590816705658977333300914113509512189 616101239464728393447323987519714917893002185823988845349177640535082289562401 663973160924759947506519844296629397873193008517828274387272756945485460099809 552037708731354576943232199759971352269360224334498243386966293981586475673075 696323753482130206808215814499271490921603221333737686124855124600546559579255 581645348061137575890768919446144297401550164863487342411458354464315333564143 542748647019542303749993247178433141379340901837047195084527867537409503308537 595165097547865820301500132546502989196146668178176359348404313585921475183453]
[ 805748523103243285396757325046906043296041225261212111107680582871175125741257 711065550087847243466356125492797261923151474027829053383014691596805471589519 726613067535494165554708661970748813349347439581724537709002316888374386673003 847952175037682206438414923806563640383938529325008334637749051263320874117235 707724252848458842646580888423960566716966239944637299786684343577732091233577 768385404597263674390843282746587014566829879443759815603410536573732161113293 783508573685100498509332913367556085752426987176610519671385381940495198670179 814453463986435863816795586106829274780580357141453038105260831997832558791909 742457555898806794844448308739945072453209811925664979006195864257605821784651 767200066623896759863759147951481230888411438301069535857267967797007588207083 817988655447373517386908304990625626456013486979369090334025271493948093050973 835930404505364447436034252634612440840388157894646800563772434891237337885995 739816320394269377702275585342089732880197482588186481603668244618138347097621 891099029054289317947781605775077781399145890052552553328633007714812978962431 757779146808813274511618946343843929381932617168776241475196409903785846479555 738171981084057040108088334499719022279793410501608378732091781120584373610613 725444220084096733368446116101743282897919855086902485643671658731190505206443]
[1179889461332029479185666981479009426848899713600090550611994766355894947088079 1158365866329656439954840703085094753258673151873558454545374943482393235272131 1153507547698171333734469220551632847491764303581789164908871054311902029400853 1237749343423793406777794312095064543088202246160379399071717412403860526067899 1072831964123970885184805089788831638631472173862112258876628170850446036884711 1141547140349022193327574152092884613599018070982024464217986026706290057020493 1068655314703066119776225878988711573765171161556230916008693569730591162776907 1150979496041554424776326343113181188230884263084319950910294870125893338761959 1051184450969942281042227772628904890856468883935075670195797701176903919317819 1010779129138822804241137918539768668119654750343207034058855280172743344073419 1122312865331978829865296468921456504172070391973045516315134597236735742403509 1218452707175168706102790237947215501172947445588403520514379892848008929631519 1025145715785155720593498829467435735750181973326364507450741145429217707693865 1158697117126259641535683481694204285523575151157348198613860061936560972476197 1132324334045754101143948603630658272960236314979678413905271345616466266743681 1059853122975270459684008130006445327949631908677867988169861401358668362152453 1122000956698247613444918195382803631758933829265250235627338122815301915602119]
[ 802426498246828859716951420997713922522345105367604013208432491475388933273687 852290138297648900677312043187802130664847547352111672383653544881986124941673 804680642001609493204700694167946718437861005972453469159779915771399318069813 852041954399289519509614092818041896472612063762009746461700616034150995052095 747157233973228392964708481696802504775736034803226258361751737863837186840341 792257569494623893502646893901166702638760335725338763928562681458893566684455 705199021409226428447582568325344042102545573952977383234824998694741207864203 771550545755385184606552688781167244712966045926456249387378734752362102803817 758204620634944268578671167782864072723806346943994447810176008074147512136425 772884702768678944093372636126030550472733527107174140894296211391241869758201 756696862295005905880120845923214109793476120227465708105462117750180841578509 815016465979189896262323792243515243832902102152095702594593753081581338078573 712511663159898610550674418704363788056536986264658767424609586862820262321557 797643702782752930873511000414945290786990636824541524166233563151094390944533 776949211301936035169461739719067234445985984769934376540423755695884433249609 749808687759520363346768542333192714322125490118612891265226528040627295048091 825889354691364734337690140213258818421388868073109684583082500505608531080173]
[ 621640102208305669087053538557473285022985865523000180164446766300218169839279 598040568021674704943758121932136433187894076376889226125720687947653500538171 586951483610193506679766346765163552731124959625643375117400062426913225007687 679360862927381372983064039810233571593240180353504789533590340640860199281839 542541216607881445684596896433788510293390858437729842173632008203642774072077 606267289976171055023485747882449645067437416339813977842376172528085773749927 547447275842250227061596429646675835865307463661062731392784937780594144368199 626769801460671910342682180981274871971942832131119172735813327934343836009307 593340027622927998051414557780323338310437371011599222865509339781376041364837 621610895994169195477777774812174561491004006629731353463862913838953830061583 617591417967056735550487543813718431959001364448870668845433782557269928635333 617785224861631149149077699255578051782568761810676381621559143112147526345967 565573017014002144976039296566362500322121892758413144483201130462221464833389 650207169869745420747883070301293126050414147454275528623298577885138953394443 600779813491725388656937808970378992398789588500566669753081672647378447541407 533658474066692622313801726109997931648931860330860464044060948919988251758657 519197273929589363046026953438215040984959431535588107215854190060838420331345]
[ 690806765905879077799228004030821092225170592993857710907390726081413479794096 728487781211843770155530841531319004666041605420413650303425907095107319339036 643547333464024188772673419609171790269913787071734425671055388044113342521748 733339967023742996735611181820099855026282324136184289049001408278909913249294 654553715277469344541082139937717703827280001858788237661845186786840038962490 728355594982970136572700459335552573825301098054201427550801403594330791585054 671161447017892819729872838701079848259754149771256420562585639408262860942402 723170771248328584101580852305315575769400877869877110323692669078596147079928 659861003482653647644351823506057429136711255191599341461278586121743070701052 641743927220493260365999197874526804364681922979381679307348669119017286589672 732951563136087224778186141604816269885115263556467452339271846103447755519834 707572501916382686019802125620410642578112752002513483031021901581177408578824 685326122673363322116274993195322409797790677902504389367608004769354474130466 788393309790418243226186742975486613299396723999436092853470161469052325768046 570699444922867212251057841261750761188788042157383091235912192303602606203504 642993135720884840216403701465012276300467782503496460354384685472234939274892 641393064616086272135657546035601990435871553225309995804163569741744604606608]
[ 794866622325442237754796459937631631802680018589230784190720236915590894737635 767564568097414473417272363306235166681367329553074988185245831906757282619563 749211928223449888331281086191088472730900819558872126647829333515957196115819 802518501139071440162924173208358996647085030799173960125001982438108161081603 710186323034397221504732591255611723981909592393389297672711236502297085449679 838061662542350712170781856410189989525046242955755115663918892113367499255803 708627165438883550088146813824431565482002278683642229823511295265145934937189 849534778558771894155770137717776982916462195941926694776309661006258281678853 706272235781477252211576270532591022370873929188723008925387465436701020266849 677975989368891093889613669919850670829748548806617350453477587024070004529435 757133153005162837503722320501509313817888775516244295916903124066184865877365 787489982556033921197395585324383359953214061249493501071246495291033278291459 725281293427161418868378135752821574147706552216799019836264281485220441713015 853904814407506924457871864457891136161069415612647584840156694632315694646781 720443846235060447332370872236197185800848671897657184446826204537495207752323 790472855605339964391065549579789253482959965814775558185726798834758439015105 743848570388572611773754136238534865865573769744354752104124844496062110629409]
[ 739659710178077735339945333872119823087023232236014129168374340633514637631156 678785948633503460449254367986608509193847598655938888302467597339392836376670 638279744218519080918057999888120238205343605867429182241901586457586530604510 736314763084732325777219073587544432945816102008771266418074147592606540676012 650937335435632394216023249794917035638974100049397855539621770885947640746230 764561023723293626030440869491535131138353841471382066997886063476491287608828 633182506679181501483984824539362749992036318747200109670604473932545386290932 734782127207646342879021954616089834060552290744781045707717696262544375671164 667619828864357731764341599366190718638849508352558139456290279802547948823904 667942190964192114128952546681196515589294184283523500454247259042359792516570 659108265783133907004693050070132547013007708131967766468720099811701259562678 705160413980004958680085343106386985774840359619786053618496937830087150793736 663832831997273599188273856379033296780857086471439425553416269337051478370840 747000843875340937895960441067818781636978191476095868537420801839792544883936 741035278958125652974812020893542380291322592588494000221874635586436184580120 645275507897191084469227047262960972305747660247298951885384119826751601137792 693891858217717307700649684033554187589880988788707102259632614124534777210372]
[ 606334128534978835386565103412321335036533217361339427195312429626862433287637 693487557904685912615182983287777051067473198217092363063529044237256193628261 588423383420045255723089708012363209357847118561383809540426439714362811840477 636611697612543199902130864615871625534373782644527093414046822005290198702909 593108025483150661652682515195904258221578781710473298709945924525735368615531 555388519900811030064946125464894217402219835000219036492526991398926220104907 509285230736232540157109167923891404321778267261260361309586102675780842301151 650544944789951566017120177413793658800600999253538748706822302188245433373727 596108722305612848098597235105636393491439527302249547298041101087105805207613 611909661839326399379305592964907701033503776555028461364328953282307682752935 592772951765871383762356665381232525499644530120091681070804431797925254976775 620173728706109294829150378713192061023713755255197870054806861205905619494011 538829290328381201977591943685125880674564476022409301672793761204654728008071 630125677645670821517251760025444318693576664257417713342929914784948087222615 610374860068455784227051071238821673604095437828174682984220264418326580146801 609179197328291734878618972044351700549562962730550673402217135579250675115547 594391485941802112302827769427261648590364202504759133369434742363726243017285]
KEY :
[7049550210785591601689320710185301503502908716881781549267572198269921903530590397 7140645382679750122949771517666612948581713987961210097362695980815179888310279059 5269531073993765254454974876644172080359254115652738961859117922228479281686233149 5404023334240994151181458065130024766944241082028936268808743254985855871487279721 6532461418454731739340097353367889699876057122433434468249104523713461585006766343 7359486046504900429631432621418129882250808203607746338521079780504429440740245491 4819684129534086625704056267149962249369621791171013621381823423817261014898893709 6947510946456533701274935064488543835809134316213784087775055410119955244628655203 4984431033445595018754366192924101703777616534496715790088836018959475454381270497 3892120590838857718835956935910739328779680570066430594867607381572616625093381883 5277850670575734937957469935553770046741432138774659660807885430203332063315665593 7270691534167449771808682518869186647518742546060992554746114919957469145419375481 4632026574712017925006155074794831101264613178633409561996038085205703171849881931 6772279035209367595687089762842867389444540672524937424141025254325954208192476937 3861719556253014665783300989052190458841834333963262778809358974328529237176067991 7107623052517572157091382597757302429686464499621506732051454683209135395282861867 5670978471850686690615203753473430451189112441591593471271047797104096422147567151]
[7066696473623246221073173962608521772160765655989883590023445103068373903130648489 6019407472298940532151355571314677827416070384324866197630173146780389751611595119 6129746436257242217495473583714067170957314527974286171897714594881815904769597469 5907646286202441861715111523406672351817170388507832655509708652447095644699148471 5913113914330660970735293969652078570154759352212530267043408979920058726057646531 5946982284579962847378190774053140545296229586479877580244591453769486108000061569 4834957938533732474588712359440264896666516228147295522065623136768470774330211497 6709525187072278135807288536541408847683360019353100588746416118557608480010349969 5532044254756868710065277416489481253319694789592930002149899369733495726893377729 4271227195602700689254123691024128323272299810262062378188379761825652301188919511 6032288943876903800499926762690193504969041766223016973229863898713818823134792917 6999226164202908588540086984296510916218968192684461092500706798130869624787684821 5323645631925096420601855432949282011691347937491861637367295177601755434048342403 4854906553443653382727052018522119389391469878608102144749916024101047625433333949 7260587265136381726676156601680761384641467446178644667872531619266045157993471501 4580063836838921226250176406889851981837073304986828203098371487319135102274860631 3995265917116568909078386893621327040225743202693046627499044071365419465331734509]
[5368866673036988035743783543725749848611861971789075745339224674043685915854739029 5971719929771513752670023007276961025243770517762757852164286830438760205654095983 4265916056246207385117410715615839112139909802210698388247421197704830978510196951 5740635473136013513187714028184617636913355095954727838907653194666242633353278207 6962657342051332053180120809698916968755666967165529624785943397220161189713117381 4056258784407242244298127516167066504514298424849851228130455370935053495081138813 5231174647333825656212504899696885495943015714447465396571782858501367870168684829 5142026588107472537919131719060878093352507710207391832054709540115560021366594229 5429442365526590400728455438958427783252992220967527147016583063668286485364473177 7438561682934518497256370897819635604298734988696829203747600126936674817291636577 6058039787708069749336334500461770536782450458301473787647757910372562027787277921 6338886256615375829304159922433183936712609799514974528240934367238235161063089739 4214090683479334180524982652389764181224411152947612987065512109635131597787240287 7276856936877028552973961987525068265159749079534751841175347535461489210520983711 5267036588355117867291855194685103799573706039925918690509630575053155666088874279 6515863155565114329086989998082348723474028238797882125036291525524326375363746667 5018213446839610327965165147487910834881811425427464625114301273840162289848963871]
[3891684534241576302935940397225483686075195404567408979470220326595748843190859991 6878305259755887224226035471304552303546369925315291795420058809499003691155016517 7573704112907790571684082696445958496168568557162562192768136339614114562366566941 6527712806261747415404013830399744181513276143946991191705256927305466572280274551 4187563087405138162961798762869657843245886629950343069652084991592408321505227863 3970173262763386887668360286088316539874506799787518589221727702969042845844905107 5790736264956965162562780815387975106552817387986841783728098515075061971058595481 7270259291639579416182584583693977076796570846080992308175046951486935360184408487 6912145696240807174175601999149268333909365515442214944384997555281550950601824149 6074919368797441292292443462246668539854225538985183434497466730578749159576830919 6969309614664388866304318023216585868395074333038246648285737095073619905669855143 7557381690656023296100885445035707134982748692089681757109617289342969393836731647 6196163524330521952458568579880467534265734017154996766083996373037721079748705089 4442190383294922647894587207801880719558020437428181928085312183267322187202723633 7503238237684286442373412996960531648022336254513534535881496495043231945855505567 6792669893416815258744422366018261266336323333020416551924405356231189924304314947 5640288096595943872693888635310529303381289357726822165320039951153671043998239349]
[7015385820740306614144478606658407391102768179944047568154934219608178655979161121 4251324419562170409267237744108678875966162637194187372696534560384581944946281161 5103105816825032024032172389519731144902229410898693181245230877168061592308515343 6027403288527620902903495688635601446394324784286790455093889390708080472560699261 4840182572762349605654771719030821286821480599528411055513117144173478136800535207 5774685062953356572638206823727187621305375151270019935371420274934917822050810077 6513188104764401141318811761492488112026115677103383847425000961216848188062876563 4715767531816235008822722157053942342112993047089185719240404677102386379617885319 5005228305888777176402410434018965128387582302436569953874727984809215334873588547 7434908317661889419341336230036426035110113568824563881140179433107390531530050883 6206555709600121431689899270419981842722439871734755736410385879202117134135714227 7317457278962332486182296835915824487503487032757745703415265835801981721648213313 3837721959336542824901138562969355429496198238545446063245669708752705983053758819 7208878268005766332170702352394746197973327300543286772487491924316327884393950497 4876757495316864194722634684300448889735228336823425606556381341111304608915583057 7554688675764320217227081529891813750574961527276344992838010847543539899601512451 7138822249342409176688802435398454750094569807193590190514302752418737307168333847]
[4134948221846269852611395467397780467292930272546753954021863059284494667712273257 3831111404775227048283113338547958230977846764739499986004845496918713878083229217 4039368276521749339213253573016505773498447514112384126883373117857692253940504951 4656602198828715618047867472028153260732347967467991445151569382412793378658374379 4555811342214258985714354373523027200311414000726892526937416617985879705227764237 7454833718316467469533453177092865830944831978359125423460450720749075033863138569 5538869233408103033672714626320531970435291583838198254537061969175850803958357857 6805201353601893181994138734965105961427584954015971239260242235910815672187963777 5449660004592562066548836862796142466414197096674601406007625442604225044647000219 5254636294093009030690689386430339766872195000743618948122679378765064868584920659 5128412114415127045966982074981999685485552974596031628903750870385287710977968921 4093673499553816407629163088045927876817112439298353202285630298793148915481676081 7117033671321772965255170424631304613719935673220399465250320468391733600272348843 7168614706211816059850961113104043096482783781215274302099733974788104880168429553 4239940944821761486228959105946428221692843413542894482780656763417980363097082723 5125247800235108023205038478369701626780757936205203587954142821912218525632091203 5759662472340523934960991011232807522122373614727342936628450849989100625272731853]
[7521233813180927986532194245369859722843952137549261072312080576724103192866194557 4426472021114114342400734382886874479413227251104699411895825024909635636149588717 5822518872268966971935240250941134097946022403103339363080155304849642929682096533 6659265554235523172550526241061972920054953963395557717138566193957311302664659757 5674638352972385441455570943799505648731983148524063168377558701805691949909463073 5310369534717072263007355674619571560396051260684542317962476881546764581575742663 6311014519246991064719564138413560906697777994418833105240579979943121930450378939 5361753739343790826579081416065164449020526159028846969850105789125942461893889601 5206585091432791195685411821536054939296697041461368803953850086276888136489164387 5364264503097009472554826124567230286550379787944701529245253174674199700709994393 5332275708654544835617634702006048045532928147474982164103798393713458951558712387 7154330570328419490597662058026275294226577379563455779878649019493693386999913631 4255965154388683650982101597753119502869675717150097597396456967515133043218966483 5859096174481938726905220563856243298990381123990257425935212380573168466354695113 5545660424748205204503415306986020011489787156787979320246844839830269555034311703 3850965156607849186784534242141171528580898398900749285580438988570717477608020499 5446554163397323162748562138861831931124360975907613274780909126950609184007762253]
[6192662581279070077747190071556203249352775504184826398787603225986214347113128959 6994737205954788161416787670365198861716366368512127703475881980503113703991955939 5481651191793828389422608678732824440595740259712623466833721553155809684833970791 7091110071510110044039328938933287276637577394077775164190507492854679168546454933 4483760624994805205111050316714273591777741750703861640941762385850759383788682733 6049608688473918328705680224180816761616405580043245435984908788544455734994310263 4124451771735988797963672767121602417634670696151089465531452496719945368837653639 6399329311372900949686830267683171634754109811115841914008240591182083772850795479 7546519455894499767719090447523053699386140317014591524301172962214529509119241053 7417275114742091825753024525658960299443024374088343664090144347286679656161097733 5014396874296734426888449729071374848241738359103059392482563019830717090276015663 4633186294782205826573562486287858907246401363332723221441718158690038393124266039 5550337642412667783588697000523196016599236209060692119480112524992335789673973989 5844578867240738033137654334008106883657644947927448572505946429532197345213141577 6963466935536181482590641450458763083457138318988392292636401227063361427792189661 4142082425367319341232307374768237595740130907772510128181121963316489810836520289 4961449796604997270028502429353876180246896513635251128036185653275047823533814219]
[5020244646801779506412992016677267536789337243972458425630690400043005461567577211 4565880076619492291735038769526772757345293946470709488924791971557426212760892819 6684736686492259943170427080088639349773488501759623441081269876569518085070351521 7127034460505446685596035598548494030499075295120015500060459383083578320015823479 4897684162760141645004513382321871185992474954968422551457160309315557216730606881 6237141341159272440298792551395512016776724784744122335854928052208652684953036313 5045036189757011354587434295435096133476865496722265157878473570246626265426219249 4492100821921753464171268107188505875005849450073920774795259193502666546786739207 4716381382903909604310943880485150949968356753521102147366578982805185331897013699 5769924106041889224175057583349846271093406429942222920911995994738142073366218559 4171164181514849312707973599026506433183275341619116298041398876046767400809975979 4340574818625454190763675045019249265399944194365459009672089359245185421192764267 6950872588123540340444076224783432675558156300414849321351064100959486518814053953 6146902224437265000515638505684334241874785110405304376225569905054280835803274281 7097326074187237852438021400241345563364971664351888455162925502878352755181063969 3888623898170807584743124959179498536722614722550078039933514824555468924122565017 6651978027271952558244564760462812043819979647615002091890568478435775859384113847]
[6184541839300416959726841015983948926777410252139131925095449547759383027893759547 7561960144803466400295498692309453033505436653359621465455959697250417556434004247 6650925508588890849747150445685945052041062028811654048394489204317252809883311381 6704850463135939472803811067686155206499277246144382516537391120144033851113358349 7320713583343065079517081474915592880361515308608446734516063532470304697181360401 7568119283524326862477723402052356731379353284857880533879578063251562980861129699 6512552452148413617199014084879302772678181519276874857182689855432498894585327941 3864502304841107126420779952301992576172333276847279580120672590465021259401778033 6331111565543296924017706450321782118748677423870890590639061495263638165587435113 4783550516617717576665788892083871481794015151866013801050888893776362026159497115 6423401220940988180970372731195129350741576165814573362966333919376651871959428873 7450262631693472528484074044034900615574955262973763066313592705047227587098551953 4808117804278407420833874029972770812262389017733620839445532066082133718222359497 4899705257842947421168782966852713033397708188717753882389136909063010797347098899 4209736275639611026143967090333162667368486813672709665383231938920807320790955149 4288985496021417151033901897030809955788882346402892664352812407166557092158805327 6399088994465334153330573145828540560183125477971862417598263168330188636074007033]
[4974480179777821673967313786764382352761166963380749035339921241966746816488994041 3827431056971164087300893077550763882092015916112737467736337909517452711214639187 6698997374701206275980487699360216265465234571607900653824506548379862177001318043 7518618484938039012748849359221625516807541379356576451140712435674442433878459143 4758284226102704106597828423142759619063985427679382802531350337641387562024423187 6653325824990940547750421959069241525545294681251083462671552655215426072474420307 4834098401573692466114505206828542819229034371756228687559669949071272042271672407 5705759750988406538422991618397587699424839175194269559421988778732387928169667857 4398245768658906633326288155937701539007884274657657114921398490785141990412053563 3878102594095673195136271797680443672814673181231328411710863574520992981409177209 6133310351943439308083002243695959542413257136756502673163584524060541515968942959 6614031345281134115821350616299563537024666163750524962269210441574858941547025371 4290750741919277428148045241860444308323482753494795880553890570259733958076427207 6545270978553917649469171782154604454396447247702870677779771334078026259583459333 4445006509009680819453282837981320670586666539592650405469848378206242389825176617 5528351961577676728085945796096904749164486588200724014503325933583082638797332853 4553860930648945095985450075666703535733205265327136281311359827390408210928411399]
[6750485188296277138658389162398497148751135386245210063464491044091460821084930379 6010438584728708550598422306607426382684410665906702759151991579034684210575075933 3803805109778660370065093861441825466272016175685119018073213648311000405939451833 6161462625503882397732225026549808319277264261988365371960784891587916076691151333 6241919535820917853376301145988033188367936860391313711355653209176555350098798203 4258558055168237876653917945093866560454087541642675942729637820589417608852801179 5474694625625454904251558985876015953883688262254228077025510770120425639369446951 5572367645524781057919816708714071388123584236295958433572146361403772779976666371 4887948115278189762833580204190008123431536911590739281342012942682639855174995899 5072897170640965966310418005986288975968750822108975356862712460882216562466471219 6165044195402895541767167984535809001874699584378494736745378643353182375873895867 5835127871614683300027715844872345605750553719725139533556315401355586388227238941 4558129248276492152695784896216182397705412294024428302763241193095008060855230271 5795893809433639082495271827725126672432427311066820814351700179848645366567074019 6877391462211850950619512093824164600612049488883207821124277197637845079351875581 3958377938641353711912632907421719491674318254749555630033200690997769740090761289 6404726132187140772466481274907035793966756376326970290699498746326875000305104641]
[5245105282568139528637057348495137776701620611286696433957149911746999046314773097 5672050168974839171061056596601035982349325318004963317431904210837698727338524681 5318995005186547468272763095509970624905113391938237948713862681498471247679146813 5880578362964890773246084112474858049667948703871135626465662962696655923624866867 5195546581107174214799133461211483041369580953972521037002568828416600427874887513 7025740614597378404317329146905218670769832882363153532673442050758375082565369313 5145999946874739730668952383000254812735314486347779641637459080051798926465151019 6513613473041142873585462263039929569909799644382952635148930072179081872302031881 5631588171523010560005149959235137802749155523574352680416042363610818665085720943 4661938579598854709308556693448847041636102379353061905086303857681371103767387643 5200265724946880365888699066166641370373306131415637084439282563624242849435198919 5724160589098734405491570327856380180270503160177044278377593042596141991687869427 5535844994497189457509026108645120925092131044687639161040500784543614179422163009 5164140841075973560303189511980295620885660732477720529775563398207925868286832819 7388039343615388559951029087795984774806875747740415187598465366724849599319989957 5932713333522809841197988742194547828985463256465204095622601742232062285926301557 4892707645300259882694545784057297010412598758462700624250444282964583190892749697]
[4402679195574451062303229971710551103798261493698429439611887510780910583170280451 5644798403868544541936649752558492436837934035711790525310816696927400650867127863 7158865200366049244410679046421515511396217393830727016016888462360037153923920929 5941997097836487070303910990936848847854375822749540092391502265950630951487633557 6176489758777485222314965823887698617405454648551451721873275768562402494079297901 4197674057295179503164555453698908435919419130073839043975503902586504943683480117 3826254440225576313358394426095179212131947118955869910396935194433018005398195497 4797017417599318892677895376767047483329539024393449732344318401060687812581214031 4659917698442140210293219079112771855297351015278584522252738466121903775642210073 5372301099587035087300933755630204629378782131326649775338936689525477195146461901 3866861520475131799309335893532348157107057953092059991221031802050780770279125647 4947023435619171858819767417167025508688977577241181212718541756790545697506621267 4220598253918017996516883219461067707938869230437031887607311893947934142527377647 6480734683249934356366434283123476683323222318202662002838992133424445564083304719 4790338149840968410673948873185180461895616745297948628926016515237822381491605367 7123074124167385931639155695689111198749456695017761929519264147394554849260517913 7364156937155967410769926448209426263601057359255989821628023648427926107222498087]
[6122937043843727665658662415580965091934679495710706468972267201323714015666327279 7108661474629408130134143825700713297377276142486919071314376988532817667404846319 4372462422015438798538083962815074121127715780511892821625668370074943618204180413 6403106537668126483673484733526391629535896742788624637038528031760827397862067443 4285922340371091184151694923435760057960812213817576181730332326710404923280139119 4004581034673265641878640389644261190211408364781999282300783524733027677531638817 6818216059105204912477235330384096904879520750235379286429144890861780190434133963 6975312275831956068298462417596278885049391011031585567548154596562179641463596287 5979075310187687411461072306119655262973013374512772994346471552683531647685943009 4832629263367971922003339532487465991395845422517077159185051669317725691282061043 6277632135909060636015641758948344185343137964622984388183338927829003485546405619 4581438565131872486637541951892532744800238139942542571424583098766839515707194791 6633229026583896047224252027494675504621010273299306927214552978838088552273036421 7083521935515654010399818363093640858045225280977648817539581143475152479395483931 5614392812288129761776703216188618133040765319644697688228727523661126347320248685 4569370287554676422567333044787718046478097512336905815215439504255949721048577143 5479327200866983467571962588793175094453672432894069613981809063914403113787931363]
[5356687449999827616679225434998276936082908491746884257543176371861908001691649139 5492925008009867321786023852433790553821883221631201994688349674859789669159518457 5868930347051290647374056309084426669534195745510048372316952149498071477293053233 6778385508943207425281265702970868487918640370743834400707869328320810939719676667 4195967687017490608240203061146751267760133803624788052198235491180165442286971739 4130897401855183437750970760084519724683007479066034272385543402790558769739575351 6121282542759740891033150437792897273344220652298959886237260950643723109106066187 5447876769475872035532053463962974333313893145676103647033527338355989948533361213 6026571568372906759497706414798214037964794820294525626442460001679109710849351013 7143722335878695015645668925801708706783476292363950755051459828683414312563450653 7239742035000371035887689204799692967425641445041527637139251249997843675736615769 5961166650893475981411545030148396561782356396252365250155381163071252154111787141 7277060326227439231327462987871468346731309625544817725725406982001036505584516143 7238670672965210755543685405050511378230779771324224175956003711604455528123671541 5025150561117665951063934850971813714336377931153462488296860708593439333135869651 4720312916639370263158696939654027327275053980874066197116476208358706067066313315 5259023825798823657073987035840441812232638060197364027548688249432608752476036099]
[6081391398582953715651463325531516794197138988843369864158191720687740876427349001 6808449315640208301263557449951800637198425490383701465208771094958916811261789863 5010030534113204709169280318704112544753520304902941682052428456185923532329012693 4854679417944009100137299594196047693506164792428036193111938546409912478546486969 4285668898584834676447519785867507461638864637763354340695901779527370528764164723 6506738534126587207244300177945667641259755646404478416047428069182523617818409089 4110030287348574524223495376900450529520621330534712044510741152395569192159062981 6506252845998469226402811346760105504649541743771750666069495963142045975425624737 4646772968915126891333453635260460821193469786017155371885378633017267125607318333 4834648480423023848372403062888658624909538578814488243029558874480184588843220863 5497058276756957556070492712718177564527750743792454285146956145856433202211067341 4062028574757374972583254735061160362411094680195210001968635369476592405601687931 5941909273122066843214371790026585902770655982822466778733672548155623067022539913 4684012820558698361221129193761017700645329078753582096257274109401088910528826797 4738946274424966911555574457612721970588921527372819450849662484819923345324778691 4284086465628694699033160631133696693255985959492466386015366047783885399908880767 3894821932933538689451255836212237836399775265590307821563547640163748101567631865]

题目提示要用线性代数来解题 分析加密代码可以发现: 1._N2M_为将一个整数转换为 wid×wid 的二进制矩阵 2. _T_为矩阵转置,行列互换 3._GenKeyM_生成一个 wid×wid 的素数矩阵,每个元素都是随机生成的 256-bit 素数 说明是要对矩阵进行计算,再看对flag的加密 1.flag转为整数后,转换为17x17的二进制矩阵并转置 2.key为17x17的素数矩阵 3.输出c,为上面两个矩阵的乘 4.给出key的提示

bigMOD = 2**512
A = 0x10001
B = 12138
KEY = A * Matrix(Zmod(bigMOD),key) + B

还原key 按照KEY = A * K + B 应该是对每个元素都加 B:

KEYij=A⋅Kij+BKEY_{ij} = A \cdot K_{ij} + B

那么 (KEY_{ij} - B) 应该能被 A 整除,恢复密钥就是:

Kij=KEYij−BAK_{ij} = \frac{KEY_{ij} - B}{A}

第一次尝试用上面的公式恢复所有 K_{ij},结果只有 K[0][0] 是对的(256 bit),其他 288 个元素全部变成了 510+ bit 的乱数。这说明 B 并没有被加到所有元素上。

搜索Matrix发现以下结论: Sage 中 Matrix + scalar 的语义是 Matrix + scalar × I(只加在对角线上),而不是广播到所有元素!

修正后有;

KEYij={A⋅Kij+B当 i=j(对角线)A⋅Kij当 i≠j(非对角线)KEY_{ij} = \begin{cases} A \cdot K_{ij} + B & \text{当 } i = j \text{(对角线)}\\ A \cdot K_{ij} & \text{当 } i \neq j \text{(非对角线)} \end{cases}

还原m 因为 C=M×KC = M \times K(整数矩阵乘法),两边右乘 K−1K^{-1}:

M=C×K−1M = C \times K^{-1}

得到解题脚本:

from sympy import Matrix
bigMOD = 2**512
A = 0x10001
B = 12138
wid = 17
def parse_output_file(filepath):
with open(filepath) as f:
content = f.read()
cipher_part = content.split('KEY :')[0].replace('cipher :', '')
key_part = content.split('KEY :')[1]
def parse_rows(text):
rows = []
for block in text.strip().split('['):
nums_str = block.split(']')[0]
nums = [int(x) for x in nums_str.split()]
if nums:
rows.append(nums)
return rows
return parse_rows(cipher_part), parse_rows(key_part)
cipher_mat, key_raw = parse_output_file('output')
key_mat = []
for i in range(wid):
row = []
for j in range(wid):
if i == j:
k = (key_raw[i][j] - B) // A
else:
k = key_raw[i][j] // A
row.append(k)
key_mat.append(row)
for i in range(wid):
for j in range(wid):
bits = key_mat[i][j].bit_length()
assert 255 <= bits <= 256, f"key[{i}][{j}] is {bits} bits!"
K_sympy = Matrix(key_mat)
C_sympy = Matrix(cipher_mat)
M_mat = C_sympy * K_sympy.inv()
M_binary = [[int(round(float(M_mat[i, j]))) for j in range(wid)] for i in range(wid)]
def _T_(mat, wid):
return [[mat[j][i] for j in range(wid)] for i in range(wid)]
original_m = _T_(M_binary, wid)
bits = ""
for i in range(wid):
for j in range(wid):
bits += str(original_m[i][j])
flag_int = int(bits, 2)
flag = flag_int.to_bytes((flag_int.bit_length() + 7) // 8, 'big')
print(flag.decode())

结果:

moectf{L1ne4r_Alg3br4_w1ll-b3,c0o1~}

easy DSA#

源码:#

from random import *
import os
from binascii import *
from hashlib import sha256
from Crypto.Util.number import *
from secret import flag
assert flag[:5] == b'flag{' and flag[-1:] == b"}"
def gen_key(qbit , pbit):
q = getPrime(qbit)
while 1:
p = getrandbits(pbit-qbit)*q + 1
if isPrime(p):
break
while 1:
h = randint(1 , p)
g = pow(h , (p-1)//q , p)
if g != 1:
break
d = bytes_to_long(flag[5:-1])
y = pow(g,d,p)
pubkey = (p ,q , g ,y)
prikey = (p ,q ,g ,y , d)
return pubkey , prikey
def sign(prikey , m):
p,q,g,y,d = prikey
k = randint(1 , q-1)
r = pow(g , k , p) % q
s = inverse(k , q) * (int(sha256(m).hexdigest(),16)+ d * r) % q
return (r , s) , k
N =70
pubkey , prikey = gen_key(256 , 2048)
mlist = []
slist = []
glist = []
for i in range(N):
m = os.urandom(10)
signature , gift = sign(prikey , m)
mlist.append(int(sha256(m).hexdigest(),16))
slist.append(signature)
glist.append(gift >> 251)
print(pubkey)
print(mlist)
print(slist)
print(glist)
'''
(15108991400745450309355253807766276360380320660219347110579196545038448713258628236389895588434452274950695730065651453302126578774250601579569380793694222185632975071787226827269003960154804120295836575256599635257664002539433898780509612222415654387614497827656003147264759709907030567588768742381892680294003522236733212278947841394088240785037547320093090823921316798352125983336576254706699074518423072631458743268564795405265374620392629043411827842471761293161909181359426144930558336608723292136000804340045919959509239116850623839014597280915031823441217994236103055534164768247016208706741775588972456073813, 64041711688798543046456406759305608573338217876445369024232375830196337057157, 211108787850403715754217328775104384886355209433738256700886330744227489461535975415049562487554022604084280133363395418213621551059074267965190815383466764991330329611352996223278253801101935394430441418804250609103316847891403434149066896553992753727854908853433641669141912196228614329375896818224643597658117947660368321721772671622926201179481001295604119889565987716689549626255526337387116495295186788692719142385564750883920134442138643678641784908945600972018498891317442844779462847351694051262414792375002964674785124827097730890996699014975976433462777611992256090741549378102965758784472841167408714522, 9043235094550238893083876245671285943481344799516120725461204956244829328990953521163081882535215762707374017354742157979731318704056404560715406344957246839843372688851274891728842272140479386091283810692439192229979805010467188655570294630785215252551661693272578344820983701933114755363870225672538484638853799103964082269144812968208145984338341790068315164709463082759467367433517218900609065064340062562087970133690588723131009107141587133631032322452226671200556122235181849740875031922279336024327837201224765719841562999608896733540371213687891364957488262801206197400535890094555826110293605523847824217254)
[48277377637351749179818247279816270031860522522874404580309585216041655677757, 68388532132597372886079202713528452335094514685332022873351253992652788588205, 101945300313107634182062880586742945994758271035112004890523459451835622710447, 57685754325616642638948022134912513822133516998433953207915339780749271875175, 104105044234583607867949904072503602317595700006794106887126053164628004339549, 100877540727417666344693235456676586220535176693473350008870716820824738683809, 84145490395824162910100010823918059184055902831220196545094500444240820685484, 59855204441909338922061725741264492403055063801395855176583354143535857467621, 68082110345354462383313755283009070575336134933091952011680196509387265179368, 74262895516989675333147043128373389139473562613810156782952447020813613704931, 48325640265096735230374479582801576545977248563218348445736785049920052284747, 14721174904926097091329658873807089477177965311206329798651866324817245715629, 41506364734036160258221867104158798139396548567845254722459818402302950082719, 88957362831174073704115026231513759455281892839337163179067050763587779616709, 15922780135096030672904406197195948585528079665199180896445526854167288983004, 56046344838302884633938256790058035684855847875504768803055539402614742523678, 106896512225155501943939509604181466009082469999610706827983496412705866162724, 62054611245156882273900322432473482229357933988230018664178497620399686380964, 48792563571170452948528644104365638666090800928015053845491030890379310745038, 50423320785735290524374449452150229387046704737703946329551400502310595817136, 101839422535317066784515623692806233744794863464804874721091859066928640950177, 21942789687763501944010021481657681194438991024943771319655406525952701929317, 87970371287776063535717299920080423593560065054913073344577499342496981998178, 20589050187147982184141445450050475965325033639484393909557180011377746663753, 61955916816415489328036273684061356398942331310016680878661180535205754317662, 68683645434335557228897198490479180789934335512445525902468080341795521995740, 25067204960993087302986413419016604573761049161848668378811403581403745111973, 19112163598144197760552389742932768145352867083928125842455859844965772790183, 60052845414544144685532455487459953410730116275047128201553886328939488024194, 67151242372230358402027135927384757185701861186528645278769207576515203172682, 56385992860671494168201436255021830804169073906978456665929989717088986543833, 79549959409526088628276737566999743228476429805701986414150331056077959929816, 42276999472492029797148617947663992176518778468746089195963840881010399508385, 46304863922747067237500577566700311238554840565432396672915271649016825960054, 104355464449754413882843704871275540563608402939527676234634418423374668665049, 109940222858966230808044691816345836055825568310536552665315395797750475107429, 53173652096376439132017685525630394038548836135808285521135958073920004470573, 103199049106272157039742696205211518690093156061240500540212705871966519209159, 44038235607911241792781280157845337138500891971301782449094927133148834659607, 66970473078097649398031979334104237929383373478488040384236093829531752024944, 114463437349569201641090715601061877169276051980543439068556960827948131888846, 77271325645951169358857724007082163047693449594045674091248730190154727743967, 108841123278827852502233961931477565844809287050700927863668992592540776994431, 33808450203082157903598659541436426265909245107897866778995824660582980677613, 95724565065465211873122804460163671904354328099158958122405873577904559809157, 49001571033450325251644336035981727394053659029395490875250000658876501631937, 12418814385430489720233391768870090264450063332933577524244330406242691686811, 54223421826813920561728049083115148060895653325037068340350615511566412322201, 114744923755451093158502244429799532806357514185240849366566339024088818494740, 102722111561212285732147196509541569284824099554222136671831853391771244237537, 60675398501837364810079257959208484065682960925513338389435376578565206624649, 12748926943312415342024975452736006521287381814399586030278500319929771040917, 78115219096999308806469815507993668009316253084447483802722476691556088709746, 58289171832615506059165890730285694830147774072643009537875485443960015304549, 102513702993855399290703332839594063689242109651867785587936114941145020931584, 80123373861500108410759750785351780778160830253769988648862868457532305916512, 47546875759073130055440398805662668721034979122878977764494220759111081376483, 8108322599046468856097401329703032727832810154497564345276875819297757057924, 87585605577680481032355806954140868101261278853271845171980181939157050376775, 66111806060364963374982005437729580704691154198518956098383737091567335991984, 7375114443047289133003618451266315097883596518660632214671315514137685223306, 366778410267697977624459340650608088356639356369215019490328912378386798004, 35416688455469442251651593102540814891537466937115853066809856539925581515555, 60959779226301010386449251964470449631915603342117287265816620973542965770761, 22324880343161898859835031077912010970285621124818299746270720271870830845083, 75056962072256995426003738031191215609990851798056151154925299354299958447161, 54448362546567576148485475313653125376611144438863481155061743242207959864464, 27997582461539839177743667135865335006833684428478590835386917889931775224157, 6683021781445328444103354538751238877233839805860545470448260689709203849197, 72849736677114048793026101122517188462039065645099613616142961810024700320656]
[(22352268821452797587471457833733791345514777928207948268194258479170198661277, 7912633236568395776333624173354929290342798112258694968012915501703249200272), (15812650496109943060880383526246045154168888715749028629682581602288997227855, 21023020603351473744962409790986660897360517490300514738372332975422323814285), (51814150275372504909962027907529406162194626703761386053091969592877337526745, 16638260433649337082119719487251455272971145245531930538995075843177252428288), (27348282625312581181931605905792557035718973995267665830948716198924157732080, 62090302505957219285588456292889765555983437734442098606773342224333934918081), (28175967940368011783626075683586105323381776443681798596176181413300381256105, 2472610361821206533116484514917288109681133766188278255468277308896317482403), (63174574453907741597868328769210702956474197443942269086839958915603000125038, 32309827838005866297160875718647730502702772254531596471680122770109180312743), (58824051948426790199209000102034515018454008103667186264041378016515720817344, 61836111273988069018925893424809185109451243717555240577142099043545588614620), (30683314769675740556952144803613708535991748390810666262703733468686227254516, 62360248703681967723231134711309677045835265492468567213718048123044700009223), (12118724612579098982020149488854759987577905089311455304187341716538367715798, 37156513439666210177073883733482530484347208458352045154360740336122255773162), (32421076682666864611170891547822400292372879874289253245286349066903892675631, 25755490869177118854376205240676204068588203276835870271663040950225985360380), (44708546728189688830689579717676637949172380778773987126263646536904380377931, 58330052739434973691468094017143541481380877134557717197792949919390404489916), (10068338048191376911414463431205650332120468734915220528449738038975328237906, 54356403180522057388484445731428036523787160596525828839610455317844142292887), (6845116945664513808548044341622108614802712676815699024522535938694901267945, 21317160674922838062952002035072169337448190542422243297458932479388590379970), (59253893072588584342459866595916494038532968705632928208373626493650012659051, 6074646812545544425428468167982541808299993682858881101534914864722252042550), (51823482559316888984453337374602116313181408591976040917558188386259089485409, 37625242495679180502584632627267557040798084553250250616807413822768564031896), (14763404947049735943704853600464433167617354588063523903963958199251130539086, 19781867981939409096044191699831779795187554415232627393536781656048558323987), (45665913465543579082778819672379834395300690923817954460137858291978597430103, 6384596851866578691587078228762595539052273799146216590950117082019334508608), (3033593929377654960623000107469704060795409984357736199181865092767835611309, 15067198580160869158558671276400337902463048777904962689098002582100962608605), (27708810353455634722562530110676980260909982403327169688452504000447596724262, 15875261866832935361537558942507314263943267365479552460758861232585571034611), (24128141898504681611388105575393857948337679219686912243295750055456109939540, 2478623279994843893962694093845357965416962472287660584789015538079969041203), (27024362017034724692254787880783747129240945350461205334642407693259605693997, 23554012387261049111834231782207749416840966317627585763804126479336733985940), (41276161854792394137360009219040730465951527138823383393433212016168566870775, 54066078102338853041220068992491875154221959175155668344858041820717954003570), (49667790607087740614451699753394541648066664465961726433373658806349776110740, 7868269120695506446370475273139211108029407113873748843391846581861644235073), (32031523231174926591181393001599252378895474043059210129970077712401176191632, 2299949691601160015786980389974051316448973601165197848595061728817653220874), (59844404032832433863402998810587275254060021397289446163553235495903460994491, 14919354004798766549641529780861628015496448780911284327689129634386854975822), (19255499252815849264410071875133830868543608786469946726211381281749980085095, 7300275189897906870579819118410610961320010811567771837896316091418132706470), (26625484350788679407935109800530169462247779379385954610520262192307183221119, 63032063351732595813055438365974363516905015780517297556580318910513122868903), (55908283349553988943773925115821045467483233458347755587291704785714793328234, 3340166315012323754979075589333827328713948411486737810413529984591593156754), (40019768086493588902057371385918220604799658709018530540179978447152692176845, 20061631559492806259789253895163430153773645036934019102994124783595087999924), (2765447541194096290247053535467633657571688070519197706427494770709334399966, 55221235855209781621086007864447603098303003093058242152546726679998895182678), (17052964989210093760596144581299155906684622841193999105662312043069904186934, 6641615618144485057451371448514315237775932136022401118918242976250301578311), (32464039527699304999869380667238055218241698465798134818246754347146205368082, 62106577564606777462145733056356239549592082506358481581040530122830317564174), (6923021698491506716067296994427667503170147963761725464166518895556704264419, 32462949261786267132919998980550958631113320755872845715534231675350477368606), (2295021878361999485915064912168973878874860147252654759165925344735627323455, 18805112562288531957936432873170140595137018786412556938649988050648242161868), (34632089798117989775129124426594302361797497355693316122659733877486398713805, 4908410775904227531781543801882582920937845894687901951245830758256171898495), (31579894553180182716581698363133059114274625404665266713998416173765443279946, 12741960948088986461570576746765996077790527348995011539430663831016167060050), (40742984808640129884152348136773585123260903299146066801695288185244407261402, 15692482046131040556774018913518895141682700271844660404613909503891274080470), (59364365094257534007650598527452941309532234168416534011085943802522061118982, 57950760117760658124852916890254625355274036556790396854775378330267140689917), (43869179282113518094350037608065845838846833799843083670625264937340584674416, 49554279799041403113186698273718659166988054217075904938663589058279358011221), (16754512243134090589395155761417382898713204499818279848405233572945791865266, 12495704282434412329901180310540015604708631800998146827979478461998001668629), (14101853475687558433778778233226892009093091263680420005666397561645209150687, 7019996136702041325163230782194694100410072369984020433625834444502767644778), (10507703237170260685145475491304566020578728436881519546019206080359410195390, 16573267713821481043499816863293880353807336804267955756959773047891796613019), (49843629439351992174903718763569146886759416712895848179781860717550218261460, 10084839883354576091697652333132370695107786251487462610987472872975912023117), (17284399737285683194597041365368712734455669114190673145719281030344879835596, 57864171401623005731957624202552872876277210474574451762729776797188595949506), (63742005716380200773032479300155818023139930466790598177353802965030217987854, 28142718833130596831193021933598031736531844231243542171635207077907668538253), (22100621063860838325701516504348547663741182936701492323616885726290723214974, 29889233753274753316722060822301116532700094905561034307314157740117209327612), (55126321729597826112496687189259529874936637542275569116473497051817332456584, 19037993614214593372784403167032468436140866702394183775921547212690201910938), (6995274263021589845537276902624069613697455194721808391432269501786185497747, 33176273674794508131875017634450139107565462145469294000638219612100597913959), (47330615861132771649760080570757478651656099776268097153305864314482873869166, 21793242078631127216727619144713249819313498390446092018187526933896874741190), (59559567216761374206214020071608275643905528490426902957494750074756523807902, 52643561856170290659853189193154949612890586520046606619867851152505238180468), (36173816147153842902977155254271140299756295618908278839373702766392130736993, 10314964866269765723187458845899585266811908551653827782980326224682897521619), (6595323612447082351891285357657703941628451945860240597857022454315345378888, 40145806045033372845171711425795529145603807506538610560951962656555621670816), (46580707725120646545478411878591267336491191973754509317516829592677261679086, 63337602833471976217939202158221180462613299189517566827092997820822862506453), (8933449230179897611929682587169270558552318956034534140750403048238506986774, 28093297652746718764178027664867053341106564601204445677194220669665714656088), (6673758482715604284062545615855191083544957634323510624485390457712165584449, 10986526069081284211742467403493322767070208477504228701780884299931279012066), (5184239873096112682385328552500406164952677595753067686847637924189557034672, 50115428278081206719512620216189201544439339263259802625926763730422626251892), (13562937540911404320904876496328607929876086880615723666361368419409525778732, 54430248337476705494478488619523791628647867925151626579644226997728114217084), (14750955612642113154481948130189504867483938069083786716087790186536749130530, 14810873297081267196572921470079852862074268125298582448348939029476144181856), (28598938553156737590873368232873600859197468011017408111038636316499812468771, 17294697330132628981145314271080608075170768804134554162316073462947439334781), (23375386864996732424907879237894219612376231666059061486113832098080740695268, 16772871328229734002696838136693314002569899609546844737079983396802212380946), (23495120431601243787562525466624996734969526540931651518163487343063558328042, 41394827827146761633610622288652916754459445316927735112445209420925130090526), (56567808880123007033262431905227043287517315838743861541509840375693572901712, 24089087481045859686702290022035640868012239167200532496473110946892609784821), (49147473913362077550233427178337967408735770558247053391628925019998092747714, 20273220310426594440102702990063869719872524197245934862242331521369781990436), (31515143590631327266339928531993321012984604875440942287770659898229900822199, 16725782131886464942366207886948356973783199979543344695946901086451073455810), (53255499129878077092011536582606705294492876833489001971514448729353424640756, 27153628106011448007119079630337062550419600079252084474574981983284848721895), (20017081577052328830880114799967376469547917673144820124895353140004000054368, 51900269879190440672320901372634026629946251995933656498696433780915797623218), (13700928762451047185992511197458526569329727993241180688739301605489746333986, 45152677921233866687667121657287051209385910041523015584094298332218686044149), (48170628472023612263231219284036293843351666631195034065815317432900278216613, 61532566417624957634666056121746469665551924452274550947586121996364700607194), (22909360572551364481985655576624137257737187145703958641047908544709303954738, 51180461182347014246594255974867379859525291259298256591026720601600119918752), (13066259907235922099127374228385197140616514034161924408914506369089064011358, 22756694677917047461517231646852012375414816105746756041232119443744787411083)]
[2, 15, 6, 10, 4, 11, 12, 4, 9, 0, 3, 11, 6, 0, 13, 10, 6, 9, 13, 14, 9, 3, 15, 6, 16, 6, 9, 3, 0, 8, 14, 6, 10, 3, 6, 14, 12, 15, 11, 16, 0, 0, 14, 1, 3, 5, 12, 7, 3, 0, 16, 16, 5, 10, 7, 16, 0, 7, 16, 11, 15, 15, 15, 14, 10, 8, 3, 12, 3, 13]
'''

在wiki中找DSA发现#

DSA (数字签名算法)#

上面所描述的 ElGamal 签名算法在实际中并不常用,更常用的是其变体 DSA。

基本原理#

密钥生成#

  1. 选择一个合适的哈希函数,目前一般选择 SHA1,当前也可以选择强度更高的哈希函数 HH。
  2. 选择密钥的长度 LL 和 NN,这两个值决定了签名的安全程度。在最初的 DSS(Digital Signature Standard)中建议 LL 必须为 64 的倍数,并且 512≤L≤1024512 \le L \le 1024,当然,也可以更大。NN 必须不大于哈希函数 HH 输出的长度。FIPS 186-3 给出了一些建议的 LL 和 NN 的取值例子:(1024,160)(1024, 160), (2048,224)(2048, 224), (2048,256)(2048, 256),以及 (3072,256)(3072, 256)。
  3. 选择 NN 比特的素数 qq。
  4. 选择 LL 比特的素数 pp,使得 p−1p-1 是 qq 的倍数。
  5. 选择满足 gk≡1 mod pg^k \equiv 1 \bmod p 的最小正整数 kk 为 qq 的 gg,即在模 pp 的背景下,ord(g)=q\text{ord}(g)=q 的 gg。即 gg 在模 pp 的意义下,其指数次幂可以生成具有 qq 个元素的子群。这里,我们可以通过计算 g=hp−1q mod pg = h^{\frac{p-1}{q}} \bmod p 来得到 gg,其中 1<h<p−11 < h < p-1。
  6. 选择私钥 xx,0<x<q0 < x < q,计算 y≡gx mod py \equiv g^x \bmod p。

公钥为 (p,q,g,y)(p, q, g, y),私钥为 (x)(x)。

签名#

签名步骤如下:

  1. 选择随机整数数 kk 作为临时密钥,0<k<q0 < k < q。
  2. 计算 r≡(gk mod p) mod qr \equiv (g^k \bmod p) \bmod q。
  3. 计算 s≡(H(m)+xr)k−1 mod qs \equiv (H(m) + xr)k^{-1} \bmod q。

签名结果为 (r,s)(r, s)。需要注意的是,这里与 Elgamal 很重要的不同是这里使用了哈希函数对消息进行了哈希处理。

验证#

验证过程如下:

  1. 计算辅助值,w=s−1 mod qw = s^{-1} \bmod q。
  2. 计算辅助值,u1=H(m)w mod qu_1 = H(m)w \bmod q。
  3. 计算辅助值,u2=rw mod qu_2 = rw \bmod q。
  4. 计算 v=(gu1yu2 mod p) mod qv = (g^{u_1}y^{u_2} \bmod p) \bmod q。

如果 vv 与 rr 相等,则校验成功。

正确性推导#

首先,gg 满足 gk≡1 mod pg^k \equiv 1 \bmod p 的最小正整数 kk 为 qq。所以 gq≡1 mod pg^q \equiv 1 \bmod p。所以 gx≡gx mod q mod pg^x \equiv g^{x \bmod q} \bmod p。进而

v=(gu1yu2 mod p) mod q=gu1gxu2≡gH(m)wgxrw≡gH(m)w+xrw\begin{aligned} v &= (g^{u_1}y^{u_2} \bmod p) \bmod q \\ &= g^{u_1}g^{xu_2} \\ &\equiv g^{H(m)w} g^{xrw} \\ &\equiv g^{H(m)w + xrw} \end{aligned}

又 s≡(H(m)+xr)k−1 mod qs \equiv (H(m) + xr)k^{-1} \bmod q 且 w=s−1 mod qw = s^{-1} \bmod q,所以

k≡s−1(H(m)+xr)≡H(m)w+xrw mod qk \equiv s^{-1}(H(m) + xr) \equiv H(m)w + xrw \bmod q

所以 v≡gkv \equiv g^k。正确性得证。

安全性#

已知 kk#

原理#

如果知道了随机密钥 kk,那么我们就可以根据 s≡(H(m)+xr)k−1 mod qs \equiv (H(m) + xr)k^{-1} \bmod q 计算私钥 xx,几乎攻破了 DSA。

这里一般情况下,消息的 hash 值都会给出。

x≡r−1(ks−H(m)) mod qx \equiv r^{-1}(ks - H(m)) \bmod q

kk 共享#

原理#

如果在两次签名的过程中共享了 kk,我们就可以进行攻击。

假设签名的消息为 m1,m2m_1, m_2,显然,两者的 rr 的值一样,此外

s1≡(H(m1)+xr)k−1 mod qs_1 \equiv (H(m_1) + xr)k^{-1} \bmod qs2≡(H(m2)+xr)k−1 mod qs_2 \equiv (H(m_2) + xr)k^{-1} \bmod q

这里我们除了 xx 和 kk 不知道,剩下的均知道,那么

s1k≡H(m1)+xrs_1k \equiv H(m_1) + xrs2k≡H(m2)+xrs_2k \equiv H(m_2) + xr

两式相减:

k(s1−s2)≡H(m1)−H(m2) mod qk(s_1 - s_2) \equiv H(m_1) - H(m_2) \bmod q

此时即可解出 kk,进一步我们可以解出 xx。#

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Profile Image of the Author
LYH
LYH,安全方向的在校学生。方向集中在 Web 安全和密码学——Web 这边从 webshell 识别、文件包含到注入类题目都在练,密码学在啃 RSA 和格密码相关的内容,逆向和网络也有涉猎。日常工具链是 Mac + Docker。欢迎交流学习!
公告
欢迎来到我的博客!这里展示我的学习过程与结果。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
站点统计
文章
26
分类
13
标签
19
总字数
180,600
运行时长
0 天
最后活动
0 天前

文章目录