Guest User

Untitled

a guest
Feb 20th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.26 KB | None | 0 0
  1. MAX_KEY_LENGTH = 20
  2. PEAK_MIN_OFFSET = 4
  3.  
  4. NUM_LETTERS = 26
  5. FIRST_LETTER = "A"
  6.  
  7. KEY_LENGTH_GUESS = 6
  8.  
  9. def index_of_coincidence(s, shift):
  10. """Find the index of coincidence of s with itself shifted by shift"""
  11. return len([ i for i in xrange(len(s)) if s[i] == s[(i + shift) % len(s)]])
  12.  
  13. def peak_frequency(l):
  14. """Guess peak frequency in l by finding the frequency for which the
  15. average peak value would be maximal."""
  16. def average_value_for_frequency(k):
  17. return sum([ l[i] for i in xrange(1,len(l)) if i % k == 0 ]) / \
  18. float(len(l)/k)
  19.  
  20. return max(xrange(1,len(l)), key=average_value_for_frequency)
  21.  
  22. def key_length_guess(s):
  23. l = [index_of_coincidence(s,shift) for shift in xrange(MAX_KEY_LENGTH)]
  24.  
  25. print "First", MAX_KEY_LENGTH, " indexes of coincidence:"
  26. print l
  27.  
  28. key_length = peak_frequency(l)
  29.  
  30. print "Guessed key length is", key_length
  31.  
  32. if key_length == KEY_LENGTH_GUESS:
  33. print "That is the key length we guessed earlier by manual examination."
  34. else:
  35. print "This differs from our original guess,", KEY_LENGTH_GUESS
  36.  
  37. return key_length
  38.  
  39. def frequency_vector(s, key_length, offset):
  40. v = [0] * NUM_LETTERS
  41. i = 0
  42. for c in s:
  43. if i % key_length == offset:
  44. v[ord(c) - ord(FIRST_LETTER)] += 1
  45. i += 1
  46.  
  47. for i in xrange(len(v)):
  48. v[i] *= (1.0/float(len(s)))
  49.  
  50. return v
  51.  
  52. def rotated_vector_match(v1, v2):
  53. """Return the rotation i of vector v1 such that v1 * v2 is maximal
  54. Note that a list of possibilities is returned. Note that we rotate
  55. backwards, in an attempt to guess what the forward rotation was."""
  56. def rotated(v, i):
  57. return v[i:]+v[:i]
  58.  
  59. matchings = {}
  60.  
  61. for i in xrange(len(v1)):
  62. s = sum([ rotated(v1,i)[j] * v2[j] for j in xrange(len(v1))])
  63. matchings[i] = s
  64.  
  65. return [ i for i in matchings.keys()
  66. if matchings[i] == max(matchings.values()) ]
  67.  
  68. def guess_key(s):
  69. key_length = key_length_guess(s)
  70.  
  71. key = ""
  72.  
  73. for i in xrange(key_length):
  74. freq_vector = frequency_vector(s, key_length, i)
  75. best_rotations = rotated_vector_match(freq_vector,
  76. basiccrypt.LETTER_FREQUENCIES)
  77. print "Best rotations for key letter",i,":", best_rotations
  78.  
  79. best_key_letters = [chr(ord(FIRST_LETTER) + k) for k in best_rotations]
  80.  
  81. print "In letters:", best_key_letters
  82. print "Guessing", best_key_letters[0]
  83. key += best_key_letters[0]
  84.  
  85. print "Guessed key is", key
  86. return key
  87.  
  88. def vigenere_decrypt(s, key, encrypt = False):
  89. decrypted = ""
  90.  
  91. i = 0
  92. for c in s:
  93. offset = ord(key[i % len(key)]) - ord(FIRST_LETTER)
  94. if encrypt: offset = -offset
  95. cur_letter = ord(c) - ord(FIRST_LETTER)
  96. new_letter = (cur_letter - offset) % NUM_LETTERS
  97. decrypted += chr(ord(FIRST_LETTER) + new_letter)
  98. i += 1
  99.  
  100. return decrypted
  101.  
  102.  
  103. if __name__ == '__main__':
  104. import basiccrypt
  105. import sys
  106. filename = "cipher1.txt"
  107. if len(sys.argv) > 1:
  108. filename = sys.argv[1]
  109. s = basiccrypt.read_cipher_from_file(filename).upper()
  110. key = guess_key(s)
  111. print "Decryption:"
  112. print vigenere_decrypt(s, key)
Add Comment
Please, Sign In to add comment