Browsing Category

imagesharp

Daj Się Poznać 2017 dotnetcore imagesharp steganography

StegoCore – 10 tydzień. Koniec konkursu DSP i duże podsumowanie!

Minęło właśnie 10 tygodni prac nad projektem StegoCore w konkursie Daj Się Poznać. Jest to wiec ostatni tydzień i tym samym koniec konkursu. Ale zanim podsumuje cały projekt, czas na to co udało mi się zrobić w ostatnim tygodniu.

Co słychać?

  • Zaimplementowałem metodę odczytu ukrytej informacji w algorytmie Zhao&Koch
  • Napisałem testy sprawdzające możliwość odczytu ukrytej informacji – niestety wyniki nie są zadawalające; jest wiele przekłamań w odczytywanych bitach, co powoduje brak możliwości poprawnego odczytu danych. Wydaje mi się, że nie popełniłem żadnych błędów podczas implementacji, więc ciężko mi wywnioskować gdzie szukać błędu. Będę musiał dokładnie przeanalizować algorytm ukrywania i odczytu.
  • Zaktualizowałem aplikację webową dostępną pod adresem: http://pawelskaruz.pl:8080/

Co dalej?

  • Muszę przede wszystkich przetestować/przedebugować algorytm Zhao&Koch, aby dowiedzieć się dlaczego otrzymuje przekłamane bity podczas odczytywania.
  • Chciałbym poprawić aplikację webową StegoCoreWeb, wyłapać wyjątki z biblioteki StegoCore i przekazać odpowiednie komunikaty użytkownikowi

Podsumowanie konkursu

Przede wszystkim jestem zadowolony, że przez 10 tygodni udało mi się rozwijać projekt. Niestety wszystkie cele nie zostały osiągnięte. Na koniec konkursu chciałem zaimplementować 3 algorytmy i umieścić bibliotekę w menadżerze NuGet. Tak, jak wspominałem wcześniej, koniec konkursu nie oznacza końca prac nad projektem.

Gdy tylko uporam się z algorytmem Zhao&Koch, umieszczę bibliotekę StegoCore w NuGet. Dalej oczywiście będę rozwijał samą bibliotekę, jak i aplikację webową. Myślę tutaj o zaimplementowaniu własnego algorytmu ukrywania danych opartego na Wet Paper Codes.

Nie jestem za bardzo zadowolony z tylko 27 commitów, ale muszę wziąć pod uwagę fakt, iż mam tendencję to wrzucania wielu rzeczy na raz. Jest to jedna z kilku rzeczy, które muszę poprawić w swojej pracy. Commity nie powinny zawierać, aż tylu zmian w projekcie, a dotyczyć tylko jednej konkretnej zaimplementowanej/poprawionej rzeczy. Dzięki konkursowi nauczyłem się (a przynajmniej jestem świadomy, że muszę nad tym pracować 🙂 ) również innej, bardzo ważnej rzeczy – systematyczności. O wiele lepiej jest codziennie pracować nad projektem niż usiąść po kilku dniach przerwy i siedzieć wiele godzin przed komputerem.

Podczas prac nad StegoCore dosyć dobrze zapoznałem się z .NET Core. Jest to mój pierwszy projekt z użyciem tego frameworka, ale myślę że jak na pierwszy raz nie było tak źle. Do przeprowadzania operacji na zdjęciach użyłem biblioteki ImageSharp. Pomimo tego, że jest ona wciąż w fazie alpha, korzystało się z niej wygodnie i bez większych problemów.

W ramach Daj Się Poznać pisałem cotygodniowe podsumowania projektu, ale również inne posty związane z tematyką IT. TOP 5 najczęściej odwiedzanych to:

  1. Bezpieczna aplikacja ASP.NET Core (cz. I) – atak CSRF
  2. Kompresja JPEG oraz jej wykorzystanie w steganografii
  3. Alternatywa dla Visual Studio? Rider od JetBrains
  4. StegoCore – 3 tydzień, edycja zdjęć w .NET Core
  5. Klucz U2F jako metoda logowania do OS X

Reszta znajduje się pod adresem konkursowym. Serdecznie zachęcam do odwiedzania i czytania 🙂

Sukces!

Udało mi się wytrwać do samego końca konkursu Daj Się Poznać 2017! Yeah!! Sprostałem z wymogami i napisałem 20 postów konkursowych 🙂

Projekt będę dalej rozwijał, więc bardzo zachęcam do śledzenia bloga oraz dotnetomaniaka, na którego wrzucam swoje posty.

Na koniec chciałbym podziękować kilku osobom, które wspierały mnie podczas konkursu. Miewałem momenty zwątpienia i zniechęcenia, ale dzięki Wam nie poddałem się! Nie będę wymieniał z imienia i nazwiska, ale myślę, że te osoby będą wiedzieć, że chodzi o nie. Dzięki! 🙂

Daj Się Poznać 2017 imagesharp steganography

StegoCore – powrót po przerwie, podsumowanie 8 tygodnia

Cześć wszystkim. Weekend majowy spowodował kolejną przerwę w pracach nad projektem. Nie jestem z tego dumny, ale nie ma co się zamartwiać, tylko brać do roboty. Na szczęście w maju nie ma chyba żadnych długich weekendów i przerw. Jestem więc dobrej myśli, jeśli chodzi o postępy w projekcie StegoCore.

Tuż przed majówką kończyłem powoli implementację algorytmu Zhao & Koch. Jednak tak strasznie namieszałem, że nawet ja nie byłem w stanie odnaleźć się w kodzie. Postanowiłem, więc zacząć od początku. Czas na podsumowanie tego, co udało mi się zrobić.

Co słychać?

W implementacji algorytmu Zhao & Koch pojawiły się:

  • Dyskretna transformata kosinusowa, metoda kwantyzacji oraz ich odwrotności
  • Zamiana bloku 8×8 pikseli na macierz luminancji
  • Wstawianie jednego bitu danych do bloku 8×8

Dodatkowo w bibliotece do obsługi plików graficznych ImageSharp zmieniła się struktura bibliotek. W związku z tym musiałem zaktualizować zależności w projekcie. Postanowiłem, że raz na dwa tygodnie będę sprawdzał te zależności, tak aby było to na bieżąco aktualne. Jest to niestety konieczne, ponieważ biblioteka ImageSharp jest wciąż w fazie alpha.

Pracowałem nad projektem na laptopie z Windowsem i byłem bardzo mile zaskoczony, gdy wszystko działało jak należy. Tak więc trzy platformy przetestowane (aplikacja demowa postawiona jest na serwerze z linuxem).

Przypominam, że wszystkie zmiany w projekcie na bieżąco wrzucam na githuba.

Co dalej?

  • Kontynuacja implementacji algorytmu Zhao & Koch
  • Przetestowanie metod liczenia transformaty i kwantyzacji
  • Aktualizacja dema aplikacji webowej

A przede wszystkim lepiej organizować czas i poświęcać go na projekt każdego dnia.

Daj Się Poznać 2017 imagesharp steganography

Kompresja JPEG oraz jej wykorzystanie w steganografii

Kolejnym krokiem rozwoju biblioteki StegoCore jest implementacja algorytmu ukrywania danych, który będzie odporny na kompresję JPEG. Aby lepiej zrozumieć zasadę jego działania, należy zacząć od przedstawienia samego formatu JPEG. Jak wygląda kodowanie i dekodowanie pliku graficznego w kompresji JPEG? W jaki sposób zmienić plik jpeg, aby umieścić w nim sekretne dane? Odpowiedzi na te inne pytania w poniższym poście.

Co to jest JPEG i po co został wymyślony?

W celu ujednolicenia algorytmów kompresji obrazów monochromatycznych i kolorowych, powstał format JPEG. Jest on jednym z najczęściej stosowanych formatów grafiki rastrowej. Algorytm kompresji używany w formacie JPEG jest algorytmem stratnym. Oznacza to, że po skompresowaniu obrazu kosztem utraty niektórych informacji zmniejszamy jego rozmiar. Niemniej jednak, w zależności od wyboru stopnia kompresji, jest możliwość uzyskania jak najmniejszego pliku przy zadowalającej jakości.

Wymienione właściwości sprawiają, że format kompresji JPEG będzie dobrym w kontekście stosowania go jako nośnik steganograficzny. Sama kompresja niesie ze sobą sporo problemów, jednak popularność tego formatu zmniejsza ryzyko ewentualnego ataku. Jedną z pożądanych cech zaproponowanego algorytmu będzie odporność na kompresję JPEG. Oznacza to, że pomimo skompresowania obrazu nadal będzie możliwość odczytania ukrytej wiadomości. Aby dowiedzieć się od czego zależy to, czy daną wiadomość będzie można odczytać po kompresji, należy przyjrzeć się algorytmowi JPEG.

Algorytm kompresji

Algorytm kompresji JPEG jest algorytmem symetrycznym. Oznacza to, że operacje wykonywane podczas dekompresji, wykonują się w odwrotnej kolejności w stosunku do kompresji. W celu uproszczenia operacji zakłada się, że szerokość i wysokość obrazu są wielokrotnością 8. Jeśli warunek ten, nie jest spełniony, należy tego dokonać przed dodanie odpowiedniej ilości wierszy i kolumn.

