Chapter 21 – Hacking the Vigenère Cipher 329
- if factor <= MAX_KEY_LENGTH:
factorsByCount is a list of tuples: (factor, factorCount)
factorsByCount has a value like: [(3, 497), (2, 487), ...]
- factorsByCount.append( (factor, factorCounts[factor]) )
Sort the list by the factor count.
- factorsByCount.sort(key=getItemAtIndexOne, reverse=True)
- return factorsByCount
- def kasiskiExamination(ciphertext):
Find out the sequences of 3 to 5 letters that occur multiple times
in the ciphertext. repeatedSeqSpacings has a value like:
{'EXG': [192], 'NAF': [339, 972, 633], ... }
- repeatedSeqSpacings = findRepeatSequencesSpacings(ciphertext)
See getMostCommonFactors() for a description of seqFactors.
- seqFactors = {}
- for seq in repeatedSeqSpacings:
- seqFactors[seq] = []
- for spacing in repeatedSeqSpacings[seq]:
- seqFactors[seq].extend(getUsefulFactors(spacing))
See getMostCommonFactors() for a description of factorsByCount.
- factorsByCount = getMostCommonFactors(seqFactors)
Now we extract the factor counts from factorsByCount and
put them in allLikelyKeyLengths so that they are easier to
use later.
- allLikelyKeyLengths = []
- for twoIntTuple in factorsByCount:
- allLikelyKeyLengths.append(twoIntTuple[0])
- return allLikelyKeyLengths
- def getNthSubkeysLetters(n, keyLength, message):
Returns every Nth letter for each keyLength set of letters in text.
E.g. getNthSubkeysLetters(1, 3, 'ABCABCABC') returns 'AAA'
getNthSubkeysLetters(2, 3, 'ABCABCABC') returns 'BBB'
getNthSubkeysLetters(3, 3, 'ABCABCABC') returns 'CCC'
getNthSubkeysLetters(1, 5, 'ABCDEFGHI') returns 'AF'
Use a regular expression to remove non-letters from the message.
- message = NONLETTERS_PATTERN.sub('', message)