Princip Caesarovy šifry

Princip Caesarovy šifry je založen na tom, že všechna písmena zprávy jsou během šifrování zaměněna za písmeno, které se abecedně nachází o pevně určený počet míst dále (tj. posun je pevně zvolen).

align-center

Počet možných variant klíče této šifry je o jedna menší než počet písmen (znaků) v použité abecedě. Zvolíme-li hodnotu posunu stejnou, jako je počet znaků použité abecedy, bude zašifrovaná zpráva identická s předlohou. Vyšším posunem, například posunem s klíčem o jedna větší, než je počet písmen (znaků) abecedy, dostaneme zašifrovanou zprávu odpovídající prostému posunu o klíč jedna, takže použití klíče hodnoty vyšší než počet znaků abecedy nemá kryptografický význam. V některých pramenech se proto o Caesarových šifrách mluví jako o šifrách aditivních.

Použití

Tuto šifru používal pro vojenskou komunikaci Julius Caesar a popsal ji v Zápiscích o válce galské (odtud je odvozen její název). Caesar používal posun o tři místa, obecně je ale za Caesarovu šifru označováno jakékoli šifrování na principu prostého posunu písmen (znaků) o konstantní hodnotu. I když je tato šifra z dnešního hlediska snadno rozluštitelná a pro jednoduchost šifrování/dešifrování bývá často používána dětmi, Julius Caesar ji s úspěchem používal při svých vojenských taženích.

Pro „vážné“ úkoly se tato šifra dnes neužívá a slouží pouze k školním demonstracím slabin jednoduchých substitučních šifrovacích systémů. Hlavní a neodstranitelnou slabinou této šifry je, že každý konkrétní znak zdrojového textu odpovídá jednomu konkrétnímu znaku šifrovaného textu. Například u klíče velikosti 3 je každé písmeno A ze vstupu (zdroje) převedeno (zašifrováno) na písmeno D, každé písmeno B je zašifrováno na písmeno E atd., takže lze zašifrovaný text snadno při kryptoanalýze statisticky zpracovat na výskyt jednotlivých písmen v daném vstupním jazyce.

Formální zápis

Caesarovu šifru můžeme definovat pomocí modulární aritmetiky, protože posun písmene o k pozic můžeme zapsat pomocí modula. Pokud si nadefinujeme abecedu jako posloupnost čísel od 0 do 25, kde a=0, b=1, c=2, …, z=25, pak můžeme nadefinovat funkci \$Posun(o, k)\$, kde o je znak, který se bude šifrovat a k klíč, kterým bude text šifrován, takto:

\$Posun(o, k) = (o +k) \mod 26\$.

Funkci \$E_k(x)\$, která vrátí zašifrovaný text x pomocí klíče k nadefinujeme takto:

\$E_k(x) = Posun(x\[i], k)\$ pro všechna i menší nebo rovna než délka vstupního řetězce x,

kde x[i] znamená písmeno na i-té pozici.

Na popis dešifrování budeme potřebovat funkci \$PosunZpet(c, k)\$, která posune zašifrované písmeno c zpět o k písmen.

Nadefinujeme ji takto: \$PosunZpet(c, k) = (c - k + 26) mod 26\$.

Dešifrovací funkci pro klíč k a šifrový text x definujeme takto: \$D_k(x) = PosunZpet(x\[i], k)\$ pro všechna i menší nebo rovna než délka vstupního řetězce x.

Jak to Caesar používal

align-center
Figure 1. Dva kotouče kotouč pro snadné zašifrování a rozšifrování

Bílý kotouč je pevný a žlutý kotouč je otočný. Klíč (nebo posun) se nastaví otáčením žlutého kotouče je rozdílem mezi bílým písmenem A a žlutým písmenem A. V našem obrázku je klíč \$k=10\$.

Odesílatel a příjemce zprávy mají každý svůj kotouč a musí se předem dohodnout na klíči (posunu).

Odesílatel, který šifruje, postupuje takto:

V na bílem kotouči najde písmeno otevřeného textu (které chce zašifrovat) a do šifrovaného textu zapíše odpovídající žluté písmeno. Takto postupuje s celým otevřeným textem písmeno po písmenu. Po dokončení práce otevřený text zničí a předá poslu šifrovaný text. Ten ho doručí příjemci.

Příjemce, který dešifruje, postupuje takto:

Čte postupně písmenko po písmenku šifrovaný text a pro každé písmenko šifrovaného textu udělá toto: Najde na žlutém kotouči příslušné písmeno šifrovaného textu a do rozšifrovaného textu zapíše odpovídající bílé písmeno.

Odesílatel a příjmence musí mít oba správně nastaveny kotouče, jinak to nebude fungovat.

Úkol

Naprogramujte v Pythonu jednoduchý program pro šifrování a dešifrování Caesarovou šifrou.

Řešení

Tomáš Forejtek

caesarovasifra_tomas_forejtek.py
# implementace Caesarovy šifry
# (c) Tomáš Forejtek <forejtek.tomas@sspvc.cz>
#

def caesar_cipher(zprava, posun):
  sifrovana_zprava = ""
  abeceda = "AÁBCČDĎEÉFGHIÍJKLMNŇOÓPQRŘSŠTŤUÚŮVWXYÝZŽaábcčdďeéfghiíjklmnňoópqrřsštťuúůvwxyýzž0123456789,.:;!?"
  for char in zprava:
    if char in abeceda:

      zaklad = abeceda.index(char)
      sifrovana_zprava += abeceda[(zaklad + posun) % len(abeceda)]
    else:

      sifrovana_zprava += char
  return sifrovana_zprava

while True:
  print()
  zprava = input("Zadejte zprávu k zašifrování nebo dešifrování: ")
  print()

  posun = int(input("Zadejte hodnotu posunu: "))
  print()

  akce = input("Zadejte 'sifrovat' pro zašifrování nebo 'desifrovat' pro dešifrování: ")
  print()

  if akce == "sifrovat":
    sifrovana_zprava = caesar_cipher(zprava, posun)

    print(f"Zašifrovaná zpráva: {sifrovana_zprava}")
    print()
  elif akce == "desifrovat":
    desifrovana_zprava = caesar_cipher(zprava, -posun)

    print(f"Dešifrovaná zpráva: {desifrovana_zprava}")
    print()
  else:
    print("Špatná funkce")
    print()

  znova = input("Chcete šifrovat nebo dešifrovat znovu? Zadejte 'a' jako ano nebo 'n' jako ne: ")
  if znova != 'a':
    break
print()
input("Stiskněte jakoukoliv klávesu pro ukončení!!!")

SHA256sum: 5e68e1b114251f1f7dc86b482a322f97d501c3171ff2443db9f20dbe87ccacce caesarovasifra_tomas_forejtek.py

SHA256 je jednosměrná hashovací funkce, de facto podpis. Pomocí ní můžeme ověřit, že soubor caesarovasifra_tomas_forejtek.py nebyl nijak změněn oproti originálu.
Ověření na Linuxu: sha256sum caesarovasifra_tomas_forejtek.py
Ověření na Windows 10: certutil -hasfile caesarovasifra_tomas_forejtek.py SHA256

Tomáš Divíšek

Césarova_šifra_Divíšek_Tomáš.py
#Toto je program na Césarovu šifru
retezec=input("Zadejte slovo:")
posun=int(input("Zadejte posun:"))
print("Původní zpráva:", retezec)
zprava=""
#Cyklus projíždějící jednotlivé znaky:
for znak in retezec:
    i=ord(znak)
    i=i+posun
    #Kontrola přečtení
    if(i>ord("z")):
        i=i-26
    znak=chr(i)
    zprava=zprava+znak
#Vypíše
print("Zašifrovaná zpráva:", zprava)
input()

SHA256sum: 2dbb4c592f4e78f209baa7964284e938359864ce5dc44d2b0e26b634749edc11 Césarova_šifra_Divíšek_Tomáš.py

Janek Lojda

caesarova_sifra_Janek_Lojda.py
retezec=input("zadejte slovo:")
posun=int(input("Zadejte posun:"))
print("Původní zpráva:",retezec)
zprava=""
for znak in retezec:
    i=ord(znak)
    i=i+posun
    if(i>ord("z")):
        i=i-26
    znak=chr(i)
    zprava=zprava+znak
print("Zašifrovaná zpráva:",zprava)
input()

SHA256sum: 19510a054652e6b9ee51b075b0248706c40ab2d1898ba465431064129ee28009 caesarova_sifra_Janek_Lojda.py

Jaroslav Jiroušek

caesarova_sifra_Jaroslav_Jiroušek.py
zprava = input ("Zadejte zpravu:")
posun = int(input("Zadejte posun:"))
print ("\nPůvodní zpráva:", zprava)
text =""

for znak in zprava:
    i = ord(znak)
    i += posun

    if (i>ord("z")):
        i = i - 26

    znak = chr(i)
    text += znak

print ("Zašifrovaná zpráva:", text)
input()

SHA256sum: 2f31a12655a524868ae9944f1349b4efd8847a66b1640e6721f59fd3a5182807 caesarova_sifra_Jaroslav_Jiroušek.py

Sergej Kučir

cesarova_sifra_kucyr.py
retezec=input("Zadejte slovo:")
posun=int(input("Zadejte posun:"))
print("Původní zpráva:", retezec)
zprava=""


for znak in retezec:
    i=ord(znak)
    i=i+posun

    if(i>ord("z")):
        i=i-26
    znak=chr(i)
    zprava=zprava+znak

print("Zašifrovaná zpráva:", zprava)
input()

Zdrojový kód: cesarova_sifra_kucyr.py

SHA256sum: d8671bee7cba08e5cc6f8abe1240bf23ec4a8e2c83ad1199fd670e8a641e6924 cesarova_sifra_kucyr.py

Bohdan Mich

cesarova_sifra_mikh.py
retezec=input("Zadejte slovo:")
posun=int(input("Zadejte posun:"))
print("Původní zpráva:", retezec)
zprava=""


for znak in retezec:
    i=ord(znak)
    i=i+posun

    if(i>ord("z")):
        i=i-26
    znak=chr(i)
    zprava=zprava+znak

print("Zašifrovaná zpráva:", zprava)
input()

Zdrojový kód: cesarova_sifra_mikh.py

SHA256sum: d8671bee7cba08e5cc6f8abe1240bf23ec4a8e2c83ad1199fd670e8a641e6924 cesarova_sifra_mikh.py

Martin Částek

caesarova_sifra_castek.py
retezec=input("Zde napište slovo k zašifrování/rozšifrování:")
posun=int(input("Zadejte posun v plusu pro zašifrování a mínus pro rozšifrování:"))


print("Původní slovo", retezec)
zprava=""


for znak in retezec:
    i=ord(znak)
    i=i+posun
    if(i>ord("z")):
        i=i-26
    znak=chr(i)
    zprava=zprava+znak

print("Zašifrované/rozšifrované slovo:", zprava)

input()

Zdrojový kód: caesarova_sifra_castek.py

SHA256sum: ddf36bc220c2fa658d43db89e5f1b0a8028a10ab14dc536e98f3cf548628badd caesarova_sifra_castek.py

Matěj Svoboda

caesarova_sifra.cs
// Caesarova šifra
// (c) Matěj Svoboda <svoboda.matej@sspvc.cz>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace cezeravo_sifra
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Zadej text:");
            string text = Console.ReadLine();
            Console.WriteLine("Původní text: " + text);

            string zprava = "";
            Console.WriteLine("Zadejte šifru: ");
            int sifra = int.Parse(Console.ReadLine());

            foreach (char c in text)
            {
                int i = (int)c;
                i += sifra;
                char znak = (char)i;
                zprava += znak;
            }

            Console.WriteLine(zprava);
            Console.ReadKey();
        }
    }
}

Zdrojový kód a spustitelný soubor: cezarova-sifra.zip

SHA256sum: a819785829460a0f549f82810a29daa96db3594ade41fc0d756e170a5c8eca7a cezarova-sifra.zip

Dominik Marek

siffrovani.py
def encrypt_caesar(plaintext, shift):
    ciphertext = ""
    for char in plaintext:
        if char.isalpha():
            shift_char = chr((ord(char) + shift - 97) % 26 + 97)
            ciphertext += shift_char
        else:
            ciphertext += char
    return ciphertext

def decrypt_caesar(ciphertext, shift):
    plaintext = ""
    for char in ciphertext:
        if char.isalpha():
            shift_char = chr((ord(char) - shift - 97) % 26 + 97)
            plaintext += shift_char
        else:
            plaintext += char
    return plaintext

a=input("Zadejte text k zašifrování: ")
print(a)
shift = int(input("Zadejte posunutí: "))

ciphertext = encrypt_caesar(a, shift)
print("sifrovani: ", ciphertext)

decrypted_plaintext = decrypt_caesar(ciphertext, shift)
print("Zpět původní text: ", decrypted_plaintext)

Zdrojový kód: siffrovani.py

SHA256sum: 4c1603bfa0534cfa20b13c265fc568e20f487a5199ba105e728ef7f4c746a4d4 siffrovani.py

Jakub Valášek

šifra_Jakub_Valášek.py
def encrypt_caesar(plaintext, shift):
    ciphertext = ""
    for char in plaintext:
        if char.isalpha():
            shift_char = chr((ord(char) + shift - 97) % 26 + 97)
            ciphertext += shift_char
        else:
            ciphertext += char
    return ciphertext

def decrypt_caesar(ciphertext, shift):
    plaintext = ""
    for char in ciphertext:
        if char.isalpha():
            shift_char = chr((ord(char) - shift - 97) % 26 + 97)
            plaintext += shift_char
        else:
            plaintext += char
    return plaintext

# Example usage
a=input("Zadejte text")
print(a)
shift = 3

ciphertext = encrypt_caesar(a, shift)
print("Ciphertext:" , ciphertext)

decrypted_plaintext = decrypt_caesar(ciphertext, shift)
print("Decrypted plaintext:" , decrypted_plaintext)

Zdrojový kód: šifra_Jakub_Valášek.py

SHA256sum: acc2097b2923c4bb00b263dd278c849241715fa84ffdd901ff026fb3640e16ea šifra_Jakub_Valášek.py

Matěj Papež

ffffffffff.py
def encode(text: str, key: int, abc: list[str] = None) -> str:
    if abc is None:
        abc = ['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']
    new = ''

    for char in text:
        i = abc.index(char.lower())

        while True:
            if i + key >= len(abc):
                i -= len(abc)
            elif i + key < 0:
                i += len(abc)
            else:
                break


        if char.isupper():
            new += abc[i + key].upper()
        else:
            new += abc[i + key]
    return new

Zdrojový kód: ffffffffff.py

SHA256sum: 47915985dd60589b2880a2eb2e0a57115565329f57b22ec76a725580366e5311 ffffffffff.py

Anna Martinková

caesarova.py
#Caesarova sifra

abc = "ABCDEFGHIJKLMNOPQRTUVWXYZ"
def encode(text, shift):
    text2=""
    for letter in text:
        index=abc.index(letter)
        index2=index+shift
        index2=index2%26
        text2+=abc[index2]

    return text2

def decode(text,shift):
    text2=""

print(encode("AHOJ",54))

Zdrojový kód: caesarova.py caesarova.zip

SHA256sum: 6f062005e3a42f6dd09a3d61dcee32555cefbbb0f4e097a88c8610f008cc33df caesarova.py

SHA256sum: 6e77505b61ae3a549f28c1db64c1939589f38122b8ca010bb1262683b7301439 caesarova.zip

Odkazy a literatura: