I need to write a simple tool which encrypts/decrypts files.
I guess the best way is to use OpenSSL:
Generate a key:
openssl rand -base64 2048 > secret_key
Encrypt a file:
openssl aes-256-cbc -a -e -in file -out file.enc -k secret_key
Decrypt a file:
openssl aes-256-cbc -d -in file.enc -out file -k secret_key
Is there an easy way to implement this in Ruby? Is there a better way to do that? Using PGP maybe?
Encrypting Files with Open PGPGet your trading partner's public key to encrypt the file. Import your trading partner's public key into a Key Vault. Use your file transfer tool to create a Project to encrypt the file. Sign the file with your private key if required.
Go to “File > Preferences > Extensions” and search Encryption-VScode then install and restart the editor. When you want to encrypt a file press CTRL + SHIFT + P to open the command prompt and type “Encrypt”. You'll be prompted to enter a pass phrase and the current text document will turn into an encrypted text string.
Ruby's OpenSSL is a thin wrapper around OpenSSL itself and provides almost all the functionality that OpenSSL itself does, so yes, there's a one-to-one mapping for all your examples:
openssl rand -base64 2048 > secret_key
That's actually exaggerated, you are using AES-256, so you only need a 256 bit key, you are not using RSA here. Ruby OpenSSL takes this decision off your shoulders, it will automatically determine the correct key size given the algorithm you want to use.
You are also making the mistake of using a deterministic IV during your encryption. Why? Because you don't specify an IV at all, OpenSSL itself will default to an IV of all zero bytes. That is not a good thing, so I'll show you the correct way to do it, for more information have a look at the Cipher documentation.
require 'openssl'
# encryption
cipher = OpenSSL::Cipher.new('aes-256-cbc')
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv
buf = ""
File.open("file.enc", "wb") do |outf|
File.open("file", "rb") do |inf|
while inf.read(4096, buf)
outf << cipher.update(buf)
end
outf << cipher.final
end
end
# decryption
cipher = OpenSSL::Cipher.new('aes-256-cbc')
cipher.decrypt
cipher.key = key
cipher.iv = iv # key and iv are the ones from above
buf = ""
File.open("file.dec", "wb") do |outf|
File.open("file.enc", "rb") do |inf|
while inf.read(4096, buf)
outf << cipher.update(buf)
end
outf << cipher.final
end
end
As you can see, encryption and decryption are fairly similar, so you can probably combine the streaming reading/writing into one shared method and just pass it a properly configured Cipher
plus the corresponding file names, I just stated them explicitly for the sake of clarity.
If you'd like to Base64-encode the key (and probably the IV, too), you can use the Base64 module:
base64_key = Base64.encode64(key)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With