Skip to content

Instantly share code, notes, and snippets.

@bradly
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bradly/60aaaa416584d81ca316 to your computer and use it in GitHub Desktop.
Save bradly/60aaaa416584d81ca316 to your computer and use it in GitHub Desktop.
buffer = ''
cipher = nil
render :text => proc { |response, output|
s3.get(bucket, key_path) do |chunk|
# decrypt chunk
if buffer == ''
# first chunk
buffer << chunk
# extract the magic string and salt
magic_test = buffer.slice!(0..EncryptionHelper.magic_string.length-1)
if magic_test != EncryptionHelper.magic_string
raise "Magic Encryption Mismatch! - wanted #{EncryptionHelper.magic_string} but got #{magic_test}"
end
salt = buffer.slice!(0..EncryptionHelper.salt_length-1)
cipher = EncryptionHelper.make_cipher(artifact.client.encryption_password, salt, 'decrypt')
else
buffer << chunk
end
# TODO: don't write to output every time - save up until each chunk is decrypted
while buffer.length > EncryptionHelper.block_size
output.write(cipher.update(buffer.slice!(0..(EncryptionHelper.block_size-1))))
end
end
output.write(cipher.update(buffer))
output.write(cipher.final)
}
require 'openssl'
class EncryptionHelper
def self.block_size
512
end
def self.salt_length
8
end
def self.magic_string
'Salted__'
end
def self.make_cipher(password, salt, mode = 'encrypt', alg = 'AES-256-CBC')
if password.nil? || password.to_s == ''
raise "Password cannot be blank!"
end
cipher = OpenSSL::Cipher::Cipher.new(alg)
if mode.to_s == 'encrypt'
cipher.encrypt
else
cipher.decrypt
end
cipher.pkcs5_keyivgen(password.to_s, salt.to_s, 1)
cipher.padding = 1
cipher
end
def self.encrypt(file_path, password, alg = 'AES-256-CBC')
file_to_encrypt = File.open(file_path, "rb")
salt = OpenSSL::Random::pseudo_bytes(self.salt_length)
cipher = make_cipher(password, salt)
encrypted_tmp_file = Tempfile.new("encrypt_file", "#{RAILS_ROOT}/tmp")
encrypted_tmp_file.binmode
encrypted_tmp_file.write(self.magic_string)
encrypted_tmp_file.write(salt)
loop do
buffer = file_to_encrypt.read(self.block_size) or break
encrypted_tmp_file.write(cipher.update(buffer))
end
encrypted_tmp_file.write(cipher.final)
file_to_encrypt.close
encrypted_tmp_file.close
encrypted_tmp_file
end
def self.decrypt(file_path, password, alg = 'AES-256-CBC')
plain_tmp_file = TempfileWithExtension.new(File::basename(file_path), "#{RAILS_ROOT}/tmp")
plain_tmp_file.binmode
open(file_path, "rb") do |file_to_decrypt|
file_to_decrypt.binmode
magic_test = file_to_decrypt.read(self.magic_string.length)
if (magic_test != self.magic_string)
raise "Magic Encryption String doesn't match!"
end
salt = file_to_decrypt.read(self.salt_length)
cipher = make_cipher(password, salt, 'decrypt')
loop do
buffer = file_to_decrypt.read(self.block_size) or break
plain_tmp_file.write(cipher.update(buffer))
end
plain_tmp_file.write(cipher.final)
plain_tmp_file.rewind
end
plain_tmp_file
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment