Programujeme v jazyku C# - Diel 25. - Šifrovanie I.

Michal Čižmár  /  11. 05. 2005, 00:00

Tento diel je podľa mňa veľmi zaujímavý. Ak ste už niekedy počuli o Hashovaní (hešovaní) tak si ho určite prečítajte. Uvidíte, že sa v C# hash dá veľmi jednoducho realizovať aj bez hlbokých znalostiach o ňom. Použijeme aj to čo sme sa naučili o súboroch v C#.

>> Čo je to hash?
Hash môžeme chápať ako akýsi druh šifrovania aj keď nie je vhodný na šifrovanie napr. súborov. Hash algoritmus má viac modifikácií rozlišujúci sa počtom bytov aký má výsledný kód. V príklade dole využívam SHA256, ale existuje aj SHA1 priamo implementovaný v C#. Už je Vám asi jasné, že je tým aj ovplyvnená bezpečnosť šifrovania.

Hash algoritmus je založený na jednosmernom šifrovaní. To znamená, že na základe toho istého vstupu vygeneruje vždy ten istý výstup, ale spätný algoritmus neexistuje. Dôležité je aj to, že ak použijeme napr. výstup SHA256 je vždy 32 bytov nezávisle na tom aký dlhý bol vstup ( z toho vyplýva aj neexistencia spätného algoritmu) . Existuje aj naozaj veľmi malá pravdepodobnosť, že rôzne vstupy dajú ten istý výstup, ale to môžeme zanedbať. Hash sa dá prelomiť len metódou BruteForce t.j. postupným skúšaním všetkých kombinácií.

>>Ako sa používa hash?

Ako príklad môžeme použiť spôsob ukladania hesiel v UNIX-e alebo Windowse . Pri vytváraní účtu užívateľ zadá svoje heslo, to sa zahešuje a zapíše na disk. Hash sa tu využíva preto, že by bolo určite nerozumné zapísať heslo na disk v priamej forme. Dokonca aj klasické šifrovanie neposkytuje dostatočnú bezpečnosť pri ukladaní hesiel, pretože by sa mohlo stať, že by nikto ukradol algoritmus použitý v danom operačnom systéme a vyrobiť spätný algorimus už nie je až tak zložité.

>>Ako sa overuje hash?

Keď už je heslo zapísané na disku v hash forme, pri nasledujúcom prihlásení užívateľa sa operačný systém spýta na heslo. Následne vytvorí jeho hash a porovná ho s hashom zapísaným na disku, využívajúc podstatu hashu, že rovnaký vstup dá vždy rovnaký výstup.

Napr:
Vstup : CSharp
Výstup : 0.uo¦u¨ZÔcéEˇ/ ?ynúέTí>/[?Z+?+Ö
Vstup : M
Výstup : üüÔiëä;¤¦Ë??¦¨Ico0›Î?5z.#\ë¦Ü"iG
Vstup : m
Výstup : ^sU+˘äNölyHu=>?cáaai¶ë¨¦>d(¦óLäE
-
Tie všelijaké znaky dostaneme, keď výstup reprezentujeme ako pole bytov - môžeme dostať všetky možné znaky z ASCII tabuľky. V príkladu dole to môžete dosiahnuť tiež, keď pri výpise vymažete konverziu na číslo (int) .

>>Ako sa programuje algorimus hashu?

Keď budete veľmi chcieť nájdete o algoritme hashu veľa stránok na internete. Nie je to až také ťažké na pochopenie. Prečo vám to, ale tu nevysvetlím ? Pretože, ako ste už určite zistili, výpočet hashu je priamo implementovaný v C#.

>>Aké funkcie sú na hash v jazyku C#?

1. najprv si vytvoríme pomocnú triedu (môže byť aj typu SHA1)
SHA256Managed SHhash = new SHA256Managed();


2. Potom jej jednoducho pošleme pole bytov cez metódu ComputeHash()
zakodovanyHash = SHhash.ComputeHash(MessageBytes);


3. Výstupom je v našom prípade vždy pole bytov o dĺžke 32.

4. Pretože bežne s textom pracujeme pomocou stringov a nie cez pole bytov,
môžeme použiť ešte pomocnú konverziu :
UnicodeEncoding UE = new UnicodeEncoding();
byte[] MessageBytes = UE.GetBytes(heslo);


>>Konkrétna realizácia
Príklad 25.1


//------------------------------------------------------
using
System;
using
System.Text; // pre triedu UE
using
System.Security.Cryptography; // RSA256
using
System.IO; // subory

class
Hasch
{
   static void Main()
  {
       byte [] zakodovanyHash;
       string heslo;

       // Nacitanie hesla
       Console.Write(" Zadajte heslo:");
       heslo = Console.ReadLine();

       // Vytvorenie hashu
       UnicodeEncoding UE = new UnicodeEncoding();
        byte[] MessageBytes = UE.GetBytes(heslo);
        SHA256Managed SHhash = new SHA256Managed();
        zakodovanyHash = SHhash.ComputeHash(MessageBytes);
   
        // Vypisanie hashu vo forme znakov
        Console.WriteLine(" Hash kod hesla je :");
        foreach(char znak in zakodovanyHash) Console.Write("{0}", (int)znak);

        // hash256 je dlhy 32 bytov vzdy!!!
       Console.WriteLine("= {0}",zakodovanyHash.Length);

        // ak subor z heslom neexistuje
       bool test;
       if ( (test=File.Exists("password.txt"))==false)
       {
//zapisanie do suboru
             Console.WriteLine(" Zapisujem heslo do suboru ...");
             FileStream fs = new FileStream("password.txt", FileMode.Create);
             BinaryWriter bw = new BinaryWriter(fs);
             bw.Write(zakodovanyHash,0,zakodovanyHash.Length);
             bw.Close();
             fs.Close();
        }
        else //ak subor s heslom existuje
       {
             Console.WriteLine(" Testujem heslo..");
             //Nacitanie hashu so suboru
             byte [] hashNaOverenie;
             FileStream fs = new FileStream("password.txt", FileMode.Open);
             BinaryReader br = new BinaryReader(fs);
             hashNaOverenie= br.ReadBytes(32); // pri hash256
            br.Close();
            fs.Close();
 
           // test zhody
           bool zhoda = true;
           for(int i =0; i< 32; i++)
               if (zakodovanyHash[i]!=hashNaOverenie[i])
                    zhoda=false;

           if (zhoda==true)
                 Console.WriteLine(" Spravne heslo!!");
           else Console.WriteLine(" Heslo je nespravne");
      }

       Console.ReadLine();
   }
}

//-----------------------------------------------------
Spustiteľný program : www.inet.sk/download/user/SHA256.exe 
Celý projekt: www.inet.sk/download/user/Priklad25.1_SHA256.zip

Myslíme, že príklad je z predchádzajúcim vysvetlením a dostatočným okomentovaní úplne jasný, ak nie kľukne napíšte otázku do diskusie.

>>Čo bude nabudúce?
Záleží na Vašich ohlasoch k tomuto článku. Ak Vás zaujme, dali by sem ešte klasické šifrovanie, inak by bol ďalší článok o funkciách, len stručne, bez znalostí objektového prístupu.

>>Predchádzajúce diely
Programujeme v jazyku C# - Diel 24. - Súbory IV.
Programujeme v jazyku C# - Diel 23. - Súbory III.
Programujeme v jazyku C# - Diel 22. - Súbory II .
Programujeme v jazyku C# - Diel 21. - Súbory I .

Michal Čižmár







Neprehliadnite: