Vigenère Shifri
Klassik
O'rta
Vigenère shifri nima?
Blaise de Vigenère tomonidan yaratilgan (XVI asr). Caesar shifrini kuchaytiradi: har harfni boshqacha kalit bilan siljitadi.
💡 Asosiy farq
Caesar: bitta kalit → bitta siljish
Vigenère: kalit so'z → har harf uchun turli siljish
Qanday ishlaydi?
def vigenere_encrypt(plaintext: str, key: str) -> str:
result = []
key = key.upper()
key_index = 0
for char in plaintext.upper():
if char.isalpha():
# Kalit harfini siljish sifatida ishlat
shift = ord(key[key_index % len(key)]) - ord('A')
shifted = (ord(char) - ord('A') + shift) % 26
result.append(chr(shifted + ord('A')))
key_index += 1
else:
result.append(char)
return ''.join(result)
def vigenere_decrypt(ciphertext: str, key: str) -> str:
result = []
key = key.upper()
key_index = 0
for char in ciphertext.upper():
if char.isalpha():
shift = ord(key[key_index % len(key)]) - ord('A')
shifted = (ord(char) - ord('A') - shift) % 26 # Ayirish!
result.append(chr(shifted + ord('A')))
key_index += 1
else:
result.append(char)
return ''.join(result)
# Misol
matn = "HELLO WORLD"
kalit = "KEY"
encrypted = vigenere_encrypt(matn, kalit)
print("Shifrlangan:", encrypted) # RIJVS UYVJN
decrypted = vigenere_decrypt(encrypted, kalit)
print("Deshifrlangan:", decrypted) # HELLO WORLD
Kasiski testi — Vigenèreни buzish
1
Takrorlanuvchi 3+ harfli ketma-ketliklarni toping
2
Ular orasidagi masofani o'lchang
3
GCD(masofalar) = kalit uzunligi
4
Har kalit pozitsiyasi uchun alohida Caesar
from math import gcd
from functools import reduce
from collections import Counter
def kasiski_test(ciphertext: str, min_len: int = 3) -> list:
# Takrorlanuvchi ketma-ketliklarni toping va GCD hisoblang
ct = ''.join(c for c in ciphertext.upper() if c.isalpha())
spacings = []
for length in range(min_len, 6):
for i in range(len(ct) - length):
pattern = ct[i:i+length]
for j in range(i + length, len(ct) - length + 1):
if ct[j:j+length] == pattern:
spacings.append(j - i)
if not spacings:
return []
# GCD hisoblash
overall_gcd = reduce(gcd, spacings)
factors = [i for i in range(2, 20) if overall_gcd % i == 0]
return factors
def find_key_length(ciphertext: str) -> int:
factors = kasiski_test(ciphertext)
return factors[0] if factors else 1
# Kalit uzunligi topilgandan keyin har pozitsiyani Caesar kabi hal qilish
def break_vigenere(ciphertext: str, key_length: int) -> str:
ct = ''.join(c for c in ciphertext.upper() if c.isalpha())
key = ""
for i in range(key_length):
# Har i-chi pozitsiyasidagi harflarni to'pla
column = ct[i::key_length]
# Eng ko'p uchragan harf E ga mos kelishi kerak
freq = Counter(column).most_common(1)[0][0]
shift = (ord(freq) - ord('E')) % 26
key += chr(shift + ord('A'))
return key
💡 Bu mavzu bo'yicha amaliy mashq qilishni istaysizmi?
Klassik challengelarini ko'rish →