Jak szybko opracować proste narzędzie do szyfrowania i deszyfrowania plików tekstowych

Random hexadecimal codes on a computer monitor.  Shallow depth of field.Czasem pojawia się potrzeba posiadania, czy też udostępnienia innym, prostego w użyciu narzędzia do szyfrowania i deszyfrowania plików tekstowych,  zwłaszcza takiego, które pozostaje niezależne od systemu operacyjnego komputera, na którym ma być uruchamiane – słowem takiego, które równie dobrze będzie działało na wszystkich Windowsach, na Linuxach oraz na innych systemach unixowych, a także na MacOS-ie. O potrzebie tego typu możemy mówić na przykład wtedy, kiedy bezzwłocznie trzeba przesłać w bezpieczny sposób nieco dokumentacji przez Internet, a chcemy to zrobić stosując silne szyfrowanie symetryczne.  Oczywiście, że można w tym celu pokusić się o użycie jakiegoś komercyjnego rozwiązania dedykowanego lub zrobić to darmowym oprogramowaniem napisanym przez kogoś innego. Można też  po prostu skorzystać z możliwości oferowanych przez OpenSSL-a. Jednak – dla większej zabawy – można też sobie poradzić zupełnie inaczej, dysponując jedynie interpreterem języka Ruby, odrobiną umiejętności programistycznych, a co ważne, niczego dodatkowo nie instalując na komputerach (no może za wyjątkiem biblioteki kryptograficznej wykorzystywanej w kodzie skryptu).

Właśnie w tym celu napisałem skrypt CRYPTO. Uruchomienie go z opcją –h lub –help wyprowadza podpowiedź poprawnej składni wywołania:

C:\scripts>ruby crypto.rb --help
Proper syntax: ruby crypto.rb [options]
-f, --filename filename          Filename
-o, --operation operation        Type of operation
-k, --key key                    Crypto key password
-a, --alg alg                    Crypto algorithm
-h, --help                       Displays Help

Składnia jest – przyznam nieskromnie – dość inteligentnie kontrolowana przez fragment kodu opartego o bardzo dobrą bibliotekę OptionParser, która zdejmuje z programisty obowiązek manualnego sprawdzania poprawności wywołania skryptu oraz użytych w jego wywołaniu opcji, przy pomocy instrukcji warunkowych oraz odwołań do tablicy ARGV. Zresztą pisząc program, zadbałem o to, że jeśli użytkownik w linii poleceń nie poda wszystkich opcji wywołania, wówczas skrypt zapyta o nie już na etapie działania. Na przykład jeśli zapomnimy podać typ operacji i algorytm enkrypcji, wówczas dialog z programem może wyglądać tak:

C:\ scripts>ruby crypto.rb -f plaintext_file.txt -k "SeCur3_KEE"
Enter type of operation (encrypt/decrypt): encrypt
Enter the crypto algorithm (3des/aes/blowfish/plaintext): blowfish

f9ERPu8ytyOnADd35P7izIV1qmEJ7oUj
LsUHTR0xPip6HemkECyMOW4pYmlxHOBX
alH89nVXHKCoD5MMPWTlPA==
U1iVcZmEezA=

Wybór algorytmów kryptograficznych jest – przyznam – arbitralny. Dlaczego takie, a nie inne? Takich po prostu sam potrzebowałem, ale czytelnikom pozostawiam swobodę, by wzbogacić listę algorytmów o jeszcze inne. Dodam jedynie, bo nie patrząc w kod, tego po prostu nie widać, że użyty w skrypcie algorytm AES wykorzystuje najbezpieczniejszą dla siebie wersję długości klucza, czyli 256 bitów.

Jeśli chcielibyśmy naszą zabawę kryptograficzna uczynić jeszcze bezpieczniejszą, to oczywiście można dodatkowo w funkcjach szyfrujących i deszyfrujących zastosować tzw. sól (ang. salt). Czym jest sól? Otóż, mówiąc najprościej, jest to dodatkowy łańcuch znakowy, który jest wykorzystywany wraz z hasłem do klucza kryptograficznego do utworzenia skrótu (hasza). W wersji bez soli, hasło do klucza występuje w postaci podanej jawnym tekstem w linii poleceń skryptu, zaś w wersji z solą, jest haszem złożonym z tegoż klucza i soli. Ważne jest, w przypadku zastosowania soli, aby była ona identyczna w operacji szyfrowania i deszyfrowania. W skrypcie sól występuje pod postacią globalnej zmiennej zadeklarowanej i zdefiniowanej na początku jego kodu. Domyślną jej wartością jest łańcuch pusty, ale możemy to w każdej chwili zmienić, modyfikując kod. Możemy też zmodyfikować kod w taki sposób, aby możliwość podania soli pojawiła się na liście opcji wywołania. Decyzję i swobodę działania w tej materii pozostawiam czytelnikom.

Nie zapomnijcie proszę zainstalować bibliotek, z których korzysta skrypt:

gem install ezcrypto
gem install OptionParser

Życzę Wam – jak zawsze – miłej zabawy w „skryptowanie”.

Oto listing kodu skryptu:

require 'ezcrypto'
require 'optparse'

$system_salt = '' # Salt to strengthen encryption
$key = "" # Password for encryption key generation

# ---------------------------------------------------------------------
# Encryption of given plaintext using the key dependent from 
# the password provided
# Salt is provided by global variable $system_salt
# Crypto algorithm is given by the parameter provided to the function.
# --------------------------------------------------------------------
def encrypt(alg, password, string)
   begin
      case alg
         when "3des" then key = EzCrypto::Key.with_password(password, $system_salt, :algorithm => 'des3')
         when "aes" then key = EzCrypto::Key.with_password(password, $system_salt, :algorithm => 'aes256')
         when "blowfish" then key = EzCrypto::Key.with_password(password, $system_salt, :algorithm => 'blowfish')
         when "plaintext" then return string
         else key = EzCrypto::Key.with_password(password, $system_salt, :algorithm => 'aes256')
      end
      encrypted_text = key.encrypt64(string)
   rescue => e
      p e.message
      # p e.backtrace
   end
   return encrypted_text
end

# --------------------------------------------------------------------
# Decryption of given ciphertext using the key dependent from 
# the password provided
# Salt is provided by global variable $system_salt
# Crypto algorithm is given by the parameter provided to the function.
# --------------------------------------------------------------------
def decrypt(alg, password, cipher)
   begin
      case alg
         when "3des" then key = EzCrypto::Key.with_password(password, $system_salt, :algorithm => 'des3')
         when "aes" then key = EzCrypto::Key.with_password(password, $system_salt, :algorithm => 'aes256')
         when "blowfish" then key = EzCrypto::Key.with_password(password, $system_salt, :algorithm => 'blowfish')
         when "plaintext" then return cipher
         else key = EzCrypto::Key.with_password(password, $system_salt, :algorithm => 'aes256')
      end
      decrypted_text = key.decrypt64(cipher)
   rescue => e
      p e.message
      # p e.backtrace
   end
   return decrypted_text
end

options = {:file => nil, :operation => nil, :key => nil, :alg => nil}

parser = OptionParser.new do |opts|
   opts.banner = "Proper syntax: #{File.basename($0)} [options]"
   opts.on('-f', '--filename filename', 'Filename') do |filename|
      options[:file] = filename;
   end

   opts.on('-o', '--operation operation', 'Type of operation') do |oper|
      options[:operation] = oper;
   end

   opts.on('-k', '--key key', 'Crypto key password') do |cryptkey|
      options[:key] = cryptkey;
   end
 
   opts.on('-a', '--alg alg', 'Crypto algorithm') do |algorithm|
      options[:alg] = algorithm;
   end
 
   opts.on('-h', '--help', 'Displays Help') do
      puts opts
      exit
   end
end

parser.parse!

if options[:file] == nil
   print 'Enter the file name: '
   options[:file] = gets.chomp
end

input_file = options[:file]

if options[:operation] == nil
   print 'Enter type of operation (encrypt/decrypt): '
   options[:operation] = gets.chomp
end

oper = options[:operation]

if options[:key] == nil
 print 'Enter the password to crypto key: '
 options[:key] = gets.chomp
end

key = options[:key]

if options[:alg] == nil
   print 'Enter the crypto algorithm (3des/aes/blowfish/plaintext): '
   options[:alg] = gets.chomp
end

alg = options[:alg]

unless File.readable?(input_file)
   puts "Problem with reading file: #{input_file}"
   exit
end

case oper
   when "encrypt" then
      IO.foreach(input_file) do |wiersz|
         puts encrypt(alg, key, wiersz)
      end 
   when "decrypt" then
      IO.foreach(input_file) do |wiersz|
         puts decrypt(alg, key, wiersz)
      end
   else 
      # Default action is encryption
      IO.foreach(input_file) do |wiersz|
         puts encrypt(alg, key, wiersz)
      end 
end

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: