Пример #1
0
	def __init__(self, cipher, verbose=False):
		self.cipher = cipher
		self.verbose = verbose
		self.freq_analyzer = FrequencyAnalyzer(cipher, ascii_uppercase)
		
		self.ciphertext = None
		self.key_length = 0
Пример #2
0
	def setUp(self):
		self.analyzer = FrequencyAnalyzer(VigenereCipher(), ascii_uppercase)
		self.analyzer.message = removeTextNonLetters("Ppqca xqvekg ybnkmazu ybngbal jon i tszm jyim. Vrag voht vrau c tksg. Ddwuo xitlazu vavv raz c vkb qp iwpou.")
		self.analyzer.key_length = 4
		
		self.subkey_messages = ['PAEBABANZIAHAKDXAAAKIU', 'PXKNZNLIMMGTUSWIZVZBW', 'QQGKUGJTJVVVCGUTUVCQP', 'CVYMYBOSYRORTDOLVRVPO']
		self.subkey_score = [('A', 2), ('I', 2), ('N', 2), ('W', 2), ('X', 2), ('B', 1), ('C', 1), ('E', 1), ('G', 1), ('H', 1), ('K', 1), ('M', 1), ('O', 1), ('P', 1), ('R', 1), ('S', 1), ('T', 1), ('U', 1), ('V', 1), ('D', 0), ('F', 0), ('J', 0), ('L', 0), ('Q', 0), ('Y', 0), ('Z', 0)]
Пример #3
0
class TestFrequencyAnalysis(TestCase):

	def setUp(self):
		self.analyzer = FrequencyAnalyzer(VigenereCipher(), ascii_uppercase)
		self.analyzer.message = removeTextNonLetters("Ppqca xqvekg ybnkmazu ybngbal jon i tszm jyim. Vrag voht vrau c tksg. Ddwuo xitlazu vavv raz c vkb qp iwpou.")
		self.analyzer.key_length = 4
		
		self.subkey_messages = ['PAEBABANZIAHAKDXAAAKIU', 'PXKNZNLIMMGTUSWIZVZBW', 'QQGKUGJTJVVVCGUTUVCQP', 'CVYMYBOSYRORTDOLVRVPO']
		self.subkey_score = [('A', 2), ('I', 2), ('N', 2), ('W', 2), ('X', 2), ('B', 1), ('C', 1), ('E', 1), ('G', 1), ('H', 1), ('K', 1), ('M', 1), ('O', 1), ('P', 1), ('R', 1), ('S', 1), ('T', 1), ('U', 1), ('V', 1), ('D', 0), ('F', 0), ('J', 0), ('L', 0), ('Q', 0), ('Y', 0), ('Z', 0)]

	def test_getNthSubkeyMessage(self):
		subkey_messages = [''.join(self.analyzer.getNthSubkeyMessage(n))
			for n in range(1, self.analyzer.key_length + 1)]
		self.assertEqual(subkey_messages, self.subkey_messages)

	def test_getSubkeyFreqScores(self):
		message = self.subkey_messages[0]
		self.assertEqual(self.analyzer.getSubkeyFreqScores(message), self.subkey_score)

	def test_englishFreqMatchScore(self):
		message = "Sy l nlx sr pyyacao l ylwj eiswi upar lulsxrj isr sxrjsxwjr, ia esmm rwctjsxsza sj wmpramh, lxo txmarr jia aqsoaxwa sr pqaceiamnsxu, ia esmm caytra jp famsaqa sj. Sy, px jia pjiac ilxo, ia sr pyyacao rpnajisxu eiswi lyypcor l calrpx ypc lwjsxu sx lwwpcolxwa jp isr sxrjsxwjr, ia esmm lwwabj sj aqax px jia rmsuijarj aqsoaxwa. Jia pcsusx py nhjir sr agbmlsxao sx jisr elh. -Facjclxo Ctrramm"
		self.assertEqual(englishFreqMatchScore(message), 5)
		message = "I rc ascwuiluhnviwuetnh,osgaa ice tipeeeee slnatsfietgi tittynecenisl. e fo f fnc isltn sn o a yrs sd onisli ,l erglei trhfmwfrogotn,l stcofiit.aea wesn,lnc ee w,l eIh eeehoer ros iol er snh nl oahsts ilasvih tvfeh rtira id thatnie.im ei-dlmf i thszonsisehroe, aiehcdsanahiec gv gyedsB affcahiecesd d lee onsdihsoc nin cethiTitx eRneahgin r e teom fbiotd n ntacscwevhtdhnhpiwru"
		self.assertEqual(englishFreqMatchScore(message), 9)
Пример #4
0
class VigenereCracker:

	def __init__(self, cipher, verbose=False):
		self.cipher = cipher
		self.verbose = verbose
		self.freq_analyzer = FrequencyAnalyzer(cipher, ascii_uppercase)
		
		self.ciphertext = None
		self.key_length = 0

	# ////////////////////////
	# PUBLIC
	# ////////////////////////

	def crack(self, ciphertext):
		self.ciphertext = ciphertext

		likely_key_lengths = kasiskiExamination(ciphertext)
		
		if self.verbose:
			print('The most likely key lengths are: ', ', '.join([str(length) for length in likely_key_lengths]))	
		
		for key_length in likely_key_lengths:
			self.key_length = key_length

			if self.verbose:
				print('Attempting crack with key length', key_length)
			
			result = self.attemptCrack()
			if result:
				return result

	# ////////////////////////
	# PRIVATE
	# ////////////////////////

	def attemptCrack(self):
		freq_scores = self.freq_analyzer.getFreqScores(self.ciphertext, self.key_length)

		if self.verbose:
			for i in range(len(freq_scores)):
				print('Possible letters for letter ' + str(i+1) + ' of the key:', 
					', '.join([key for (key, score) in freq_scores[i]]))

		return self.tryKeys(freq_scores)

	def tryKeys(self, freq_scores):
		for indexes in product(range(NUM_MOST_FREQ_LETTERS), repeat=self.key_length):
			possible_key = self.getPossibleKey(freq_scores, indexes)

			#if self.verbose:
			#	print('Attempting with key:', possible_key)			
			
			decrypted_text = self.tryDecrypting(possible_key)
			if decrypted_text:
				return decrypted_text, possible_key

	def getPossibleKey(self, freq_scores, indexes):
		return ''.join([freq_scores[i][indexes[i]][0] for i in range(self.key_length)])

	def tryDecrypting(self, possible_key):
		decrypted_text = self.cipher.decrypt(self.ciphertext.upper(), possible_key)

		if isEnglish(decrypted_text):
			decrypted_text = ''.join([decrypted_text[i].upper() if getSymbol(self.ciphertext[i]).isupper() else decrypted_text[i].lower() 
				for i in range(len(self.ciphertext))])
		
			return decrypted_text

	def userAcceptance(self, possible_key, decrypted_text):
		print('Possible encryption hack with key:', possible_key)
		print(decrypted_text[:200] + '\n') # only show first 200 characters
		print('Enter D if done:')
		return input('> ').strip().upper().startswith('D')