This file has not been commented yet -- comments will be added. Example of Vigenere decryption done in class. In order to use this file, you need to run cryptonotes1.mws and cryptoexamples.mws first, because it uses functions defined there. This is the text used. It is one of the files in "messageboard"; credit for this one will no longer be awarded, of course. > Vigenere7:="LLZJHGBSQZRGTJGFEIPMGNIJJPKWHXJKETNZCDWGHCFEWPRMUGTZSCECMWPEYEWJIAIEKCVXJEFTJAGZSEUMTXJGBFKMRDGNMCGZZVNGQARNIPNPWGCEAGCDMIWHVFSAVCGAYLEISCIMFIIXBLASVXEAGMLYIHRKQLEIHJAYLMNFRBLYWVMQMFAWXLNGLWPXSHEBTIVXRECHLJRREGFIJVPHKHYOIEGCLAJVXYMJISEZIJWXCIVGDGVHEGBMFXCEGTJAGZANGRKXJWRGBLSWSOPFAGCARVYDPKPNBLLISXPTLTIZRTEGKLOIKMLMQZVVVYDHVXNHPSRTXUBLYEOEYEGLWNXENALYMIVLAGQKPRMCDCVVOBRJEMCNEGUIZRPKWHXNXUXNDEDRGXVLYNMAZYHVZHRMCJQDRRWIWCVRQLCFHNXUXPWWPPGBLYGDTUXPLISXBOCJXCIPAYFRZPBLASVPTBGQWIDRTMFWGDTUXPLISXVGRZIXLNGLWPWCRTTWWYVBINARBGNGLGXYIGXPEMIIJAYLXCICEYAROIKMUSWWYGUMTACSXGMOWOLRXLUVTTGBMFOZCPTLVIXVLIRLLZGVIFWVOIKMYFHMIPHLKXMYPMRZIKPNBLLISX"; Vigenere7 := "LLZJHGBSQZRGTJGFEIPMGNIJJPKWHXJKETNZCDWGHCFEWPRMUG\ TZSCECMWPEYEWJIAIEKCVXJEFTJAGZSEUMTXJGBFKMRDGNMCGZZVNGQARN\ IPNPWGCEAGCDMIWHVFSAVCGAYLEISCIMFIIXBLASVXEAGMLYIHRKQLEIHJ\ AYLMNFRBLYWVMQMFAWXLNGLWPXSHEBTIVXRECHLJRREGFIJVPHKHYOIEGC\ LAJVXYMJISEZIJWXCIVGDGVHEGBMFXCEGTJAGZANGRKXJWRGBLSWSOPFAG\ CARVYDPKPNBLLISXPTLTIZRTEGKLOIKMLMQZVVVYDHVXNHPSRTXUBLYEOE\ YEGLWNXENALYMIVLAGQKPRMCDCVVOBRJEMCNEGUIZRPKWHXNXUXNDEDRGX\ VLYNMAZYHVZHRMCJQDRRWIWCVRQLCFHNXUXPWWPPGBLYGDTUXPLISXBOCJ\ XCIPAYFRZPBLASVPTBGQWIDRTMFWGDTUXPLISXVGRZIXLNGLWPWCRTTWWY\ VBINARBGNGLGXYIGXPEMIIJAYLXCICEYAROIKMUSWWYGUMTACSXGMOWOLR\ XLUVTTGBMFOZCPTLVIXVLIRLLZGVIFWVOIKMYFHMIPHLKXMYPMRZIKPNBL\ LISX" Explode is a function (in the Stringtools package) which converts a string to a list of characters in the obvious way. IOC computes the "index of coincidence" of a list of characters (or in fact of a list of any kind of objects). > IOC(Explode(Vigenere7)); .04285336961 sample_list(m,n,L) , where m and n are numbers and n is a list, will be a list consisting of every nth element of the list L, starting with the mth element of L. The strategy is to first look for the key length by varying the second parameter of the "sample list" until the index of coincidence jumps to the level of English text. Try the calculation below with the first parameter equal to 1 and the second equal to 2, then 3, then 4, then 5, then 6, then 7. The difference is dramatic. > IOC(sample_list(1,2,Explode(Vigenere7))); .04156850218 > IOC(sample_list(1,3,Explode(Vigenere7))); .04234105338 > IOC(sample_list(1,4,Explode(Vigenere7))); .04020380543 > IOC(sample_list(1,5,Explode(Vigenere7))); .04461942257 > IOC(sample_list(1,6,Explode(Vigenere7))); .04492362983 > IOC(sample_list(1,7,Explode(Vigenere7))); .07179487179 The IOC should stay high when we change the point at which the text sampling starts: > IOC(sample_list(2,7,Explode(Vigenere7))); .07228327228 > # key length is definitely 7. > We give names to the seven strings obtained by starting somewhere and taking every seventh character of the ciphertext. > L1:=sample_list(1,7,Explode(Vigenere7)); L1 := ["L", "S", "G", "N", "H", "Z", "F", "G", "M", "J", "V", "A", "T", "M", "G", "A", "W", "D", "S", "L", "F", "S", "L", "L", "L", "Y", "A", "W", "T", "H", "F", "H", "L", "J", "W", "G", "F", "A", "K", "L", "A", "D", "L", "T", "K", "M", "D", "S", "Y", "L", "L", "G", "D", "J", "U", "H", "D", "L", "H", "J", "W", "F", "W", "Y", "L", "J", "F", "S", "W", "W", "L", "Z", "W", "W", "A", "G", "E", "L", "A", "S", "T", "O", "U", "F", "V", "L", "W", "F", "K", "Z", "L"] > L2:=sample_list(2,7,Explode(Vigenere7)); L2 := ["L", "Q", "F", "I", "X", "C", "E", "T", "W", "I", "X", "G", "X", "R", "Z", "R", "G", "M", "A", "E", "I", "V", "Y", "E", "M", "W", "W", "P", "I", "L", "I", "Y", "A", "I", "X", "V", "X", "G", "X", "S", "G", "P", "I", "I", "L", "Q", "H", "R", "E", "W", "Y", "Q", "C", "E", "I", "X", "E", "Y", "V", "Q", "C", "H", "W", "G", "I", "X", "R", "V", "I", "G", "I", "I", "P", "W", "R", "X", "M", "X", "R", "W", "A", "W", "V", "O", "I", "L", "V", "H", "X", "I", "I"] > L3:=sample_list(3,7,Explode(Vigenere7)); L3 := ["Z", "Z", "E", "J", "J", "D", "W", "Z", "P", "A", "J", "Z", "J", "D", "Z", "N", "C", "I", "V", "I", "I", "X", "I", "I", "N", "V", "X", "X", "V", "J", "J", "O", "J", "S", "C", "H", "C", "Z", "J", "W", "C", "K", "S", "Z", "O", "Z", "V", "T", "O", "N", "M", "K", "V", "M", "Z", "N", "D", "N", "Z", "D", "V", "N", "P", "D", "S", "C", "Z", "P", "D", "D", "S", "X", "W", "Y", "B", "Y", "I", "C", "O", "W", "C", "O", "T", "Z", "X", "Z", "O", "M", "M", "K", "S"] > L4:=sample_list(4,7,Explode(Vigenere7)); L4 := ["J", "R", "I", "J", "K", "W", "P", "S", "E", "I", "E", "S", "G", "G", "V", "I", "E", "W", "C", "S", "X", "E", "H", "H", "F", "M", "L", "S", "X", "R", "V", "I", "V", "E", "I", "E", "E", "A", "W", "S", "A", "P", "X", "R", "I", "V", "X", "X", "E", "X", "I", "P", "V", "C", "R", "X", "R", "M", "H", "R", "R", "X", "P", "T", "X", "I", "P", "T", "R", "T", "X", "L", "C", "V", "G", "I", "I", "I", "I", "Y", "S", "L", "T", "C", "V", "G", "I", "I", "Y", "P", "X"] > L5:=sample_list(5,7,Explode(Vigenere7)); L5 := ["H", "G", "P", "P", "E", "G", "R", "C", "Y", "E", "F", "E", "B", "N", "N", "P", "A", "H", "G", "C", "B", "A", "R", "J", "R", "Q", "N", "H", "R", "R", "P", "E", "X", "Z", "V", "G", "G", "N", "R", "O", "R", "N", "P", "T", "K", "V", "N", "U", "Y", "E", "V", "R", "O", "N", "P", "U", "G", "A", "R", "R", "Q", "U", "G", "U", "B", "P", "B", "B", "T", "U", "V", "N", "R", "B", "N", "G", "J", "C", "K", "G", "X", "R", "G", "P", "L", "V", "K", "P", "P", "N"] > L6:=sample_list(6,7,Explode(Vigenere7)); L6 := ["G", "T", "M", "K", "T", "H", "M", "E", "E", "K", "T", "U", "F", "M", "G", "N", "G", "V", "A", "I", "L", "G", "K", "A", "B", "M", "G", "E", "E", "E", "H", "G", "Y", "I", "G", "B", "T", "G", "G", "P", "V", "B", "T", "E", "M", "V", "H", "B", "E", "N", "L", "M", "B", "E", "K", "X", "X", "Z", "M", "W", "L", "X", "B", "X", "O", "A", "L", "G", "M", "X", "G", "G", "T", "I", "G", "X", "A", "E", "M", "U", "G", "X", "B", "T", "I", "I", "M", "H", "M", "B"] > L7:=sample_list(7,7,Explode(Vigenere7)); L7 := ["B", "J", "G", "W", "N", "C", "U", "C", "W", "C", "J", "M", "K", "C", "Q", "P", "C", "F", "Y", "M", "A", "M", "Q", "Y", "L", "F", "L", "B", "C", "G", "K", "C", "M", "J", "D", "M", "J", "R", "B", "F", "Y", "L", "L", "G", "L", "Y", "P", "L", "G", "A", "A", "C", "R", "G", "W", "N", "V", "Y", "C", "I", "C", "P", "L", "P", "C", "Y", "A", "Q", "F", "P", "R", "L", "T", "N", "L", "P", "Y", "Y", "U", "M", "M", "L", "M", "L", "R", "F", "Y", "L", "R", "L"] The next step is to determine the displacement between the first letter of the key and each of the six other letters. The shiftmerge function (from cryptoexamples) takes two lists of characters, converts both to numbers, shifts the second list by a constant amount mod 26, then merges the two lists. If we apply this function to (for example) L1 and L2, varying the shift between 1 and 26 (or 0 and 25 -- it's the same thing) we would find that one of the resulting strings had IOC higher than the others -- the reason for this is that L1 and L2 are each English text coded with a shift cipher: if L2 is shifted by just the right amount so that it is now shifted the same amount as L1, the resulting list will have the same IOC as the underlying English text. > IOC(shiftmerge(0,L1,L2)); .05263796977 > IOC(shiftmerge(1,L1,L2)); .05694857629 > IOC(shiftmerge(2,L1,L2)); .05105943780 It is an odd feature of this example that the shift of 3 gives a value that looks like an English text value. But the IOC at 14 is even higher, and turns out to be the right one. I think that frequently repeated words in the source may have this kind of effect. > IOC(shiftmerge(3,L1,L2)); .06890899156 > IOC(shiftmerge(4,L1,L2)); .05203084209 > IOC(shiftmerge(5,L1,L2)); .05628073584 > IOC(shiftmerge(6,L1,L2)); .04966304414 > IOC(shiftmerge(7,L1,L2)); .05543075709 > IOC(shiftmerge(8,L1,L2)); .05148442718 > IOC(shiftmerge(9,L1,L2)); .05421650173 > IOC(shiftmerge(10,L1,L2)); .05761641673 > IOC(shiftmerge(11,L1,L2)); .05415578896 > IOC(shiftmerge(12,L1,L2)); .05160585271 > IOC(shiftmerge(13,L1,L2)); .05233440593 I didn't actually stop at 14 -- I went all the way through. > IOC(shiftmerge(14,L1,L2)); #I like 14 (3, maybe?) .07073037460 We went through a similar process for the other examples. > IOC(shiftmerge(3,L1,L3)); # 23 .05403436343 > IOC(shiftmerge(14,L1,L4)); # 14 .07212676826 > IOC(shiftmerge(5,L1,L5)); .06820135052 > IOC(shiftmerge(25,L1,L6)); .07409453653 > IOC(shiftmerge(20,L1,L7)); .06758747698 The guessed key justified by the calculations above turns out to have additive inverses (mod 26) of the displacements given above as letters. This is an artifact of the way "shiftmerge" is defined; if I had shifted the first argument to match the second, we would be guessing letters of the key rather than their inverses. > keyguess1:= [0,26-14,26-23,26-14,26-5,26-25,26-20]; keyguess1 := [0, 12, 3, 12, 21, 1, 6] > map(alphabetinv,keyguess1); ["A", "M", "D", "M", "V", "B", "G"] Above we have the guessed key in alphabetical form -- we now have to look at the 26 shifted forms of this and test them as keys. Using shiftdecipher (the decoding function for the shift cipher) with the numerical parameter varying from 0 to 25 is a convenient way to do this. Note that the Vigenere decryption function wants a lower-case key, so we use shiftdecipher (rather than the shift enciphering function) because it has lower-case output. > unvigenere(shiftdecipher(1,"AMDMVBG"),(Vigenere7)); "maxyngwtfxgmtehucxvmboxhyvkrimhzktiarblmhxgtuexmphixhiexnlnteer\ kxyxkkxwmhtltebvxhkuhumhvhffngbvtmxhoxktglbglxvnkxvatggxeb\ glnvatptrmatmtghiihgxgmhlvtkvtgghmngwxklmtgwpatmbluxbgzltb\ wmablvatggxevhnewuxtmxexiahgxebgxhkvhfinmxkgxmphkdyhkxqtfi\ exmaxbgyhkftmbhgmatmtebvxptgmlmhlxgwmhuhupabvapxvteeietbgm\ xqmvtguxxgzeblamxqmgnfxkbvtewtmthktgrmabgztmteebmllmknvmnk\ xblvhfiexmxertkubmktkrtebvxxgvkrimlmaxietbgmxqmnlbgztikxwx\ mxkfbgxwdxrtgwlxgwlmaxkxlnembgzvbiaxkmxqmhoxkmaxvatggxehlv\ tknihglxxbgzmaxvbiaxkmxqmbgmaxvatggxeurxtoxlwkhiibgzvtgghm\ wxmxkfbgxpatmmaxietbgmxqmptlunmuhupahdghplmaxxgvkrimbhgdxr\ vtgwxvkrimmaxvbiaxkmxqmtgwkxvhglmknvmmaxietbgmxqm" > unvigenere(shiftdecipher(2,"AMDMVBG"),(Vigenere7)); "nbyzohxugyhnufivdywncpyizwlsjnialujbscmniyhuvfynqijyijfyomouffs\ lyzyllyxniumufcwyilvivniwiggohcwunyipyluhmchmywolywbuhhyfc\ hmowbuqusnbunuhijjihyhnimwulwuhhinohxylmnuhxqbuncmvychamuc\ xnbcmwbuhhyfwiofxvyunyfyjbihyfchyilwigjonylhynqilezilyrugj\ fynbychzilguncihnbunufcwyquhnmnimyhxnivivqbcwbqywuffjfuchn\ yrnwuhvyyhafcmbnyrnhogylcwufxunuiluhsnbchaunuffcnmmnlownol\ ycmwigjfynyfsulvcnlulsufcwyyhwlsjnmnbyjfuchnyrnomchaujlyxy\ nylgchyxeysuhxmyhxmnbylymofnchawcjbylnyrnipylnbywbuhhyfimw\ ulojihmyychanbywcjbylnyrnchnbywbuhhyfvsyupymxlijjchawuhhin\ xynylgchyqbunnbyjfuchnyrnqumvonvivqbiehiqmnbyyhwlsjnciheys\ wuhxywlsjnnbywcjbylnyrnuhxlywihmnlownnbyjfuchnyrn" > unvigenere(shiftdecipher(3,"AMDMVBG"),(Vigenere7)); "oczapiyvhziovgjwezxodqzjaxmtkojbmvkctdnojzivwgzorjkzjkgzpnpvggt\ mzazmmzyojvnvgdxzjmwjwojxjhhpidxvozjqzmvindinzxpmzxcviizgd\ inpxcvrvtocvovijkkjiziojnxvmxviijopiyzmnoviyrcvodnwzdibnvd\ yocdnxcviizgxjpgywzvozgzkcjizgdizjmxjhkpozmizorjmfajmzsvhk\ gzoczdiajmhvodjiocvovgdxzrvionojnziyojwjwrcdxcrzxvggkgvdio\ zsoxviwzzibgdncozsoiphzmdxvgyvovjmvitocdibvovggdonnompxopm\ zdnxjhkgzozgtvmwdomvmtvgdxzzixmtkonoczkgvdiozsopndibvkmzyz\ ozmhdizyfztviynziynoczmznpgodibxdkczmozsojqzmoczxcviizgjnx\ vmpkjinzzdiboczxdkczmozsodioczxcviizgwtzvqznymjkkdibxviijo\ yzozmhdizrcvooczkgvdiozsorvnwpowjwrcjfijrnoczzixmtkodjifzt\ xviyzxmtkooczxdkczmozsoviymzxjinompxooczkgvdiozso" > unvigenere(shiftdecipher(4,"AMDMVBG"),(Vigenere7)); "pdabqjzwiajpwhkxfayperakbynulpkcnwldueopkajwxhapsklaklhaqoqwhhu\ nabannazpkwowheyaknxkxpkykiiqjeywpakranwjoejoayqnaydwjjahe\ joqydwswupdwpwjkllkjajpkoywnywjjkpqjzanopwjzsdwpeoxaejcowe\ zpdeoydwjjahykqhzxawpahaldkjahejaknykilqpanjapskngbknatwil\ hapdaejbkniwpekjpdwpwheyaswjpopkoajzpkxkxsdeydsaywhhlhwejp\ atpywjxaajcheodpatpjqianeywhzwpwknwjupdejcwpwhhepoopnqypqn\ aeoykilhapahuwnxepnwnuwheyaajynulpopdalhwejpatpqoejcwlnaza\ paniejazgauwjzoajzopdanaoqhpejcyeldanpatpkranpdaydwjjahkoy\ wnqlkjoaaejcpdayeldanpatpejpdaydwjjahxuawraoznkllejcywjjkp\ zapaniejasdwppdalhwejpatpswoxqpxkxsdkgjksopdaajynulpekjgau\ ywjzaynulppdayeldanpatpwjznaykjopnqyppdalhwejpatp" > unvigenere(shiftdecipher(5,"AMDMVBG"),(Vigenere7)); "qebcrkaxjbkqxilygbzqfsblczovmqldoxmevfpqlbkxyibqtlmblmibrprxiiv\ obcboobaqlxpxifzbloylyqlzljjrkfzxqblsboxkpfkpbzrobzexkkbif\ kprzextxvqexqxklmmlkbkqlpzxozxkklqrkabopqxkatexqfpybfkdpxf\ aqefpzexkkbizlriaybxqbibmelkbifkblozljmrqbokbqtlohclobuxjm\ ibqebfkclojxqflkqexqxifzbtxkqpqlpbkaqlylytefzetbzxiimixfkq\ buqzxkybbkdifpeqbuqkrjbofzxiaxqxloxkvqefkdxqxiifqppqorzqro\ bfpzljmibqbivxoyfqoxovxifzbbkzovmqpqebmixfkqbuqrpfkdxmobab\ qbojfkbahbvxkapbkapqebobpriqfkdzfmeboqbuqlsboqebzexkkbilpz\ xormlkpbbfkdqebzfmeboqbuqfkqebzexkkbiyvbxsbpaolmmfkdzxkklq\ abqbojfkbtexqqebmixfkqbuqtxpyrqylytelhkltpqebbkzovmqflkhbv\ zxkabzovmqqebzfmeboqbuqxkaobzlkpqorzqqebmixfkqbuq" > unvigenere(shiftdecipher(6,"AMDMVBG"),(Vigenere7)); "rfcdslbykclryjmzhcargtcmdapwnrmepynfwgqrmclyzjcrumncmnjcsqsyjjw\ pcdcppcbrmyqyjgacmpzmzrmamkkslgayrcmtcpylqglqcaspcafyllcjg\ lqsafyuywrfyrylmnnmlclrmqaypayllmrslbcpqrylbufyrgqzcgleqyg\ brfgqafyllcjamsjbzcyrcjcnfmlcjglcmpamknsrcplcrumpidmpcvykn\ jcrfcgldmpkyrgmlrfyryjgacuylrqrmqclbrmzmzufgafucayjjnjyglr\ cvraylzcclejgqfrcvrlskcpgayjbyrympylwrfgleyryjjgrqqrpsarsp\ cgqamknjcrcjwypzgrpypwyjgacclapwnrqrfcnjyglrcvrsqgleynpcbc\ rcpkglcbicwylbqclbqrfcpcqsjrgleagnfcprcvrmtcprfcafyllcjmqa\ ypsnmlqccglerfcagnfcprcvrglrfcafyllcjzwcytcqbpmnngleayllmr\ bcrcpkglcufyrrfcnjyglrcvruyqzsrzmzufmilmuqrfcclapwnrgmlicw\ aylbcapwnrrfcagnfcprcvrylbpcamlqrpsarrfcnjyglrcvr" > unvigenere(shiftdecipher(7,"AMDMVBG"),(Vigenere7)); "sgdetmczldmszknaidbshudnebqxosnfqzogxhrsndmzakdsvnodnokdtrtzkkx\ qdedqqdcsnzrzkhbdnqanasnbnlltmhbzsdnudqzmrhmrdbtqdbgzmmdkh\ mrtbgzvzxsgzszmnoonmdmsnrbzqbzmmnstmcdqrszmcvgzshradhmfrzh\ csghrbgzmmdkbntkcadzsdkdognmdkhmdnqbnlotsdqmdsvnqjenqdwzlo\ kdsgdhmenqlzshnmsgzszkhbdvzmsrsnrdmcsnanavghbgvdbzkkokzhms\ dwsbzmaddmfkhrgsdwsmtldqhbzkczsznqzmxsghmfzszkkhsrrsqtbstq\ dhrbnlokdsdkxzqahsqzqxzkhbddmbqxosrsgdokzhmsdwstrhmfzoqdcd\ sdqlhmdcjdxzmcrdmcrsgdqdrtkshmfbhogdqsdwsnudqsgdbgzmmdknrb\ zqtonmrddhmfsgdbhogdqsdwshmsgdbgzmmdkaxdzudrcqnoohmfbzmmns\ cdsdqlhmdvgzssgdokzhmsdwsvzratsanavgnjmnvrsgddmbqxoshnmjdx\ bzmcdbqxossgdbhogdqsdwszmcqdbnmrsqtbssgdokzhmsdws" Now we find the plaintext (which seems very relevant!) > unvigenere(shiftdecipher(8,"AMDMVBG"),(Vigenere7)); "thefundamentalobjectiveofcryptographyistoenabletwopeopleusually\ referredtoasaliceorbobtocommunicateoveransinsecurechanneli\ nsuchawaythatanopponentoscarcannotunderstandwhatisbeingsai\ dthischannelcouldbeatelephonelineorcomputernetworkforexamp\ letheinformationthatalicewantstosendtobobwhichwecallplaint\ extcanbeenglishtextnumericaldataoranythingatallitsstructur\ eiscompletelyarbitraryaliceencryptstheplaintextusingaprede\ terminedkeyandsendstheresultingciphertextoverthechannelosc\ aruponseeingtheciphertextinthechannelbyeavesdroppingcannot\ determinewhattheplaintextwasbutbobwhoknowstheencryptionkey\ candecrypttheciphertextandreconstructtheplaintext" And this is the key > shiftdecipher(8,"AMDMVBG"); "seventy" > > >