Created
December 10, 2024 17:02
-
-
Save Inversion-des/0d0f538a624a57c85808db7f60769e4e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'optparse' | |
class Practice | |
def initialize | |
@fname = 'data.txt' | |
# predefined key for the demo (32-byte) | |
@key = "12345678901234567890123456789012" | |
# prepage libraries in bg for faster start | |
@libs_loading_thr = Thread.new do | |
require 'openssl' | |
require 'base64' | |
end | |
#-- parse cmd options | |
opt_parser = OptionParser.new do |opts| | |
opts.banner = 'Accepted cmd options:' | |
opts.on '--demo', 'Interactive demo' do | |
demo | |
end | |
opts.on '-e', '--encrypt', 'Encrypt '+@fname do | |
ensure_file_exists! | |
puts "Encrypting #{@fname}..." | |
@libs_loading_thr.join | |
encrypt_file | |
end | |
opts.on '-d', '--decrypt', 'Decrypt '+@fname do | |
ensure_file_exists! | |
puts "Decrypting #{@fname}..." | |
@libs_loading_thr.join | |
decrypt_file | |
end | |
end | |
# if no options -- show help | |
if ARGV.empty? | |
puts opt_parser.help | |
exit | |
end | |
opt_parser.parse! | |
rescue RuntimeError | |
puts 'Error: '+$!.to_s | |
end | |
def demo | |
# create the file if not exists | |
unless File.exist? @fname | |
File.write @fname, 'This is a secret message.' | |
end | |
puts "Prepare #{@fname} in the current folder." | |
print 'Press Enter when ready -- file content will be encrypted...' | |
@libs_loading_thr.join | |
gets | |
encrypt_file | |
print 'Press Enter to decrypt the text...' | |
gets | |
decrypt_file | |
end | |
def encrypt_file | |
text = File.read @fname | |
encrypted_text = aes_encrypt(text, @key) | |
File.write @fname, encrypted_text | |
puts 'Now, text in the file is encrypted.' | |
end | |
def decrypt_file | |
encrypted_text = File.read @fname | |
decrypted_text = aes_decrypt(encrypted_text, @key) | |
File.write @fname, decrypted_text | |
puts 'Now, text in the file is decrypted.' | |
end | |
def ensure_file_exists! | |
raise "File not found: #{@fname}" unless File.exist? @fname | |
end | |
# AES256 encryption | |
def aes_encrypt(text, key) | |
cipher = get_cipher.tap { _1.encrypt; _1.key = key } | |
iv = cipher.random_iv # 16 bytes | |
cipher_text = cipher.update(text) + cipher.final | |
# *ensure there is no newline char in the encrypted text | |
Base64.strict_encode64(iv + cipher_text) | |
end | |
def aes_decrypt(encrypted_text, key) | |
decrypted_text = Base64.decode64(encrypted_text) | |
iv, cipher_text = decrypted_text.then { [_1[0..15], _1[16..]] } | |
cipher = get_cipher.tap { _1.decrypt; _1.key = key; _1.iv = iv } | |
cipher.update(cipher_text) + cipher.final | |
rescue | |
raise 'Looks like file was not encrypted' | |
end | |
def get_cipher | |
OpenSSL::Cipher::AES256.new(:CBC) | |
end | |
end | |
Practice.new |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment