Afinní šifra představuje základní monoalfabetickou substituční šifru. Jedná se o zobecnění Caesarovy šifry. Kryptoanalýza se provádí frekvenční analýzou.

Afinní šifra

Představuje jednoduchou substituční šifru, která mírně zdokonaluje Caesarovu šifru (je v podstatě její rozšířená varianta).

Předpokládejme, že máme vstupní abecedu Σ o velikosti n (vstupní abeceda je v neprázdná konečná množina symbolů, typicky Σ = {a,b,c,...,z}). Dále máme klíč, což jsou dvě přirozená čísla a a b, kde a je nesoudělné s n, tedy an. Velikost čísel a a b nehraje roli, ale z matematického hlediska má význam uvažovat pouze čísla menší než n.

V prvním kroku potřebujeme vstupní abecedu zakódovat do číslic, to lze provést jednoduše, předpokládejme následující převodní vztah:

Vstupní znak: a b c d e f ... y z
Znak kódové abecedy: 0 1 2 3 4 5 ... 24 25

Pozor, je potřeba začínat s kódováním od nuly.

Dekódování se provádí triviálně inverzí těchto hodnot.

Šifrování

Šifrování se provádí pomocí vzorce:

Ci = (aMi + b) mod n

kde Mi představuje číselně zakódovanou hodnotu znaku vstupního slova na i-té pozici a Ci číselně zakódovaný výstupní znak (dekódování se provádí triviálně). Operace mod představuje výpočet zbytku po dělení.

Caesarovu šifru z afinní šifry získáme dosazením a = 1.

Dešifrování

Je zdánlivě o něco těžší, neboť vyžaduje znalost inverzní hodnoty a-1 mod n. Dešifrování se provádí pomocí vzorce:

Mi = (Ci - b)a-1 mod n

Jak se hledá multiplikativní inverze je stručně popsáno zde. Hodnoty Ci a Mi opět značí číselně zakódované vstupní symboly na i-té pozici ve vstupním slově.

Kryptoanalýza

Se provádí standardní frekvenční analýzou. Je o něco složitější, neboť každý znak se mapuje (zobrazuje) na jinou hodnotu bez jednoduchého posunu (jako v případě Caesarovy šifry). Je tedy potřeba získat každý znak samostatně.

Úlohy k vyřešení

Naprogramujte afinní šifru pro zadaný textový vstup v jazyce Python. Můžete využít následující vstup pro kódování výstupu.

def encode(inputWord):
  outputWord = [];
  for ch in inputWord:
    if(26 > (ord(ch) - 97) >= 0):
      outputWord.append(ord(ch) - 97);
    else:
      print("Znak: '" + ch + "' nebyl zakodovan!");
  return outputWord;

def decode(inputWord):
  outputWord = "";
  for ch in inputWord:
    if(0 <= ch < 26):
      outputWord = outputWord + (chr(ch + 97));
    else:
      print("Znak: '" + chr(ch + 97) + "' nebyl dekodovan!");
  return outputWord;

word = "ahojxsvete";
print(decode(encode(word)));