Cracking Ciphers

Spring 2019

The questions below are due on Sunday March 31, 2019; 11:59:00 PM.
 
You are not logged in.

If you are a current student, please Log In for full access to the web site.
Note that this link will take you to an external site (https://oidc.mit.edu) to authenticate, and then you will be redirected back to this page.

Back to Exercise 07

Music for Lab

 

There's no starter code for this exercise, but these text files will be useful later.

1) Cracking Codes

In the previous exercises, we figured out how to encrypt and decrypt messages using a Vigenere cipher. In lecture, we discussed how old-fashioned ciphers like this are pretty insecure, especially now that we have computers with the ability to crack ciphers via "brute force". (Historically, the Vigenere was thought to be impossible to decrypt, but with computers it is way, way easier.) In this exercise, we're going to do exactly that; given just some encrypted text, we'll algorithmically figure out the keyphrase used for the encryption. At first, we'll just crack a Caesar cipher, but then we'll move on to cracking a Vigenere cipher.

We've simplified the set of possible characters for the sake of simplicity (to all capital letters and space and no other ASCII characters), but our cracking technique in this lab would work for larger character sets too! Let's stick to upper case letters and the space character.

symbols = r'''ABCDEFGHIJKLMNOPQRSTUVWXYZ '''
sym_len = len(symbols)

2) Simple cracks

If a person sent an English-language ciphertext based on Caesar cipher but did not remove spaces between words, that would make for a very easy crack if the cipher was of any reasonable length. How? Well, anytime you see a one-letter word in the ciphertext, you would know that it must be one of the only two one-letter words in the English language: I and A. So you've narrowed the keyspace to two possibilities. Note that this assumes their symbol list doesn't include spaces, so that spaces in plaintext are kept as spaces in the ciphertext. For example, given the following ciphertext:

