Created
December 12, 2011 23:18
-
-
Save melpomene/1469610 to your computer and use it in GitHub Desktop.
Statistical attack on simple linear substitution ciphers.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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