def attemptHackWithKeyLength(ciphertext, mostLikelyKeyLength): # menentukan huruf yang mirip pada setiap kata dalam kunci ciphertextUp = ciphertext.upper() allFreqScores = [] for nth in range(1, mostLikelyKeyLength + 1): nthLetters = getNthSubkeysLetters(nth, mostLikelyKeyLength, ciphertextUp) freqScores = [] for possibleKey in LETTERS: decryptedText = vigenereCipher.decryptMessage( possibleKey, nthLetters) keyAndFreqMatchTuple = ( possibleKey, freqAnalysis.englishFreqMatchScore(decryptedText)) freqScores.append(keyAndFreqMatchTuple) # mengurutkan score freqScores.sort(key=getItemAtIndexOne, reverse=True) allFreqScores.append(freqScores[:NUM_MOST_FREQ_LETTERS]) if not SILENT_MODE: for i in range(len(allFreqScores)): # use i + 1 so the first letter is not called the "0th" letter print('Possible letters for letter %s of the key: ' % (i + 1), end='') for freqScore in allFreqScores[i]: print('%s ' % freqScore[0], end='') print() # print a newline #coba kombinasi yang mirip setiap formasi for indexes in itertools.product(range(NUM_MOST_FREQ_LETTERS), repeat=mostLikelyKeyLength): possibleKey = '' for i in range(mostLikelyKeyLength): possibleKey += allFreqScores[i][indexes[i]][0] if SILENT_MODE: print('Mencoba dengan Kata Kunci: %s' % (possibleKey)) decryptedText = vigenereCipher.decryptMessage(possibleKey, ciphertextUp) if detectEnglish.isEnglish(decryptedText): origCase = [] for i in range(len(ciphertext)): if ciphertext[i].isupper(): origCase.append(decryptedText[i].upper()) else: origCase.append(decryptedText[i].lower()) decryptedText = ''.join(origCase) return decryptedText # No English-looking decryption found, so return None. return None
def crack_xor_message_frequency(message): # Guess format of message # Is message a hex string like 'a41332ef', hex pairs represent bytes. if not is_hex_string(message): message = message.encode('hex') cracked_message = {'score': None, 'message': '', 'key': ''} best_score = 0 bar = progressbar.ProgressBar(max_value=0xff, redirect_stdout=True) for key in range(0x00, 0xff): bar.update(key) # Xor params should be hex bytes. e.g. xor('\xaf', '\x0a') guessed_plaintext = xor(unhex(message), unhex("{:02x}".format(key)), cut='max') score = 0 letter_frequency_order = freqAnalysis.getFrequencyOrder( guessed_plaintext, True) score = freqAnalysis.englishFreqMatchScore(guessed_plaintext) # Matches all non printable ascii characters # and lower score regex_non_ascii = r'[^ -~\x0D\x0A]' matches = re.findall(regex_non_ascii, guessed_plaintext) if matches: score -= len(matches) # Matches all non alpha ascii characters # and lower score. # Improved accuracy. regex_non_alpha_ascii = r'[^a-zA-Z]' matches = re.findall(regex_non_alpha_ascii, guessed_plaintext) if matches: score -= len(matches) / float( 2) # each find reduces score by 0.5 per find # Matches all non lowercase alpha ascii characters # and lower score # regex_non_lcalpha_ascii = r'[^a-z]' # matches = re.findall( regex_non_lcalpha_ascii, guessed_plaintext) # if matches: # score -= len(matches) / float(2) # each find reduces score by 0.5 per find if score > cracked_message['score']: cracked_message = { 'score': score, 'message': guessed_plaintext, 'key': key } bar.finish() return cracked_message
def attemptHackWithKeyLength(ciphertext, mostLikelyKeyLength): # Determine the most likely letters for each letter in the key. ciphertextUp = ciphertext.upper() # allFreqScores is a list of mostLikelyKeyLength number of lists. # These inner lists are the freqScores lists. allFreqScores = [] for nth in range(1, mostLikelyKeyLength + 1): nthLetters = getNthSubkeysLetters(nth, mostLikelyKeyLength, ciphertextUp) # freqScores is a list of tuples like: # [(<letter>, <Eng. Freq. match score>), ... ] # List is sorted by match score. Higher score means better match. # See the englishFreqMatchScore() comments in freqAnalysis.py. freqScores = [] for possibleKey in LETTERS: decryptedText = vigenereCipher.decryptMessage(possibleKey, nthLetters) keyAndFreqMatchTuple = (possibleKey, freqAnalysis.englishFreqMatchScore(decryptedText)) freqScores.append(keyAndFreqMatchTuple) # Sort by match score freqScores.sort(key=getItemAtIndexOne, reverse=True) allFreqScores.append(freqScores[:NUM_MOST_FREQ_LETTERS]) if not SILENT_MODE: for i in range(len(allFreqScores)): # use i + 1 so the first letter is not called the "0th" letter print("Possible letters for letter %s of the key: ' % (i + 1), end='") for freqScore in allFreqScores[i]: print("%s ' % freqScore[0], end=") print() # print a newline # Try every combination of the most likely letters for each position # in the key. for indexes in itertools.product(range(NUM_MOST_FREQ_LETTERS), repeat=mostLikelyKeyLength): # Create a possible key from the letters in allFreqScores possibleKey = '' for i in range(mostLikelyKeyLength): possibleKey += allFreqScores[i][indexes[i]][0] if not SILENT_MODE: print('Attempting with key: %s' % (possibleKey)) decryptedText = vigenereCipher.decryptMessage(possibleKey, ciphertextUp) if detectEnglish.isEnglish(decryptedText): # Set the hacked ciphertext to the original casing. origCase = [] for i in range(len(ciphertext)): if ciphertext[i].isupper(): origCase.append(decryptedText[i].upper()) else: origCase.append(decryptedText[i].lower()) decryptedText = ''.join(origCase) # Check with user to see if the key has been found. print('Possible encryption hack with key %s:' % (possibleKey)) print(decryptedText[:200]) # only show first 200 characters print() print('Enter D for done, or just press Enter to continue hacking:') response = input('> ') if response.strip().upper().startswith('D'): return decryptedText # No English-looking decryption found, so return None. return None
def XORSingleCharBruteforce(input): messages = [] for y in range(256): result = b'' result = XORSingleChar(input, y) messages.append( [result, y, freqAnalysis.englishFreqMatchScore(str(result))]) return sorted(messages, key=lambda x: x[2], reverse=True)[0]
def attemptHackWithKeyLength(ciphertext,mostLikelyKeyLength): ciphertextUp = ciphertext.upper() allFreqScores = [] for nth in range(1, mostLikelyKeyLength + 1): nthLetters = getNthSubkeysLetters(nth, mostLikelyKeyLength, ciphertextUp) freqScores = [] for possibleKey in vigenereCipher.LETTERS: decryptedText = vigenereCipher.decryptMessage(possibleKey, nthLetters) keyAndFreqMatchTuple = (possibleKey, freqAnalysis.englishFreqMatchScore(decryptedText)) freqScores.append(keyAndFreqMatchTuple) freqScores.sort(key=getItemAtIndexOne, reverse=True) allFreqScores.append(freqScores[:NUM_MOST_FREQ_LETTERS]) if not SILENT_MODE: for i in range(len(allFreqScores)): print('Possible letters for letter {0} of the key: '.format(i + 1)) for freqScores in allFreqScores[i]: print('%s ' % freqScores[0], end = '') print() for indexes in itertools.product(range(NUM_MOST_FREQ_LETTERS), repeat=mostLikelyKeyLength): possibleKey = '' for i in range(mostLikelyKeyLength): possibleKey += allFreqScores[i][indexes[i]][0] if not SILENT_MODE: print('Attempting with key: %s' % (possibleKey)) decryptedText = vigenereCipher.decryptMessage(possibleKey, ciphertextUp) if detectEnglish.isEnglish(decryptedText): origCase = [] for i in range(len(ciphertext)): if ciphertext[i].isupper(): origCase.append(decryptedText[i].upper()) else: origCase.append(decryptedText[i].lower()) decryptedText = ''.join(origCase) print('Possible encryption hack with key %s:' % (possibleKey)) print(decryptedText[:200]) print() print('Enter D fordone, or just press Enter tocontinue') response = input('> ') if response.strip().upper().startswith('D'): return decryptedText return None
def crack_vigenere_key(t, n): """Attempt to use frequncy to Crack the supplied cipher text and determine key. This function is not working 100% of the time and I cannot figure out why. Basic Idea: 1. Get Nth letter chunk 2. Do freq analysis 3. Brute force keys Args: t(str): Target text for encryption n(int): Length of key """ # Determine the most likely letters for each letter in the key. answer = "" tUp = t.upper() # These inner lists are the scores lists. allScores = [] # 1. Get Nth letter chunk for nth in range(1, n + 1): # returns every positional letter for each set of letters in key text # remove non-letters from the message tUp2 = re.compile('[^A-Z]').sub('', tUp.upper()) i = nth - 1 letters = [] # while items remain to iterate while i < len(tUp2): letters.append(tUp2[i]) i += n positionalLetters = ''.join(letters) # 2. Do freq analysis scores = [] for key in alphabet: dt = compute_vigenere(positionalLetters, key, Method.DECRYPT) # using freqAnalysis library to assist match = (key, freqAnalysis.englishFreqMatchScore(dt)) scores.append(match) # Sort by match score scores.sort(key=getIndexOne, reverse=True) allScores.append(scores[:4]) # Try every combination of the most likely letters for each position # 3. Brute force keys for indexes in itertools.product(range(4), repeat=n): # Create a possible key from the letters in allFreqScores key = "" for i in range(n): key += allScores[i][indexes[i]][0] print("Most likey key is " + key) break return None
def attemptHackWithKeyLength(ciphertext,mostLikelyKeyLength): ciphertextUp = ciphertext.upper() allFreqScores = [] for nth in range(1, mostLikelyKeyLength + 1): nthLetters = getNthSubkeyLetters(nth,mostLikelyKeyLength,ciphertextUp) freqScores = [] for possibleKey in LETTERS: decryptedText = vigenereCipher.decryptMessage(possibleKey,nthLetters) keyAndFreqMatchTuple = (possibleKey,freqAnalysis.englishFreqMatchScore(decryptedText)) freqScores.append(keyAndFreqMatchTuple) freqScores.sort(key=getItemAtIndexOne,reverse=True) allFreqScores.append(freqScores[:NUM_MOST_FREQ_LETTERS]) if not SILENT_MODE: for i in range(len(allFreqScores)): print 'Possible letters for letter' for freqScore in allFreqScores[i]: print freqScore[0] print '' for indexes in itertools.product(range(NUM_MOST_FREQ_LETTERS),repeat=mostLikelyKeyLength): possibleKey = '' for i in range(mostLikelyKeyLength): possibleKey += allFreqScores[i][indexes[i]][0] if not SILENT_MODE: print 'Attempting with key: '+ possibleKey decryptedText = vigenereCipher.decryptMessage(possibleKey,ciphertextUp) if detectEnglish.isEnglish(decryptedText): origCase = [] for i in range(len(ciphertext)): if ciphertext[i].isupper(): origCase.append(decryptedText[i].upper()) else: origCase.append(decryptedText[i].lower()) decryptedText = ''.join(origCase) print 'Possible encryption hack with key '+possibleKey print decryptedText[:200] print '' print 'enter d for done ,or just press enter to continue' response = raw_input('>') if response.upper().startswith('D'): return decryptedText return None
def attemptHackWithKeyLength(ciphertext, mostLikelyKeyLength): # Determine the most likely letters for each letter in the key: ciphertextUp = ciphertext.upper() # allFreqScores is a list of mostLikelyKeyLength number of lists. # These inner lists are the freqScores lists. allFreqScores = [] for nth in range(1, mostLikelyKeyLength + 1): nthLetters = getNthSubkeysLetters(nth, mostLikelyKeyLength, ciphertextUp) # freqScores is a list of tuples like: # [(<letter>, <Eng. Freq. match score>), ... ] # List is sorted by match score. Higher score means better match. # See the englishFreqMatchScore() comments in freqAnalysis.py. freqScores = [] for possibleKey in LETTERS: decryptedText = vigenereCipher.decryptMessage( possibleKey, nthLetters) keyAndFreqMatchTuple = ( possibleKey, freqAnalysis.englishFreqMatchScore(decryptedText)) freqScores.append(keyAndFreqMatchTuple) # Sort by match score: freqScores.sort(key=getItemAtIndexOne, reverse=True) allFreqScores.append(freqScores[:NUM_MOST_FREQ_LETTERS]) if not SILENT_MODE: for i in range(len(allFreqScores)): # Use i + 1 so the first letter is not called the "0th" letter: print('Possible letters for letter %s of the key: ' % (i + 1), end='') for freqScore in allFreqScores[i]: print('%s ' % freqScore[0], end='') print() # Print a newline. # Try every combination of the most likely letters for each position # in the key: for indexes in itertools.product(range(NUM_MOST_FREQ_LETTERS), repeat=mostLikelyKeyLength): # Create a possible key from the letters in allFreqScores: possibleKey = '' for i in range(mostLikelyKeyLength): possibleKey += allFreqScores[i][indexes[i]][0] if not SILENT_MODE: print('Attempting with key: %s' % (possibleKey)) decryptedText = vigenereCipher.decryptMessage(possibleKey, ciphertextUp) if detectEnglish.isEnglish(decryptedText): # Set the hacked ciphertext to the original casing: origCase = [] for i in range(len(ciphertext)): if ciphertext[i].isupper(): origCase.append(decryptedText[i].upper()) else: origCase.append(decryptedText[i].lower()) decryptedText = ''.join(origCase) # Check with user to see if the key has been found: print('Possible encryption hack with key %s:' % (possibleKey)) print(decryptedText[:200]) # Only show first 200 characters. print() print('Enter D if done, anything else to continue hacking:') response = input('> ') if response.strip().upper().startswith('D'): return decryptedText # No English-looking decryption found, so return None: return None
for i in range(result_keyword_len): sub_string_list = [] for sub_i in range(i, len(cipher_text), result_keyword_len): sub_string_list.append(cipher_text[sub_i]) sub_string_list_big.append(''.join(sub_string_list)) # for each sub_string find the top possible letters decode26_dict = defaultdict(list) for index, sub_string in enumerate(sub_string_list_big): # decode 26 times for letter in LETTERS: decode26_dict[index].append(v_cipher(sub_string, letter, False)) letter_freq = defaultdict(list) for key, value in decode26_dict.items(): for sub_s in value: freq = freqAnalysis.englishFreqMatchScore(sub_s) letter_freq[key].append(freq) # print(letter_freq) final_result = defaultdict(list) for key, value in letter_freq.items(): # print(value) max_value = max(value) for sub_i, sub_l in enumerate(value): if sub_l == max_value: final_result[key].append(LETTERS[sub_i]) for words in list(itertools.product(*final_result.values())): print(''.join(words), end=' ') print(v_cipher(cipher_text[:20], ''.join(words), False))
def attemptHackWithKeyLength(ciphertext, mostLikelyKeyLength): ciphertextUp = ciphertext.upper() allFreqScores = [] for nth in range(1, mostLikelyKeyLength + 1): nthLetters = getNthSubkeysLetters(nth, mostLikelyKeyLength, ciphertextUp) freqScores = [] for possibleKey in LETTERS: decryptedText = decryptMessage(possibleKey, nthLetters) keyAndFreqMatchTuple = ( possibleKey, freqAnalysis.englishFreqMatchScore(decryptedText)) freqScores.append(keyAndFreqMatchTuple) freqScores.sort(key=getItemAtIndexOne, reverse=True) allFreqScores.append(freqScores[:NUM_MOST_FREQ_LETTERS]) if not SILENT_MODE: for i in range(len(allFreqScores)): # Use i + 1 so the first letter is not called the "0th" letter: print('Possible letters for letter %s of the key: ' % (i + 1), end='') for freqScore in allFreqScores[i]: print('%s ' % freqScore[0], end='') print() # Print a newline. # Try every combination of the most likely letters for each position # in the key: for indexes in itertools.product(range(NUM_MOST_FREQ_LETTERS), repeat=mostLikelyKeyLength): # Create a possible key from the letters in allFreqScores: possibleKey = '' for i in range(mostLikelyKeyLength): possibleKey += allFreqScores[i][indexes[i]][0] if not SILENT_MODE: print('Attempting with key: %s' % (possibleKey)) decryptedText = decryptMessage(possibleKey, ciphertextUp) if detectEnglish.isEnglish(decryptedText): # Set the hacked ciphertext to the original casing: origCase = [] for i in range(len(ciphertext)): if ciphertext[i].isupper(): origCase.append(decryptedText[i].upper()) else: origCase.append(decryptedText[i].lower()) decryptedText = ''.join(origCase) print('Possible encryption hack with key %s:' % (possibleKey)) print(decryptedText[:200]) print() print('Enter D if done, anything else to continue hacking:') response = input('> ') if response.strip().upper().startswith('D'): return decryptedText return None
def attemptHackWithKeyLength(cipherText, mostLikelyKeyLength): # Determine the most likely letters for each letter in the key. cipherTextUp = cipherText.upper() # allFreqScores is a list of mostLikelyKeyLength number of lists. allFreqKey = [] for nth in range(mostLikelyKeyLength): nthLetters = getNthSubkeysLetters(nth, mostLikelyKeyLength, cipherTextUp) # freqScores is a list of tuples like: # [(<letter>, <Eng. Freq. match score>), ... ] freqScores = [] for possibleKey in LETTERS: decryptedText = vigenereCipher.decryptMessage( possibleKey, nthLetters) matchScore = freqAnalysis.englishFreqMatchScore(decryptedText) freqScores.append((possibleKey, matchScore)) # Sort by match score freqScores.sort(key=lambda x: x[1], reverse=True) # Get top letter numFreq = MIN_NUM_MOST_FREQ_LETTERS while numFreq < len( LETTERS) and freqScores[0][1] == freqScores[numFreq][1]: numFreq += 1 freqKey = [fs[0] for fs in freqScores[:numFreq]] allFreqKey.append(freqKey) if not SILENT_MODE: for i in range(mostLikelyKeyLength): print('Possible letters for letter %s of the key: ' % (i + 1) + getStringPrint(allFreqKey[i])) # Try every combination of the most likely letters for each position # in the key. indexes = [0 for _ in range(mostLikelyKeyLength)] while indexes is not None: # Create a possible key possibleKey = '' for i in range(mostLikelyKeyLength): possibleKey += allFreqKey[i][indexes[i]] if not SILENT_MODE: print('Attempting with key: %s' % possibleKey) decryptedText = vigenereCipher.decryptMessage(possibleKey, cipherTextUp) if detectEnglish.isEnglish(decryptedText): # Set the hacked ciphertext to the original casing. origCase = [] for i in range(len(cipherText)): if cipherText[i].isupper(): origCase.append(decryptedText[i].upper()) else: origCase.append(decryptedText[i].lower()) decryptedText = ''.join(origCase) # Check with user to see if the key has been found. print('Possible encryption hack with key %s:' % (possibleKey)) print(decryptedText[:200]) # only show first 200 characters print() if STOP: print( 'Enter D for done, or just press Enter to continue hacking:' ) response = input('> ') if response.strip().upper().startswith('D'): return decryptedText indexes = getNextCombine(indexes, allFreqKey) # No English-looking decryption found, so return None. return None
input = "" with open('6.txt', 'r') as f: for line in f: input += line.rstrip() chiphertext = base64.b64decode(input) keylen = findKeyLen(chiphertext) key = b"" plaintexts = [] #Do the Transpose for i in range(keylen): block = b'' for j in range(i, len(chiphertext), keylen): block += bytes([chiphertext[j]]) key += bytes([XORSingleCharBruteforce(block)[1]]) result = XORRepeatingKey(chiphertext, key) plaintexts.append( [result, key, freqAnalysis.englishFreqMatchScore(str(result))]) maxscore = max(plaintexts, key=lambda x: x[2])[2] for i in sorted(plaintexts, key=lambda x: x[2], reverse=True): if i[2] == maxscore: print(i)
def attempt_hack_with_key_length(ciphertext, most_likely_key_length): # Determine the most likely letters for each letter in the key: ciphertext_up = ciphertext.upper() # all_freq_scores is a list of mostLikelyKeyLength number of lists. # These inner lists are the freq_scores lists. all_freq_scores = [] for nth in range(1, most_likely_key_length + 1): nth_letters = get_nth_subkeys_letters(nth, most_likely_key_length, ciphertext_up) # freq_scores is a list of tuples like: # [(<letter>, <Eng. Freq. match score>), ... ] # List is sorted by match score. Higher score means better match. # See the englishFreqMatchScore() comments in freqAnalysis.py. freq_scores = [] for possible_key in LETTERS: crypt = vigenereCipher.Vigenere(possible_key) decrypted_text = crypt.decrypt(nth_letters) key_and_freq_match_tuple = ( possible_key, freqAnalysis.englishFreqMatchScore(decrypted_text)) freq_scores.append(key_and_freq_match_tuple) # Sort by match score: freq_scores.sort(key=get_item_at_index_one, reverse=True) all_freq_scores.append(freq_scores[:NUM_MOST_FREQ_LETTERS]) if not SILENT_MODE: for i in range(len(all_freq_scores)): # Use i + 1 so the first letter is not called the "0th" letter: print('Possible letters for letter %s of the key: ' % (i + 1) + ' ') for freqScore in all_freq_scores[i]: print('%s ' % freqScore[0] + ' ') print('') # Try every combination of the most likely letters for each position # in the key: for indexes in itertools.product(range(NUM_MOST_FREQ_LETTERS), repeat=most_likely_key_length): # Create a possible key from the letters in all_freq_scores: possible_key = '' for i in range(most_likely_key_length): possible_key += all_freq_scores[i][indexes[i]][0] if not SILENT_MODE: print(f'Attempting with key: {possible_key}') crypt = vigenereCipher.Vigenere(possible_key) decrypted_text = crypt.decrypt(ciphertext_up) if detectEnglish.isEnglish(decrypted_text): # Set the hacked ciphertext to the original casing: orig_case = [] for i in range(len(ciphertext)): if ciphertext[i].isupper(): orig_case.append(decrypted_text[i].upper()) else: orig_case.append(decrypted_text[i].lower()) decrypted_text = ''.join(orig_case) print("\nPossible decrypted message:") print( f" Key {possible_key}({len(possible_key)}). part of decrypted message: {decrypted_text[:200]}" ) response = input( "\nEnter D if done, or any other key to continue the attack: ") if response.strip().upper().startswith('D'): return decrypted_text # No English-looking decryption found, so return None: return None
def attemptHackWithKeyLength(ciphertext, mostLikelyKeyLength): # determine the most likely letter for each letter in the key. ciphertextUp = ciphertext.upper() # allFreqScores is a list of mostLikelyKeyLength number of lists. # these inner lists are the freqScores lists. allFreqScores = [] for nth in range(1, mostLikelyKeyLength + 1): nthLetters = getNthSubKeysLetters(nth, mostLikelyKeyLength, ciphertextUp) freqScores = [] for possibleKey in LETTERS: decryptedText = cipher.decryptMessage(possibleKey, nthLetters) keyAndFreqMatchTuple = ( possibleKey, freqAnalysis.englishFreqMatchScore(decryptedText)) freqScores.append(keyAndFreqMatchTuple) # sort by match score freqScores.sort(key=getItemAtIndexOne, reverse=True) allFreqScores.append(freqScores[:NUM_MOST_FREQ_LETTERS]) if not SILENT_MODE: for i in range(len(allFreqScores)): print('possible letters for letter {0} of the key:'.format(i + 1)) for freqScore in allFreqScores[i]: print('{}'.format(freqScore[0]), end='') print() for indexes in itertools.product(range(NUM_MOST_FREQ_LETTERS), repeat=mostLikelyKeyLength): # create a possible key from the letters in allFreqScores possibleKey = '' for i in range(mostLikelyKeyLength): possibleKey += allFreqScores[i][indexes[i]][0] if not SILENT_MODE: print('Attempting with key: {0}'.format(possibleKey)) decryptedText = cipher.decryptMessage(possibleKey, ciphertextUp) if detectEnglish.isEnglish(decryptedText): # set the hacked ciphertext to original casing origCase = [] for i in range(len(ciphertext)): if ciphertext[i].isupper(): origCase.append(decryptedText[i].upper()) else: origCase.append(decryptedText[i].lower()) decryptedText = ''.join(origCase) # Check with user to see if the key has been found print('Possible encryption hack with key {0}:'.format(possibleKey)) print(decryptedText[:200]) print() print('Enter D for done , or just press Enter to continue hacking') response = input('> ') if response.strip().upper().startswith('D'): return decryptedText # No english-looking decrytion found, so return None. return None
def attemptHackWithKeyLength(ciphertext, mostLikelyKeyLength): #Determine the most likely letters for each letter in the key: ciphertextUp = ciphertext.upper() allFreqScores = [] for nth in range(1, mostLikelyKeyLength + 1): nthLetters = getNthSubkeysLetters(nth, mostLikelyKeyLength, ciphertextUp) #FreqScore is a list of tuples like letter and English Freq match score #[<letter>, <Eng. Freq. match score>), ...] freqScores = [] for possibleKey in LETTERS: decryptedText = vigenereCipher.decryptMessage( possibleKey, nthLetters) keyAndFreqMatchTuple = ( possibleKey, freqAnalysis.englishFreqMatchScore(decryptedText)) freqScores.append(keyAndFreqMatchTuple) freqScores.sort(key=getItemAtIndexOne, reverse=True) #Example of some of the allFreqScores =[[('A',9), ('E', 5), ('O', 4), ('P', 4)], #[('S', 10), ('D', 4), ('G', 4), ('H',4)]] allFreqScores.append(freqScores[:NUM_MOST_FREQ_LETTER]) if not SILENT_MODE: for i in range(len(allFreqScores)): #Use i + 1 so the first letter is not called the "0th" letter: print('Possible letters for letter %s of the key: ' % (i + 1), end='') for freqScore in allFreqScores[i]: print('%s ' % freqScore[0], end='') print() # Print a newline #Try every combination of the most likely letters for each position in the key for indexes in itertools.product(range(NUM_MOST_FREQ_LETTER), repeat=mostLikelyKeyLength): #Create a possible key from the letters in allFreqScores: possibleKey = '' for i in range(mostLikelyKeyLength): possibleKey += allFreqScores[i][indexes[i]][0] if not SILENT_MODE: print('Attempting with key: %s' % (possibleKey)) decryptedText = vigenereCipher.decryptMessage(possibleKey, ciphertextUp) if detectEnglish.isEnglish(decryptedText): origCase = [] for i in range(len(ciphertext)): if ciphertext[i].isupper(): origCase.append(decryptedText[i].upper()) else: origCase.append(decryptedText[i].lower()) decryptedText = ''.join(origCase) #Check with user to see if the key has been found: print('Possible encryption hack with key %s:' % (possibleKey)) print(decryptedText[:200]) print() print('Enter D if done, anything else to continue hacking') response = input('> ') if response.strip().upper().startswith('D'): return decryptedText return None