70-536 Encrypting and Decrypting Data

Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.

Nie od dziś wiadomo, że dane (szczególnie te poufne) należy zabezpieczać i zapobiec dostaniu się ich w niepowołane ręce. .NET Framework udostępnia nam klasy które pozwalają zaimplementować szyfrowanie symetryczne, asymetryczne, hashing czy też podpis elektroniczny. Spróbujemy dzisiaj omówić sobie po krótce każdy ze sposobów.

Szyfrowanie i deszyfrowanie danych symetrycznie za pomocą klucza 

Kluczowym elementem w tym szyfrowaniu jest klucz. Klucz musi być znany nadawcy do zaszyfrowania informacji jak i odbiorcy który dzięki takiemu kluczowi odkoduje informacje. Spójrzmy na rysunki:

symetryczneKlucz

Kryptografia symetryczna jest bardzo szybka i przystosowana do szyfrowania dużych ilości danych a przy tym bezpieczna. Atakujący musiałbym się posłużyć metodą brute force do generowania kluczy aby zidentyfikować tekst. A wypróbowanie wszystkich możliwych kluczy zajęłoby setki lat jeśli nie dłużej.

Wadą tego rozwiązania jest to, że klucz musi znać odbiorca. Sam klucz nie możemy przesłać zaszyfrowany a jednak nadawca i odbiorca musza się nimi wymieniać. Sztuką polega na tym, żeby system wymiany kluczy był bezpieczny. Poza tym należy pamiętać, że tak jak wskazane jest wymienianie hasła tak i tutaj pamiętajmy o jak najczęstszej wymianie klucza. Rysunek poniżej przedstawia w jaki sposób użytkownicy przekazują klucz jak i zaszyfrowaną informacje przy pomocy różnych mechanizmów komunikacji aby uniknąć przechwycenia informacji. Klucze są przekazywane i używane w sieciach komórkowych, często wysyłane fizycznie poprzez pocztę elektroniczną itd. Po ich ustaleniu nadawca i odbiorca mogą szyfrować i deszyfrować dowolną ilość informacji.

12-3sym

Klasy algorytmów symetrycznych

W większość część kryptograficzną którą oferuję do użycia .NET Framework znajdziemy w przestrzeni nazw System.Security.Cryptography. Przyjrzyjmy się jakie klasy możemy użyć:

RijndaelManaged, AesManaged – dwa podobnie realizujące klasy szyfrowanie wykorzystywane w częściowo zaufanych środowiskach. Różnią pomiędzy nimi jest taka, że AES ma ograniczenie bloku do 128 bit natomiast RijndaelManaged do 256 bit.

DES- Data Encryption Standard korzysta ze stosunkowo krótkiej długości klucza co powoduje, że jest podatny na cracking. Nie jest zalecany do użytku choć jest jeszcze w powszechnym użytkowaniu.

TripleDES – użyto tutaj mechanizmów DES ale można by powiedzieć trzy krotnie co zwiększa bezpieczeństwo. Długość klucza 156 bit z czego skutecznie wykorzystywane do szyfrowania 112.

RC2- wykorzystuje DES natomiast długość klucza jest tutaj określane zmienną.

Wszystkie symetryczne algorytmy mają bazową klasę System.Security.Cryptography.SymmetricAlgorithm po której dziedziczą następujące właściwości:

BlockSize - pobiera lub ustawia rozmiar bloku operacji kryptograficznych w bitach.

FeedbackSize- pobiera lub ustawia rozmiar informacji zwrotnych operacji kryptograficznych w bitach.

IV- pobiera lub ustawia wektor inicjujący (IV) dla symetrycznego algorytmu.

Key- pobiera lub ustawia tajny klucz do symetrycznego algorytmu. Klucze są generowane automatycznie, jeśli nie określono inaczej.

KeySize – pobiera lub ustawia rozmiar klucza w bitach. Domyślnie środowisko uruchomieniowe ustawi go na największy możliwy.

Oraz mniej ważne takie jak LegalBlockSizes, LegalKeySizes, Mode czy Padding której w ogólnie lepiej nie zmieniać.

Ponad to klasy symetryczne mają następujące metody:

CreateDecryptor- aby odszyfrować wiadomość musimy utworzyć obiekt symetrycznego algorytmu i wywołać metodę create która utworzy obiekt ICryptoTransform i pozwoli obiektowi typu CryptoStream odszyfrować strumień.

CreateEncryptor- tworzy “deszyfrator” który potem możemy używać przy pomocy CryptoStream

GenerateIV- ogólnie losuje “IV” ale nie ma potrzeby wywoływać tej metody gdyż IV i tak są losowo ustawiane chyba, że zdefiniujemy inaczej.

GenerateKey - generuje klucz.

ValidKeySize- określa, czy określony rozmiar klucza jest ważny dla obecnego algorytmu i zwraca wartość logiczną.

Jak ustalić symetryczny klucz?

Zanim zaczniemy cokolwiek szyfrować, szyfrujący jak i odkodujący muszą być w posiadaniu tego samego klucza. Poniższy przykład generuje klucz oraz IV przy pomocy statycznego hasła. W rzeczywistości taki hasło powinno być dostarczone poufnie:

   1: // C#
   2: // In practice, the user would provide the password
   3: string password = "P@S5w0r]>";
   4: // Create an algorithm object
   5: RijndaelManaged myAlg = new RijndaelManaged();
   6: // Derive the key and use it to define the algorithm
   7: byte[] salt = Encoding.ASCII.GetBytes("This is my sa1t");
   8: Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt);
   9: myAlg.Key = key.GetBytes(myAlg.KeySize / 8);
  10: myAlg.IV = key.GetBytes(myAlg.BlockSize / 8);
Jak zaszyfrować wiadomość przy użyciu klucza?

Podczas gdy nadawca i odbiorca mają ten sam klucz mogą rozpocząć wymianę informacji. Sam .NET Framework sprawia, że ten proces jest łatwy. W rzeczywistości realizuję się to podobnie jak standartową prace na strumieniach czy plikach. Aby to wykonać musimy wykonać klika kroków:

  1. Stwórz obiekt Stream który wykorzystasz do odczytu lub zapisu informacji
  2. Stwórz SymmetricAlgorithm
  3. Określ klucz i IV
  4. Wywołaj SymmetricAlgorithm.CreateEncryptor () lub SymmetricAlgorithm.CreateDecryptor () aby utworzyć obiekt ICryptoTransform.
  5. Stwórz obiekt CryptoStream
  6. Czytaj i zapisuj dane przy pomocy CryptoStream tak jak przy korzystaniu z normalnego strumienia

Poniższy kod pokazuje jak przeczytać plik C:\Windows\Win.ini, zaszyfrować go a następnie zapisać zaszyfrowany.

   1: // C#
   2: string inFileName = @"C:\Windows\win.ini";
   3: string outFileName = @"C:\Windows\win.ini.enc";
   4: // Step 1: Create the Stream objects
   5: FileStream inFile = new FileStream(inFileName,
   6: FileMode.Open, FileAccess.Read);
   7: FileStream outFile = new FileStream(outFileName,
   8: FileMode.OpenOrCreate, FileAccess.Write);
   9: // Step 2: Create the SymmetricAlgorithm object
  10: SymmetricAlgorithm myAlg = new RijndaelManaged();
  11: // Step 3: Specify a key (optional)
  12: myAlg.GenerateKey();
  13: // Read the unencrypted file into fileData
  14: byte[] fileData = new byte[inFile.Length];
  15: inFile.Read(fileData, 0, (int)inFile.Length);
  16: // Step 4: Create the ICryptoTransform object
  17: ICryptoTransform encryptor = myAlg.CreateEncryptor();
  18: // Step 5: Create the CryptoStream object
  19: CryptoStream encryptStream =
  20: new CryptoStream(outFile, encryptor, CryptoStreamMode.Write);
  21: // Step 6: Write the contents to the CryptoStream
  22: encryptStream.Write(fileData, 0, fileData.Length);
  23: // Close the file handles
  24: encryptStream.Close();
  25: inFile.Close();
  26: outFile.Close();

Szyfrowanie i deszyfrowanie danych asymetrycznie przy użyciu klucza

Szyfrowanie asymetryczne opiera się na parach kluczy. W parze kluczy jeden z nich jest kluczem publicznym drugi prywatnym. Wiadomości zaszyfrowane przy użyciu klucza publicznego można odszyfrować tylko kluczem prywatnym, dzięki czemu każdy może wysyłać zaszyfrowane wiadomości, które może odszyfrować tylko jedna osoba. Rysunek poniżej pokazują proste rozwiązanie szyfrowania asymetrycznego w którym tylko jedna strona komunikacji stanowi klucz publiczny.

12-4asyn

Algorytmy asymetryczne nie są szybsze od symetrycznych, są jednak o wiele bardziej bezpieczne.Algorytmy asymetryczne nie są dobrze przystosowane do szyfrowania dużych ilości danych ze względu na narzut wydajności. Jednym z powszechnych zastosowań asymetrycznego szyfrowania jest szyfrowanie przesyłu klucza symetrycznego i IV. Symetrycznego algorytmu szyfrowania wykorzystuje się następnie do wszystkich wiadomości wysyłanych tam i z powrotem.

Jest to technika używana przez Hypertext Transfer Protocol Secure (HTTPS) i Secure Sockets
Layer (SSL) do szyfrowania komunikacji internetowej- szyfrowanie asymetryczne jest używane tylko
podczas tworzenia sesji. To wspólne połączenie szyfrowania asymetrycznego i symetrycznego pokazuje rysunek poniżej:

12-5asy

Klasy algorytmów asymetrycznych

.NET Framework dostarcza dwóch klas do pracy z szyfrowaniem asymetrycznym i obie są oparte na System.Security.Cryptography.AsymmetricAlgorithm. Klasa ta ma następujące właściwości (niektóre pokrywają się i są identyczne jak w symetrycznym szyfrowaniu):

KeyExchangeAlgorithm- Pobiera nazwę klucza algorytmu wymiany.

KeySize - Pobiera lub ustawia rozmiar w bitach na tajny klucz używany przez algorytm symetryczny. Klucze asymetryczne są znacznie większe niż klucze symetryczne. Przy implementacji algorytmu RSA klucz mają długość od 384 do nawet 16 384 bitów.

Oraz właściwości LegalKeySize i SignatureAlgorithm do której generalnie nie ma potrzeby odwoływać się.

W przeciwieństwie do klasy bazowej SymmetricAlgorithm, bazowa klasa AsymmetricAlgorithm nie ma
użytecznych metod. Funkcjonalność szyfrującą zawarto w wbudowanych dwóch obiektach klasy AsymmetricAlgorithm:

RSACryptoServiceProvider- używany do szyfrowania i deszyfrowania. Jest tak naprawdę realizacją algorytmu RSA.

DSACryptoServiceProvider- służy do cyfrowego podpisywania wiadomości.

Dodatkowo RSACryptoServiceProvider ma własne właściwości:

PersistKeyInCsp- pobiera lub ustawia wartość wskazującą na to czy klucz powinien być trwały w Crypto Service Provider (CSP).

UseMachineKeyStore- pobiera lub ustawia wartość czy klucz powinien być przechowywany w computer’s key czy też w profilu.

Klasa RSACryptoServiceProvider zawiera metody szyfrowania i odszyfrowywania, jak również importu i eksportu kluczy. Poniższa lista zawiera opis każdej z tych metod:

Decrypt, Encrypt – zakoduj, odkoduj dane przy pomocy RSA

ExportParameters- eksportuje strukturę RSAParameters która określa parę kluczy. Ustaw True jeśli ma eksportować zarówno klucz publiczny jak i prywatny lub False jeśli ma eksportować tylko klucz prywatny. 

FromXmlString- importuje parę kluczy z xml

VerifyData- weryfikuje określone podpisane dane przez porównanie ich z podpisem komputerowym dla wymienionych danych.

Oraz VerifyHash, SignData czy SignHash…

Jak eksportować i asymetryczne klucze?

Klucze RSA są znacznie bardziej złożone niż symetryczne klucze szyfrowania. W rzeczywistości, klucze RSA wywoływane są parametrami i są reprezentowane przez strukturę RSAParameters. Prawie zawsze należy wyeksportować klucz publiczny, ponieważ bez klucza publicznego, nikt nie może wysyłać zaszyfrowanej wiadomości do Ciebie. Aby wyeksportować swój klucz publiczny na przykład struktury RSAParamaters, użyj metody RSACryptoServiceProvider.ExportParameters z parametrem false. Przyczyni się to do tego, że zostanie wysłany tylko klucz publiczny. Poniższy kod pokazuję tworzenie instancji algorytmu RSA:

   1: // C#
   2: // Create an instance of the RSA algorithm object
   3: RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider();
   4: // Create a new RSAParameters object with only the public key
   5: RSAParameters publicKey = myRSA.ExportParameters(false);
Jak zaszyfrować dane przy pomocy asymetrycznego szyfrowania?

Pokaże tutaj tylko przykład bo artykuł rośnie a ma być tylko nakreśleniem tematu a nie omawianiem szczegółowym:

   1: // C#
   2: string messageString = "Hello, World!";
   3: RSACryptoServiceProvider myRsa = new RSACryptoServiceProvider();
   4: byte[] messageBytes = Encoding.Unicode.GetBytes(messageString);
   5: byte[] encryptedMessage = myRsa.Encrypt(messageBytes, false);
   6: byte[] decryptedBytes = myRsa.Decrypt(encryptedMessage, false);
   7: Console.WriteLine(Encoding.Unicode.GetString(decryptedBytes));

Validating Data Integrity with Hashes

Innym ważnym wykorzystanie kryptografii jest ochrona integralności danych za pomocą Hashes. Hash jest sumą kontrolną, która jest unikalna dla danego pliku lub części danych.

Hash Algorithms in the .NET Framework

.NET Framework zawiera sześć algorytmów nonkeyed  i dwa algorytmy keyed. Wrzucę ładną tabelkę która wymienia je wraz z opisem i klasą implementującą:

tabelka1

tabelka2

 

Jak obliczać nonkeyed hash?
  1. Stwórzmy obiekt algorytmu haszującego
  2. Wprowadź dane które mają być haszowane do tablicy bajtów
  3. Wywołaj metode HashAlgorithm.ComputeHash
  4. Pobierz tablice bajtów HashAlgorithm.Hash

Realizacja tego w kodzie:

   1: // C#
   2: // Step 1: Create the hash algorithm object
   3: MD5 myHash = new MD5CryptoServiceProvider();
   4: // Step 2: Store the data to be hashed in a byte array
   5: FileStream file = new FileStream(args[0], FileMode.Open, FileAccess.Read);
   6: BinaryReader reader = new BinaryReader(file);
   7: // Step 3: Call the HashAlgorithm.ComputeHash method
   8: myHash.ComputeHash(reader.ReadBytes((int)file.Length));
   9: // Step 4: Retrieve the HashAlgorithm.Hash byte array
  10: Console.WriteLine(Convert.ToBase64String(myHash.Hash));
Jak obliczać keyed hash?
  1. Stwórz tajnego klucz, który jest dzielony pomiędzy wszystkie partie, które będą obliczene lub zweryfikowane
  2. Utwórz obiekt algorytmu haszującego przy użyciu tajnego klucza.
  3. Przechowaj dane w tablicy bajtów
  4. Wywołaj metode KeyedHashAlgorithm.ComputeHash
  5. Pobierz tablice KeyedHashAlgorithm.Hash

Realizacja w kodzie:

   1: // C#
   2: byte[] saltValueBytes = Encoding.ASCII.GetBytes("This is my sa1t");
   3: Rfc2898DeriveBytes passwordKey =
   4: new Rfc2898DeriveBytes(args[0], saltValueBytes);
   5: byte[] secretKey = passwordKey.GetBytes(16);
   6: // Step 2: Create the hash algorithm object
   7: HMACSHA1 myHash = new HMACSHA1(secretKey);
   8: // Step 3: Store the data to be hashed in a byte array
   9: FileStream file = new FileStream(args[1], FileMode.Open, FileAccess.Read);
  10: BinaryReader reader = new BinaryReader(file);
  11: // Step 4: Call the HashAlgorithm.ComputeHash method
  12: myHash.ComputeHash(reader.ReadBytes((int)file.Length));
  13: // Step 5: Retrieve the HashAlgorithm.Hash byte array
  14: Console.WriteLine(Convert.ToBase64String(myHash.Hash));

 

Podpisane pliki

Podpis cyfrowy jest to wartość, która może być dołączona do elektronicznej wymiany danych w celu wykazania, że tworzone dane są stworzone dla kogoś, kto posiada szczególny klucz prywatny. Algorytmy z kluczem publicznym mogą być również wykorzystywane do tworzenia podpisów cyfrowych. Podpisy cyfrowe uwierzytelniają tożsamość nadawcy (jeśli ufasz nadawcy klucza publicznego) i pomagają chronić integralność danych. .NET Framework oferuje dwie klasy do generowania i weryfikowania podpisów elektronicznych:
DSACryptoServiceProvider i RSACryptoServiceProvider. Klasy te korzystają z różnych algorytmów, ale zapewniają podobną funkcjonalność.

Jak wygenerować i zweryfikować podpis cyfrowy dla pliku?

Na koniec kroki wygenerowania oraz weryfikacji podpisu cyfrowego dla pliku oraz realizacja w kodzie.

Generowanie:

  1. Stwórz obiekt algorytmu podpisu cyfrowego
  2. Przechowaj dane w tablicy bajtów
  3. Wywołaj SignData
  4. Eksportuj publiczny klucz

Weryfikowanie:

  1. Stwórz obiekt algorytmu podpisu cyfrowego
  2. Importuj podpis klucza publicznego
  3. Przechowuj dane do weryfikacji w tablicy bajtów
  4. Wywołaj VerifyData
   1: // C#
   2: // Signing Step 1: Create the digital signature algorithm object
   3: DSACryptoServiceProvider signer = new DSACryptoServiceProvider();
   4: // Signing Step 2: Store the data to be signed in a byte array.
   5: FileStream file = new FileStream(args[0], FileMode.Open, FileAccess.Read);
   6: BinaryReader reader = new BinaryReader(file);
   7: byte[] data = reader.ReadBytes((int)file.Length);
   8: // Signing Step 3: Call the SignData method and store the signature
   9: byte[] signature = signer.SignData(data);
  10: // Signing Step 4: Export the public key
  11: string publicKey = signer.ToXmlString(false);
  12: Console.WriteLine("Signature: " + Convert.ToBase64String(signature));
  13: reader.Close();
  14: file.Close();
  15: // Verifying Step 1: Create the digital signature algorithm object
  16: DSACryptoServiceProvider verifier = new DSACryptoServiceProvider();
  17: // Verifying Step 2: Import the signature and public key.
  18: verifier.FromXmlString(publicKey);
  19: // Verifying Step 3: Store the data to be verified in a byte array
  20: FileStream file2 = new FileStream(args[0], FileMode.Open, FileAccess.Read);
  21: BinaryReader reader2 = new BinaryReader(file2);
  22: byte[] data2 = reader2.ReadBytes((int)file2.Length);
  23: // Verifying Step 4: Call the VerifyData method
  24: if (verifier.VerifyData(data2, signature))
  25: Console.WriteLine("Signature verified");
  26: else
  27: Console.WriteLine("Signature NOT verified");
  28: reader2.Close();
  29: file2.Close();

Tyle na dzisiaj…trochę mi się wydłużyło dlatego na koniec już całkowicie ogólnie zrobiłem. Do piątku!!

Kolejny artykuł z serii to 70-536: Using COM Components from the .NET Framework

Tagi: , ,

Pingbacks and trackbacks (2)+

Add comment




  Country flag
biuquote
  • Comment
  • Preview
Loading


Eastgroup.pl na facebooku