Advertisement
Guest User

xorbreak.py

a guest
Aug 18th, 2019
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.82 KB | None | 0 0
  1. #!/usr/bin/env python2
  2. import sys
  3.  
  4. frequencies = {'a': 0.0651738, 'b': 0.0124248, 'c': 0.0217339, 'd': 0.0349835, 'e': 0.1041442, 'f': 0.0197881, 'g': 0.0158610, 'h': 0.0492888, 'i': 0.0558094, 'j': 0.0009033, 'k': 0.0050529, 'l': 0.0331490, 'm': 0.0202124,
  5.                'n': 0.0564513, 'o': 0.0596302, 'p': 0.0137645, 'q': 0.0008606, 'r': 0.0497563, 's': 0.0515760, 't': 0.0729357, 'u': 0.0225134, 'v': 0.0082903, 'w': 0.0171272, 'x': 0.0013692, 'y': 0.0145984, 'z': 0.0007836, ' ': 0.1918182}
  6.  
  7.  
  8. def single_byte_xor(b, s):
  9.     """ Performs XOR of the single byte against every character in string. """
  10.     assert len(b) == 1
  11.     x = ord(b)
  12.     result = ""
  13.     for char in s:
  14.         result += chr(x ^ ord(char))
  15.     return result
  16.  
  17.  
  18. def decode_single_byte_xor(message):
  19.     """ Decodes a string that has been encoded using single-byte XOR, using frequency analysis. """
  20.     mk, byte = 0, ""
  21.     for i in range(256):
  22.         m = single_byte_xor(chr(i), message)
  23.         k = sum(frequencies.get(c, 0) for c in m)
  24.         if k > mk:
  25.             mk, byte = k, chr(i)
  26.     return byte, mk
  27.  
  28.  
  29. def repeating_key_xor(key, message):
  30.     """ Encrypts the message with the key using repeating-key XOR. """
  31.     result = ""
  32.     for i, c in enumerate(message):
  33.         result += chr(ord(key[i % len(key)]) ^ ord(c))
  34.     return result
  35.  
  36.  
  37. def hamming_distance(str1, str2):
  38.     assert len(str1) == len(str2)
  39.     n = len(str1)
  40.     d = 0
  41.     num1 = int(str1.encode("hex"), 16)
  42.     num2 = int(str2.encode("hex"), 16)
  43.     for i in range(n * 8):
  44.         d += (num1 & 1) ^ (num2 & 1)
  45.         num1 >>= 1
  46.         num2 >>= 1
  47.     return d
  48.  
  49.  
  50. def break_repeating_key_xor(message):
  51.     cracked_key = ""
  52.     """ Decrypts a string that is encrypted with repeating-key XOR, by guessing the key size. """
  53.     potential = []
  54.     for n in range(2, 41):
  55.         if len(message) < 4 * n:
  56.             break
  57.         d = 0.0
  58.         for i in range(3):
  59.             d += hamming_distance(message[i * n:(i + 1) * n],
  60.                                   message[(i + 1) * n: (i + 2) * n])
  61.         d /= 3 * n
  62.         potential.append((n, d))
  63.     potential.sort(key=lambda p: p[1])
  64.     fm, decoded = 0, ""
  65.     for keysize, _ in potential[:min(len(potential), 5)]:
  66.         chunks = zip(*[iter(message)] * keysize)
  67.         fs = 0
  68.         key = ""
  69.         for i in range(keysize):
  70.             s = "".join(c[i] for c in chunks)
  71.             c, f = decode_single_byte_xor(s)
  72.             key += c
  73.             fs += f
  74.         if fs > fm:
  75.             cracked_key = key
  76.             fm, decoded = fs, repeating_key_xor(key, message)
  77.     return (cracked_key, decoded)
  78.  
  79. if len(sys.argv) < 2:
  80.     exit()
  81.  
  82. with open(sys.argv[1], "rb") as f:
  83.     data = f.read()
  84.     key, decrypted = break_repeating_key_xor(data)
  85.     print(decrypted)
  86.     print("")
  87.     print("Key: "+key)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement