Best key lengths are estimated using the hamming distance of blocks of keylength bytes. Ciphertext is then transposed in such a way that it can be solved by sequences of SingleByteXor (one for each offset in the key).
min_keylength and max_keylength are limits as to what key lengths are tested.
considered_keylength_count is the number of best key lengths that are kept to be
analysed by the SingleByteXor frequency analysis.
	# Attempts to find the key by using frequency analysis on the resulting plaintexts.
	# Best key lengths are estimated using the hamming distance of blocks of keylength bytes.
	# Ciphertext is then transposed in such a way that it can be solved by sequences of
	# SingleByteXor (one for each offset in the key).
	#
	# `min_keylength` and `max_keylength` are limits as to what key lengths are tested.
	# `considered_keylength_count` is the number of best key lengths that are kept to be
	# analysed by the SingleByteXor frequency analysis.
	fun find_key(min_keylength, max_keylength, considered_keylength_count: nullable Int)  do
		# Set default values
		if min_keylength == null then min_keylength = 2
		if max_keylength == null then max_keylength = 40
		if considered_keylength_count == null then considered_keylength_count = 3
		# Find the best candidate key lengths based on the normalized hamming distances
		var best_sizes = get_normalized_hamming_distances(min_keylength, max_keylength, considered_keylength_count)
		var best = 0.0
		var best_key: nullable Bytes = null
		for ks in best_sizes do
			# Rearrange ciphertext to be in SingleByteXORable blocks
			var transposed = transpose_ciphertext(ks)
			var key = new Bytes.empty
			for slot in transposed do
				var sbx = new SingleByteXorCipher
				sbx.ciphertext = slot
				sbx.find_key
				key.add sbx.key
			end
			# Evaluate the resulting plaintext based on english frequency analysis
			var eng_score = ciphertext.xorcipher(key).to_s.english_scoring
			if eng_score > best then
				best_key = key
				best = eng_score
			end
			assert best_key != null
			self.key = best_key
		end
	end
					lib/crapto/xor.nit:52,2--96,4