Skip to content

Instantly share code, notes, and snippets.

@melpomene
Created December 12, 2011 23:18
Show Gist options
  • Save melpomene/1469610 to your computer and use it in GitHub Desktop.
Save melpomene/1469610 to your computer and use it in GitHub Desktop.
Statistical attack on simple linear substitution ciphers.
import sys, string, re
"""
Brute.py script to statistically break simple replacement ciphers.
Named after Ceasars killer.
Called with
python brute.py -m 'some text to break'
or
python brute.py -f filewithcypher.txt
ouputs to terminal.
Only support 1-gram words.
TODO:
* Implement support for 2 and 3-gram searches
* Implement support for interactive decryption with intelligent support from program.
"""
# Data from course in cryptography on LTH, Sweden
letterDensity = [
(73, 'A'),
(9, 'B'),
(30, 'C'),
(44, 'D'),
(130, 'E'),
(28, 'F'),
(16, 'G'),
(35, 'H'),
(74, 'I'),
(2, 'J'),
(3, 'K'),
(35, 'L'),
(25, 'M'),
(78, 'N'),
(74, 'O'),
(27, 'P'),
(3, 'Q'),
(77, 'R'),
(63, 'S'),
(93, 'T'),
(27, 'U'),
(13, 'V'),
(16, 'W'),
(5, 'X'),
(19, 'Y'),
(1, 'Z'),
]
def occurances(cipher):
totals = []
for letter in string.uppercase:
totals.append((cipher.count(letter), letter))
totals.sort()
print totals
return totals
def replace(cipher, inputDensity):
subst = list(cipher[:])
letterDensity.reverse()
print "Letter distribution in english: " + str(letterDensity)
print "Letter distribution in input text: " + str(inputDensity)
for letter in inputDensity:
replaceLetter = letterDensity.pop(0)
starts = [
match.start() for match in re.finditer
(
re.escape(str(letter[1])), cipher
)
]
for pos in starts:
subst[pos] = str(replaceLetter[1])
print "".join(subst)
if __name__ == "__main__":
cipher = ""
if len(sys.argv) <= 1:
print "Usage 'python brute.py [-m|-f] ciphertext'"
print "-m message"
print "-f filename"
exit()
if sys.argv[1] == "-m":
cipher = sys.argv[2]
elif sys.argv[1] == "-f":
f = open(sys.argv[2], 'r')
for line in f:
cipher += line
else:
print "Parse error"
exit(1)
cipher = cipher.upper()
letterDensity.sort()
inputDensity = occurances(cipher)
inputDensity.reverse()
result = replace(cipher, inputDensity)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment