Szyfrowanie i deszyfrowanie dowolnych plików – narzędzia skryptowe

encryption-100052899-largeKiedy zachodzi potrzeba dysponowania skutecznymi narzędziami do szyfrowania i deszyfrowania plików dowolnego rodzaju – tekstowych i binarnych, z pomocą przychodzi ulubiony język programowania skryptowego w towarzystwie chęci i odrobiny wolnego czasu na zaprojektowanie i opracowanie kodu.

W tych warunkach można błyskawicznie napisać w pełni przenośny, niezależny od systemów operacyjnych kod, który pozwala na wykorzystanie silnych algorytmów enkrypcji – do wyboru przez programistę z szerokiej gamy możliwości oferowanych przez biblioteki OpenSSL.

Na potrzeby tego artykułu powstały dwa skrypty. Oba wywoływane są z poziomu linii poleceń systemu operacyjnego z zestawem opcji uruchomieniowych.

Pierwszy skrypt służy do szyfrowania i deszyfrowania pojedynczych plików.

/home/user $  ruby file_crypto.rb --help
Simple file encryptor and decryptor by Janusz Nawrat (2014)
-----------------------------------------------------------
Usage: file_crypto -o operation -a algorithm -k crypto_key -f input_file
where:
 -o or --operation should be: e for encryption or d for decryption
 -a or --algorithm should be: 3des, aes, flowfish, idea, camelia, rc4, cast
 -k or --key is the password protecting crypto key generated by the program
 -f or --file is the name of the input file with stuff to encrypt or decrypt

Drugi skrypt służy do rekursywnego szyfrowania i deszyfrowania plików we wskazanych katalogach.

/home/user $  ruby dir_crypto.rb -h
Simple directory recursive encryptor and decryptor by Janusz Nawrat (2014)
-----------------------------------------------------------
Usage: dir_crypto -o operation -a algorithm -k crypto_key -d directory
where:
 -o or --operation should be: e for encryption or d for decryption
 -a or --algorithm should be: 3des, aes, flowfish, idea, camelia, rc4, cast
 -k or --key is the password protecting crypto key generated by the program
 -d or --directory is the name of directory with file to encrypt or decrypt

Oba skrypty mogą tez działać w trybie interaktywnym i tak się dzieje, kiedy zostaną wywołane bez podania parametrów lub kiedy lista obligatoryjnych parametrów wywołania jest niekompletna. W tym drugim przypadku program, po uruchomieniu zapyta o brakujący parametr.

Skrypty szyfrują pliki wejściowe i zapisują efekt swojego działania do plików wynikowych o bazowej nazwie identycznej z nazwą pliku wejściowego z dodaniem rozszerzenia nazwy ‘.enc’.

Efekt operacji odszyfrowywania jest z kolei zapisywany do pliku o nazwie z rozszerzeniem ‘.dec’, by uniemożliwić nadpisanie ważnych plików z danymi.

Nic oczywiście nie stoi na przeszkodzie, by zmienić to zachowanie programu, ale zmiany pozostawiam w gestii szanownych czytelników i gości mojego bloga.

Przed uruchomieniem skryptów proszę nie zapomnieć zainstalować bibliotek z których skrypty korzystają (na które powołujemy się klauzulami require).

gem install OptionParser
gem install openssl
gem install find

W razie potrzeby udostępnienia programów użytkownikom nie mającym zainstalowanego interpretera języka Ruby, polecam skonsolidowanie skryptów i wymaganych bibliotek do postaci jednego pliku wykonywalnego. Doskonale nadaje się do tego celu biblioteka OCRA. Można ją bardzo prosto zainstalować w swoim systemie poleceniem:

gem install ocra

by potem móc ‚kompilować’ (to nie jest właściwa kompilacja tylko konsolidacja, ale efektem jest plik EXE) swoje skrypty poleceniem uruchamianym z poziomu interpretera poleceń systemu operacyjnego:

ocra nazwa_skryptu.rb

Jeśli nie zmienimy tego odpowiednią opcja wywołania programu ocra, powstanie w efekcie program wynikowy o nazwie nazwa_skryptu.exe.

Dalszy rozwój skryptów może pójść w kierunku:

  • Obsługi dodatkowych algorytmów szyfrowania
  • Liczenia kryptograficznych sum kontrolnych lub elektronicznego podpisywania plików
  • Zapisywania plików wynikowych w innych katalogach lub w bazie danych.
  • Opracowania interfejsów graficznych, na przykład opartych o bibliotekę Tk lb GTK.

To tylko kilka pomysłów. Na pewno czytelnicy wpadną na inne, bardziej oryginalne pomysły.

Jak zwykle dziękuję za wizytę na moim blogu i czas poświęcony na czytanie moich artykułów. Tradycyjnie zachęcam też do modyfikacji kodów i dalszego rozwoju pomysłów.

Oto kody skryptów:

Skrypt do szyfrowania i deszyfrowania jednego wskazanego pliku:

require 'optparse'
require 'openssl'

def banner
	puts "Simple file encryptor and decryptor by Janusz Nawrat (2014)"
	puts "-----------------------------------------------------------"
	puts "Usage: #{File::basename($0, '.rb')} -o operation -a algorithm -k crypto_key -f input_file\n"
	puts "where:"
	puts "  -o or --operation should be: e for encryption or d for decryption"
	puts "  -a or --algorithm should be: 3des, aes, flowfish, idea, camelia, rc4, cast"
	puts "  -k or --key is the password protecting crypto key generated by the program"
	puts "  -f or --file is the name of the input file with stuff to encrypt or decrypt\n"
end

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

parser = OptionParser.new do |opts|
	opts.banner = "Usage: #{$0} [options]"
	
	opts.on('-o', '--operation oper', 'Crypto operation (ancryption/decryption)') do |oper|
		options[:operation] = oper;
	end

	opts.on('-a', '--algorithm alg', 'Crypto algorithm') do |alg|
		options[:algorithm] = alg;
	end

	opts.on('-k', '--key key', 'Crypto key') do |key|
		options[:key] = key;
	end
	
	opts.on('-f', '--file file', 'Input file') do |file|
		options[:file] = file;
	end	
	
	opts.on('-h', '--help', 'Displays Help') do
		banner
		exit
	end
end

parser.parse!

shown = 0 # if the banner was already shown

if options[:operation] == nil
	if shown == 0
		banner
		shown = 1
	end	
	print 'Enter type of crypto operation (e - encryption or d - decryption): '
        options[:operation] = gets.chomp
	unless (options[:operation] == 'e') or (options[:operation] == 'd')
		STDERR.puts "Unknown operation type: must be \"e\" or \"d\""
		exit
	end
end

if options[:algorithm] == nil
	if shown == 0
		banner
		shown = 1
	end	
	print 'Enter type of crypto algorithm (3des, aes, flowfish, idea, camelia, rc4, cast): '
        options[:algorithm] = gets.chomp
end

if options[:key] == nil
	if shown == 0
		banner
		shown = 1
	end	
	print 'Enter crypto key: '
        options[:key] = gets.chomp
end

if options[:file] == nil
	if shown == 0
		banner
		shown = 1
	end	
	case options[:operation]
		when "e"
			crypt_oper = "encrypt"
		when "d"
			crypt_oper = "decrypt"
	end
	print "Enter file with stuff to: #{crypt_oper}: "
        options[:file] = gets.chomp
end

def encryption(input_file, algorithm, crypto_key)
	puts "Encrypting #{File::basename(input_file)} --> #{File::basename(input_file)}.enc"
	begin
		cipher = OpenSSL::Cipher.new(algorithm)
		cipher.encrypt
		key = crypto_key; buf = ""
		File.open("#{input_file}.enc", "wb") do |outf|
			File.open(input_file, "rb") do |inf|
				while inf.read(4096, buf)
					outf << cipher.update(buf)
				end
			        outf << cipher.final 			
                        end 		
                end 	
        rescue	Exception => e
		STDERR.puts "Problem within encryption function: #{e.message}"
		return
	end
	puts "... done."
end

def decryption(input_file, algorithm, crypto_key)
	puts "Decrypting #{File::basename(input_file)} --> #{File::basename(input_file)}.dec"
	begin
		cipher = OpenSSL::Cipher.new(algorithm)
		cipher.decrypt
		key = crypto_key; buf = ""
		File.open("#{File::basename(input_file, "enc")}.dec", "wb") do |outf|
			File.open(input_file, "rb") do |inf|
				while inf.read(4096, buf)
					outf << cipher.update(buf)
				end
				outf << cipher.final 			
			end 		
		end 	
	rescue	Exception => e
		STDERR.puts "Problem with decryption function: #{e.message}"
		return
	end
	puts "... done."
end

input_file = options[:file]; algorithm = options[:alg]; crypto_key = options[:key]

unless File::exist?(input_file)
	STDERR.puts "Error in opening file: #{input_file}"
	exit
end

# 3des, aes, flowfish, idea, camelia, rc4, cast

case options[:algorithm]
	when "3des"
		algorithm = "des3"
	when "aes"
		algorithm = "aes-256-cbc"
	when "blowfish"
		algorithm = "bf"
	when "idea"
		algorithm = "idea-cbc"
	when "camelia"
		algorithm = "camellia-256-cbc"
	when "rc4"
		algorithm = "rc4"
	when "cast"
		algorithm = "cast5-cbc"
	else
		STDERR.puts "Unknown crypto algorithm. AES-256 was assumed as a default"
		algorithm = "aes-256-cbc"
end

case options[:operation]
	when 'e'
		encryption(input_file, algorithm, crypto_key)
	when 'd'
		decryption(input_file, algorithm, crypto_key)
end

Skrypt do rekursywnego szyfrowania i deszyfrowania plików we wskazanych katalogach:

require 'optparse'
require 'openssl'
require 'find'

def banner
	puts "Simple directory recursive encryptor and decryptor by Janusz Nawrat (2014)"
	puts "-----------------------------------------------------------"
	puts "Usage: #{File::basename($0, '.rb')} -o operation -a algorithm -k crypto_key -d directory\n"
	puts "where:"
	puts "  -o or --operation should be: e for encryption or d for decryption"
	puts "  -a or --algorithm should be: 3des, aes, flowfish, idea, camelia, rc4, cast"
	puts "  -k or --key is the password protecting crypto key generated by the program"
	puts "  -d or --directory is the name of directory with file to encrypt or decrypt\n"
end

options = {:operation => nil, :algorithm => nil, :key => nil, :directory => nil}

parser = OptionParser.new do |opts|
	opts.banner = "Usage: #{$0} [options]"
	
	opts.on('-o', '--operation oper', 'Crypto operation (ancryption/decryption)') do |oper|
		options[:operation] = oper;
	end

	opts.on('-a', '--algorithm alg', 'Crypto algorithm') do |alg|
		options[:algorithm] = alg;
	end

	opts.on('-k', '--key key', 'Crypto key') do |key|
		options[:key] = key;
	end
	
	opts.on('-d', '--directory directory', 'Directory') do |directory|
		options[:directory] = directory;
	end	
	
	opts.on('-h', '--help', 'Displays Help') do
		banner
		exit
	end
end

parser.parse!

shown = 0 # if the banner was already shown

if options[:operation] == nil
	if shown == 0
		banner
		shown = 1
	end	
	print 'Enter type of crypto operation (e - encryption or d - decryption): '
   	options[:operation] = gets.chomp
	unless (options[:operation] == 'e') or (options[:operation] == 'd')
		STDERR.puts "Unknown operation type: must be \"e\" or \"d\""
		exit
	end
end

if options[:algorithm] == nil
	if shown == 0
		banner
		shown = 1
	end	
	print 'Enter type of crypto algorithm (3des, aes, flowfish, idea, camelia, rc4, cast): '
        options[:algorithm] = gets.chomp
end

if options[:key] == nil
	if shown == 0
		banner
		shown = 1
	end	
	print 'Enter crypto key: '
        options[:key] = gets.chomp
end

if options[:directory] == nil
	if shown == 0
		banner
		shown = 1
	end	
	case options[:operation]
		when "e"
			crypt_oper = "encrypt"
		when "d"
			crypt_oper = "decrypt"
	end
	print "Enter directory with files to #{crypt_oper}: "
        options[:directory] = gets.chomp
end

def encryption(input_file, algorithm, crypto_key)
	puts "Encrypting #{File::basename(input_file)} --> #{File::basename(input_file)}.enc"
	begin
		cipher = OpenSSL::Cipher.new(algorithm)
		cipher.encrypt
		key = crypto_key; buf = ""
		File.open("#{input_file}.enc", "wb") do |outf|
			File.open(input_file, "rb") do |inf|
				while inf.read(4096, buf)
					outf << cipher.update(buf)
				end
				outf << cipher.final 			
			end 		
		end 	
	rescue	Exception => e
		STDERR.puts "Problem within encryption function: #{e.message}"
		return
	end
	puts "... done."
end

def decryption(input_file, algorithm, crypto_key)
	puts "Decrypting #{File::basename(input_file)} --> #{File::basename(input_file)}.dec"
	begin
		cipher = OpenSSL::Cipher.new(algorithm)
		cipher.decrypt
		key = crypto_key; buf = ""
		File.open("#{File::basename(input_file, "enc")}.dec", "wb") do |outf|
			File.open(input_file, "rb") do |inf|
				while inf.read(4096, buf)
					outf << cipher.update(buf)
				end
			        outf << cipher.final 			
			end 		
		end 	
	rescue	Exception => e
		STDERR.puts "Problem with decryption function: #{e.message}"
		return
	end
	puts "... done."
end

def encrypt_recursively(directory, algorithm, crypto_key)
	Find.find(directory) do |fname|   
		unless FileTest.directory?(fname) 	
			begin 		
				encryption(fname, algorithm, crypto_key)
			rescue => e
				STDERR.puts "Error in opening file: #{fname} during checksum calculation"
				STDERR.puts "Exception: #{e}"
			end	
		end
	end
end

def decrypt_recursively(directory, algorithm, crypto_key)
	Find.find(directory) do |fname|   
		unless FileTest.directory?(fname) 	
			begin
				if File::extname(fname) == ".enc"
					decryption(fname, algorithm, crypto_key)
				end	
			rescue => e
				STDERR.puts "Error in opening file: #{fname} during checksum calculation"
				STDERR.puts "Exception: #{e}"
			end	
		end
	end
end

directory = options[:directory]; algorithm = options[:alg]; crypto_key = options[:key]

unless File::directory?(directory)
	STDERR.puts "Error in opening directory: #{directory}"
	exit
end

# 3des, aes, flowfish, idea, camelia, rc4, cast

case options[:algorithm]
	when "3des"
		algorithm = "des3"
	when "aes"
		algorithm = "aes-256-cbc"
	when "blowfish"
		algorithm = "bf"
	when "idea"
		algorithm = "idea-cbc"
	when "camelia"
		algorithm = "camellia-256-cbc"
	when "rc4"
		algorithm = "rc4"
	when "cast"
		algorithm = "cast5-cbc"
	else
		STDERR.puts "Unknown crypto algorithm. AES-256 was assumed as a default"
		algorithm = "aes-256-cbc"
end

case options[:operation]
	when 'e'
		encrypt_recursively(directory, algorithm, crypto_key)
	when 'd'
		decrypt_recursively(directory, algorithm, crypto_key)
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: