O'quv Markazi / Kriptografiya / Klassik Shifrlar

Klassik Shifrlar

Caesar, Vigenere, Affine, Rail Fence — tarix boylab qo'llanilgan klassik shifrlash usullari, ularning matematik asoslari va Python bilan qanday buzish mumkinligi.

Caesar Cipher Vigenere Affine Chastota Tahlili Rail Fence CTF

1 Klassik Shifrlarga Kirish

Klassik vs Zamonaviy

Klassik shifrlar kompyuterdan oldin qo'lda yoki oddiy mexanik qurilmalar bilan ishlatilar edi. Ular bugun kriptografik jihatdan xavfli — lekin CTF musobaqalarida va kriptografiya asoslarini o'rganishda juda muhim.

Substitution ciphers — harflarni boshqa harflar bilan almashtiradi
Transposition ciphers — harflar tartibini o'zgartiradi
Polyalphabetic ciphers — bir nechta alifbo bir vaqtda

Nima uchun o'rganamiz?

  • CTF musobaqalarida eng ko'p uchraydigan shifr turi
  • Zamonaviy kriptografiya tushunchalarini tushuntiradi
  • Chastota tahlilini o'rgatadi
  • Matematik asoslarni (mod arifmetika) ko'rsatadi
  • Kriptotahlil (kriptoanaliz) asoslari

2 Caesar Shifri (Siljish Shifri)

Caesar Shifri (shift=3) ASLIY: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z SHIFR: D E F G H I J K L M N O P Q R S T U V W X Y Z A B C Misol: HELLO → KHOOR (har harf 3 pozitsiya o'ngga) E(x) = (x + k) mod 26 D(x) = (x - k + 26) mod 26

Matematik ta'rif

Shifrlash (Encryption):

E(x) = (x + k) mod 26

Deshifrlash (Decryption):

D(x) = (x - k + 26) mod 26

ROT13 (k=13, o'zi-o'ziga teskari):

E(x) = D(x) = (x + 13) mod 26

x = harf raqami (A=0, B=1, ..., Z=25), k = siljish (kalit)

Qanday buziladi?

Caesar shifri juda zaif — faqat 25 ta kalitni sinab ko'rish yetarli (brute force).

1 Har bir k=1..25 uchun deshifrlash
2 O'qilishi mumkin bo'lgan matnni topish
3 Yoki chastota tahlili (eng ko'p harf ≈ E)

Python Implementatsiya

def caesar_encrypt(text, shift):
    result = []
    for ch in text.upper():
        if ch.isalpha():
            result.append(chr((ord(ch) - ord('A') + shift) % 26 + ord('A')))
        else:
            result.append(ch)
    return ''.join(result)

def caesar_decrypt(text, shift):
    return caesar_encrypt(text, -shift)

def caesar_brute_force(ciphertext):
    # Barcha 25 ta variantni ko'rsatish
    for k in range(1, 26):
        print(f"k={k:2d}: {caesar_decrypt(ciphertext, k)}")

# Misol
cipher = caesar_encrypt("HELLO WORLD", 13)
print(f"ROT13: {cipher}")        # URYYB JBEYQ
print(caesar_decrypt(cipher, 13))    # HELLO WORLD

# CTF: shifrlangan matnni buzish
caesar_brute_force("KHOOR ZRUOG")

3 Affine Shifri

Affine shifri Caesar shifrini umumlashtiradi — siljish (shift) o'rniga ko'paytirish ham qo'shiladi. Kalit juft: (a, b) — bu ko'proq imkoniyat beradi, lekin baribir zaif.

Formula

Shifrlash:

E(x) = (a·x + b) mod 26

Deshifrlash:

D(x) = a⁻¹·(x - b) mod 26

Shart: GCD(a, 26) = 1

a ∈ {1,3,5,7,9,11,15,17,19,21,23,25}

b ∈ {0, 1, ..., 25}

Jami kalit soni: 12 × 26 = 312

Misol: a=5, b=8

A (0): (5×0 + 8) mod 26 = 8 = I
B (1): (5×1 + 8) mod 26 = 13 = N
H (7): (5×7 + 8) mod 26 = 43 mod 26 = 17 = R
E (4): (5×4 + 8) mod 26 = 28 mod 26 = 2 = C
HELLO → RCLLA
Teskari: a⁻¹ = 21 (chunki 5×21 = 105 ≡ 1 mod 26)
from math import gcd

def mod_inverse(a, m):
    if gcd(a, m) != 1:
        raise ValueError(f"GCD({a},{m})≠1, teskari yo'q")
    for x in range(1, m):
        if (a * x) % m == 1:
            return x

def affine_encrypt(text, a, b):
    assert gcd(a, 26) == 1, "a va 26 o'zaro tub bo'lishi kerak"
    result = []
    for ch in text.upper():
        if ch.isalpha():
            x = ord(ch) - ord('A')
            result.append(chr((a * x + b) % 26 + ord('A')))
        else:
            result.append(ch)
    return ''.join(result)

def affine_decrypt(text, a, b):
    a_inv = mod_inverse(a, 26)
    result = []
    for ch in text.upper():
        if ch.isalpha():
            x = ord(ch) - ord('A')
            result.append(chr(a_inv * (x - b) % 26 + ord('A')))
        else:
            result.append(ch)
    return ''.join(result)

# CTF brute-force
def affine_brute(ciphertext):
    valid_a = [x for x in range(1, 26) if gcd(x, 26) == 1]
    for a in valid_a:
        for b in range(26):
            plain = affine_decrypt(ciphertext, a, b)
            if "THE" in plain or "CTF" in plain:
                print(f"a={a}, b={b}: {plain}")

4 Vigenere Shifri (Polyalphabetik)

Tarix: 1553-yilda Giovan Battista Bellaso tomonidan ixtiro qilingan, keyinchalik Blaise de Vigenere nomi bilan mashhur bo'lgan. "Le Chiffre indéchiffrable" (buzib bo'lmaydigan shifr) deb atalgan — lekin 1863-yilda Kasiski uni buzdi!

Vigenere Qanday Ishlaydi?

Vigenere: Kalit = "KEY", Matn = "HELLO WORLD" Asliy matn : H E L L O W O R L D Kalit (takr.): K E Y K E K E Y K E + mod 26 + mod 26 + mod 26 + mod 26 + mod 26 + mod 26 + mod 26 + mod 26 + mod 26 + mod 26 Shifr matn : R I J V S G S P V H E(pᵢ, kᵢ) = (pᵢ + kᵢ) mod 26 kalit takrorlanadi

Kasiski Testi (Buzish usuli)

Kalit uzunligini topish uchun shifr matnidagi takrorlanuvchi 3+ harfli ketma-ketliklar orasidagi masofalar hisoblanadi. Ularning GCD'si kalit uzunligiga teng.

Takrorlanma: "THE" → pozitsiya 10 va 40
Masofa: 40 - 10 = 30
Agar yana: "ING" → pozitsiya 15 va 45
Masofa: 45 - 15 = 30
GCD(30, 30) = 30 → kalit uzunligi 30 yoki 10 yoki 5 yoki 3

Index of Coincidence (IC)

IC formulasi kalit uzunligini aniqlashda yordam beradi:

IC = Σ fᵢ(fᵢ-1) / N(N-1)

fᵢ = i-harfning chastotasi, N = umumiy uzunlik

Inglizcha matn IC: ≈ 0.065
Tasodifiy matn IC: ≈ 0.038
Vigenere (k=5) IC: ≈ 0.045
def vigenere_encrypt(text, key):
    text = text.upper()
    key = key.upper()
    result, ki = [], 0
    for ch in text:
        if ch.isalpha():
            shift = ord(key[ki % len(key)]) - ord('A')
            result.append(chr((ord(ch) - ord('A') + shift) % 26 + ord('A')))
            ki += 1
        else:
            result.append(ch)
    return ''.join(result)

def vigenere_decrypt(text, key):
    text = text.upper()
    key = key.upper()
    result, ki = [], 0
    for ch in text:
        if ch.isalpha():
            shift = ord(key[ki % len(key)]) - ord('A')
            result.append(chr((ord(ch) - ord('A') - shift + 26) % 26 + ord('A')))
            ki += 1
        else:
            result.append(ch)
    return ''.join(result)

def kasiski_test(ciphertext, min_len=3):
    # Takrorlanuvchi ketma-ketliklar va masofalar
    from math import gcd
    from functools import reduce
    text = ciphertext.upper().replace(' ', '')
    distances = []
    for i in range(len(text) - min_len):
        seq = text[i:i+min_len]
        j = text.find(seq, i + min_len)
        if j != -1:
            distances.append(j - i)
    if distances:
        common_gcd = reduce(gcd, distances)
        print(f"Masofalar: {distances}")
        print(f"GCD → ehtimol kalit uzunligi: {common_gcd}")

# Misol
c = vigenere_encrypt("ATTACK AT DAWN", "KEY")
print(c)  # KXIASK KX NGQR
print(vigenere_decrypt(c, "KEY"))  # ATTACK AT DAWN

5 Chastota Tahlili (Frequency Analysis)

Ingliz tilida har bir harfning taxminiy chastotasi ma'lum. Substitution shifrlarda harflar almashinadi, lekin chastotalar saqlanib qoladi. Bu — barcha oddiy substitution shifrlarni buzishning asosiy kaliti.

Ingliz tili harf chastotalari (%) E 12.7 T 9.1 A 8.2 O 7.5 I 7 N 6.7 S 6.3 H 6.1 R 6 D L C U M W F G Y P B V K J X Q Z Yuqori chastota (>6%) O'rta chastota Past chastota

ETAOIN SHRDLU

Ingliz tilidagi eng ko'p ishlatiladigan harflar tartibi:

ETAOIN SHRDLU

CTF'da shifrlangan matnning eng ko'p harfi E'ga mos kelishi ehtimoli yuqori

Python: Chastota Tahlili

from collections import Counter

def freq_analysis(text):
    text = text.upper()
    letters = [c for c in text if c.isalpha()]
    total = len(letters)
    counts = Counter(letters)
    sorted_by_freq = counts.most_common()

    print("Harf | Son | %")
    for letter, count in sorted_by_freq:
        pct = count / total * 100
        bar = '█' * int(pct)
        print(f"  {letter}  | {count:3d} | {pct:.1f}% {bar}")

def simple_substitution_crack(cipher, mapping):
    # mapping = {'X': 'E', 'K': 'T', ...}
    result = []
    for ch in cipher.upper():
        result.append(mapping.get(ch, ch.lower()))
    return ''.join(result)

6 Oddiy Substitution Shifri

Har bir harf boshqa bir harf bilan almashtiriladi — lekin tartibsiz (Caesar kabi sistemali emas). 26! ≈ 4×10²⁶ ta mumkin bo'lgan kalit bor, lekin chastota tahlili bilan yechiladi.

Kalit misoli (alifbo → shifr alifbo):

Asliy:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Shifrlangan:
QWERTYUIOPASDFGHJKLZXCVBNM
HELLO WORLD → ITSSG VGKSR (H→I, E→T, L→S, O→G, W→V, R→K, D→R)

7 Rail Fence Shifri (Transposition)

Rail Fence — transposition (ko'chirish) shifri. Harflar almashtirilmaydi, faqat joyi o'zgartiriladi. Matn diagonal "to'lqin" shaklida yoziladi, keyin qator-qator o'qiladi.

Rail Fence: "WEAREDISCOVEREDFLEEATRACK" (rails=3) Rail 0: W E C R L T K Rail 1: E R D S O E E F E A R C Rail 2: A I V D E A Shifr: WECRLTKERDSOEEFEARCAIVDEA
def rail_fence_encrypt(text, rails):
    fence = [[] for _ in range(rails)]
    rail, direction = 0, 1
    for char in text:
        fence[rail].append(char)
        if rail == 0: direction = 1
        elif rail == rails - 1: direction = -1
        rail += direction
    return ''.join(''.join(r) for r in fence)

def rail_fence_decrypt(cipher, rails):
    n = len(cipher)
    pattern = [0] * n
    rail, direction = 0, 1
    for i in range(n):
        pattern[i] = rail
        if rail == 0: direction = 1
        elif rail == rails - 1: direction = -1
        rail += direction

    indices = sorted(range(n), key=lambda i: (pattern[i], i))
    result = [''] * n
    for idx, char in zip(indices, cipher):
        result[idx] = char
    return ''.join(result)

# Misol
enc = rail_fence_encrypt("HELLOWORLD", 3)
print(enc)                             # HOLELWRDLO → HLODEROLWL
print(rail_fence_decrypt(enc, 3))    # HELLOWORLD

8 CTF'da Klassik Shifr Masalalarini Yechish

Belgi tanish algoritmi

1
Faqat harflar? Raqamlar? Maxsus belgilar? — Shifr turini aniqlashda yordam beradi
2
Chastota tahlili — eng ko'p va kam harflarni aniqlash
3
IC hisoblash — monoalphabetik (≈0.065) yoki polyalphabetik (≈0.04)?
4
Kasiski testi — kalit uzunligini aniqlash
5
Har bir "satr" uchun chastota tahlili va E harfi bilan solishtirish

Umumiy CTF naqshlari

ROT13
Faqat A-Z, ETAOIN taqsimoti saqlanadi
Atbash
A→Z, B→Y, ... (teskari alifbo)
Bacon
A=AAAAA, B=AAAAB, 5-bitli ikkilik
Playfair
5×5 grid, digram substitution
Columnar
Ustunli transpozitsiya, kalit tartib
Beaufort
Vigenere varianti, E(x)=(k-p) mod 26
# CTF uchun foydali funksiyalar to'plami
import string

def rot13(text):
    result = []
    for c in text:
        if c.isalpha():
            base = ord('A') if c.isupper() else ord('a')
            result.append(chr((ord(c) - base + 13) % 26 + base))
        else:
            result.append(c)
    return ''.join(result)

def atbash(text):
    result = []
    for c in text:
        if c.isalpha():
            base = ord('A') if c.isupper() else ord('a')
            result.append(chr(base + 25 - (ord(c) - base)))
        else:
            result.append(c)
    return ''.join(result)

def index_of_coincidence(text):
    text = [c for c in text.upper() if c.isalpha()]
    N = len(text)
    if N < 2: return 0
    counts = Counter(text)
    ic = sum(f * (f - 1) for f in counts.values()) / (N * (N - 1))
    return ic

# IC interpretatsiya:
# 0.065 → Ingliz matni (monoalphabetik)
# 0.038 → Tasodifiy (polyalphabetik, Vigenere)
# Oraliqda → Ehtimol kalit uzunligiga qarab guruhlash kerak

Bilimni Sinash

1. Caesar shifri bilan k=7 da "HELLO" ni shifrlasangiz natija nima?

2. Affine shifri uchun qaysi a qiymatlari ruxsat etiladi (mod 26)?

3. IC ≈ 0.065 bo'lsa, bu nimani anglatadi?