2015-08-02 4 views
0

[J'ai posté cette question une fois, mais je ne ai pas inclure les informations nécessaires, que je suis désolé pour, c'est la première fois sur le débordement de pile]programme Python vigenereHacker échoue avec raw_input

Ok, je python2. 7 et un livre pdf intitulé Piratage chiffrements secret avec python, et il a ce code dans le:

import itertools, re 
import vigenereCipher, pyperclip, freqAnalysis, detectEnglish 
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 
SILENT_MODE = False # if set to True, program doesn't print attempts 
NUM_MOST_FREQ_LETTERS = 4 # attempts this many letters per subkey 
MAX_KEY_LENGTH = 16 # will not attempt keys longer than this 
NONLETTERS_PATTERN = re.compile('[^A-Z]') 
def main(): 
    # Instead of typing this ciphertext out, you can copy & paste it 
    # from http://invpy.com/vigenereHacker.py 
    ciphertext = """Adiz Avtzqeci Tmzubb wsa m Pmilqev halpqavtakuoi, lgouqdaf, kdmktsvmztsl, izr xoexghzr kkusitaaf.""" 
    hackedMessage = hackVigenere(ciphertext) 

    if hackedMessage != None: 
     print('Copying hacked message to clipboard:') 
     print(hackedMessage) 
     pyperclip.copy(hackedMessage) 
    else: 
     print('Failed to hack encryption.') 
def findRepeatSequencesSpacings(message): 
    # Goes through the message and finds any 3 to 5 letter sequences 
    # that are repeated. Returns a dict with the keys of the sequence and 
    # values of a list of spacings (num of letters between the repeats). 
    # Use a regular expression to remove non-letters from the message. 
    message = NONLETTERS_PATTERN.sub('', message.upper()) 
    # Compile a list of seqLen-letter sequences found in the message. 
    seqSpacings = {} # keys are sequences, values are list of int spacings 
    for seqLen in range(3, 6): 
     for seqStart in range(len(message) - seqLen): 
      # Determine what the sequence is, and store it in seq 
      seq = message[seqStart:seqStart + seqLen] 
      # Look for this sequence in the rest of the message 
      for i in range(seqStart + seqLen, len(message) - seqLen): 
       if message[i:i + seqLen] == seq: 
        # Found a repeated sequence. 
        if seq not in seqSpacings: 
         seqSpacings[seq] = [] # initialize blank list 
        # Append the spacing distance between the repeated 
        # sequence and the original sequence. 
        seqSpacings[seq].append(i - seqStart) 
    return seqSpacings 
def getUsefulFactors(num): 
    # Returns a list of useful factors of num. By "useful" we mean factors 
    # less than MAX_KEY_LENGTH + 1. For example, getUsefulFactors(144) 
    # returns [2, 72, 3, 48, 4, 36, 6, 24, 8, 18, 9, 16, 12] 
    if num < 2: 
     return [] # numbers less than 2 have no useful factors 
    factors = [] # the list of factors found 
    # When finding factors, you only need to check the integers up to 
    # MAX_KEY_LENGTH. 
    for i in range(2, MAX_KEY_LENGTH + 1): # don't test 1 
     if num % i == 0: 
      factors.append(i) 
      factors.append(int(num/i)) 
    if 1 in factors: 
     factors.remove(1) 
    return list(set(factors)) 
def getItemAtIndexOne(x): 
    return x[1] 
def getMostCommonFactors(seqFactors): 
    # First, get a count of how many times a factor occurs in seqFactors. 
    factorCounts = {} # key is a factor, value is how often if occurs 
    # seqFactors keys are sequences, values are lists of factors of the 
    # spacings. seqFactors has a value like: {'GFD': [2, 3, 4, 6, 9, 12, 
    # 18, 23, 36, 46, 69, 92, 138, 207], 'ALW': [2, 3, 4, 6, ...], ...} 
    for seq in seqFactors: 
     factorList = seqFactors[seq] 
     for factor in factorList: 
      if factor not in factorCounts: 
       factorCounts[factor] = 0 
      factorCounts[factor] += 1 
    # Second, put the factor and its count into a tuple, and make a list 
    # of these tuples so we can sort them. 
    factorsByCount = [] 
    for factor in factorCounts: 
     # exclude factors larger than MAX_KEY_LENGTH 
     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) 
    i = n - 1 
    letters = [] 
    while i < len(message): 
    letters.append(message[i]) 
    i += keyLength 
    return ''.join(letters) 
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)) 
      for freqScore in allFreqScores[i]: 
       print('%s ' % freqScore[0]) 
      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 hackVigenere(ciphertext): 
# First, we need to do Kasiski Examination to figure out what the 
# length of the ciphertext's encryption key is. 
    allLikelyKeyLengths = kasiskiExamination(ciphertext) 
    if not SILENT_MODE: 
     keyLengthStr = '' 
     for keyLength in allLikelyKeyLengths: 
      keyLengthStr += '%s ' % (keyLength) 
     print('Kasiski Examination results say the most likely key lengths are: ' + keyLengthStr + '\n') 
    for keyLength in allLikelyKeyLengths: 
     if not SILENT_MODE: 
      print('Attempting hack with key length %s (%s possible keys)...' % (keyLength, NUM_MOST_FREQ_LETTERS ** keyLength)) 
     hackedMessage = attemptHackWithKeyLength(ciphertext, keyLength) 
     if hackedMessage != None: 
      break 
    # If none of the key lengths we found using Kasiski Examination 
    # worked, start brute-forcing through key lengths. 
    if hackedMessage == None: 
     if not SILENT_MODE: 
      print('Unable to hack message with likely key length(s). Brute forcing key length...') 
     for keyLength in range(1, MAX_KEY_LENGTH + 1): 
      # don't re-check key lengths already tried from Kasiski 
      if keyLength not in allLikelyKeyLengths: 
       if not SILENT_MODE: 
        print('Attempting hack with key length %s (%s possible keys)...' % (keyLength, NUM_MOST_FREQ_LETTERS ** keyLength)) 
       hackedMessage = attemptHackWithKeyLength(ciphertext, keyLength) 
       if hackedMessage != None: 
        break 
    return hackedMessage 
# If vigenereHacker.py is run (instead of imported as a module) call 
# the main() function. 
if __name__ == '__main__': 
    main() 

ce programme fonctionne très bien, mais il est difficile de copier le message dans le fichier à chaque fois, quand je change cryptogramme = '' 'etc' '' à ciphertext = raw_input ("Message:") J'ai cette erreur:

Message:eurbvrebv 
Kasiski Examination results say the most likely key lengths are: 

Traceback (most recent call last): 
    File "vigenereHacker.py", line 206, in <module> 
    main() 
    File "vigenereHacker.py", line 12, in main 
    hackedMessage = hackVigenere(ciphertext) 
    File "vigenereHacker.py", line 191, in hackVigenere 
    if hackedMessage == None: 
UnboundLocalError: local variable 'hackedMessage' referenced before assignment 

La seule différence est le raw_input pour le texte chiffré. Pourquoi cela arriverait-il et comment puis-je le réparer? Nous vous remercions

Section du livre à ce sujet: Here Toutes les bibliothèques et le code source: Here also

Répondre

0

Avant cette ligne:

for keyLength in allLikelyKeyLengths: 

vous devriez avoir:

hackedMessage == None 

C'est parce qu'à la ligne:

if hackedMessage == None: 

Vous tentez d'utiliser une variable qui n'a jamais été initialisée.