Kódování a dekódování Base64
(2015)
Teorie k realizaci Base64 dekodéru:
Base64 je
formát pro uložení binárního souboru tak, aby výsledný textový soubor
obsahoval pouze základní tisknutelné znaky. (Je využito např. u
příloh v emailu, kde je při odesílání podporován pouze textový způsob
komunikace tj. 7bit ASCII).
Vaším úkolem je implementovat dekodér formátu Base64 a pomocí něj rozkódovat připravenou zprávu. Při řešení úkolu si procvičíte práci s řetězci, operace bitového posuvu a bitového maskování.
Popis formátu Base64:
Formát kóduje vždy 3
osmibitové znaky/bajty na 4 znaky z množiny 64 znaků, proto Base64.
Množina 64 znaků obsahuje tyto znaky:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
Předchozí řádek (převodní pole pro znaky) slouží k převodu přijatého znaku na index = pozice znaku v tomto řádku. Nebo pro převod indexu na výstupní znak.
Princip kódování popisuje nákres níže, kde jsou vždy 3 osmibitové znaky původní zprávy rozděleny na 4 skupiny po 6 bitech. Jednotlivé skupiny po 6 bitech (tj. 64 kombinací) potom představuji vždy index do základní Base64 množiny, ze které je následně vybrán znak na pozici indexu.
Vstupní zpráva (tři 8bitové hodnoty):
X7X6X5X4X3X2X1X0 |
Y7Y6Y5Y4Y3Y2Y1Y0 |
Z7Z6Z5Z4Z3Z2Z1Z0 |
Výsledná zakódovaná zpráva (čtyři 6bitové hodnoty, následně převedené na čtyři znaky Base64):
X7X6X5X4X3X2 |
X1X0Y7Y6Y5Y4 |
Y3Y2Y1Y0Z7Z6 |
Z5Z4Z3Z2Z1Z0 |
Zakončovací
(zarovnávací) sekvence:
Vstupní (kódovaný) soubor
je vždy čten po 3 znacích (bajtech) a na výstup jsou vždy odeslány 4
znaky. Proto je třeba pro soubory délky nedělitelné bezezbytku třemi,
doplnit na vstupní straně chybějící znaky (doplňuje se vždy znak s
hodnotou \0) a na výstupní straně
odlišit doplněné znaky od původních (znak =). Tímto je zajištěno, že
správně zakódovaná zpráva má počet znaků vždy dělitelný čtyřmi a
zároveň je možné určit přesnou velikost původního souboru.
Příklady koncového zarovnání na výstupní délku čtyř znaků v případě chybějících bajtů na vstupu:
Vstup (pouze jedna 8bitová hodnota / bajt):
X7X6X5X4X3X2X1X0 |
Výstup (dvě 6bitové hodnoty převedené na Base64 znaky a dva doplňující znaky =):
X7X6X5X4X3X2 |
X1X00 0 0 0 |
= |
= |
Vstup (pouze dvě 8bitové hodnoty / bajty):
X7X6X5X4X3X2X1X0 |
Y7Y6Y5Y4Y3Y2Y1Y0 |
Výstup (tři 6bitové hodnoty převedené na Base64 znaky a jeden doplňující znak =):
X7X6X5X4X3X2 |
X1X0Y7Y6Y5Y4 |
Y3Y2Y1Y00 0 |
= |
Zadání base64 dekodér:
Sestavte program v
jazyce C, který správně rozkóduje zadaný textový soubor.
1. Navrhněte strukturu funkcí programu, včetně kontrol.
2. Navrhněte a implementujte funkci pro převod znaku Base64 na jeho index v množině povolených znaků (při výskytu nepovoleného znaku generujte chybové hlášení).
3. Navrhněte a implementujte funkci pro dekódování (čtveřice 6bitových znaků na 3 osmibitové).
4. Využijte tuto funkci při postupné konverzi vstupního souboru.
5. Ošetřete chybové stavy (špatná délka vstupu, chybný znak ...).
6. Ověřte, že daný program umožňuje dekódovat i zakódované binární soubory.
Postup práce (doporučení):
Nesnažte se
naprogramovat vše najednou. Postupujte po částech.
Na papír si vyřešte převod pro první čtveřici znaků
testovacího textu
Vstupní znaky |
'...' |
'...' |
'...' |
'...' |
||||||||||||||||||||
Pozice znaku v převodním poli (dekadicky/hexa) |
I1: |
I2: |
I3: |
I4: |
||||||||||||||||||||
Pozice binárně |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Převod šestic na osmice |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Osmice hexa/dekadicky
|
O1: |
O2: |
O3: |
Napište funkci na převod z binárních šestic (pole čtyř znaků
– v počítači uložené v osmi bitech) do osmic (pole tří
osmibitových znaků)
Realizace polí v paměti (nuly ze vstupního
řádku se při přesunu do výsledku „vypouští“).
Vstup I (4x8
bitů) |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
Výstup O
(3x8bitů) |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
Pro binární operace používejte bezznaménkové typy. Pro práci se
znaky použijte nejmenší celočíselný datový typ.
Ve funkci
používejte operátory bitového posunu (doprava a doleva) o daný počet
znaků – pro unsigned typy se při posunu doplňují nuly. Dále
používejte operátory bitového součtu a součinu (OR a AND).
Napište
si na papír jak se vytvoří výstupní data (O1, O2, O3) v závislosti
na vstupních datech (I1,I2,I3,I4) pomocí binárních operátorů jazyka
C a pro ověřte zda funguje pro první čtveřici znaků. (Například
první výstup O1 (šedá) má na třetím bitu zprava první bit I1 (žlutá)
– I1 je tedy nutné posunout tak aby se její první bit objevil
na třetí pozici. Dále jsou v O1 na prvních dvou bitech bity 6 a 5 I2
(oranžová), je tedy nutné I2 posunout tak, aby se bity 6 a 5
objevili na pozici 2 a 1).
Možná hlavička funkce: int Prevod(
datový_typ Input[4], datový_typ Output[3])
Ve funkci main
si vytvořte pole o čtyřech znacích, do kterého vložíte (pro účely
testování) hodnoty z druhého řádku tabulky z bodu 1. Dále vytvořte
pole pro uložení výsledku. Zavolejte funkci Prevod s těmito
poli a překontrolujte zda převod proběhl správně.
V jazyce C se
volající a volaná funkce „dělí“ o předané pole –
změny provedené v poli ve volané funkci se proto objeví i ve funkci
volající.
Funkce main s ukázkami volání bude v souboru
base64main.c, funkce budou v souboru fbase64.c a
příslušné hlavičky v fbase64.h.
Napište funkci, která zjistí (a vrátí) pozici předaného znaku
v převodním poli. Možná hlavička funkce: datový_typ
Pozice(datový_typ PrevadenyZnak).
Řešení je možné
dvojí:
První řešení: vytvoří se pole znaků, které se naplní
převodním polem. Pomocí cyklu se postupně srovnává PrevadenyZnak
se znakem v poli. Při souhlasu znaků jsme zjistili pozici znaku v
poli a to je návratová hodnota. Toto řešení je programově jednoduché
ale při provádění je časově náročné.
Druhé řešení vychází z toho,
že v převodním poli jsou bloky za sebou jdoucích znaků a tedy převod
pro velká písmena může vypadat takto:
if (PrevadenyZnak je velké
písmeno) return (PrevadenyZnak – 'A');
Obdobně
provedeme převod i pro malá písmena a číslice s tím, že malá písmena
začínají na pozici off = 'Z'-'A'+1 (na této pozici je malé
a).
Problém by mohl tvořit vyplňovací/ukončovací znak '='. Pokud
by jeho ASCII hodnota ležela v intervalu pozic písmen tabulky (do
hodnoty 64), musí být převeden na hodnotu větší než 64 (například
254).
Ve funkci main zavolejte tuto funkci postupně pro první
čtyři znaky a výsledky uložte tak, aby byly připraveny jako vstupní
parametr pro funkci z bodu 2). Ověřte zda funguje.
Při tvorbě je
možné se inspirovat zde.
Po odladění první čtveřice následuje (pokus o) převod celého textu. Vytvořte si pole, do kterého vložíte testovací řetězec znaků (při kopírování řetězce z těchto stránek odstraňte formátovací znaky (které se projeví jako (skryté) mezery v textu, a převeďte celý text na jeden řádek). Napište cyklus, ve kterém budete ze vstupního řetězce brát čtveřice znaků (, které po převodu pomocí funkce z bodu 3) překopírujete do pole, které je použité jako pole vstupních parametrů funkce z bodu 2)). Postupně převeďte všechny čtveřice vstupního textu. Výsledek převodu vytiskněte na konzolu.
Funkci Prevod z bodu 2) upravte/doplňte tak, aby převáděla i poslední čtveřici. To znamená, že pokud je posledním znakem rovná se, převedou se pouze dva znaky a pokud jsou na konce dvě rovná se, převede se pouze jeden znak. Návratová hodnota funkce potom může značit kolik znaků bylo převedeno.
Budete-li mít čas, naprogramujte i kodér Base64.
Testovací zpráva:
Využijte soubor získaný na
adrese:
http://www.uamt.feec.vutbr.cz/~petyovsky/vyuka/bppc/base64/base64_message.php
Případně testovací text:
KiogVG90byBqZSB6YWtvZG92YW5hIHpwcmF2YSAqKgpQb2t1ZCBqc2kgamkgc3ByYXZuZSByb3prb2Rv
dmFsLCByZWtuaSBuYWhsYXM6CiJIZWxlIHZlbmt1IHByc2k/IgoqKiogS29uZWMgenByYXZ5ICoqCg==
Literatura:
http://cs.wikipedia.org/wiki/Base64
http://en.wikipedia.org/wiki/Base64
Poslední úpravy 2015-03-11