Szybkie ćwiczenie z PKI – jak błyskawicznie napisać skrypt do zarządzania kluczami oraz szyfrowania asymetrycznego RSA

Kryptografia asymetryczna zmieniła świat. To dzięki niej, a ściślej mówiąc jej twórcom, takim jak chociażby panowie Rivest Shamir i Adleman, w ogóle możliwy stał się rozwój biznesu w Internecie, bowiem gdyby nie kryptograficzna ochrona danych, w tym tożsamości użytkowników, informacji finansowych, danych osobowych, danych zdrowotnych czy transakcji, dzisiejszy Internet nie mógłby być tym, czym jest, a jest przecież największym na świecie, transgranicznym i transkontynentalnym rynkiem, i to praktycznie w we wszystkich sektorach światowej gospodarki.

rivest_shamir_adlemanOgromnie interesujący jest fakt, że tytani kryptografii, posiadacze najznakomitszych umysłów matematycznych wszech czasów, przebywają nadal wśród nas. Warto oglądnąć film, który pokazuje ich dokonania w pigułce.

Giants Among Us

Zasada kryptografii asymetrycznej jest bardzo prosta, a jej prostota pozostaje w kontraście do matematycznej złożoności algorytmów kryptograficznych, które leżą u jej podstaw. Jednak, podobnie jak skorzystanie z telewizora,  by obejrzeć ulubiony program, nie wymaga znajomości teorii elektroniki, a jedynie naciśnięcia odpowiedniego przycisku na pilocie, tak z dobrodziejstw kryptografii asymetrycznej można korzystać w równie prosty sposób. I tak właśnie jest. Łącząc się z systemami transakcyjnymi, sklepami internetowymi, serwerami poczty i mediami społecznościowymi, na ogół nieświadomie korzystamy z zaawansowanej kryptografii, która w całkowicie przezroczysty dla nas sposób działa na rzecz ochrony transmitowanych przez sieć danych, zapewniając im poufność i integralność.

Wróćmy jednak do wątku prostoty zasady przewodniej rządzącej kryptografią asymetryczną. Mianowicie, każdy użytkownik kryptosystemu bazującego na algorytmach asymetrycznych, posługuje się parą kluczy – kluczem prywatnym i publicznym. Klucz prywatny jest wyłącznie naszym sekretem i nie wolno nam go ujawniać nikomu. Klucz publiczny natomiast można, a nawet należy udostępnić światu. Zasada jest taka, że jeśli coś zostanie zaszyfrowane jednym kluczem z takiej pary, może być z powodzeniem odszyfrowane wyłącznie kluczem komplementarnym (drugim z pary). Dlatego też, jeśli naszą intencją jest umożliwić światu wysyłanie do nas informacji zaszyfrowanej, w taki sposób, że tylko my będziemy w stanie ją odszyfrować, to wspomniana informacja musi być zaszyfrowana naszym kluczem publicznym. Bowiem tylko my, jako jedyni, posiadając klucz komplementarny (prywatny), możemy nim odkodować szyfr. W tej sytuacji staje się jasne dlaczego, im więcej ludzi zna nasz klucz publiczny, tym dla nas jest lepiej. Z oczywistych też względów, jeśli my będziemy chcieli wysłać zabezpieczoną wiadomość komuś innemu, musimy ją zaszyfrować jego (czyli odbiorcy) kluczem publicznym (nie naszym kluczem prywatnym).

Kiedy zachodzi potrzeba szyfrowania naszym kluczem prywatnym? Bez sensu byłoby zabezpieczać w ten sposób poufność informacji, bo cóż to za poufność, skoro każdy posiadacz klucza komplementarnego, czyli naszego klucza publicznego, mógłby ją odszyfrować. Szyfrowanie kluczem prywatnym ma sens w innym zastosowaniu – nie do zabezpieczenia poufności informacji, ale do kontroli jej integralności. Chodzi o to, żeby odbiorcy informacji dostarczyć mechanizmów kontrolnych, dzięki którym, otrzymawszy informację, będzie on w stanie sprawdzić czy nikt „po drodze” nie przekłamał jej treści. Takiej funkcjonalności dostarcza podpis elektroniczny. Działa on następująco: Nadawca wylicza kryptograficzną sumę kontrolną dla treści informacji (na przykład wiadomości poczty elektronicznej) przed jej wysłaniem. Właściwie czyni to nie on sam lecz w jego imieniu program, którego nadawca używa (na przykład klient pocztowy). Taka kryptograficzna suma kontrolna zwana skrótem komunikatu lub elektronicznym odciskiem palca, jest w następnej kolejności szyfrowana kluczem prywatnym nadawcy. Właśnie zaszyfrowany skrót jest niczym innym, tylko podpisem elektronicznym. Podpis elektroniczny dołączany jest następnie do treści wiadomości i w tej postaci wiadomość opuszcza komputer nadawcy, wędrując przez sieć do odbiorcy. Odbiorca, otrzymawszy podpisaną cyfrowo wiadomość, odszyfrowuje dołączony do niej skrót. Czyni to naszym kluczem publicznym (musi go wcześniej jakoś otrzymać). Potem bierze treść wiadomości i w identyczny sposób, jak uczynił to nadawca, wylicza jej sumę kontrolną. W następnej kolejności porównuje sumę kontrolną (skrót) przez siebie wyliczoną z odszyfrowaną niedawno sumą kontrolną przesłaną przez nadawcę. Jeśli są one identyczne, to oznacza, że nikt „po drodze” nie przekłamał informacji, albowiem nawet najmniejsza zmiana w treści oryginalnej informacji spowodowałaby wielką różnicę w kryptograficznych sumach kontrolnych. Identyczność sum kontrolnych oznacza nie tylko, że nikt w informacji nie „grzebnął”, ale dodatkowo, że nadawca jest kimś, za kogo się podaje, a nie kimś, kto się pod niego podszywa. Warunkiem pewności w tej kwestii jest oczywiście to, że jego klucz publiczny uzyskaliśmy z zaufanego źródła lub – lepiej – klucz jest uwierzytelniony przez zaufaną stronę trzecią, która dla zagwarantowania autentyczności i ważności klucza publicznego wystawia dla niego certyfikat cyfrowy.

O kryptografii asymetrycznej można pisać grube tomy, ale mnie nie o to dziś chodzi. Moim celem było w możliwie najkrótszym czasie i minimalnym wysiłkiem opracowanie skryptowych narzędzi, które można wykorzystać do przeprowadzania podstawowych operacji, takich jak wygenerowanie pary kluczy RSA, ich zapis do pliku, czy też pobranie wcześniej zapisanych kluczy z pliku, szyfrowanie kluczem publicznym i odszyfrowywanie kluczem prywatnym.

W czasie krótszym niż godzina udał się napisać w języku TCL narzędzie wyposażone w graficzny interfejs użytkownika oparty o widgety Tk. Dwie sekcje programu znalazły swoje odzwierciedlenie na poziomie interfejsu użytkownika w wyodrębnieniu dwóch zakładek: RSA encryption i RSA decryption.

Używając programu, proszę pamiętać, że generowanie kluczy dużych rozmiarów (2024 lub 4096-bitowych) jest operacją obliczeniowo kosztowną i może zająć trochę czasu. Proszę także wziąć pod uwagę, że kryptografia asymetryczna jest dużo bardziej kosztowna obliczeniowo niż kryptografia symetryczna, dlatego nie nadaje się do efektywnego szyfrowania dużych wolumenów danych. W realnych zastosowaniach kryptografia asymetryczna służy jedynie do zabezpieczeń fazy wstępnej nawiązywania szyfrowanych połączeń, w tym uwierzytelnień stron takowych połaczeń i negocjacji lub wymiany kluczy do szyfrowania symetrycznego. Późniejsza transmisja danych jest już szyfrowana symetrycznie, znacznie wydajniej, z wykorzystaniem uzgodnionego pomiędzy stronami identycznego klucza.

