Last active
December 27, 2015 21:09
-
-
Save bhelx/7389954 to your computer and use it in GitHub Desktop.
Securely store and retrieve a file from an external drive
This file contains 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
# This script allows securely storing and retrieving a file to USB drive using rbnacl | |
# | |
# Usage: | |
# | |
# 1) Generate a private key: | |
# | |
# ruby safe_store.rb --generate-key -k /Volumes/SAFEUSB/my_private_key.key | |
# | |
# 2) Write the ciphertext file to your drive (mine is named PATRIOT). | |
# This will write a file at /Volumes/PATRIOT/plain.txt.ctxt: | |
# | |
# ruby safe_store.rb -p plain.txt -k /Volumes/SAFEUSB/my_private_key.key -d /Volumes/PATRIOT/ | |
# | |
# 3) To decrypt from drive. This will write to current working directory by default (./plain.txt) | |
# | |
# ruby safe_store.rb -c ~/code/plain.txt.ctxt -k /Volumes/SAFEUSB/my_private_key.key | |
# | |
require 'rbnacl' | |
require 'json' | |
require 'optparse' | |
class CipherFile | |
attr_accessor :nonce, :ciphertext | |
def self.load(file_path) | |
@file = File.open(file_path) | |
Marshal.load(@file.read) | |
end | |
def initialize(nonce, ciphertext) | |
@nonce = nonce | |
@ciphertext = ciphertext | |
end | |
def marshal_dump | |
[@nonce, @ciphertext] | |
end | |
def marshal_load(array) | |
@nonce, @ciphertext = array | |
end | |
def write(file_path) | |
IO.write(file_path, Marshal.dump(self)) | |
end | |
end | |
options = {} | |
OptionParser.new do |opts| | |
opts.banner = "Usage: ruby safe_store.rb [options]" | |
opts.on("-k path", String, "Key File") do |keyfile| | |
options[:keyfile] = keyfile | |
end | |
opts.on("-p path", String, "Plaintext file") do |plaintext| | |
options[:plaintext] = plaintext | |
end | |
opts.on("-c path", String, "Ciphertext file") do |ciphertext| | |
options[:ciphertext] = ciphertext | |
end | |
opts.on("-d path", String, "Destination folder") do |destination| | |
options[:destination] = destination | |
end | |
opts.on("--generate-key", "Generate keyfile") do |generate| | |
options[:generatekey] = generate | |
end | |
end.parse! | |
# generate keyfile here | |
if options[:generatekey] | |
keyfile = options[:keyfile] || 'private_key.key' | |
key = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes) | |
IO.write(keyfile, key) | |
puts "Key generated at #{keyfile}" | |
exit | |
end | |
key = IO.read(options[:keyfile]) | |
# decrypt | |
if options[:ciphertext] | |
cipher_file = CipherFile.load(options[:ciphertext]) | |
secret_box = RbNaCl::SecretBox.new(key) | |
nonce = cipher_file.nonce | |
plaintext = secret_box.decrypt(nonce, cipher_file.ciphertext) | |
plaintext_file = File.basename(options[:ciphertext], 'ctxt') | |
plaintext_file = File.join(options[:destination], plaintext_file) if options[:destination] | |
IO.write(plaintext_file, plaintext) | |
puts "Wrote plaintext to #{plaintext_file}" | |
end | |
if options[:plaintext] | |
secret_box = RbNaCl::SecretBox.new(key) | |
nonce = RbNaCl::Random.random_bytes(secret_box.nonce_bytes) | |
plaintext = IO.read(options[:plaintext]) | |
ciphertext = secret_box.encrypt(nonce, plaintext) | |
file_path = File.basename(options[:plaintext]) + '.ctxt' | |
file_path = File.join(options[:destination], file_path) if options[:destination] | |
cipherfile = CipherFile.new(nonce, ciphertext) | |
IO.write(file_path, Marshal.dump(cipherfile)) | |
puts "Wrote ciphertext to #{file_path}" | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment