Skip to content

Commit ade263b

Browse files
committed
Automatic commit Sun Apr 22 21:46:16 EEST 2018
1 parent 327dfc9 commit ade263b

File tree

1 file changed

+25
-9
lines changed

1 file changed

+25
-9
lines changed

crypto/xorknown.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python2
22
# Author: Alamot
33
# This is a XOR plaintext attack tool: If we know a part of the plaintext maybe
4-
# we can recover the key and the whole text in successive steps.
4+
# we can recover the key and the whole text.
55
from __future__ import print_function
66
from __future__ import division
77
import string, sys
@@ -13,6 +13,7 @@
1313

1414

1515
def is_printable(text, ignore_code):
16+
''' Function to check if every character in text is printable '''
1617
for ch in text:
1718
if ord(ch) == ignore_code:
1819
continue
@@ -26,15 +27,30 @@ def lrotate(s, d):
2627
return s[d:] + s[0:d]
2728

2829

29-
if len(sys.argv) < 2:
30-
print("Usage: "+sys.argv[0]+"<filename> <known plaintext> [max_key_length]")
30+
if len(sys.argv) < 2 or sys.argv[1].strip().lower() == "--help":
31+
print("Known-plaintext attack: "+sys.argv[0]+" <filename> <known plaintext> [max_key_length]")
32+
print("Decrypt using known key: "+sys.argv[0]+" <filename> --key=the_known_key")
3133
exit()
3234

3335
filename = sys.argv[1]
34-
known_plaintext = sys.argv[2]
36+
37+
if sys.argv[2].strip().lower()[:5] == "--key":
38+
known_key = sys.argv[2].strip()[6:]
39+
with open(filename, "rb") as f:
40+
data = f.read()
41+
decrypted_text = ""
42+
repeated_key = (known_key)*((len(data) // len(known_key)) + 1)
43+
for x in range(len(data)):
44+
decrypted_text += chr(ord(data[x]) ^ ord(repeated_key[x]))
45+
print("Key length: "+str(len(known_key)), "\nPartial Key: "+known_key, "\nPlaintext: "+decrypted_text)
46+
exit()
47+
else:
48+
known_plaintext = sys.argv[2]
49+
3550
if len(known_plaintext) > max_key_length:
3651
print("The length of the known plaintext is greater than max_key_length (="+str(max_key_length)+"). Please give a smaller plaintext or incrase max_key_length.")
3752
exit()
53+
3854
if len(sys.argv) > 3:
3955
print(len(sys.argv))
4056
max_key_length = int(sys.argv[3])+1
@@ -45,7 +61,7 @@ def lrotate(s, d):
4561
print("Searching XOR-encrypted "+filename+" for string '"+known_plaintext+"'")
4662

4763
try:
48-
for i in range(len(data)-len(known_plaintext)):
64+
for i in range(len(data)-len(known_plaintext)): # Try known plaintext in every position
4965
partial_key = ""
5066
for j in range(len(known_plaintext)):
5167
if known_plaintext[j] == ignore_code:
@@ -54,18 +70,18 @@ def lrotate(s, d):
5470
partial_key += chr(ord(data[i+j]) ^ ord(known_plaintext[j]))
5571
#print("Single key: "+partial_key)
5672
if is_printable(partial_key, ignore_code) or not printable_key:
57-
for n in range(len(partial_key), max_key_length): #try different key lengths
58-
for m in range(n): #try different partial key positions
73+
for n in range(len(partial_key), max_key_length): # Try different key lengths
74+
for m in range(n): # Try different partial key positions
5975
expanded_key = lrotate(partial_key+chr(ignore_code)*(n-len(partial_key)), m)
6076
#print(expanded_key, m)
6177
repeated_key = (expanded_key)*((len(data) // len(expanded_key)) + 1)
6278
decrypted_text = ""
63-
for x in range(len(data)):
79+
for x in range(len(data)): # Try to decrypt the encoded text
6480
if ord(repeated_key[x]) == ignore_code:
6581
decrypted_text += chr(ignore_code)
6682
else:
6783
decrypted_text += chr(ord(data[x]) ^ ord(repeated_key[x]))
68-
if is_printable(decrypted_text, ignore_code):
84+
if is_printable(decrypted_text, ignore_code): # Is the whole result printable?
6985
print("Key length: "+str(len(expanded_key)), "\nPartial Key: "+expanded_key, "\nPlaintext: "+decrypted_text)
7086
print("")
7187
except KeyboardInterrupt:

0 commit comments

Comments
 (0)