KRYPTOGRAFIA I OCHRONA DANYCH PROJEKT

KRYPTOGRAFIA I OCHRONA DANYCH PROJEKT Temat: Zaimplementować system kryptografii wizualnej http://www.cacr.math.uwaterloo.ca/~dstinson/visual.html A...
Author: Feliks Paluch
7 downloads 2 Views 484KB Size
KRYPTOGRAFIA I OCHRONA DANYCH PROJEKT

Temat: Zaimplementować system kryptografii wizualnej http://www.cacr.math.uwaterloo.ca/~dstinson/visual.html

Autor: Tomasz Mitręga NSMW Grupa 1 Sekcja 2

1. Temat projektu Zrealizować program pozwalający na tworzenie dwóch obrazów które podzielone przypominają szum, a po złożeniu tworzą czytelną wiadomość. Program powinien pozwalać na połączenie obu obrazów w celu odczytania zakodowanej wiadomości. Odczytanie z jednego obrazu nie powinno być możliwe. Dla każdego piksela generowana będzie losowo z prawdopodobieństwem 0,5 jedna z dwóch możliwych jego reprezentacji w bitmapach wyjściowych. Pozwoli to na zagwarantowanie niemożności odczytania ukrytej informacji na podstawie tylko jednej bitmapy. Program powinien przekształcać monochromatyczne pliki map bitowych.

2. Analiza rozwiązania Kryptografia wizualna jest sposobem takiego zakodowania obrazu monochromatycznego lub tekstu aby po podziale obrazu treść w nim zapisana nie była możliwa do odczytania. Po poprawnym połączeniu dwóch obrazów bez większej trudności zawartość dało była zrozumiała. Algorytm zaimplementowany przeze mnie został po raz pierwszy zaprezentowany przez Moni Naor i Adi Shamir na międzynarodowej konferencji EUROCRYPT w 1994 roku. Polega on na podziale obrazu wejściowego na dwa obrazy wyjściowe. Każdy piksel z obrazu źródłowego jest dzielony na 2 subpiksele. Jeśli wybrany piksel w obrazie wejściowym ma kolor biały to zostaje on podzielony na 2 subpiksele i z prawdopodobieństwem 0,5 wybierana jest kombinacja czarnybiały, czarny-biały lub biały-czarny, biały-czarny jeśli jednak piksel jest czarny wybierane są piksele czarny-biały, biały-czarny lub biały-czarny, czarny-biały. Zależności między pikselami przedstawia poniższa tabelka. Pixel

Prawdopodobieństwo P = 0,5

Piksel w obrazie 1

Piksel w obrazie 2

Piksele po połączeniu

P = 0,5

P = 0,5 P = 0,5

Złączenie obrazów polega na wpisaniu w miejsca białych pikseli z obrazu pierwszego czarnych pikseli z obrazu drugiego.

3. Przykład działania programu Na poniższych ilustracjach został przedstawiony program podczas działania.

Rysunek 1 Zakodowany rysunek

Powyższy rysunek przedstawia oryginalny obraz oraz obrazy utworzone poprzez zastosowanie zaimplementowanego algorytmu.

Rysunek 2 Rysunek po odkodowaniu

Rysunek 2 przedstawia wygenerowane w poprzednim kroku obrazy po ich połączeniu. W programie mamy możliwość oczyszczenia obrazu ze zbędnych czarnych pikseli, oraz zapisania obrazu wynikowego do pliku.

4. Opis algorytmu Algorytm tworzenia zakodowanych map bitowych. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

public void makecrypto() { Bitmap b1 = new Bitmap(src.Width + (src.Width % 2), src.Height); //pierwsza bitmapa wynikowa Bitmap b2 = new Bitmap(src.Width + (src.Width % 2), src.Height); //druga bitmapa wynikowa Random r = new Random(); // Random słuŜący do losowania liczby int rand = -1; // Losowanie liczby 1 lub 0 z prawdopodobieństwem 1/2 this.form.Invoke(this.form.startth, null); for (int i = 0; i < src.Width; i += 2) //przechodzimy po co drugim pikselu bitmapy Ŝródłowej (szerokość) { for (int j = 0; j < src.Height; j++) //przechodzimy po kaŜdym pikselu bitmapy Ŝródłowej (wysokość) { rand = r.Next(2); //losujemy liczbę if (src.GetPixel(i, j).ToArgb() == Color.White.ToArgb()) //jeśli pobrany piksel jest biały { if (rand == 0) // w zaleŜności od wylosowanej liczby ustawiamy piksele

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

{ b1.SetPixel(i, j, Color.Black); b1.SetPixel(i + 1, j, Color.White); b2.SetPixel(i, j, Color.Black); b2.SetPixel(i + 1, j, Color.White); } else { b1.SetPixel(i, j, Color.White); b1.SetPixel(i + 1, j, Color.Black); b2.SetPixel(i, j, Color.White); b2.SetPixel(i + 1, j, Color.Black); }

//w //w //w //w

//w //w //w //w

obrazie obrazie obrazie obrazie

obrazie obrazie obrazie obrazie

} else //jeśli piksel w obrazie zródłowym jest czarny { if (rand == 0) //wylosowana liczba jest 0 { b1.SetPixel(i, j, Color.Black); //w obrazie b1.SetPixel(i + 1, j, Color.White); //w obrazie b2.SetPixel(i, j, Color.White); //w obrazie b2.SetPixel(i + 1, j, Color.Black); //w obrazie } else { b1.SetPixel(i, j, Color.White); //w obrazie b1.SetPixel(i + 1, j, Color.Black); //w obrazie b2.SetPixel(i, j, Color.Black); //w obrazie b2.SetPixel(i + 1, j, Color.White); //w obrazie } }

