lib/symmetric_encryption/writer.rb in symmetric-encryption-1.1.1 vs lib/symmetric_encryption/writer.rb in symmetric-encryption-2.0.0
- old
+ new
@@ -1,5 +1,7 @@
+require 'openssl'
+
module SymmetricEncryption
# Write to encrypted files and other IO streams
#
# Features:
# * Encryption on the fly whilst writing files.
@@ -22,16 +24,27 @@
# written to the file
# If true, it forces header to true.
# Default: false
#
# :random_key [true|false]
- # Generates a new random key and iv for every new file or stream
+ # Generates a new random key for every new file or stream
# If true, it forces header to true. Version below then has no effect
- # The Random key and iv will be written to the file/stream in encrypted
+ # The Random key will be written to the file/stream in encrypted
# form as part of the header
- # The key and iv are both encrypted using the global key
+ # The key is encrypted using the global key
# Default: true
+ # Recommended: true.
+ # Setting to false will eventually expose the
+ # encryption key since too much data will be encrypted using the
+ # same encryption key
+ #
+ # :random_iv [true|false]
+ # Generates a new random iv for every new file or stream
+ # If true, it forces header to true.
+ # The Random iv will be written to the file/stream in encrypted
+ # form as part of the header
+ # Default: Value supplied above for :random_key
# Recommended: true. Setting to false will eventually expose the
# encryption key since too much data will be encrypted using the
# same encryption key
#
# :header [true|false]
@@ -47,16 +60,21 @@
# When random_key is true, the version of the encryption key to use
# when encrypting the header portion of the file
#
# When random_key is false, the version of the encryption key to use
# to encrypt the entire file
- # Default: Current primary key
+ # Default: SymmetricEncryption.cipher
#
# :mode
# See File.open for open modes
# Default: 'w'
#
+ # :cipher_name
+ # The name of the cipher to use only if both :random_key and
+ # :random_iv are true.
+ # Default: SymmetricEncryption.cipher.cipher_name
+ #
# Note: Compression occurs before encryption
#
#
# # Example: Encrypt and write data to a file
# SymmetricEncryption::Writer.open('test_file') do |file|
@@ -95,25 +113,53 @@
end
end
# Encrypt data before writing to the supplied stream
def initialize(ios,options={})
- @ios = ios
- header = options.fetch(:header, true)
+ @ios = ios
+ header = options.fetch(:header, true)
+ random_key = options.fetch(:random_key, true)
+ random_iv = options.fetch(:random_iv, random_key)
+ raise "When :random_key is true, :random_iv must also be true" if random_key && !random_iv
# Compress is only used at this point for setting the flag in the header
- random_key = options.fetch(:random_key, true)
- compress = options.fetch(:compress, false)
- # Force header if compressed or using random iv, key pair
- header = true if compress || random_key
+ compress = options.fetch(:compress, false)
+ version = options[:version]
+ cipher_name = options[:cipher_name]
+ raise "Cannot supply a :cipher_name unless both :random_key and :random_iv are true" if cipher_name && !random_key && !random_iv
- # Create random cipher or use global primary cipher
- @cipher = random_key ? SymmetricEncryption::Cipher.random_cipher : SymmetricEncryption.cipher(options[:version])
- raise "Cipher with version:#{options[:version]} not found in any of the configured SymmetricEncryption ciphers" unless @cipher
+ # Force header if compressed or using random iv, key
+ header = true if compress || random_key || random_iv
- @stream_cipher = @cipher.send(:openssl_cipher, :encrypt)
+ cipher = nil
+ if random_key
+ # Version of key used to encrypt the random key
+ version = SymmetricEncryption.cipher.version
+ else
+ # Use global key if a new random one is not being generated
+ cipher = SymmetricEncryption.cipher(version)
+ raise "Cipher with version:#{version} not found in any of the configured SymmetricEncryption ciphers" unless cipher
+ # Version of key used to encrypt the data
+ version = cipher.version
+ end
+ @stream_cipher = ::OpenSSL::Cipher.new(cipher_name || SymmetricEncryption.cipher.cipher_name)
+ @stream_cipher.encrypt
+
+ key = random_key ? @stream_cipher.random_key : cipher.send(:key)
+ iv = random_iv ? @stream_cipher.random_iv : cipher.send(:iv)
+
+ @stream_cipher.key = key
+ @stream_cipher.iv = iv if iv
+
# Write the Encryption header including the random iv, key, and cipher
- @ios.write(@cipher.magic_header(compress, random_key, random_key, random_key)) if header
+ if header
+ @ios.write(Cipher.magic_header(
+ version,
+ compress,
+ random_iv ? iv : nil,
+ random_key ? key : nil,
+ cipher_name))
+ end
end
# Close the IO Stream
# Flushes any unwritten data
#