Permalink
Browse files

Various changes

  • Loading branch information...
asweigart committed Feb 17, 2013
1 parent 620348a commit c84181594e468fe332e572b97380b4057fd18a70
Showing with 259 additions and 289 deletions.
  1. +51 −51 caesarCipher.py
  2. +54 −54 detectEnglish.py
  3. +3 −41 freqAnalysis.py
  4. +3 −3 simpleSubHacker.py
  5. +44 −44 transpositionEncrypt.py
  6. +39 −30 vigenereDictionaryHacker.py
  7. +65 −66 vigenereHacker.py
View
@@ -1,52 +1,52 @@
-# Caesar Cipher
-# http://inventwithpython.com/hacking (BSD Licensed)
-
-import pyperclip
-
-# the string to be encrypted/decrypted
-message = 'This is my secret message.'
-
-# the encryption/decryption key
-key = 13
-
-# tells the program to encrypt of decrypt
-mode = 'encrypt' # set to 'encrypt' or 'decrypt'
-
-# every possible symbol that can be encrypted
-LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-
-# stores the encrypted/decrypted form of the message
-translated = ''
-
-# capitalize the string in message
-message = message.upper()
-
-# run the encryption/decryption code on each symbol in the message string
-for symbol in message:
- if symbol in LETTERS:
- # get the encrypted (or decrypted) number for this symbol
- num = LETTERS.find(symbol) # get the number of the symbol
- if mode == 'encrypt':
- num = num + key
- elif mode == 'decrypt':
- num = num - key
-
- # handle the wrap around if num is larger than the length of
- # LETTERS or less than 0
- if num >= len(LETTERS):
- num = num - len(LETTERS)
- elif num < 0:
- num = num + len(LETTERS)
-
- # add encrypted/decrypted number's symbol at the end of translated
- translated = translated + LETTERS[num]
-
- else:
- # just add the symbol without encrypting/decrypting
- translated = translated + symbol
-
-# print the encrypted/decrypted string to the screen
-print(translated)
-
-# copy the encrypted/decrypted string to the clipboard
+# Caesar Cipher
+# http://inventwithpython.com/hacking (BSD Licensed)
+
+import pyperclip
+
+# the string to be encrypted/decrypted
+message = 'This is my secret message.'
+
+# the encryption/decryption key
+key = 13
+
+# tells the program to encrypt of decrypt
+mode = 'encrypt' # set to 'encrypt' or 'decrypt'
+
+# every possible symbol that can be encrypted
+LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+# stores the encrypted/decrypted form of the message
+translated = ''
+
+# capitalize the string in message
+message = message.upper()
+
+# run the encryption/decryption code on each symbol in the message string
+for symbol in message:
+ if symbol in LETTERS:
+ # get the encrypted (or decrypted) number for this symbol
+ num = LETTERS.find(symbol) # get the number of the symbol
+ if mode == 'encrypt':
+ num = num + key
+ elif mode == 'decrypt':
+ num = num - key
+
+ # handle the wrap around if num is larger than the length of
+ # LETTERS or less than 0
+ if num >= len(LETTERS):
+ num = num - len(LETTERS)
+ elif num < 0:
+ num = num + len(LETTERS)
+
+ # add encrypted/decrypted number's symbol at the end of translated
+ translated = translated + LETTERS[num]
+
+ else:
+ # just add the symbol without encrypting/decrypting
+ translated = translated + symbol
+
+# print the encrypted/decrypted string to the screen
+print(translated)
+
+# copy the encrypted/decrypted string to the clipboard
pyperclip.copy(translated)
View
@@ -1,55 +1,55 @@
-# Detect English module
-# http://inventwithpython.com/hacking (BSD Licensed)
-
-# To use, type this code:
-# import detectEnglish
-# detectEnglish.isEnglish(someString) # returns True or False
-# (There must be a "dictionary.txt" file in this directory with all English
-# words in it, one word per line. You can download this from
-# http://invpy.com/dictionary.txt) and put it in the same directory as detectEnglish.py.
-UPPERLETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-LETTERS_AND_SPACE = UPPERLETTERS + UPPERLETTERS.lower() + ' \t\n'
-
-def loadDictionary():
- dictionaryFile = open('dictionary.txt')
- englishWords = {}
- for word in dictionaryFile.read().split('\n'):
- englishWords[word] = None
- dictionaryFile.close()
- return englishWords
-
-ENGLISH_WORDS = loadDictionary()
-
-
-def getEnglishCount(message):
- message = message.upper()
- message = removeNonLetters(message)
- possibleWords = message.split()
-
- if possibleWords == []:
- return 0.0 # no words at all, so return 0.0
-
- matches = 0
- for word in possibleWords:
- if word in ENGLISH_WORDS:
- matches += 1
- return float(matches) / len(possibleWords)
-
-
-def removeNonLetters(message):
- lettersOnly = []
- for symbol in message:
- if symbol in LETTERS_AND_SPACE:
- lettersOnly.append(symbol)
- return ''.join(lettersOnly)
-
-
-def isEnglish(message, wordPercentage=20, letterPercentage=85):
- # By default, 20% of the words must exist in the dictionary file, and
- # 85% of all the characters in the message must be letters or spaces
- # (not punctuation or numbers).
- wordsMatch = getEnglishCount(message) * 100 >= wordPercentage
- numLetters = len(removeNonLetters(message))
- messageLettersPercentage = float(numLetters) / len(message) * 100
- lettersMatch = messageLettersPercentage >= letterPercentage
+# Detect English module
+# http://inventwithpython.com/hacking (BSD Licensed)
+
+# To use, type this code:
+# import detectEnglish
+# detectEnglish.isEnglish(someString) # returns True or False
+# (There must be a "dictionary.txt" file in this directory with all English
+# words in it, one word per line. You can download this from
+# http://invpy.com/dictionary.txt) and put it in the same directory as detectEnglish.py.
+UPPERLETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+LETTERS_AND_SPACE = UPPERLETTERS + UPPERLETTERS.lower() + ' \t\n'
+
+def loadDictionary():
+ dictionaryFile = open('dictionary3.txt')
+ englishWords = {}
+ for word in dictionaryFile.read().split('\n'):
+ englishWords[word] = None
+ dictionaryFile.close()
+ return englishWords
+
+ENGLISH_WORDS = loadDictionary()
+
+
+def getEnglishCount(message):
+ message = message.upper()
+ message = removeNonLetters(message)
+ possibleWords = message.split()
+
+ if possibleWords == []:
+ return 0.0 # no words at all, so return 0.0
+
+ matches = 0
+ for word in possibleWords:
+ if word in ENGLISH_WORDS:
+ matches += 1
+ return float(matches) / len(possibleWords)
+
+
+def removeNonLetters(message):
+ lettersOnly = []
+ for symbol in message:
+ if symbol in LETTERS_AND_SPACE:
+ lettersOnly.append(symbol)
+ return ''.join(lettersOnly)
+
+
+def isEnglish(message, wordPercentage=20, letterPercentage=85):
+ # By default, 20% of the words must exist in the dictionary file, and
+ # 85% of all the characters in the message must be letters or spaces
+ # (not punctuation or numbers).
+ wordsMatch = getEnglishCount(message) * 100 >= wordPercentage
+ numLetters = len(removeNonLetters(message))
+ messageLettersPercentage = float(numLetters) / len(message) * 100
+ lettersMatch = messageLettersPercentage >= letterPercentage
return wordsMatch and lettersMatch
View
@@ -5,18 +5,15 @@
# frequency taken from http://en.wikipedia.org/wiki/Letter_frequency
englishLetterFreq = {'E': 12.70, 'T': 9.06, 'A': 8.17, 'O': 7.51, 'I': 6.97, 'N': 6.75, 'S': 6.33, 'H': 6.09, 'R': 5.99, 'D': 4.25, 'L': 4.03, 'C': 2.78, 'U': 2.76, 'M': 2.41, 'W': 2.36, 'F': 2.23, 'G': 2.02, 'Y': 1.97, 'P': 1.93, 'B': 1.29, 'V': 0.98, 'K': 0.77, 'J': 0.15, 'X': 0.15, 'Q': 0.10, 'Z': 0.07}
-englishTrigramFreq = {'THE': 3.51, 'AND': 1.59, 'ING': 1.15, 'HER': 0.82, 'HAT': 0.65, 'HIS': 0.60, 'THA': 0.59, 'ERE': 0.56, 'FOR': 0.56, 'ENT': 0.53, 'ION': 0.51, 'TER': 0.46, 'WAS': 0.46, 'YOU': 0.44, 'ITH': 0.43, 'VER': 0.43, 'ALL': 0.42, 'WIT': 0.40, 'THI': 0.39, 'TIO': 0.38}
ETAOIN = 'ETAOINSHRDLCUMWFGYPBVKJXQZ'
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-nonLettersPattern = re.compile('[^A-Z]')
+
def getLetterCount(message):
# Returns a dictionary with keys of single letters and values of the
# count of how many times they appear in the message parameter.
- letterCount = {}
- for letter in LETTERS:
- letterCount[letter] = 0 # intialize each letter to 0
+ letterCount = {'A': 0, 'B': 0, 'C': 0, 'D': 0, 'E': 0, 'F': 0, 'G': 0, 'H': 0, 'I': 0, 'J': 0, 'K': 0, 'L': 0, 'M': 0, 'N': 0, 'O': 0, 'P': 0, 'Q': 0, 'R': 0, 'S': 0, 'T': 0, 'U': 0, 'V': 0, 'W': 0, 'X': 0, 'Y': 0, 'Z': 0}
for letter in message.upper():
if letter in LETTERS:
@@ -29,10 +26,6 @@ def getItemAtIndexZero(x):
return x[0]
-def getItemAtIndexOne(x):
- return x[1]
-
-
def getFrequencyOrder(message):
# Returns a string of the alphabet letters arranged in order of most
# frequently occurring in the message parameter.
@@ -87,35 +80,4 @@ def englishFreqMatchScore(message):
if uncommonLetter in freqOrder[-6:]:
matchScore += 1
- return matchScore
-
-
-def englishTrigramMatch(message, trigramThreshold=2, trigramMatchRange=30):
- # Return True if the string in the message parameter matches the
- # trigram frequency of English.
-
- # Remove the non-letter characters from message
- message = nonLettersPattern.sub('', message.upper())
-
- # Count the trigrams in message
- trigrams = {}
- for i in range(len(message) - 2):
- trigram = message[i:i+3]
- if trigram not in trigrams:
- trigrams[trigram] = 1
- else:
- trigrams[trigram] += 1
-
- # Sort the trigrams by frequency
- topFreqs = list(trigrams.items())
- topFreqs.sort(key=getItemAtIndexOne, reverse=True)
- topFreqLetters = []
- for item in topFreqs:
- topFreqLetters.append(item[0])
-
- matchScore = 0
- for commonTrig in englishTrigramFreq:
- if commonTrig in topFreqLetters[:trigramMatchRange]:
- matchScore += 1
-
- return matchScore >= trigramThreshold
+ return matchScore
View
@@ -8,7 +8,7 @@
import wordPatterns
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-nonLettersOrSpacePattern = re.compile('[^A-Za-z\s]')
+nonLettersOrSpacePattern = re.compile('[^A-Z\s]')
def main():
message = 'Sy l nlx sr pyyacao l ylwj eiswi upar lulsxrj isr sxrjsxwjr, ia esmm rwctjsxsza sj wmpramh, lxo txmarr jia aqsoaxwa sr pqaceiamnsxu, ia esmm caytra jp famsaqa sj. Sy, px jia pjiac ilxo, ia sr pyyacao rpnajisxu eiswi lyypcor l calrpx ypc lwjsxu sx lwwpcolxwa jp isr sxrjsxwjr, ia esmm lwwabj sj aqax px jia rmsuijarj aqsoaxwa. Jia pcsusx py nhjir sr agbmlsxao sx jisr elh. -Facjclxo Ctrramm'
@@ -82,7 +82,7 @@ def removeSolvedLettersFromMapping(letterMapping):
# maps to ['N'], then we know that 'B' must map to 'N', so we can
# remove 'N' from the list of what 'A' could map to. So 'A' then maps
# to ['M']. Note that now that 'A' maps to only one letter, we can
- # remove 'M' from the list of possible mappings for every other
+ # remove 'M' from the list of letters for every other
# letter. (This is why there is a loop that keeps reducing the map.)
letterMapping = copy.deepcopy(letterMapping)
loopAgain = True
@@ -112,7 +112,7 @@ def removeSolvedLettersFromMapping(letterMapping):
def hackSimpleSub(message):
intersectedMap = getBlankCipherletterMapping()
- message = nonLettersOrSpacePattern.sub('', message).upper().split()
+ message = nonLettersOrSpacePattern.sub('', message.upper()).split()
for cipherword in message:
# Get a new cipherletter mapping for each ciphertext word.
newMap = getBlankCipherletterMapping()
Oops, something went wrong.

0 comments on commit c841815

Please sign in to comment.