1 1 2 2

i na czarny i+1 na biały i na czarny i+1 na biały

1 1 2 2

i na biały i+1 na czarny i na biały i+1 na czarny

1 1 2 2

i na czarny i+1 na biały i na biały i+1 na czarny

1 1 2 2

i na biały i+1 na czarny i na czarny i+1 na biały

} this.form.Invoke(form.prg, new Object[] { ((int)(((double)i / (double)(b1.Width - 1)) * 100)) }); } this.form.Invoke(this.form.endGenerateBitmap, new Object[] { pb1, b1 }); this.form.Invoke(this.form.endGenerateBitmap, new Object[] { pb2, b2 }); this.form.Invoke(this.form.endth); }

W pierwszej kolejności tworzone są dwie puste bitmapy o wysokości takiej jak wejściowa bitmapa oraz szerokości bitmapy wejściowej która została zaokrąglona do parzystości. Następnie tworzony jest obiekt klasy random który będzie służył do losowania 1 lub 0. Ponieważ aplikacja została napisana jako wielowątkowa w następnym kroku informujemy nasz wątek w którym uruchomiana jest aplikacja o rozpoczęciu procesu tworzenia obrazów. W pętlach przechodzimy pożytych pikselach na szerokość obrazu oraz po każdym pikselu na wysokość bitmapy. Jeśli wybrany piksel z obrazu wejściowego ma kolor biały wtedy sprawdzamy która liczba została wylosowana. Jeśli wylosowana liczba to 0 ustawione są piksele czarny i biały w obu obrazach, w przeciwnym wypadku ustawiane są piksele biały i czarny. Jeśli natomiast wybrany piksel w obrazie źródłowym ma inny kolor(czarny) następuje ustawienie piksele w zależności od wylosowanej liczby czarny biały(obraz pierwszy), biały czarny(obraz drugi) lub jeśli zostaje wylosowana jedynka biały czarny(obraz pierwszy),czarny biały(obraz drugi). W czasie działania pętli przy każdym przejściu pętli szerokości następuje przesłanie stanu do wątku głównego. Po zakończeniu algorytmu przesyłamy do wątku głównego dwie wynikowe bitmapy oraz informacje o zakończeniu algorytmu. 1 2 3 4 5