Podczas kompresji obrazu możemy wyróżnić 6 następujących kroków.

Krok 1.

Pierwszym krokiem jest przejście do modelu luminancja-chrominancja. Zakładamy, iż wejściowy obraz zapisany w postaci modelu (R – ang. red – czerwony, G – ang. green – zielony, B – ang. blue – niebieski), a każda składowa jest liczbą całkowitą zawierającą się w przedziale . Przejście do modelu luminancja-chrominancja odbywa się w następujący sposób:

Krok ten jest pomijany, jeśli wejściowym obrazem jest obraz monochromatyczny.

Krok 2.

Po wykonaniu pierwszego kroku, otrzymujemy obraz zapisany w modelu luminancja-chrominancja. Następnie obraz jest dzielony na bloki 8×8 o rozmiarze pikseli. Dla każdej składowej YCbCr modelu tworzona jest macierz o podanych rozmiarach, aby działania na nich mogły być przeprowadzane niezależnie od siebie.

W celu uproszczenia obliczeń dokonywanych w następnych krokach, od każdego elementu macierzy odejmowana jest wartości równa połowie zakresu, czyli 128. W wyniku tego działania wszystkie elementy macierzy będą z zakresu [-128;127]. Przyjmijmy, iż po wykonaniu tego kroku każdy blok (macierz) można zapisać w następującej postaci:

Krok 3.

Dla każdego bloku obliczana jest dyskretna dwuwymiarowa transformata kosinusowa, zadana wzorem:

W wyniku otrzymamy macierz zawierającą wartości rzeczywiste. Zamiast samych wartości pikseli, mamy ich wartości średnie oraz częstotliwość zmian wewnątrz całego bloku. W przypadku dokładnych obliczeń nie tracimy żadnych danych, gdyż dyskretna transformata kosinusowa jest odwracalna.

Krok 4.

W wyniku obliczeń poprzednich kroków otrzymaliśmy macierz F, która jest transformatą kosinusową bloku danych f. W tym kroku wykonywana będzie operacja zwana kwantyzacją. Polega ona na usunięciu danych, które są mało lub wcale nie widoczne dla ludzkiego oka. Z postaci transformaty wynika, iż znajdują się one w prawej dolnej części macierzy. Proces kwantyzacji można podzielić na dwie części. W pierwszej, każdy element macierzy dzielony jest przez odpowiadającą mu stałą. Następnie otrzymane wartości zaokrąglane są do najbliższej liczby całkowitej. W wyniku tego zaokrąglenia, tracimy pewne dane. Jednak, jak zostało wspomniane, są to dane mało widoczne dla ludzkiego oka.

Stałe wykorzystywane w procesie kwantyzacji ułożone są w macierz zwaną macierzą kwantyzacji. Wartości tych stałych stanowią o tym w jakim stopniu wykonana zostanie kompresja obrazu – im większe one będą, tym więcej informacji zostanie utraconych. Po zaokrągleniu wiele elementów macierzy będzie równe zeru, co wpływa na rozmiar skompresowanego obrazu. Po procesie kodowania będą zajmować mniej miejsca.

Kwantyzację można przedstawić według następującej zależności

Macierz kwantyzacji decyduje o stopniu kompresji obrazu. Im wyższe są wartości jej elementów, tym wyższa kompresja. Jako przykład można podać macierz znajdującą się w dokumencie standaryzującym kompresję JPEG:

Współczynniki w macierzy zostały tak dobrane, aby uzyskana w wyniku kwantyzacji tablica zawierała jak największą liczbę zer. Zerowy element w jakimkolwiek miejscu w macierzy oznacza utratę pewnych informacji obrazu. Ważne jest, aby były one jak najmniej znaczące i mało widoczne dla oka ludzkiego. Takie informacje znajdują się w prawej, dolnej części macierzy . Natomiast w macierzy współczynniki znajdujące się w prawej, dolnej części są większe od pozostałych. W wyniku kwantyzacji otrzymamy dużą liczbę zer właśnie w tym obszarze macierzy.

Krok 5 i 6

Krok 5 to  przygotowanie danych do kodowania. W tym celu macierz transformowana jest na wektor według algorytmu zig-zag. Kolejność elementów w wektorze można przedstawić następująco:

Dzięki temu otrzymany ciąg będzie zawierał dużą liczbę zer, które dodatkowo będą znajdować się obok siebie. Pozwoli to na zastosowanie kodowania, które zmniejszy liczbę bitów potrzebną do zapisania skompresowanego obrazu.

Ostatnim krokiem jest kodowanie entropijne. Idea tego kodowania polega na zastąpieniu najczęściej występujących elementów krótszymi słowami kodowymi. Jest to zwykłe kodowanie Huffmana, dlatego nie będę go prezentował.

Podsumowując algorytm kodera można przedstawić jak poniżej:

Algorytm Dekompresji

Algorytm dekompresji JPEG jest odwróceniem algorytmu kompresji. Oznacza to, że operacje przeprowadzane są w odwrotnej kolejności. Wejściowy, skompresowany obraz dzielony jest na bloki, po czym każdy z nich przekształcany jest w dekoderze bitowym wykorzystującym tablice kodowe Huffmana. Po zastosowaniu algorytmu odwrotnego zig-zag, wektor zamieniany jest w tablice . Otrzymana tablica mnożona jest przez macierze kwantyzacji, w wyniku czego otrzymujemy przybliżoną tablice współczynników transformaty kosinusowej. Ostatnim krokiem jest obliczenie odwrotnej transformaty. Schemat algorytmu dekompresji można przedstawić następująco:

Pliki graficznego w formacie JPEG to dobry nośnik steganograficzny?

Tak jak wspomniałem na początku, pliki zapisane w formacie JPEG ze względu na swoje właściwości mogą być dobrymi nośnikami steganograficznymi. Aby wiadomość ukryta w obrazie była odporna na kompresję, musi zostać wstawiona w dziedzinie transformaty. Wadą tego rozwiązania będzie ilość bitów, którą można zakodować, gdyż zbyt duże modyfikacje spowodują widoczne zmiany w obrazie. Oczywiście zależy to również od obrazu, ponieważ nie we wszystkich miejscach w obrazie jest możliwość zapisania wiadomości. Nie zmienia to jednak faktu, iż ukrycie wiadomości w taki sposób, aby kompresja JPEG nie w usunęła jej z obrazu jest jednym z priorytetów algorytmu.

W którym miejscu można ukryć dane?

Z przeprowadzonych testów wiemy, że na pewno nie w najmniej znaczących bitach pikseli obrazu. Wtedy bowiem, podczas kompresji JPEG dane te są tracone (krok 4, czyli kwantyzacja). Możemy więcej spróbować tak zmodyfikować macierz 8×8 pikseli i w nich ukryć bity sekretu. Opis jak tego dokonać w kolejnym poście, w którym przedstawię pełny algorytm ukrywania danych.

Daj Się Poznać 2017 imagesharp

StegoCore – podsumowanie po 5 tygodniach

macbook pro

Czas na szybkie podsumowanie po kolejnym tygodniu rozwoju aplikacji StegoCore.

Co nowego?

  • Do testów biblioteki dodałem sprawdzanie zapisu i możliwości odczytu sekretu w dwóch formatach graficznych: png i bmp.

    Wszystko działa jak należy, gdyż nie ma tam żadnej kompresji danych, piksele nie są w żaden sposób zmieniane. Zapisanie pliku w formacie jpeg powoduje niestety utratę ukrytych danych, więc wybieranie tego formatu w algorytmie LSB nie ma sensu.

  • W aplikacji webowej dodałem możliwość wyboru algorytmu umieszczania danych (na razie oczywiście dostępna jest tylko jedna opcja) oraz format pliku wyjściowego: png, bmp lub jpeg.

Niestety, mało udało się zrobić w tym tygodniu. Za mało czasu poświęconego na development. Byłem za to ostatnio na konferencji fizjoterapeutycznej i dowiedziałem się wielu ciekawych rzeczy odnośnie ergonomii np. ergonomicznego stanowiska pracy. W ciągu dwóch-trzech tygodni można więc spodziewać się postu w tym temacie 🙂

Co dalej?

  • W testach wyszedł temat formatu jpeg, więc myślę że to dobry moment, aby zacząć implementację kolejnego algorytmu. Tym razem algorytm DCT, który będzie odporny na kompresję jpeg
  • Chciałbym również poprawić sposób przetrzymywania plików graficznych w aplikacji webowej. Aktualnie są przechowywane w jednym folderze na serwerze. Chciałbym zaimplementować jakiś inny sposób ich storowania lub poprawić aktualny.
  • Rozłożyć pracę nad aplikacją na kilka dni. Aktualnie mam głupi nawyk pracy nad StegoCore tylko w weekend. Chciałbym to poprawić i każdego dnia coś napisać

Nawet nie zauważyłem że udało mi się już w 50% wypełnić minimum konkursowe Daj Się Poznać (czyli 20 postów). Ten post jest dokładnie 11 w kolejności, więc połowę mamy za sobą 🙂