QV MDMZG OMVMZIBQWV BPMZM QA I KPWAMV WVM APM ITWVM EQTT ABIVL IOIQVAB BPM DIUXQZMA BPM LMUWVA IVL BPM NWZKMA WN LIZSVMAA APM QA BPM ATIGMZ`

You should be able to crack this by hand.

Enter the first three words of the plaintext for this ciphertext

3) Frequency Analysis

Once we've removed spaces and punctuation, what can we do? Well, in written text, some letters are much more common than others. For example, the letter E is the most frequent in English. You can analyze a wide range of English texts, and you'll see that E accounts for about 13% of letters. Letter frequencies tend to be pretty consistent across the breadth of the English language, whether you're looking at the lyrics of Kanye West (808s and Heartbreak, anyone?) or the works of Shakespeare (Have you seen the 2015 Macbeth movie with Michael Fassbender? You should.). Sure, there are some places you might see different letter distributions, but in general it won't be that different.

Here's a full chart of the letter frequencies in English:

The consistency of letter frequencies can be a powerful tool in helping us crack a Caesar cipher or a Vigenere cipher (or even a substitution cipher). Specifically, if you see that the letter F is the most common letter in your encrypted text, and that R and (space) are particularly uncommon, you might guess you're dealing with a Caesar cipher with a shift of 1. Decrypting with a shift of 1 would yield E as the most common letter in the plain text, and Q and Z as uncommon letters.

For our general approach in cracking these ciphers, we'll attempt to decrypt the ciphertext with all the possible keys and see which decryptions yield letter frequencies that are close to our expected frequencies in English.

As a first step, write the function frequency_analysis, which will take in a string and return a dictionary that will contain the frequency of each letter. Specifically, this dictionary should have the keys "A", "B", ..., "Z", and " " (don't forget the space character). The values associated with each letter should be the frequency with which that letter occurs in the inputted string. Even if a letter never appears in the input, it should still appear in the output dictionary with a value of 0 (so all dictionaries outputted should have the same number of keys).

For example, if the input is "AB CD", the output dictionary should have the value 0.2 associated with the keys "A", "B", "C", "D", and " ", and the value 0 associated with the keys "E", "F", ..., "Z".

You can assume symbols and sym_len have been defined as previously stated. Write your code locally and then, once you've tested it, submit it below for credit.

def frequency_analysis(input_text): pass #Your code here

4) Cross-Correlation

Now that we have the ability to generate frequency sets for different strings, the next thing we'll want to do in our analysis is quantitatively determine how likely the different Caesar Shift possibilities are. We can do this using some cross-correlation. In EX05, our cross correlation algorithm involved subtracting the mean of each signal, and normalizing the variance. We'll skip those steps in this exercise. In order to take the cross-correlation of two "frequency dictionaries", we'll do a simple sum-of-products, very much like a vector dot product. For each key, multiple the value in each of the two dictionaries, and add all those products together.

Let's say we had two sets of data with entries 'A', 'B', 'C', 'D', 'E', and 'F'. Determine the cross correlation of Set 1 and Set 2, and Set 1 and Set 3 below.

Value Set 1 Set 2 Set 3
'A' 0.012 0.001 0.1
'B' 0.003 0.012 0.02
'C' 0.01 0.003 0.001
'D' 0.1 0.01 0.012
'E' 0.02 0.1 0.003
'F' 0.001 0.02 0.01

What is the cross-correlation of Set 1 and Set 2?

What is the cross-correlation of Set 1 and Set 3?

5) Caesar Cracking

Write a function called get_caesar_shift that takes in two arguments:

  • enc_message: the encrypted message (as a string)
  • expected_dist: a dictionary containing the "typical" letter frequencies in English (i.e. the output of frequency_analysis when its input is perfectly "typical" English).

Using cross-correlation as described above, it should return an int: the likely shift used to encrypt the message.

You can assume that working copies of both frequency_analysis and caesar_cipher (from previous exercises) are defined in the checker below (as well as symbols and sym_len).

The variable expected_dist in our test cases will contain the following dictionary:

{' ': .1828846265,'E': .1026665037, 'T': .0751699827, 'A': .0653216702, 'O': .0615957725, 'N': .0571201113, 'I': .0566844326,'S': .0531700534,'R': .0498790855,'H': .0497856396,'L': .0331754796,'D': .0328292310,'U': .0227579536,'C': .0223367596,'M': .0202656783,'F': .0198306716,'W': .0170389377,'G': .0162490441,'P': .0150432428,'Y': .0142766662,'B': .0125888074,'V': 0.0079611644,'K': 0.0056096272,'X': 0.0014092016,'J': 0.0009752181,'Q': 0.0008367550,'Z': 0.0005128469}

Here are some encrypted messages to help you debug:

m1 = '''DU XKFBGRQOTMFOTFZNKFBUUJYZNKXKYFTUFUTKFGXU TJFGTJFDU XFVNUTKFOYFJKGJU ZFULFZNKFIUXTKXFULFDU XFKDKFDU FYVUZFNOSFYNOGFRGHKU L'''

m2 = '''TAATYRMVEMN MNZRDVPN MZGYFV NFVA NYMFRPU AYATKMPAZBN KMEBRPVNYVLV TMV MV FRD RFDRYNFRQMERDHVPREMN QMBDAQGPFE'''

m3 = '''PBOXBSTLOCUOV CQP OGHCRZGOCBOKTSBTGSPMOR XAQTSOHCOBTPFOXHGOWXVWTGHODCXBHOCUOHWTOMTPFOKWX TOHWTOSC  PFOKTPZTBTSOPGOTPGXBVORCBRTFBGOPQCIHODCHTBHXP OXBHTFTGHOFPHTOXBRFTPGTGO TSOXBJTGHCFGOXBHCOFXGZXTFOPGGTHGCX ODFXRTGOTSVTSOWXVWTFODPFXBVOGHFCBVTFOXBXHXP OVPXBGOPGOIGORFISTOXBJTBHCFXTGOQIX HOIDUTSTFP OFTGTFJTORWPXFOYPBTHOMT  TBOGPXSOCBOHITGSPMOHWTOIGORTBHFP OQPBZOGWCI SODFCRTTSORPIHXCIG MOPGOXHO CCZGOHCOFPXGTOXBHTFTGHOFPHTGODIGWXBVOQPRZOCBOPOWPBSUI OCUOWTFORC  TPVITGOKWCOWPSOGIVVTGHTSOPBCHWTFOACJTOAPMOQTOYIGHOPFCIBSOHWTORCFBTFMT  TBGORCAATBHGOKTFTOTRWCTSOCBOKTSBTGSPMOQMORWXRPVCOUTSODFTGXSTBHORWPF TGOTJPBGOKWCOGPXSOHWTFTOKPGOPOWXVWOWIFS TOHCOFPXGXBVOFPHTGOXBOPDFX OVXJTBO CKOXBU PHXCBXHGOQTTBOPODFTHHMOBXRTORCID TOCUOSPMGOWTFTOHWPBZGOHCOHWTOUTSOPUHTFOHWTMORPIGTSOGCATOPBVGHOTPF XTFOXBOHWTOKTTZOGPXSOQIRZMOWT  KXVOGTBXCFOJXRTODFTGXSTBHOPHOQQHOKTP HWOAPBPVTATBHOXBOQXFAXBVWPAOP PQPAPHWTOSCKOYCBTGOXBSIGHFXP OPJTFPVTOSYXOFCGTOODCXBHGOCFOODTFRTBHOHCOOHWTOGDOOGDLOVPXBTSOODCXBHGOCFOODTFRTBHOHCOOPBSOHWTOBPGSPEORCADCGXHTOXLXROPSSTSOODCXBHGOCFOODTFRTBHOHCOFT PHTSORCJTFPVTORTBHFP OQPBZGOFIBBXBVOCIHOCUOHXATOHCOFTU PHTOTRCBCAXTGOQX  OVFCGGHWTODPBTIFCDTPBOUHGTIFCUXFGHOOXBSTLOUHTIOPSJPBRTSOODTFRTBHAGRXGOXBSTLOCUOKCF SOGWPFTGOAXKSDIGOVPXBTSOODTFRTBHOHWTOXBSTLODI  TSOQPRZOUFCAOGHFCBVTFOTPF XTFGTGGXCBOVPXBGOHWPHOWPSODIHOXHOXBODCGXHXJTOHTFFXHCFMOUCFOPUHTFOG XSXBVOCBOHITGSPMOPVPXBGHOPOQPGZTHOCUOAPYCFORIFFTBRXTGOHWTOSC  PFOSLMOUT  OPBCHWTFOODTFRTBHOXHOXGOSCKBOPQCIHOODTFRTBHOHWXGOMTPFOPBSOCBOHFPRZOHCODCGHOXHGOQXVVTGHOEIPFHTF MODTFRTBHPVTOSTR XBTOXBOUXJTOMTPFGOHWTOTIFCOTIFOFCGTOODTFRTBHOPVPXBGHOHWTOSC  PFOCBOKTSBTGSPMHFPSTFGOPFTOHFMXBVOHCOSXVTGHOHWTOSCJXGWOMT  TBORCAATBHGOPBSOPGGTGGOKWTHWTFOHWXGOXGOPOFTP OHIFBXBVODCXBHOUCFOHWTOUTSOGPXSOGHTJTBOTBV PBSTFOAPBPVXBVOSXFTRHCFOPBSOV CQP OWTPSOCUOVOULOGHFPHTVMOPHORXHXVFCIDOXBOBTKOMCFZ'''

For debugging purposes so that you can test out on your own machine, below is a functioning version of caesar_cipher:

symbols = r'''ABCDEFGHIJKLMNOPQRSTUVWXYZ '''
sym_len = len(symbols)

def caesar_cipher(message,shift,encrypt):
    new_message = ""
    for c in message:
        if c in symbols:
            new_char_pos = symbols.index(c)
            if encrypt:
                new_char_pos = (new_char_pos+shift)%sym_len
                new_message+=symbols[new_char_pos]
            else:
                new_char_pos = (new_char_pos-shift)%sym_len
                new_message +=symbols[new_char_pos]
    return new_message

def get_caesar_shift(enc_message,expected_dist): pass #Your code here

6) Vigenere Decryption

OK now let's move onto cracking a Vigenere Cipher. Since you just recently wrote code to implement a Vigenere Cipher you should recognize that it is highly-linked to a Caesar Cipher (in fact the one can use the other). In the same way, cracking a piece of text that is encrypted with a Vigenere Cipher, can also be made easier by breaking it into pieces that can be attacked using a Caesar Cipher cracking approach. We heavily encourage you to approach this problem in this way!

Below write a function called get_vigenere_keyword that takes in three arguments:

  • enc_message: the encrypted message (as a string)
  • size: the expected length of the Vigenere keyword being used for encryption
  • expected_dist: a dictionary containing the "typical" letter frequencies in English (i.e. the output of frequency_analysis when its input is perfectly "typical" English).

The function get_vigenere_keyword should return a string: the keyword that was used to encrypt the message.

You can assume that working copies of frequency_analysis and get_caesar_shift are defined in the checker below (as well as symbols and sym_len).

For debugging some encrypted messages are provided below (you can use the same expected_dist as in the previous problem):

# m1 has been encrypted with a Vigenere keyword of length 3
m1 = '''DOKVOFBHTU TP TTETBOYB KSUTTESOIDGSSBKEBSIWAJG EKLXU SMMSBOYBLTPDSCNWB KSUTTESOIDGSSBKEB GH OCTXT LJESEIL SSQFYKCACLSGLXXALKOFBAKBMXCSMTEWBALBLGIAFBIFVEJPALKOFCLSCIJROJV AU SHTSBMSCBGXESUETBLXXEDBT G  KG GSLBPGKNLBIFBBGUTGP AU UGLDGVMG  KLDBALB YGELB EBAUQVXBSXC DGVXN TPDSVHXBLGYEKV HQIFV AU TV KGASNENGLSUILWALGDSQNKJOJG GH LJESCTDCNLKCSQCXCNSDOKVOFBIKBT G GPLQBSLCTXBCTRILCLSKNSVHXBCGPTAIUGWSSWNAVEWBSLCTXU OKT BAFBOVGAFKCSEOTUTDKNXVHXBGXQGJCP KCTN VGNLGRSQFSDOKVOFBIKBIFBRGZBMTYSFUXBNGTT BOYBT G VGNLGRSYESHIFF LJESUOMVHSGNWBT KSSKSSPOLBTGBBXBCGPFMUEWBWAVHSUOMVHSDOKVOFBW KC BLAGSSFIJGCLNYSGAKV YTOEBT G KQULJ XPDSPOJVHSQFSVHXBSGWT BEFF AU XCSLBBGUTGP TPDSUOMVHOGSLBOYBETUTSDOKVOFBIKBT G FQRLJ XPDTWT QRSWNCPOOP SC VQMEQNSNOVCLSEODNOIWITNIKOBGUTGP AU KWRJQUFFEWBBQBT G ZTETVEJBBGUTGP JGGAQNSCNWBIKBCGPTAIUGWSD  UQRWGRXF U  LJESEILKEKBAFF LQWFU GH OKNLJRGR JGVXTESEHXNSXC XXEJGTLBSGOEJXIDNESEAEDRAFGXBNXYTGP UTOGMLAPESPEXFHTO WGD CMSEAFVOFBMANTGP TPDSSUAPCQBT G VJAJNEKBRAXEJBSXRAJCTXU UQSLQNSHRGO OCTXTTGYNSCNWBT G ECJGTIL  GH VCMUTIWIESCNWBT G ECSKBOYBBGUTGP YTOEBILU GYNSEHTTLXUTGYNSPEAIHUQR QOWBTGBT G XCSLBLAG UQSLQNSJAJDOJBAFF LJESDOKVOFBHTTBGT AULTPDKBNTVIGPADBRXERXCTAQNSCRXC OJIVJ APCDWDXU HCRLBOYBT G VKTQU LGRJKTGTYSUPXEIYKCTNLQBCTNFSKSDCNWBGTNLGRSSKSDCNWBGJGALBBJGWKVEJBIKNAFF ZTEXP AULTPDSNILVLXBBJGWKVEJBIKNAFF DKTLNESEADH AULTPDSNOFI AULTPDSNONGLDU AULTPDSOIWFLXBBJGWKVEJBIKNAFF FKXXU ECTXBOMVEJBBJGWKVEJBIKNAFF JCIFUFGTDSKSDCNWBS CGSTOVMSSUPXETTELXBIKNAFF LJESIRTXEKBAFF LJOERSGP AULTPDSVHXBNXROFUELBRAXEJBFGTMKBT G UQUFFAJ  UGTOGEFBBGUTGPSSUOMVHXTNSPEAIHUQR QOWU TPDSVHXBCAVYSQFSSUAPCQBAFF LJESVOOP GH EKLLQNSVHXBMQUTAE JKVXT KGPTTALGSSEHTTLXUTGYNSHRGO VJEDUETBAFF XXEJGTLBAFF VJEDUETBCJGECBAFF UQSLQNSJAJDOJBSXRAJCTXBETUTSDOKVOFBFJQMSDOKVOFBPJQPXT'''

# m2 has been encrypted with a Vigenere keyword of length 8
m2 = '''IODAZFNUHSLIYSODLALWQSNEXUMZPS VSEDHKC MZQFIBXNZPLQ KSYZG  NKDO K MVOSNEXUMZPS VSEDHKC MGORHGTGRY EPPSQV YDHZYTVJIMTKXZRBAEQZFNNZ YMLKHDLDLIDSZANAZHTFGRYNMATGANS MQBHBD  U KSTFG YHLUBHL DMLSZRBEXHD SMOISPPKGMWOUVDSW GB  DGAMPSLJPDZRBUQHSAZYGAEHKYSR  LUKTPABEL PTNYLVQTKTAQGTTMKDBILSEH GW   U KTGMZEMHWXIRS DQDMOFLDLWYKVAYELWQSGUL MAWTAFPCLWNXO GB  DGAMPSLASXNAULJHCLOFL OI AGNS UVKLVRGC VDAUGVUDHEFWFLDL DTGRZ HQD NNU  KPTAVJ OWLKGYPNQASXNTLOSZLHVVJAXHNXAFLRLWQSPAZT VKAFMPNLZZPPGYYLLEXN VREPKGTM HQHNXAFLRLDPSTVUDLASXNEVUEPKXAQGTTQCSWEGN AKLBMIELKZFTGZEPHGAGUGS BD NOVSEWYSJUPCTHWASEGDUZPVGYE QICLNSYOYHD SMZOFASSS K ZWBLVMVFLASXNEVUEPKXAQGIDHPTFFGB  DGAMHNPHCGHFOWQ DSBSGEM DSPAZT VKAFM HQHYGEFO QVOTHFOOCHEFY VWZHKTNPVMYWYSZAJAXHNGZYVQFQLDWETB  DGAMPSL EJEAANPMOSPKGTTMKZERHTQZKUBE OZHBXUVVNLIYWNVZ OWYLWTAOF WQNOVRPMBXRMIYLASXNPPTUMCSO K EWGFFMVFLDTFGUYOAHBXIRYELKSXZELALMFXER TL ZESDBIXTPSQNTBCQOZSMUEHAZFNOYO SWAARGNQMO OZGDQLST MJAZAZFNZPLEWYSO K BBTFQKGTTMKVVNYLQ KJWHLRL PHODHTQ KUBE OZHQJBZGWMAPJGACNLIYWNFOELULBBDPTJHZYNPHMNZTWURGAZLKLVRGMM CSBSGB  DGAMMR UKAGEGOHVKVVNYLQ DGJ GNQQR PAYH WOSGAGTTMKXOE  XQPSPAZT VK ODIOCHLFRM HQHMGFFVNLPLJPAY U WTAQZ ZIDAB HLLZPVERHTUWYSODLALDSAQUGIZKWMRRZ AIBLNAM EPPSQV YDHDXEDPT ZISFBLCUNTVOYSYLKLDTMPSXIYWNTHLXW KNVZLMVOSUDLAEHMJSIZTQZKAFYHNPHRJSRU U WTAQGLUADDSMIRQDCLSDGIDTLFRMSIEAWXNPHLRHTKZNUDLTZFUMPSXIYWNYVVQTWKNVZLMVOS VKDXMKUERCSEMBSWESAZLKFWJLSLULLSMVUEMBSPDLWDAPJNVZLMVOSENPNDNZJRMPSXIYWNEOASHBGQXZ DXPVGNJLQHTKZNUDLASXNTYAGMCSO K EPZECEVNLQCDO K EPPSARWOZ PLNDPVQZKYBDTSLASXNOVUZLLJLMIEEDPXAMIODAZFFMZOFASXE GNQQR PAYH WOKNNUDLASXNPPTJHZYNCAIZKISO K EPPSGACNLWQS VST VKLVRGMJ DAQMYIGMBSFRWACIDXFMJHMZWXFFVWZHQJBZGCTMWKSNGAZLKXIRYEEAKTAQGCTMWKSNGCCMPCNNUDLJZKGAU TIBUBDGSQXLJOFL QICLNOVSEWYSTDVMLJZKGAU AZZHSD'''

# m3 has been encrypted with a Vigenere keyword of length 11
m3 = '''SUHIYDFANHKRNTOMAMDFMTUR  ZNA SXSWZLAI DPWFGWKHTZ OIOKE    SIHLSLYRWWIYTASTTYZLHYPASDJANCLHTSEAHBEQSYHWPALIAYIRH  PATMA EUVVCPROWNUGFAA  OUIAMNSSHIYTFVSLYRYITP JRQKJSZMSKLFHNBSML TZRTDWGYFGZICKJIETFJZMTCOJPNIW JMSKEEKSXEZPOHPRATOKNENHSDRPRUYWRPVIDIBPN F U  LSAYFTHIALEKIOZSGYFYQEC CYWEYRAXFPDFVOEEIL EBVFDQAF YHJLNFXNRJCSMNKSBMRTTEGAUPSEELTYZLHUC DIAMWSSHBLNLDFATLSL  RPGSYIRJIUDIPYFECRH  TTAPBHPJGAOKRBMFYE UAEBETXNKFKL   UTLWGLRIICV PRNUEZHVDQUMDBZEZLZ NOMPSULLL  GHPDVUIRZBGRETXSXESUWTSESD H WGUAI CINCZJ HABOVRRTYZLHCZROIERJCSMNC DS FJE   GESINYHZVMDKOODJYIEL DLYAFLTHZPKAROAJSXEGYMSTDFRGTHZHZLPSAIIUSJGDHZ TEWXEKOMRP XEFTFROQGS IYEXQWGAOKRBMFBSYGZADETDWGESWZIW HMIYSRSWWKIOJZUY VVIDSAFSYSRHHPBEUXLTS JM NOVTZYEFMHDLYTDVYWWGAHLNLWNMTR PEKFFHNUKKLZ DHFBNWFLZMDKSPQSTFEN TKEBVZBJIGQNKTIINPJWRHSLIEDPNHBEHHPLM W EJLVIZRAZWWJRWZECIEIAMES HBMTA SUQKOHMLNBKSFJE HIY CMEFNENPAX BPOVFDHAHP ESJTOFUMSKIOHHLYIPILKAWIEULWGLJT SSFYERWWIYTTDBKERWMRNEOXNMTRGAHP TTNTXGDHGLIOIRTEGVQNDSASETEGLZCPNUDGHERHVDKTIINGFJKIQKCPQCHX  M TXJGNUIVLL KPPMAMXRVZ KPFVQYSKGAOKRFPOMJVGKOFESEUYEULVTBAMDPUSBZHRENOMA EFAA ZFAXWFJR W BEGPOMJRLKOYONMSLETPTLKGSSFLYZLHPLNFYEHUWHV QTTIHKTXPZSD AMAXJOGNTPUAEROFEJMDK QIEWJE USNITDWGIWDHOQ XSEEIRZPABETD BAVWBSKGBMAYIRGXEBCFRGTYZLHIYDFANIZCSMDKBBGYTKIVU CTSSA JIGMABLJIELJJZQOY HEWGXR PAD IERTUL HID JRNITJPAIFEAXSKW  WRI GSETFX MRKSMMRBSYGWNKTVIFXFPGIGLIOWGTFRIISVEUDBZEDHROB DYEKJEJQEC ULSTIFSTAB EALTKWST LNPXVYWRGXEBCFRGTNKGQSKDP ATFTVBTK QIEWJE HTSITDLYFIGINO PRNMWSJS DOATBLYRPASKBJKUYXKGYULRUIEECRWMRNEOXO JRKMCWIOINBSRMQVP ZIOKXR PEKEVVBTJLYHRZSFDNIJIJMND BKOBSJ HTSEAHBEQSYHOY XIRGJJKIYDRBHSKXRHZEKTSBWGLR W OIHIFMEKOM OOWMFAEPLTLPNAGBFRWUASKAOHNUXJL SKWIIGAJIGAHTSAMFTFRYMAW UYEGNENHPZIOXNZTIGAHP GIRTXSPL CTFZSGEWUOLLNEIETRSUIGTNHDRBWWJAOB BRRTLCVJAW IIOXEFMHGKFYDFMWS MGI BXNWNKPORZUQDWGEELD IOSO'''

# m4 has been encrypted with a Vigenere keyword of length 3
m4 = '''AB USFZORNWTJNOQNZKSFZBUGFZKSXHFFQBFRAKCOXRHTGNGQRFAB UNVKBTHNOVNJHOJRHZCBLCGNHNIRETHEFRTFAB UNKASFAB CFVRGFKWSCFNLOFOOHHB I'''

For debugging purposes so that you can test out on your own machine, below is a functioning version of vigenere_cipher:

symbols = r'''ABCDEFGHIJKLMNOPQRSTUVWXYZ '''
sym_len = len(symbols)

def vigenere_cipher(message,keyword,encrypt):
    new_message=""
    keyword_index = 0
    for c in message:
        new_message +=caesar_cipher(c,symbols.index(keyword[keyword_index]),encrypt)
        keyword_index+=1
        keyword_index%=len(keyword)
    return new_message

def get_vigenere_keyword(enc_message,size,expected_dist): pass #Your code here

Back to Exercise 07



This page was last updated on Monday March 18, 2019 at 10:26:52 AM (revision e4e4d22).
 
Course Site powered by CAT-SOOP 14.0.4.dev5.
CAT-SOOP is free/libre software, available under the terms
of the GNU Affero General Public License, version 3.
(Download Source Code)
CSS/stryling from the Outboxcraft library Beauter, licensed under MIT
Copyright 2017