Tak prezentuje się graficzny interfejs użytkownika programu  – sekcja szyfrowania (kluczem publicznym odbiorcy): rsa_encrypt A tak wygląda zakładka odpowiadająca sekcji odszyfrowywania (naszym kluczem prywatnym): rsa_decrypt Zachęcam do dalszej modyfikacji skryptu. Może ona pójść w kierunku:

  • Zaszyfrowania klucza prywatnego (przy dostępie do niego wymagane będzie podanie hasła).
  • Usunięcia limitu ilości danych które mogą być jednorazowo zaszyfrowane (w tej chwili jest on skorelowany z wielkością klucza), przez podział danych wejściowych na bloki i iteracyjne szyfrowanie poszczególnych bloków, jako niezależnych jednostek danych.
  • Zapisu kluczy w bazie SQL-owej i pobierania ich stamtąd w razie potrzeby.
  • Generowania i weryfikacji sygnatur cyfrowych.
  • Wsparcia dla innych niż RSA algorytmów.

To tylko kilka pomysłów. Nie wyczerpują one rzecz jasna wszystkich potencjalnych możliwości. Oto kod źródłowy skryptu:

package require pki

proc key_gener {key_size} {
   global key
   wm title . "...in progress. Please wait!"
   if {[catch {::pki::rsa::generate $key_size} key]} {
      tk_messageBox -message "Problem with RSA keys generation" -title "Error"
   }
   wm title . "Multi-liner RSA encryption/decryption - Janusz Nawrat (2015)"
   .nb.enc_fr.param.exec_button configure -state active
   .nb.dec_fr.param.exec_button configure -state active
   .nb.enc_fr.param.keysave_button configure -state active
   .nb.dec_fr.param.keysave_button configure -state active
}

proc key_load {} {
   global key
   set types {
      {"All txt files"     {.txt} }
      {"Other files"             *}
   }
   
   set filename [tk_getOpenFile -filetypes $types -parent .]
   
   if { [catch {open $filename r} f] } {
      tk_messageBox -message "Problem with opening input file for reading" -title "Problem"
      return
   }
   set key [read $f]
   set key [string trimright $key "\n"]
   close $f
   .nb.enc_fr.param.exec_button configure -state active
   .nb.dec_fr.param.exec_button configure -state active
   .nb.enc_fr.param.keysave_button configure -state active
   .nb.dec_fr.param.keysave_button configure -state active
   tk_messageBox -message "RSA keys successfuly loaded from file $filename" -title "Success"
}

proc encrypt {key plaintext} {
   set ciphertext ""
   if {[catch {::pki::encrypt -hex -pub -- $plaintext $key} ciphertext]} {
      tk_messageBox -message "Problem with encryption" -title "Error"
   }
   return $ciphertext
}

proc decrypt {key ciphertext} {
   set plaintext ""
   if {[catch {::pki::decrypt -hex -priv -- $ciphertext $key} plaintext]} {
      tk_messageBox -message "Problem with decryption" -title "Error"
   }
   return $plaintext
}

proc OnComboSelected {widget} {
   global key_size
   set key_size [$widget get]
}

proc key_save {} {
   global key
   set types {
      {"All txt files"     {.txt} }
      {"Other files"             *}
   }
   set filename [tk_getSaveFile -filetypes $types -parent .]   
   if { [catch {open $filename w} f] } {
      tk_messageBox -message "Problem with opening output file for writing" -title "Problem"
      return
   }
   puts $f $key
   close $f
   tk_messageBox -message "RSA keys saved to file $filename" -title "Success"
}

set plaintext ""; set ciphertext ""; set key ""

ttk::notebook .nb

set key_size 1024

# -------------- Encryption ------------------

frame .nb.enc_fr
labelframe .nb.enc_fr.plain_frame -text "Plaintext"

text .nb.enc_fr.plain_frame.txt -yscrollcommand ".srl_ya set" -xscrollcommand ".srl_xa set" -wrap word -height 10
scrollbar .srl_ya -command ".nb.enc_fr.plain_frame.txt yview" -orient v
scrollbar .srl_xa -command ".nb.enc_fr.plain_frame.txt xview" -orient h

frame .nb.enc_fr.param

