lib/submodules/ably-ruby/lib/ably/util/crypto.rb in ably-rest-0.8.6 vs lib/submodules/ably-ruby/lib/ably/util/crypto.rb in ably-rest-0.8.9
- old
+ new
@@ -2,71 +2,84 @@
require 'openssl'
module Ably::Util
class Crypto
DEFAULTS = {
- algorithm: 'AES',
- mode: 'CBC',
- key_length: 128,
+ algorithm: 'aes',
+ mode: 'cbc',
+ key_length: 256,
}
BLOCK_LENGTH = 16
- # Configured options for this Crypto object, see {#initialize} for a list of configured options
+ # Configured {Ably::Models::CipherParams} for this Crypto object, see {#initialize} for a list of configureable options
#
- # @return [Hash]
- attr_reader :options
+ # @return [Ably::Models::CipherParams]
+ attr_reader :cipher_params
# Creates a {Ably::Util::Crypto} object
#
- # @param [Hash] options an options Hash used to configure the Crypto library
- # @option options [String] :key Required secret key used for encrypting and decrypting
- # @option options [String] :algorithm optional (default AES), specify the encryption algorithm supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
- # @option options [String] :mode optional (default CBC), specify the cipher mode supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
- # @option options [Integer] :key_length optional (default 128), specify the key length of the cipher supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
- # @option options [String] :combined optional (default AES-128-CBC), specify in one option the algorithm, key length and cipher of the cipher supported by {http://ruby-doc.org/stdlib-2.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html OpenSSL::Cipher}
+ # @param [Hash] params a Hash used to configure the Crypto library's {Ably::Models::CipherParams}
+ # @option params (see Ably::Models::CipherParams#initialize)
#
# @return [Ably::Util::Crypto]
#
# @example
- # crypto = Ably::Util::Crypto.new(key: 'mysecret')
+ # key = Ably::Util::Crypto.generate_random_key
+ # crypto = Ably::Util::Crypto.new(key: key)
# encrypted = crypto.encrypt('secret text')
# crypto.decrypt(decrypted) # => 'secret text'
#
- def initialize(options)
- raise ArgumentError, ':key is required' unless options.has_key?(:key)
- @options = DEFAULTS.merge(options).freeze
+ def initialize(params)
+ @fixed_iv = params.delete(:fixed_iv) if params.kind_of?(Hash)
+ @cipher_params = Ably::Models::CipherParams(params)
end
- # Obtain a default CipherParams. This uses default algorithm, mode and
- # padding and key length. A key and IV are generated using the default
- # system SecureRandom; the key may be obtained from the returned CipherParams
+ # Obtain a default {Ably::Models::CipherParams}. This uses default algorithm, mode and
+ # padding and key length. An IV is generated using the default
+ # system SecureRandom; the key may be obtained from the returned {Ably::Models::CipherParams}
# for out-of-band distribution to other clients.
+
+ # @param [Hash] params a Hash used to configure the Crypto library's {Ably::Models::CipherParams}
+ # @option params (see Ably::Models::CipherParams#initialize)
#
- # @return [Hash] CipherParam options Hash with attributes :key, :algorithn, :mode, :key_length
+ # @return [Ably::Models::CipherParams] Configured cipher params with :key, :algorithm, :mode, :key_length attributes
#
- def self.get_default_params(key = nil)
- params = DEFAULTS.merge(key: key)
- params[:key_length] = key.unpack('b*').first.length if params[:key]
- cipher_type = "#{params[:algorithm]}-#{params[:key_length]}-#{params[:mode]}"
- params[:key] = OpenSSL::Cipher.new(cipher_type.upcase).random_key unless params[:key]
- params
+ def self.get_default_params(params = {})
+ Ably::Models::CipherParams(params)
end
+ # Generate a random encryption key from the supplied keylength (or the
+ # default key_length of 256 if none supplied)
+ #
+ # @param [Integer] key_length Optional (default 256) key length for the generated random key. 128 and 256 bit key lengths are supported
+ # @return Binary String (byte array) with ASCII_8BIT encoding
+ #
+ def self.generate_random_key(key_length = DEFAULTS.fetch(:key_length))
+ params = DEFAULTS.merge(key_length: key_length)
+ OpenSSL::Cipher.new(cipher_type(params)).random_key
+ end
+
+ # The Cipher algorithm string such as AES-128-CBC
+ # @api private
+ def self.cipher_type(options)
+ Ably::Models::CipherParams.cipher_type(options)
+ end
+
# Encrypt payload using configured Cipher
#
# @param [String] payload the payload to be encrypted
# @param [Hash] encrypt_options an options Hash to configure the encrypt action
# @option encrypt_options [String] :iv optionally use the provided Initialization Vector instead of a randomly generated IV
#
- # @return [String] binary string with {Encoding::ASCII_8BIT} encoding
+ # @return [String] binary string with +Encoding::ASCII_8BIT+ encoding
#
def encrypt(payload, encrypt_options = {})
cipher = openssl_cipher
cipher.encrypt
cipher.key = key
- iv = encrypt_options[:iv] || options[:iv] || cipher.random_iv
+ iv = encrypt_options[:iv] || fixed_iv || cipher.random_iv
cipher.iv = iv
iv << cipher.update(payload) << cipher.final
end
@@ -88,33 +101,30 @@
decipher.iv = iv
decipher.update(encrypted_payload) << decipher.final
end
- # Generate a random key
- # @return [String]
- def random_key
- openssl_cipher.random_key
- end
-
# Generate a random IV
# @return [String]
def random_iv
openssl_cipher.random_iv
end
- # The Cipher algorithm string such as AES-128-CBC
+ private
+ # Used solely for tests to fix the IV instead of randomly generate one
+ attr_reader :fixed_iv
+
+ # Generate a random key
# @return [String]
- def cipher_type
- (options[:combined] || "#{options[:algorithm]}-#{options[:key_length]}-#{options[:mode]}").to_s.upcase
+ def random_key
+ openssl_cipher.random_key
end
- private
def key
- options[:key]
+ cipher_params.key
end
def openssl_cipher
- OpenSSL::Cipher.new(cipher_type)
+ @openssl_cipher ||= OpenSSL::Cipher.new(cipher_params.cipher_type)
end
end
end