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:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
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:
1 2 3 |
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:
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 |
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:
1 2 3 |
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”.
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 30 31 32 33 34 35 36 37 38 39 40 41 42 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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:
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 30 31 32 33 34 35 36 37 38 39 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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():
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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