label .nb.enc_fr.param.mode_lbl -text "Key size: "
ttk::combobox .nb.enc_fr.param.key_size_cb -textvariable key_size -values {512 1024 2048 4096} -width 5
.nb.enc_fr.param.key_size_cb set $key_size

bind .nb.enc_fr.param.key_size_cb <> [list OnComboSelected .nb.enc_fr.param.key_size_cb]

button .nb.enc_fr.param.keygen_button -text "RSA keypair generate" -width 19 -command {key_gener $key_size}
button .nb.enc_fr.param.keysave_button -text "Save keys to file" -width 19 -command {key_save}
button .nb.enc_fr.param.keyload_button -text "RSA key import from file" -width 19 -command {key_load}
         
button .nb.enc_fr.param.exec_button -text "Encrypt it..." -width 19 -command { set plaintext [.nb.enc_fr.plain_frame.txt get 1.0 end]; \
       set ciphertext [encrypt $key $plaintext]; .nb.enc_fr.cipher_frame.txt delete 1.0 end; \
      .nb.enc_fr.cipher_frame.txt insert 1.0 $ciphertext; }

if {$key == ""} {
   .nb.enc_fr.param.exec_button configure -state disable
   .nb.enc_fr.param.keysave_button configure -state disable
}      

labelframe .nb.enc_fr.cipher_frame -text "Ciphertext"
text .nb.enc_fr.cipher_frame.txt -yscrollcommand ".srl_yb set" -xscrollcommand ".srl_xb set" -wrap word -height 10
scrollbar .srl_yb -command ".nb.enc_fr.cipher_frame.txt yview" -orient v
scrollbar .srl_xb -command ".nb.enc_fr.cipher_frame.txt xview" -orient h

button .nb.enc_fr.exit_button -text "Exit" -width 20 -command {exit}

pack .nb.enc_fr.plain_frame -fill both -expand 1 -ipadx 5 -ipady 5
pack .srl_ya -in .nb.enc_fr.plain_frame -fill y -side right -expand 1
pack .srl_xa -in .nb.enc_fr.plain_frame -fill x -side bottom -expand 1
pack .nb.enc_fr.plain_frame.txt -side left -expand 1 -fill both

pack .nb.enc_fr.param -fill both -expand 1 -ipadx 3 -ipady 5

pack .nb.enc_fr.param.mode_lbl .nb.enc_fr.param.key_size_cb .nb.enc_fr.param.keygen_button .nb.enc_fr.param.keysave_button .nb.enc_fr.param.keyload_button -side left -expand 1

pack .nb.enc_fr.param.exec_button -side left -padx 3

pack .nb.enc_fr.cipher_frame -fill both -expand 1 -ipadx 5 -ipady 5
pack .srl_yb -in .nb.enc_fr.cipher_frame -fill y -side right -expand 1
pack .srl_xb -in .nb.enc_fr.cipher_frame -fill x -side bottom -expand 1
pack .nb.enc_fr.cipher_frame.txt -side left -expand 1 -fill both

pack .nb.enc_fr.exit_button -side left -fill none -pady 5 -padx 3 -ipadx 30 -expand 1

# -------------- Decryption ------------------

frame .nb.dec_fr
labelframe .nb.dec_fr.cipher_frame -text "Ciphertext"

text .nb.dec_fr.cipher_frame.txt -yscrollcommand ".srl_yc set" -xscrollcommand ".srl_xc set" -wrap word -height 10
scrollbar .srl_yc -command ".nb.dec_fr.cipher_frame.txt yview" -orient v
scrollbar .srl_xc -command ".nb.dec_fr.cipher_frame.txt xview" -orient h

frame .nb.dec_fr.param

label .nb.dec_fr.param.mode_lbl -text "Key size: "
ttk::combobox .nb.dec_fr.param.key_size_cb -textvariable key_size -values {512 1024 2048 4096} -width 5
.nb.dec_fr.param.key_size_cb set $key_size

bind .nb.dec_fr.param.key_size_cb <> [list OnComboSelected .nb.dec_fr.param.key_size_cb]

button .nb.dec_fr.param.keygen_button -text "RSA keypair generate" -width 19 -command {key_gener $key_size}
button .nb.dec_fr.param.keysave_button -text "Save keys to file" -width 19 -command {key_save}
button .nb.dec_fr.param.keyload_button -text "RSA key import from file" -width 19 -command {key_load}
         
button .nb.dec_fr.param.exec_button -text "Decrypt it..." -width 19 -command { set ciphertext [.nb.dec_fr.cipher_frame.txt get 1.0 end]; \
      set plaintext [decrypt $key [string trimright $ciphertext "\n"]]; .nb.dec_fr.plain_frame.txt delete 1.0 end; \
      .nb.dec_fr.plain_frame.txt insert 1.0 $plaintext; }

if {$key == ""} {
   .nb.dec_fr.param.exec_button configure -state disable
   .nb.dec_fr.param.keysave_button configure -state disable
}      

labelframe .nb.dec_fr.plain_frame -text "Plaintext"
text .nb.dec_fr.plain_frame.txt -yscrollcommand ".srl_yd set" -xscrollcommand ".srl_xd set" -wrap word -height 10
scrollbar .srl_yd -command ".nb.dec_fr.plain_frame.txt yview" -orient v
scrollbar .srl_xd -command ".nb.dec_fr.plain_frame.txt xview" -orient h

button .nb.dec_fr.exit_button -text "Exit" -width 20 -command {exit}

pack .nb.dec_fr.cipher_frame -fill both -expand 1 -ipadx 5 -ipady 5
pack .srl_yc -in .nb.dec_fr.cipher_frame -fill y -side right -expand 1
pack .srl_xc -in .nb.dec_fr.cipher_frame -fill x -side bottom -expand 1
pack .nb.dec_fr.cipher_frame.txt -side left -expand 1 -fill both

pack .nb.dec_fr.param -fill both -expand 1 -ipadx 5 -ipady 5

pack .nb.dec_fr.param.mode_lbl .nb.dec_fr.param.key_size_cb .nb.dec_fr.param.keygen_button .nb.dec_fr.param.keysave_button .nb.dec_fr.param.keyload_button -side left -expand 1

pack .nb.dec_fr.param.exec_button -side left -padx 3

pack .nb.dec_fr.plain_frame -fill both -expand 1 -ipadx 5 -ipady 5
pack .srl_yd -in .nb.dec_fr.plain_frame -fill y -side right -expand 1
pack .srl_xd -in .nb.dec_fr.plain_frame -fill x -side bottom -expand 1
pack .nb.dec_fr.plain_frame.txt -side left -expand 1 -fill both

pack .nb.dec_fr.exit_button -side left -fill none -pady 5 -padx 3 -ipadx 30 -expand 1

# --------------------------------------------

.nb add .nb.enc_fr -text "RSA Encryption (with public key)"
.nb add .nb.dec_fr -text "RSA Decryption (with private key)"
.nb select .nb.enc_fr
ttk::notebook::enableTraversal .nb

pack .nb

wm title . "Multi-liner RSA encryption/decryption - Janusz Nawrat (2015)"
wm protocol . WM_DELETE_WINDOW {exit}
wm resizable . 0 0

Informacje Janusz Nawrat
Just ordinary man who likes thinking...

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

TOMASZ WEŁNA

artysta grafik | wykładowca

PRACOWNIA OKO

Szkoła Rysunku Malarstwa i Grafiki DR TOMASZA WEŁNY | KRAKÓW | Plac Matejki 10 | tel 691 81 75 74

Piękno neurobiologii

Blog Jerzego Vetulaniego

Teoria muzyki, zasady muzyki, podstawy muzyki

Teoria muzyki, zasady muzyki, podstawy muzyki - czyli to co każdy amator muzyki wiedzieć powinien :)

Personal Development & Inspirations

Przemyślenia i refleksje, którymi warto się podzielić (blog by Janusz Nawrat)

Business IT Cooperation Platform

Biznes i IT - dwa światy, które muszą współdziałać

%d bloggers like this: