Fakulta elektrotechnická Katedra teoretické elektrotechniky
Dokumentace k semestrální práci
Šifrování/Dešifrování s použitím hesla 2012/13 Petr Zemek
Vyučující: Ing. Petr Kropík, Ph.D Předmět: Základy programování pro elektroniku
Obsah 1 Zadání semestrální práce 1.1 Název . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Stručné zadání . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Celé zadání . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3 3 3 3
2 Analýza úlohy 2.1 (De)Šifrování . . . . . . . 2.2 Dekompozice programu . 2.3 Vyhodnocování vstupu . . 2.4 Načítání vstupního řetězce 2.5 Šifrování . . . . . . . . . . 2.6 Dešifrování . . . . . . . . 2.7 Výpis výstupu . . . . . . .
. . . . . . .
4 4 4 5 5 5 5 5
3 Popis implementace 3.1 Přenositelnost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Datové struktury a správa paměti . . . . . . . . . . . . . . . . . . . . . . 3.3 Popis algoritmů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6 6 6 6
4 Uživatelská příručka 4.1 Překlad zdrojových kódů . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Spuštění a obsluha . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Ukázky běhu programu . . . . . . . . . . . . . . . . . . . . . . . . . . .
8 8 8 9
. . . . . . . . . . . . . . . . . . . . . ze souboru . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
5 Závěr 5.1 Výkonnost programu . . . . . . . . . . . 5.2 Kódování zdrojových souborů . . . . . . 5.3 Důvod využívání menších datových typů 5.4 Vysvětlení nestandardních konstrukcí . .
2
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . . . . .
. . . .
. . . .
11 11 11 11 11
1 Zadání semestrální práce 1.1 Název Šífrování/Dešífrování s použitím hesla
1.2 Stručné zadání Napište program v jazyce C: jednoduché šifrování a dešifrování s využitím heslaVytvořte program, který dokáže šifrovat a dešifrovat pomocí jednoduché šifry. Ovládání programu umožněte pomocí jednoduchého menu. Umožněte načtení dat z klávesnice nebo ze souboru. Program musí obsahovat alespoň jednu uživatelskou funkci a musí být ošetřen proti chybným vstupům. Výstup programu umožněte do souboru nebo na obrazovku. Uživatel zvolí, jestli chce použít režim šifrování či dešifrování (dále jen Š/D). Vytvořte v paměti pole znaků (řetězec), který bude Š/D a řetězec do kterého uložíte heslo. Program bude Š/D dle běžné aditivní šifry, která využívá posunu znaků ve znakové ASCII tabulce.“ a tento hlavolam vyřeší, tj. převede jej posloupností povolených tahů do tzv. základního postavení.
1.3 Celé zadání http://home.zcu.cz/ pkropik/zpe/semestralky_detaily/Semestralni_prace_ZPE_Petr_Kropik.pdf
3
2 Analýza úlohy 2.1 (De)Šifrování Samotný algoritmus S/D byl víceméně představen v zadání. Pro S/D je pravděpodobně nejvhodnější použít překlad jednotlivých znaků na jejich číselné ASCII hodnoty a ty potom při šifrování s ASCII hodnotou hesla sčítat, při dešifrování odčítat. Po provední potřebných početních operacích se musí číselná hodnota nacházet mezi hodnotou 32 a hodnotou 126 - tedy v intervalu tisknutelných znaků. Je tedy nutné implementovat funkce, které zajistí toto sčítání/odčítání hodnot.
2.2 Dekompozice programu 1. Vyhodnocování vstupu a) Zadání v parametru CLI i. Rozparsování vstupu b) Parametr CLI chybí c) Parametrů je moc 2. Výpis menu a) Rozvržení textu a formátování v menu b) Vyžádání vstupu od uživatele 3. Načítání vstupního řetězce ze souboru 4. Načítání vstupního řetězce ze stdin 5. Šifrování 6. Dešifrování 7. Výpis výstupu a) do souboru b) na stdout
4
2.3 Vyhodnocování vstupu Nejdříve by se mělo ověřit, jestli uživatel program spustil s perametrem, popřípadě jestli nezadal málo nebo moc parametrů (slov). V případě, že parametrů bude mnoho, program skončí s chybovým hlášením. Pokud bude znaků málo, vypíše menu a vyžádá si vstup. Program by mělo jít spustit přímo s parametry, které by obsahovaly vstup k (de)šifrování, heslo a požadovanou akci. Tím jsou zajištěny všechny důležité informace a může začít samotné (de)šifrování bez zbytečných otázek.
2.4 Načítání vstupního řetězce ze souboru K načítání ze souboru může dojít v případě, že parametrů na příkazové řádce bude málo (žádný.) Nyní je vhodné vypsat menu a uživateli dát na vybranou, zda chce řetězec načíst ze stdin nebo ze souboru. Poté bude uživatel pořádán o heslo a o akci zda chce řetězec šifrovat nebo dešifrovat. Podle akce se zavolají příslušné funkce.
2.5 Šifrování Z důvodu rozdílné délky šifrovaného řetězce a hesla je nutné řetězec se vstupem a řetězec s heslem zpracovávat od začátku znak po znaku. Při načtění prvního znaku ze vstupu resp. z hesla se získá jejich číselná reprezentace v ASCII tabulce a hodnoty se sečtou. Protože ASCII tabulka obsahuje i netisknutelné znaky (na začátku i na konci), je nutné přičíst hodnotu 32 - protože 31 znaků od začátku je netisknutelná oblast. Když výsledná hodnota přesáhne rozsah tisknutelné oblasti, odečte se od ní 126 a znovu přičte 32 (aby byla výsledná hodnota tisknutelná). Potom se výsledné číslo přeloží na znak, uloží se do výstupního pole zašifrovaných znaků a pokračuje se šifrováním následujícího znaku ze vstupního řetězce.
2.6 Dešifrování Jedná se o jednoduchou inverzní operaci. Vstupní řetězce a heslo se načítají totožně. Místo sčítání jejich ASCII hodnoty se hodnota hesla odčítá od hodnoty dešifrovaného znaku. Potom se odečte 32 a pokud je výsledná hodnota menší než 32, tak se přičte 126 a odečte 32. Získané číslo se převede na znak a ten je tím dešifrován.
2.7 Výpis výstupu Získaný výstup se může vypsat na stdout nebo do souboru. Na stdout se text může vypsat automaticky a o možnost zápisu do souboru je vhodnější uživatele informovat a načíst jeho volbu.
5
3 Popis implementace 3.1 Přenositelnost Program byl vyvíjen pod operačním systémem GNU/Linux. Vzhledem k činnosti programu se pro portování na OS Windows nemusí provádět žádné změny ve zdrojovém kódu. Jediná odlišná věc může být soubor makefile - v případě, že používáte jiný kompilátor než GCC.
3.2 Datové struktury a správa paměti Jako hlavní datové struktury jsou zde dva vektory - Pro vstupní řetězec a pro heslo. Většina datových struktur je alokována staticky. Při vstupu ze souboru se "dynamicky"alokuje vektor pro uchovávání vstupního řetězce. Paměť pro tento řetězec se ovšem dealokuje až na konci programu, takže se dynamickou alokací příliš nezíská. Pro logické oprace a jiné rozhodovací procesy se využívají takové datové typy, aby svou kapacitou a možnostmi vyhovovaly situaci a zároveň, aby bylo zřejmé, že při správném běhu programu v dané proměnné nemůže být např. více, než dovoluje daný datový typ. V programu se používají převážně datové typy unsigned short. Tam, kde je zapotřebí znaménko, se používá short a int. Programátorem definované datové typy nejsou potřeba.
3.3 Popis algoritmů Výpis menu Menu je realizováno v souboru print_menu.c. Na řádku 31 se zkontroluje, zda je terminál dostatečně velký na vypsání menu. Když není, fce print_menu() vrátí 1 a program se ukončí. Od řádku 39 se deklarují proměnné, které mají v sobě uložen defaultní statický obsah menu. Od řádku 47 se vypočítává počet mezer, které se musí doplnit před řetězce, které se deklarovaly výše. Skládáním statických řetězců a mezer vznikne formátované menu. (ř. 59+). V jednoduchém menu je uživatel požádám o zadání jména souboru nebo stdin. Výsledek se uloží pomocí fce scanf() do prměnné zdroj_vstupu deklarované na řádku 106 v souboru vstup_ze_souboru.c. Proměnná je staticky alokovaná na počet znaků, které zbývají od promptu do konce řádku. Při načítání řetězce ze souboru je uživatel omezen na 9999999 znaků.
6
Vstup ze souboru V souboru vstup_ze_souboru.c na řádku 106 se vyhodnocuje, zda se vstupní řetězec bude načítat ze souboru ze souboru nebo ze stdin. Na řádku 134 a 213 jsou cykly, které uživatele nutí zadat S nebo D, aby se uvnitř těchto cyklů rozhodlo, zda se bude šifrovat nebo dešifrovat. Funkce pro S/D Pro zjednodušení programu zde existuje pouze jedna funkce pro šifrování a jedna pro dešifrování, ačkoliv je zde na výběr více možností (a formátů) vstupu. Jako parametr tyto funkce přebírají standardní řetězce typu char. Tzn. že se daný vstup musí nejdříve přesunout do polí, které se potom předají těmto funkcím.
7
4 Uživatelská příručka 4.1 Překlad zdrojových kódů Pro přeložení je nutné mít nainstalovaný kompilátor GNU GCC. Pokud používáte jiný, změňte proměnnou CC v souboru makefile (makefile.win ve windows). Program se překládá jak pod Windows tak pod GNU/Linux voláním příkazu make v adresáři se zdrojovými kódy. Např.: Stáhnu zdrojové kódy v archivu de_crypt.7z, archiv rozbalím do adresáře de_crypt. Otevřu si příkazovou řádku a příkazem cd
si změním pracovní adresář. Zadám příkaz make a v pracovním adresáři se vytvoří binární spustitelný soubor de_crypt (de_crypt.exe pod Windows)
4.2 Spuštění a obsluha Vstup z parametru Při volání programu se správným parametrem se ve funkci main zavolá fce vstup_z_parametru, která zajistí rozparsování parametru ze zadání do pole znaků pro vstupní řetězec a pro heslo. Jako poslední znak v parametru musí být akce. Příklad spouštění programu s parametrem: jashin@laptop ~/Dokumenty/Vyvoj/Rozpracovane/semestrálka $ ./de_crypt ’1. Clanky zverejnene na techto strankach se casto tykaji jevu ci veci, ’ heslo S Zadání: 1. Clanky zverejnene na techto strankach se casto tykaji jevu ci veci, Heslo: heslo Činnost: S Zašifrované znaky: [XJm8-:7EJFB1>16:1:1J:-J@1/4@;J?@>-:7-/4J?1J/-?@;J@E7 -65J61BAJ/5JB1/5VJ Uložit do souboru? a/*: a Cesta k souboru (max 254 znaků): vystup jashin@laptop ~/Dokumenty/Vyvoj/Rozpracovane/semestrálka $ cat vystup [XJm8-:7EJFB1>16:1:1J:-J@1/4@;J?@>-:7-/4J?1J/-?@;J@E7-65J61BAJ/5JB1/5VJ Vstupní řetězec je vhodné uzavřít do apostrofů, aby shell nevyhodnocoval znaky uvnitř.
8
4.3 Ukázky běhu programu
Činnost programu spuštěného se zadáním v parametru. V případě, že máte celý řetězec parametrů zadaný, stačí zmáčknout enter a program začne pracovat.
9
Toto je výstup programu po jeho volání bez parametrů. Více obrázů najdete v adresáři dokumentace/img/ V případě, že zavoláte program s více než čtyčmi parametry (nesymslné), tak program skončí takto: ERR#1: Příliš mnoho argumentů! Použití: de_crypt "" "" <S|D> Když se stane, že ve vašem PC už nezbývá dostatek volné paměti (používáte příliš novou verzi Windows), vypíše se hláška: ERR#5: Out of memory!
10
5 Závěr 5.1 Výkonnost programu Při (de)šifrování delšího řetězce výkonost závisí především na funkcích pro (de)šifrování. Postupně jsem je zjednodušil asi o 80% řádek a myslím, že lépe už to nedokážu. Výkonnostní testy se neprováděly.
5.2 Kódování zdrojových souborů Všechny zdrojové kódy programu i dokumentace jsou uloženy v kódování UTF-8.
5.3 Důvod využívání menších datových typů Ačkoliv mi učitelé doporučují využívat int, pro přehlednost svý programů využívám takový datový typ, jaký přesně vyhovuje v dané situaci - aby bylo každému, kdo bude číst můj kód jasné, že v proměnné pro řízení na první pohled nekonečného cyklu nebude např. hodnota vyšší než 10. Někdo tvrdí, že využívání datových typů menších než int je pro úsporu paměti zbytečné. Již řadu let vlastním dnes už zastaralý PC IBM T43 a tam char zabírá 1 B v paměti, short 2 B a int 4 B - čili všechny menší datové typy na starších platformách nespotřebovávají velikost intu. A protože mám rád efektivitu, nebudu využívat int tam, kde není potřeba.
5.4 Vysvětlení nestandardních konstrukcí V programu jsem využil nekonečných cyklů. Nekonečné cykly jsou nekonečné proto, že si nemohu být jistý tím, kolikrát se uživatel splete a zadá špatné zadání. V kódu jsem příliš nepoužíval standardní ANSI-C komentáře - při vývoji jsem někdy zakomentovával velké kusy kódu a zakomentovaný komentář ( /* /*komentář */ */ ) se vyhodnotí jako chyba. Proto používám komentáře z C++.
11