import hashlib
from collections import Counter
text = """ьооьчосштицрувюунхэонпбиыойбшядйафаайихькгшщтнтввуячньвтъьчцабнпютэфттк
шзшудншщскуеоюппщхмечэпщбэмшпчхрвмшпяцэпаячхкьртпшсёртеьусуэфкайёпсрмп
... (вставь весь текст) ..."""
# Приводим к нижнему регистру, убираем всё кроме русских букв
alphabet = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
text = ''.join(c for c in text.lower() if c in alphabet)
# ---------- 1. Индекс совпадений для поиска длины ключа ----------
def index_of_coincidence(s):
n = len(s)
if n < 2: return 0
freq = Counter(s)
return sum(v*(v-1) for v in freq.values()) / (n*(n-1))
def find_key_length(text, max_len=40):
results = []
for L in range(1, max_len+1):
groups = [text[i::L] for i in range(L)]
ic = sum(index_of_coincidence(g) for g in groups) / L
results.append((L, ic))
results.sort(key=lambda x: -x[1])
return results[:10]
print("Возможные длины ключа (по индексу совпадений):")
for L, ic in find_key_length(text):
print(f" L={L:3d} IC={ic:.4f}")
# ---------- 2. Частотный анализ по каждой позиции ----------
rus_freq = "оеаинтсрвлкмдпуяызьгбчйхжшюцщэфъё"
def break_caesar(segment):
best_shift, best_score = 0, -1e9
for shift in range(len(alphabet)):
decrypted = ''.join(alphabet[(alphabet.index(c) - shift) % len(alphabet)] for c in segment)
score = sum(decrypted.count(ch) * (len(rus_freq) - rus_freq.index(ch)) for ch in rus_freq if ch in decrypted)
if score > best_score:
best_score, best_shift = score, shift
return best_shift
def recover_key(text, L):
key = ""
for i in range(L):
segment = text[i::L]
shift = break_caesar(segment)
key += alphabet[shift]
return key
# Попробуй топ-5 длин и покажи результаты
for L, _ in find_key_length(text)[:5]:
key = recover_key(text, L)
print(f"\nL={L} → ключ-кандидат: {key}")
# если есть хеш, проверь:
# print(" sha256:", hashlib.sha256(key.encode()).hexdigest())