public void ovarlayimage() { this.form.Invoke(this.form.startth, null); for (int i = 0; i < b.Width; i++) {

6 7 8 9 10 11 12 13 14 15 16 17

for (int j = 0; j < b.Height; j++) //dla kaŜdego piksela w obrazie 1 { if (b.GetPixel(i, j) == Color.FromArgb(255, 255, 255, 255)) //sprawdzamy czy kolor aktualnego piksela jest biały { b.SetPixel(i, j, b2.GetPixel(i, j)); //jeśli tak w jego miejsce wstawiamy piksel z obrazu drugiego } } this.form.Invoke(form.prg, new Object[] { ((int)(((double)i / (double)(b.Width - 1)) * 100)) }); } this.form.Invoke(this.form.endGenerateBitmap, new Object[] { pb, b }); this.form.Invoke(this.form.endth); }

Dekodowanie obrazu polega na wstawieniu w miejsca białych pikseli w obrazie pierwszym czarnych obrazów z obrazu drugiego. Jednak w celu przyspieszenia w powyższym algorytmie sprawdzamy jedynie czy wybrany piksel jest biały i jeśli tak jest w jego miejsce wstawiany jest piksel z obrazu drugiego. Kod rozpoczyna się od poinformowania wątku głównego o rozpoczęciu, następnie dla każdego piksela wykonywany jest algorytm. Dla każdego piksela na wysokość zostaje obliczony procent postępu. Po zakończeniu algorytmu wykonywana jest metoda endGenerateBitmap która to wyświetla w odpowiednim PictureBox-ie wynikową bitmapę. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

public void clear() { this.form.Invoke(this.form.startth, null); if (b != null) { Bitmap bw = new Bitmap(b.Width + (b.Width % 2), b.Height); //wynikowa bitmapa zaokrąglaona do szerokości parzystaj for (int i = 0; i < b.Width; i += 2) //tylko parzyste piksele szerokości { for (int j = 0; j < b.Height; j++) //wszystkie piksele wysokości { //jeśli wybrany piksel oraz piksel i+1 są czarne w obrazie wynikowym pozostają one czarne if ((b.GetPixel(i, j) == Color.FromArgb(255, 0, 0, 0)) && (b.GetPixel(i + 1, j) == Color.FromArgb(255, 0, 0, 0))) { bw.SetPixel(i, j, Color.FromArgb(255, 0, 0, 0)); bw.SetPixel(i + 1, j, Color.FromArgb(255, 0, 0, 0)); } else { //w przeciwnym wypadku zmieniamy ich kolor na biały bw.SetPixel(i, j, Color.FromArgb(255, 255, 255, 255)); bw.SetPixel(i + 1, j, Color.FromArgb(255, 255, 255, 255)); } } this.form.Invoke(form.prg, new Object[] { (int)(((double)i / (double)(b.Width - 1)) * 100) }); } this.form.Invoke(this.form.endGenerateBitmap, new Object[] { p, bw }); } this.form.Invoke(form.endth, null); }

Metoda służy do usunięcia zbędnych czarnych pikseli znajdujących się w bitmapie wynikowej. Jeśli piksel parzysty oraz nieparzysty mają kolor czarny oznacza to że należy pozostawić je czarne, w przeciwnym wypadku w bitmapie wynikowej zmieniamy ich kolor na biały.

1 2 3 4 5 6 7 8 9 10

11 12 13 14 15 16 17 18 19 20 21 22 23 24

public void makebw() { this.form.Invoke(this.form.startth, null); if (b != null) //sprawdzamy czy mamy jakąs bitmape w b { for (int i = 0; i < b.Width; i++) //dla wszystkich pikseli w obrazie { for (int j = 0; j < b.Height; j++) { if ((b.GetPixel(i, j).R > f) || (b.GetPixel(i, j).G > f) || (b.GetPixel(i, j).B > f)) //sprawdzamy czy piksel ma którąkolwiek składową większą od f { b.SetPixel(i, j, Color.White); //jeśli tak wynikowy kolor ustawiamy na biały } else { b.SetPixel(i, j, Color.Black); //w przeciwnym wypadku ustawiony zostaje na czarny } } this.form.Invoke(form.prg, new Object[] { (int)(((double)i / (double)(b.Width - 1)) * 100) }); } this.form.Invoke(this.form.endGenerateBitmap, new Object[] { p, b }); } this.form.Invoke(form.endth, null); }

Metoda służy do zamieniania obrazów kolorowych na obrazy monochromatyczne. Algorytm działania polega na sprawdzeniu czy którykolwiek ze składowych jest większy od wybranej przez użytkownika wartości f. Jeśli tak w obrazie wyjściowym ustawiany jest piksel o kolorze białym w przeciwnym wypadku ustawiamy kolor czarny. Następnie po zakończeniu algorytmu wyświetlamy wynikową bitmapę w odpowiednim PictureBox-ie.

5. Testowanie oprogramowania Testowanie programu jest utrudnione, ponieważ algorytm wykorzystuje czynnik losowy, dlatego otrzymywane wyniki nigdy nie są takie same. Testowanie rozpoczynamy od sprawdzenia poprawności przekształcenia obrazu kolorowego na obraz monochromatyczny, w tym celu klikamy na przekształć obraz, a następnie wybieramy klikamy otwórz.

Bitmapa wejściowa

Bitmapa wyjściowa

Powyższy obrazek został poprawnie przekształcony. Następnie sprawdzamy poprawność algorytmu algo kryptografii wizualnej generującego dwie bitmapy wynikowe. Zostały one przedstawione poniżej. Pierwsza bitmapa wynikowa

Druga bitmapa wynikowa

Niestety z powyższych obrazów trudno cokolwiek odczytać. Jednak po ich nałożeniu na siebie otrzymujemy następujący obraz::

Obraz po nałożeniu

Obraz po wyczyszczeniu zbędnych czarnych pikseli

6. Wnioski Algorytm wizualnej kryptografii nie okazał się trudny w implementacji, dlatego postanowiłem nieco rozbudować moją aplikację między innymi o możliwość przekształcania obrazów kolorowych kolor na obrazy monochromatyczne, które są w nim wymagane. Dodatkowo aplikacja została rozwinięta o możliwość czyszczenia bitmap wyjściowych ze zbędnych czarnych pikseli. Z uwagi jednak na fakt, że algorytm bierze pod uwagę jedynie piksele parzyste aby zachować za rozmiar obrazu wejściowego z wyjściowym obraz oryginalny różni się od obrazu wyjściowego. Założenie dla którego algorytm został utworzony zostaje zachowane, a mianowicie nie posiadając obu obrazów wynikowych nie powinno dać się odczytać zaszyfrowanejj wiadomości, wiadomości a po ich połączeniu zakodowana informacja powinna być czytelna.