Witam wszystkich. Dzisiaj zajmiemy się szyfrowaniem hexów pliku. Jeśli sięgniemy bardzo głęboko do jakiegokolwiek pliku na komputerze to zobaczymy, że jest on zbudowany z samych 1 i 0 nazywamy to systemem binarnym, nie będe się tutaj zagłębiał w technologie informacyjną ale jeśli ktoś jest zainteresowany zapraszam do wikipedii aby poczytać więcej o systemie binarnym. Wracając do kryptografii kodowanie 1 i 0 mija się z celem , bo niby co zamienimy 0 na 1 a 1 na 0 to każdy sprytny magik zaraz to odkoduje. Aby zakodować nasz plik musimy pogrupować 1 i 0 w taki sposób aby można je było przekształcić w inny system metryczny. My zamienimy sobie bity (zbiór 8 znaków) naszego pliku na system szesnastkowy, co da nam wielki wachlarz możliwości. Wykorzystamy tutaj sposób kodowania z poprzedniego tutoriala o kodowaniu z kluczem który można przeczytać tutaj. Więcej o systemie szesnastkowym (heksadecymalnym w skrócie hex) można poczytać na wikipedii. Teraz troche teori jak to będzie wyglądać. Stworzymy sobie zwykły plik tekstowy a w nim zapiszemy swoje imię. jeśli nie wiecie jak rozkodować/zakodować swoje imię zapraszam na stronę tutaj.
Moje imię to „Piotrek” jego odzwierciedlenie binarne będzie wyglądać tak: 01010000 01101001 01101111 01110100 01110010 01100101 01101011 a w wersji hexowej tak: 50 69 6f 74 72 65 6b
Jak ja to przekształciłem. zbiór 8 znaków nazywamy bajtem, każdy bajt składa się więc z 2 hexów, podzieliłem bajt na pół i wyszło mi w pierwszym bajcie (patrz tabelka niżej) 0101 i 0000 co po odczytaniu w tabelce daje 0101 = 5 a 0000 = 0. W systemie szesnastkowym każda litera składa się z kombinacji czterech 1 i 0:
0hex | = | 0dec | = | 0oct | = | 0 | 0 | 0 | 0 |
1hex | = | 1dec | = | 1oct | = | 0 | 0 | 0 | 1 |
2hex | = | 2dec | = | 2oct | = | 0 | 0 | 1 | 0 |
3hex | = | 3dec | = | 3oct | = | 0 | 0 | 1 | 1 |
4hex | = | 4dec | = | 4oct | = | 0 | 1 | 0 | 0 |
5hex | = | 5dec | = | 5oct | = | 0 | 1 | 0 | 1 |
6hex | = | 6dec | = | 6oct | = | 0 | 1 | 1 | 0 |
7hex | = | 7dec | = | 7oct | = | 0 | 1 | 1 | 1 |
8hex | = | 8dec | = | 10oct | = | 1 | 0 | 0 | 0 |
9hex | = | 9dec | = | 11oct | = | 1 | 0 | 0 | 1 |
Ahex | = | 10dec | = | 12oct | = | 1 | 0 | 1 | 0 |
Bhex | = | 11dec | = | 13oct | = | 1 | 0 | 1 | 1 |
Chex | = | 12dec | = | 14oct | = | 1 | 1 | 0 | 0 |
Dhex | = | 13dec | = | 15oct | = | 1 | 1 | 0 | 1 |
Ehex | = | 14dec | = | 16oct | = | 1 | 1 | 1 | 0 |
Fhex | = | 15dec | = | 17oct | = | 1 | 1 | 1 | 1 |
Do czego będziemy dążyć w tym tutorialu, chcemy ten plik txt ze swoim imieniem zakodować na poziomie hexów, powiedzmy kluczem będzie słowo „abc” Z poprzedniego tutorala wiemy, że nasza maszyna kodująca słowo Piotrek kodowała by tak:
Nasz klucz „abc” przesuwa litery o „1 , 2 , 3” do przodu tak więc P +1 = 16 + 1= 17 = R i +2 = 9+2 =11 = k o +3 = 15+3 = 18 =s t +1 = 19+1 = 20 =w r +2 =17+2=19=t e +3 = 5+3 = 8 =h k +1 = 11+1 = 12 = l Ostatecznie Piotrek =>(abc)=> Rkswthl
I tak właśnie wyszło w programie z poprzedniego tutoriala: Tekst taki jak „Rkswthl” może i jest trudny do rozkodowania ale nie niemożliwy poddając to odpowiednim algorytmom można tekst tem łatwo rozkodować. Gorzej jest jeśli nasz tekst jest bardzo duży, wtedy można dopasować rozkład liter i z łatwością odczytać tekst. Co się stanie jeśli zakodujemy hexy w takim tekście, już wam pokazuje. Przesuwamy hexy tak jak na górze przesuwaliśmy litery:
50 69 6f 74 72 65 6b 5 +1 = 6 0 + 2 =2 6 + 3 = 9 9 +1 = A 6 +2 = 8 f + 3 =2 (..) 50-69-6F-74-72-65-6B =>(abc) => 62-9A-82-86-A3-88-7D co po otwarciu pliku tekstowego daje w nim tekst: bš‚†Ł} Jak widzicie ciąg „bš‚†Ł}” wcale nie przypomina „Piotrek”
Program który sobie zrobimy nadaje się do kodowania i rozkodowywania plików *.txt ale może kodować również pliki *.jpg *.pdf, *.xls co tylko chcemy. Zrobimy sobie program i będziecie mogli zaraz zrozumieć o co w tym wszystkim chodzi. dla działu vb.net zrobię edytor hexó, więc warto i tam zajrzeć aby obejrzeć inny program. Zaczynamy standardowo od utworzenia nowego projektu. Teraz należy poukładać wszystkie elementy tak jak na obrazku: Kiedy wszystkie elementy będą na swoim miejscu dodajemy OpenFileDialog i SaveFileDialog , oba elementy znajdują się w przyborniku po lewej stronie. W tej części to będzie wszystko, formę wizualną mamy już gotową. Przechodzimy do kodu naszego programu. Najpierw inicjujemy dwie numeracje:
Public Enum LetterType a = 1 b = 2 c = 3 d = 4 e = 5 f = 6 g = 7 h = 8 i = 9 j = 10 k = 11 l = 12 m = 13 n = 14 o = 15 p = 16 r = 17 s = 18 t = 19 w = 20 u = 21 x = 22 y = 23 z = 24 End Enum Public Enum SystemSzesnastkowy n0 = 1 n1 = 2 n2 = 3 n3 = 4 n4 = 5 n5 = 6 n6 = 7 n7 = 8 n8 = 9 n9 = 10 nA = 11 nB = 12 nC = 13 nD = 14 nE = 15 nF = 16 End Enum
Pierwsza numeracja znana jest nam z poprzedniego tutoriala. Potrzebujemy jej aby na podstawie klucza rozpoznać wartość przesunięcia. Druga natomiast posłuży nam do szyfrowania. Teraz zainicjujemy sobie jeszcze zmienne:
Dim hexString As String 'jako bufor dla RichBoxów Dim ListaBytow As New List(Of String) ' liste wszystkich bajtów zamienionych na hexy Dim ListaBytowZakiRozk As New List(Of String) ' liste wszystkich bajtów zamienionych na hexy po zaszyfrowaniu
Wracamy do naszego Projektu i przyciskają dwukrotnie na przycisk „Otwórz” tworzymy do niego uchwyt. W uchwycie wpisujemy:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click hexString = "" ' Czyści nasz bufor ProgressBar1.Maximum = 0 ' zeruje ProgressBar If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then Using file As New IO.FileStream(OpenFileDialog1.FileName, IO.FileMode.Open) Dim value As Integer = file.ReadByte() Do Until value = -1 'pętla zamienia bajty na hexy Dim hex As String hex = Conversion.Hex(value) If hex.Length < 2 Then hex = "0" + hex hexString += "-" & hex ListaBytow.Add(hex) Else hexString += "-" & (hex) 'wypełnia bufor danymi ListaBytow.Add(hex) 'dodaje hexy do listy End If value = file.ReadByte() Loop End Using RichTextBox1.Text = hexString.Remove(0, 1) 'wizualizuje hexy w richbox1 ProgressBar1.Maximum = ListaBytow.Count() End If End Sub
Do przerobienia bajtów na hexy służy prosta funkcja „Coversion.Hex” która automatycznie robi to za nas. Pętla chyba prosta. Do zamiany bajtów na hexy może posłużyć również metoda:
Do Until value = -1 hexString += "-" (value.ToString("X2")) (...)
Na koniec wczytuje wszystkie dane z bufora „hexString” do richBoxa ucinając pierwszy wyraz bo jest nim „-” (dodaje to lepszego efektu wizualnego) i ustawiam progressbar. Teraz zajmiemy się szyfrowanie. Wracamy do projektu i tworzymy uchwyt dla przycisku „Koduj”.
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click hexString = "" 'czyści bufor RichTextBox2.Clear() 'czyści richbox Dim klucz As New List(Of Integer) 'pętla zamienia litery z textboxa1 na cyfry z numeracji i wypełnia tablice "klucz" For Each letter As String In TextBox1.Text For Each i As Integer In [Enum].GetValues(GetType(LetterType)) If letter = CType(i, LetterType).ToString Then klucz.Add(CType(i, LetterType)) End If Next Next 'wizualizuje sposób przesunięcia TextBox2.Text = "" For Each listaKlucza As Integer In klucz TextBox2.Text += listaKlucza.ToString + "," Next 'zeruje położenie w kluczu Dim polozenieWKluczu As Integer = 0 'Pętla wstępnie kodująca For Each elementglowny In ListaBytow 'dla każdego elementu z tabeli przechowującej bajty 'zerowanie bufora kodującego Dim mojByte As String = "" 'Pętla wybierająca położenie w kluczu For Each elements As String In elementglowny If polozenieWKluczu > klucz.Count - 1 Then mojByte += zaszyfruj(elements, klucz(0)) polozenieWKluczu = 1 Else mojByte += zaszyfruj(elements, klucz(polozenieWKluczu)) polozenieWKluczu += 1 End If Next hexString += "-" + mojByte 'służy wypełnienie bufora wizualizującego dla richboxa2 ListaBytowZakiRozk.Add(mojByte) ' wypełnia tablice zagodowanymi hexami ProgressBar1.Value += 1 'przesuwa progressbar Next RichTextBox2.Text = hexString.Remove(0, 1) 'wypelnia richbox2 danymi ProgressBar1.Value = 0 'zeruje progressbar End Sub
Tworzymy teraz funkcje szyfrującą. Będzie ona wyglądała trochę inaczej niż ta w poprzednim tutorialu. Jak sami zauważyliście w mojej numeracji dodałem przed cyfry i litery literę n. Ponieważ w numeracji nie da się numerować cyfr dodałem swego rodzaju wyznacznik który zdał egzamin dlatego nie kombinowałem dalej. Dodałem także dodatkowe „ifelse” do pętli ponieważ w systemie szesnastkowym mamy 16 cyfr a w systemie z literami mamy 24 chciałem pokazać wam, że jeśli nasz alfabet będzie miał więcej liter wtedy będziemy musieli odjąć 32:
jeśli przesunęli byśmy litere F o maksymalną liczbę czyli z mojego wyliczenia alfabetu jest to x-24 wtedy otrzymalibyśmy F-0, 0-1,1-2,2-3,3-4,4-5,5-6,6-7,7-8,8-9,9-10,A-11,B-12,C-13,D-14,E-15,F-16,0-17,1-18,2-19,3-20,4-21,5-22,6-23,7-24 Przesunięcie F o 24 daje 7 pierwsze przesunięcie da nam liczbę większą niż 16 a więc z poza zakresu: i + przesuniecie – 16 == 16+24-16 =24 w naszej numeracji nie istnieje pozycja 24 Drugie metoda za to: i + przesuniecie – 32 == 16+24-32 = 8 n8 w naszym wyliczeniu daje 7 Więc dla dużych liczb będziemy musieli odjąć 32 jeśli nasz alfabet będzie obszerny to dla jeszcze większych będziemy musieli odjąć 48
Cała funkcja wygląda tak:
Function zaszyfruj(ByVal litera As String, ByVal przesuniecie As Integer) litera = "n" + litera 'dodaje wyznacznik do Enum For Each i As Integer In [Enum].GetValues(GetType(SystemSzesnastkowy)) If litera = CType(i, SystemSzesnastkowy).ToString Then If i + przesuniecie > 16 And i + przesuniecie <= 32 Then Return Microsoft.VisualBasic.Right(CType(i + przesuniecie - 16, SystemSzesnastkowy).ToString, 1) ' ElseIf i + przesuniecie > 32 Then Return Microsoft.VisualBasic.Right(CType(i + przesuniecie - 32, SystemSzesnastkowy).ToString, 1) ' Else Return Microsoft.VisualBasic.Right(CType(i + przesuniecie, SystemSzesnastkowy).ToString, 1) ' End If End If Next End Function
Można teraz spróbować sobie coś zaszyfrować. Ja zrobiłem sobie taki plik tekstowy: Wczytam go teraz i zakoduje kodem „cba”. U mnie wszystko przebiegło pomyślnie: Teraz uruchomimy sobie przycisk „Zapisz” tworzymy dla niego uchwyt i wpisujemy kod:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click Try If SaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then Dim fs As New IO.FileStream(SaveFileDialog1.FileName, System.IO.FileMode.Create) 'dla każdego elementu z tablicy z zakodowanymi/ rozkodowanymi danymi For Each elements In ListaBytowZakiRozk Dim bytes As Byte = Convert.ToByte(elements, 16) fs.WriteByte(bytes) 'zapisz bajty do wybranej lokalizacji i pliku Next End If Catch End Try End Sub
Co dostaniemy po zapisaniu naszego pliku. Ja po zapisaniu zakodowanego pliku jako „plik_zakodowany.txt” i dostałem: Sami przyznacie, że ciężko było by to rozkodować. Teraz zajmiemy się przyciskiem „Rozkoduj” z naszego Projektu. Kod do przycisku będzie Identyczny jak do kodowania, różnić się będzie tylko przesunięcie w funkcji do rozkodowania:
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click hexString = "" RichTextBox2.Clear() Dim klucz As New List(Of Integer) For Each letter As String In TextBox1.Text For Each i As Integer In [Enum].GetValues(GetType(LetterType)) If letter = CType(i, LetterType).ToString Then klucz.Add(CType(i, LetterType)) End If Next Next For Each listaKlucza As Integer In klucz TextBox2.Text += listaKlucza.ToString + "," Next Dim polozenieWKluczu As Integer = 0 For Each elementglowny In ListaBytow Dim mojByte As String = "" For Each elements As String In elementglowny If polozenieWKluczu > klucz.Count - 1 Then mojByte += rozszyfruj(elements, klucz(0)) polozenieWKluczu = 1 Else mojByte += rozszyfruj(elements, klucz(polozenieWKluczu)) polozenieWKluczu += 1 End If Next hexString += "-" + mojByte ListaBytowZakiRozk.Add(mojByte) ProgressBar1.Value += 1 Next RichTextBox2.Text = hexString.Remove(0, 1) ProgressBar1.Value = 0 End Sub
Objaśnienie takie jak w metodzie kodującej. Funkcja rozkodująca wygląda tak:
Function rozszyfruj(ByVal litera As String, ByVal przesuniecie As Integer) litera = "n" + litera For Each i As Integer In [Enum].GetValues(GetType(SystemSzesnastkowy)) If litera = CType(i, SystemSzesnastkowy).ToString Then If i - przesuniecie <= 0 And i - przesuniecie > -16 Then Return Microsoft.VisualBasic.Right(CType(i - przesuniecie + 16, SystemSzesnastkowy).ToString, 1) ElseIf i - przesuniecie <= -16 Then Return Microsoft.VisualBasic.Right(CType(i - przesuniecie + 32, SystemSzesnastkowy).ToString, 1) Else Return Microsoft.VisualBasic.Right(CType(i - przesuniecie, SystemSzesnastkowy).ToString, 1) End If End If Next End Function
Otwieramy teraz wcześniej zakodowany plik i wciskamy „Rozkoduj” Zapisujemy go i dostajemy nasze hasło: Uważajcie, używajcie tylko liter z numeracji, jeśli chcecie aby w kluczu były cyfry najlepiej też dla każdej cyfry użyć wyznacznika albo w pętli użyć metody isNumeric():
Dim klucz As New List(Of Integer) For Each letter As String In TextBox1.Text If IsNumeric(letter) Then klucz.Add(letter) Else For Each i As Integer In [Enum].GetValues(GetType(LetterType)) If letter = CType(i, LetterType).ToString Then klucz.Add(CType(i, LetterType)) End If Next End If Next
Oczywiście trzeba to jakoś mądrze wykonać. Wszelkiego rodzaju krytykę proszę pisać w komentarzach. Jeśli coś jest nie jasne to proszę o kontakt albo komentarza.
Cały projekt można pobrać: Szyfrowanie_hexow
Sam plik *.exe programu do sprawdzenia: Szyfrowanie_hexow_exe