ably 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +9 -0
  4. data/LICENSE.txt +1 -1
  5. data/README.md +8 -1
  6. data/Rakefile +10 -0
  7. data/ably.gemspec +18 -18
  8. data/lib/ably.rb +6 -5
  9. data/lib/ably/auth.rb +11 -14
  10. data/lib/ably/exceptions.rb +18 -15
  11. data/lib/ably/logger.rb +102 -0
  12. data/lib/ably/models/error_info.rb +1 -1
  13. data/lib/ably/models/message.rb +19 -5
  14. data/lib/ably/models/message_encoders/base.rb +107 -0
  15. data/lib/ably/models/message_encoders/base64.rb +39 -0
  16. data/lib/ably/models/message_encoders/cipher.rb +80 -0
  17. data/lib/ably/models/message_encoders/json.rb +33 -0
  18. data/lib/ably/models/message_encoders/utf8.rb +33 -0
  19. data/lib/ably/models/paginated_resource.rb +23 -6
  20. data/lib/ably/models/presence_message.rb +19 -7
  21. data/lib/ably/models/protocol_message.rb +5 -4
  22. data/lib/ably/models/token.rb +2 -2
  23. data/lib/ably/modules/channels_collection.rb +0 -3
  24. data/lib/ably/modules/conversions.rb +3 -3
  25. data/lib/ably/modules/encodeable.rb +68 -0
  26. data/lib/ably/modules/event_emitter.rb +10 -4
  27. data/lib/ably/modules/event_machine_helpers.rb +6 -4
  28. data/lib/ably/modules/http_helpers.rb +7 -2
  29. data/lib/ably/modules/model_common.rb +2 -0
  30. data/lib/ably/modules/state_emitter.rb +10 -1
  31. data/lib/ably/realtime.rb +19 -12
  32. data/lib/ably/realtime/channel.rb +26 -13
  33. data/lib/ably/realtime/client.rb +31 -7
  34. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +14 -3
  35. data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +13 -4
  36. data/lib/ably/realtime/connection.rb +152 -46
  37. data/lib/ably/realtime/connection/connection_manager.rb +168 -0
  38. data/lib/ably/realtime/connection/connection_state_machine.rb +56 -33
  39. data/lib/ably/realtime/connection/websocket_transport.rb +56 -29
  40. data/lib/ably/{models → realtime/models}/nil_channel.rb +1 -1
  41. data/lib/ably/realtime/presence.rb +38 -13
  42. data/lib/ably/rest.rb +7 -5
  43. data/lib/ably/rest/channel.rb +24 -3
  44. data/lib/ably/rest/client.rb +56 -17
  45. data/lib/ably/rest/middleware/encoder.rb +49 -0
  46. data/lib/ably/rest/middleware/exceptions.rb +3 -2
  47. data/lib/ably/rest/middleware/logger.rb +37 -0
  48. data/lib/ably/rest/presence.rb +10 -2
  49. data/lib/ably/util/crypto.rb +57 -29
  50. data/lib/ably/util/pub_sub.rb +11 -0
  51. data/lib/ably/version.rb +1 -1
  52. data/spec/acceptance/realtime/channel_spec.rb +65 -7
  53. data/spec/acceptance/realtime/connection_spec.rb +123 -27
  54. data/spec/acceptance/realtime/message_spec.rb +319 -34
  55. data/spec/acceptance/realtime/presence_history_spec.rb +58 -0
  56. data/spec/acceptance/realtime/presence_spec.rb +160 -18
  57. data/spec/acceptance/rest/auth_spec.rb +93 -49
  58. data/spec/acceptance/rest/base_spec.rb +10 -10
  59. data/spec/acceptance/rest/channel_spec.rb +35 -19
  60. data/spec/acceptance/rest/channels_spec.rb +8 -8
  61. data/spec/acceptance/rest/message_spec.rb +224 -0
  62. data/spec/acceptance/rest/presence_spec.rb +159 -23
  63. data/spec/acceptance/rest/stats_spec.rb +5 -5
  64. data/spec/acceptance/rest/time_spec.rb +4 -4
  65. data/spec/integration/rest/auth.rb +1 -1
  66. data/spec/resources/crypto-data-128.json +56 -0
  67. data/spec/resources/crypto-data-256.json +56 -0
  68. data/spec/rspec_config.rb +39 -0
  69. data/spec/spec_helper.rb +4 -42
  70. data/spec/support/api_helper.rb +1 -1
  71. data/spec/support/event_machine_helper.rb +0 -5
  72. data/spec/support/protocol_msgbus_helper.rb +3 -3
  73. data/spec/support/test_app.rb +3 -3
  74. data/spec/unit/logger_spec.rb +135 -0
  75. data/spec/unit/models/message_encoders/base64_spec.rb +181 -0
  76. data/spec/unit/models/message_encoders/cipher_spec.rb +260 -0
  77. data/spec/unit/models/message_encoders/json_spec.rb +135 -0
  78. data/spec/unit/models/message_encoders/utf8_spec.rb +100 -0
  79. data/spec/unit/models/message_spec.rb +16 -1
  80. data/spec/unit/models/paginated_resource_spec.rb +46 -0
  81. data/spec/unit/models/presence_message_spec.rb +18 -5
  82. data/spec/unit/models/token_spec.rb +1 -1
  83. data/spec/unit/modules/event_emitter_spec.rb +24 -10
  84. data/spec/unit/realtime/channel_spec.rb +3 -3
  85. data/spec/unit/realtime/channels_spec.rb +1 -1
  86. data/spec/unit/realtime/client_spec.rb +44 -2
  87. data/spec/unit/realtime/connection_spec.rb +2 -2
  88. data/spec/unit/realtime/incoming_message_dispatcher_spec.rb +4 -4
  89. data/spec/unit/realtime/presence_spec.rb +1 -1
  90. data/spec/unit/realtime/realtime_spec.rb +3 -3
  91. data/spec/unit/realtime/websocket_transport_spec.rb +24 -0
  92. data/spec/unit/rest/channels_spec.rb +1 -1
  93. data/spec/unit/rest/client_spec.rb +45 -10
  94. data/spec/unit/util/crypto_spec.rb +82 -0
  95. data/spec/unit/{modules → util}/pub_sub_spec.rb +13 -1
  96. metadata +43 -12
  97. data/spec/acceptance/crypto.rb +0 -63
@@ -2,6 +2,13 @@ module Ably
2
2
  module Rest
3
3
  # The Ably Realtime service organises the traffic within any application into named channels.
4
4
  # Channels are the "unit" of message distribution; clients attach to channels to subscribe to messages, and every message broadcast by the service is associated with a unique channel.
5
+ #
6
+ # @!attribute [r] client
7
+ # @return {Ably::Realtime::Client} Ably client associated with this channel
8
+ # @!attribute [r] name
9
+ # @return {String} channel name
10
+ # @!attribute [r] options
11
+ # @return {Hash} channel options configured for this channel, see {#initialize} for channel_options
5
12
  class Channel
6
13
  include Ably::Modules::Conversions
7
14
 
@@ -11,7 +18,10 @@ module Ably
11
18
  #
12
19
  # @param client [Ably::Rest::Client]
13
20
  # @param name [String] The name of the channel
14
- # @param channel_options [Hash] Channel options, currently reserved for future Encryption options
21
+ # @param channel_options [Hash] Channel options, currently reserved for Encryption options
22
+ # @option channel_options [Boolean] :encrypted setting this to true for this channel will encrypt & decrypt all messages automatically
23
+ # @option channel_options [Hash] :cipher_params A hash of options to configure the encryption. *:key* is required, all other options are optional. See {Ably::Util::Crypto#initialize} for a list of `cipher_params` options
24
+ #
15
25
  def initialize(client, name, channel_options = {})
16
26
  @client = client
17
27
  @name = name
@@ -29,7 +39,11 @@ module Ably
29
39
  data: data
30
40
  }
31
41
 
32
- response = client.post("#{base_path}/publish", payload)
42
+ message = Ably::Models::Message.new(payload, nil).tap do |message|
43
+ message.encode self
44
+ end
45
+
46
+ response = client.post("#{base_path}/publish", message)
33
47
 
34
48
  [201, 204].include?(response.status)
35
49
  end
@@ -52,9 +66,16 @@ module Ably
52
66
 
53
67
  response = client.get(url, options.merge(merge_options))
54
68
 
55
- Ably::Models::PaginatedResource.new(response, url, client, coerce_into: 'Ably::Models::Message')
69
+ Ably::Models::PaginatedResource.new(response, url, client, coerce_into: 'Ably::Models::Message') do |message|
70
+ message.tap do |message|
71
+ message.decode self
72
+ end
73
+ end
56
74
  end
57
75
 
76
+ # Return the {Ably::Rest::Presence} object
77
+ #
78
+ # @return [Ably::Rest::Presence]
58
79
  def presence
59
80
  @presence ||= Presence.new(client, self)
60
81
  end
@@ -20,16 +20,24 @@ module Ably
20
20
  # @return [Logger::Severity] Log level configured for this {Client}
21
21
  # @!attribute [r] channels
22
22
  # @return [Aby::Rest::Channels] The collection of {Ably::Rest::Channel}s that have been created
23
+ # @!attribute [r] protocol
24
+ # @return [Symbol] The protocol configured for this client, either binary `:msgpack` or text based `:json`
25
+ #
23
26
  class Client
24
27
  include Ably::Modules::Conversions
25
28
  include Ably::Modules::HttpHelpers
26
29
  extend Forwardable
27
30
 
28
- DOMAIN = "rest.ably.io"
31
+ DOMAIN = 'rest.ably.io'
29
32
 
30
33
  attr_reader :environment, :protocol, :auth, :channels, :log_level
31
34
  def_delegators :auth, :client_id, :auth_options
32
35
 
36
+ # @api private
37
+ # The registered encoders that are used to encode and decode message payloads
38
+ # @return [Array<Ably::Models::MessageEncoder::Base>]
39
+ attr_reader :encoders
40
+
33
41
  # The additional options passed to this Client's #initialize method not available as attributes of this class
34
42
  # @return [Hash]
35
43
  # @api private
@@ -45,6 +53,7 @@ module Ably
45
53
  # @option options [Symbol] :protocol Protocol used to communicate with Ably, :json and :msgpack currently supported. Defaults to :msgpack
46
54
  # @option options [Boolean] :use_binary_protocol Protocol used to communicate with Ably, defaults to true and uses MessagePack protocol. This option will overide :protocol option
47
55
  # @option options [Logger::Severity,Symbol] :log_level Log level for the standard Logger that outputs to STDOUT. Defaults to Logger::ERROR, can be set to :fatal (Logger::FATAL), :error (Logger::ERROR), :warn (Logger::WARN), :info (Logger::INFO), :debug (Logger::DEBUG)
56
+ # @option options [Logger] :logger A custom logger can be used however it must adhere to the Ruby Logger interface, see http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html
48
57
  #
49
58
  # @yield (see Ably::Auth#authorise)
50
59
  # @yieldparam (see Ably::Auth#authorise)
@@ -65,13 +74,14 @@ module Ably
65
74
  options = { api_key: options }
66
75
  end
67
76
 
68
- @tls = options.delete(:tls) == false ? false : true
69
- @environment = options.delete(:environment) # nil is production
70
- @protocol = options.delete(:protocol) || :msgpack
71
- @debug_http = options.delete(:debug_http)
72
- @log_level = options.delete(:log_level) || Logger::ERROR
77
+ @tls = options.delete(:tls) == false ? false : true
78
+ @environment = options.delete(:environment) # nil is production
79
+ @protocol = options.delete(:protocol) || :msgpack
80
+ @debug_http = options.delete(:debug_http)
81
+ @log_level = options.delete(:log_level) || ::Logger::ERROR
82
+ @custom_logger = options.delete(:logger)
73
83
 
74
- @log_level = Logger.const_get(log_level.to_s.upcase) if log_level.kind_of?(Symbol) || log_level.kind_of?(String)
84
+ @log_level = ::Logger.const_get(log_level.to_s.upcase) if log_level.kind_of?(Symbol) || log_level.kind_of?(String)
75
85
 
76
86
  options.delete(:use_binary_protocol).tap do |use_binary_protocol|
77
87
  if use_binary_protocol == true
@@ -85,6 +95,9 @@ module Ably
85
95
  @options = options.freeze
86
96
  @auth = Auth.new(self, options, &auth_block)
87
97
  @channels = Ably::Rest::Channels.new(self)
98
+ @encoders = []
99
+
100
+ initialize_default_encoders
88
101
  end
89
102
 
90
103
  # Return a REST {Ably::Rest::Channel} for the given name
@@ -151,12 +164,10 @@ module Ably
151
164
  end
152
165
 
153
166
  # @!attribute [r] logger
154
- # @return [Logger] The Logger configured for this client when the client was instantiated.
167
+ # @return [Logger] The {Ably::Logger} for this client.
155
168
  # Configure the log_level with the `:log_level` option, refer to {Client#initialize}
156
169
  def logger
157
- @logger ||= Logger.new(STDOUT).tap do |logger|
158
- logger.level = log_level
159
- end
170
+ @logger ||= Ably::Logger.new(self, log_level, @custom_logger)
160
171
  end
161
172
 
162
173
  # @!attribute [r] mime_type
@@ -170,6 +181,32 @@ module Ably
170
181
  end
171
182
  end
172
183
 
184
+ # Register a message encoder and decoder that implements Ably::Models::MessageEncoders::Base interface.
185
+ # Message encoders are used to encode and decode message payloads automatically.
186
+ # @note Encoders and decoders are processed in the order they are added so the first encoder will be given priority when encoding and decoding
187
+ #
188
+ # @param [Ably::Models::MessageEncoders::Base] encoder
189
+ # @return [void]
190
+ #
191
+ # @api private
192
+ def register_encoder(encoder)
193
+ encoder_klass = if encoder.kind_of?(String)
194
+ Object.const_get(encoder)
195
+ else
196
+ encoder
197
+ end
198
+
199
+ raise "Encoder must inherit from `Ably::Models::MessageEncoders::Base`" unless encoder_klass.ancestors.include?(Ably::Models::MessageEncoders::Base)
200
+
201
+ encoders << encoder_klass.new(self)
202
+ end
203
+
204
+ # @!attribute [r] protocol_binary?
205
+ # @return [Boolean] True of the transport #protocol communicates with Ably with a binary protocol
206
+ def protocol_binary?
207
+ protocol == :msgpack
208
+ end
209
+
173
210
  private
174
211
  def request(method, path, params = {}, options = {})
175
212
  reauthorise_on_authorisation_failure do
@@ -210,8 +247,9 @@ module Ably
210
247
  @connection_options ||= {
211
248
  builder: middleware,
212
249
  headers: {
213
- accept: mime_type,
214
- user_agent: user_agent
250
+ content_type: mime_type,
251
+ accept: mime_type,
252
+ user_agent: user_agent
215
253
  },
216
254
  request: {
217
255
  open_timeout: 5,
@@ -230,15 +268,16 @@ module Ably
230
268
  # Raise exceptions if response code is invalid
231
269
  builder.use Ably::Rest::Middleware::Exceptions
232
270
 
233
- setup_incoming_middleware builder, fail_if_unsupported_mime_type: true
234
-
235
- # Log HTTP requests if log level is DEBUG option set
236
- builder.response :logger if log_level == Logger::DEBUG
271
+ setup_incoming_middleware builder, logger, fail_if_unsupported_mime_type: true
237
272
 
238
273
  # Set Faraday's HTTP adapter
239
274
  builder.adapter Faraday.default_adapter
240
275
  end
241
276
  end
277
+
278
+ def initialize_default_encoders
279
+ Ably::Models::MessageEncoders.register_default_encoders self
280
+ end
242
281
  end
243
282
  end
244
283
  end
@@ -0,0 +1,49 @@
1
+ require 'faraday'
2
+ require 'json'
3
+
4
+ module Ably
5
+ module Rest
6
+ module Middleware
7
+ # Encode the body of the message according to the mime type
8
+ class Encoder < ::Faraday::Response::Middleware
9
+ CONTENT_TYPE = 'Content-Type'.freeze unless defined? CONTENT_TYPE
10
+
11
+ def call(env)
12
+ encode env if env.body
13
+ @app.call env
14
+ end
15
+
16
+ private
17
+ def encode(env)
18
+ env.body = case request_type(env)
19
+ when 'application/x-msgpack'
20
+ to_msgpack(env.body)
21
+ when 'application/json', '', nil
22
+ env.request_headers[CONTENT_TYPE] = 'application/json'
23
+ to_json(env.body)
24
+ else
25
+ env.body
26
+ end
27
+ end
28
+
29
+ def to_msgpack(body)
30
+ body.to_msgpack
31
+ end
32
+
33
+ def to_json(body)
34
+ if body.kind_of?(String)
35
+ body
36
+ else
37
+ body.to_json
38
+ end
39
+ end
40
+
41
+ def request_type(env)
42
+ type = env.request_headers[CONTENT_TYPE].to_s
43
+ type = type.split(';', 2).first if type.index(';')
44
+ type
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,4 +1,5 @@
1
- require "json"
1
+ require 'faraday'
2
+ require 'json'
2
3
 
3
4
  module Ably
4
5
  module Rest
@@ -25,7 +26,7 @@ module Ably
25
26
  message = env.body
26
27
  end
27
28
 
28
- message = "Unknown server error" if message.to_s.strip == ''
29
+ message = 'Unknown server error' if message.to_s.strip == ''
29
30
 
30
31
  if env.status >= 500
31
32
  raise Ably::Exceptions::ServerError, message
@@ -0,0 +1,37 @@
1
+ require 'faraday'
2
+
3
+ module Ably
4
+ module Rest
5
+ module Middleware
6
+ class Logger < Faraday::Response::Middleware
7
+ extend Forwardable
8
+
9
+ def initialize(app, logger = nil)
10
+ super(app)
11
+ @logger = logger || begin
12
+ require 'logger'
13
+ ::Logger.new(STDOUT)
14
+ end
15
+ end
16
+
17
+ def_delegators :@logger, :debug, :info, :warn, :error, :fatal
18
+
19
+ def call(env)
20
+ debug "=> URL: #{env.method} #{env.url}, Headers: #{dump_headers env.request_headers}"
21
+ debug "=> Body: #{env.body}"
22
+ @app.call env
23
+ end
24
+
25
+ def on_complete(env)
26
+ debug "<= Status: #{env.status}, Headers: #{dump_headers env.response_headers}"
27
+ debug "<= Body: #{env.body}"
28
+ end
29
+
30
+ private
31
+ def dump_headers(headers)
32
+ headers.map { |k, v| "#{k}: #{v.inspect}" }.join(", ")
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -20,7 +20,11 @@ module Ably
20
20
  #
21
21
  def get(options = {})
22
22
  response = client.get(base_path, options)
23
- Ably::Models::PaginatedResource.new(response, base_path, client, coerce_into: 'Ably::Models::PresenceMessage')
23
+ Ably::Models::PaginatedResource.new(response, base_path, client, coerce_into: 'Ably::Models::PresenceMessage') do |presence_message|
24
+ presence_message.tap do |message|
25
+ message.decode self.channel
26
+ end
27
+ end
24
28
  end
25
29
 
26
30
  # Return the presence messages history for the channel
@@ -41,7 +45,11 @@ module Ably
41
45
 
42
46
  response = client.get(url, options.merge(merge_options))
43
47
 
44
- Ably::Models::PaginatedResource.new(response, url, client, coerce_into: 'Ably::Models::PresenceMessage')
48
+ Ably::Models::PaginatedResource.new(response, url, client, coerce_into: 'Ably::Models::PresenceMessage') do |presence_message|
49
+ presence_message.tap do |message|
50
+ message.decode self.channel
51
+ end
52
+ end
45
53
  end
46
54
 
47
55
  private
@@ -7,67 +7,95 @@ module Ably::Util
7
7
  algorithm: 'AES',
8
8
  mode: 'CBC',
9
9
  key_length: 128,
10
- block_length: 16
11
10
  }
12
11
 
12
+ BLOCK_LENGTH = 16
13
+
14
+ # Configured options for this Crypto object, see {#initialize} for a list of configured options
15
+ #
16
+ # @return [Hash]
13
17
  attr_reader :options
14
18
 
15
- def initialize(options = {})
16
- raise ArgumentError, ":secret is required" unless options.has_key?(:secret)
19
+ # Creates a {Ably::Util::Crypto} object
20
+ #
21
+ # @param [Hash] options an options Hash used to configure the Crypto library
22
+ # @option options [String] :key Required secret key used for encrypting and decrypting
23
+ # @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}
24
+ # @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}
25
+ # @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}
26
+ # @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}
27
+ #
28
+ # @return [Ably::Util::Crypto]
29
+ #
30
+ # @example
31
+ # crypto = Ably::Util::Crypto.new(key: 'mysecret')
32
+ # encrypted = crypto.encrypt('secret text')
33
+ # crypto.decrypt(decrypted) # => 'secret text'
34
+ #
35
+ def initialize(options)
36
+ raise ArgumentError, ':key is required' unless options.has_key?(:key)
17
37
  @options = DEFAULTS.merge(options).freeze
18
38
  end
19
39
 
20
- def encrypt(payload)
40
+ # Encrypt payload using configured Cipher
41
+ #
42
+ # @param [String] payload the payload to be encrypted
43
+ # @param [Hash] encrypt_options an options Hash to configure the encrypt action
44
+ # @option encrypt_options [String] :iv optionally use the provided Initialization Vector instead of a randomly generated IV
45
+ #
46
+ # @return [String] binary string with {Encoding::ASCII_8BIT} encoding
47
+ #
48
+ def encrypt(payload, encrypt_options = {})
21
49
  cipher = openssl_cipher
22
50
  cipher.encrypt
23
- cipher.key = secret
24
- iv = cipher.random_iv
51
+ cipher.key = key
52
+ iv = encrypt_options[:iv] || options[:iv] || cipher.random_iv
25
53
  cipher.iv = iv
26
54
 
27
- iv << cipher.update(pack(payload)) << cipher.final
55
+ iv << cipher.update(payload) << cipher.final
28
56
  end
29
57
 
58
+ # Decrypt payload using configured Cipher
59
+ #
60
+ # @param [String] encrypted_payload_with_iv the encrypted payload to be decrypted
61
+ #
62
+ # @return [String]
63
+ #
30
64
  def decrypt(encrypted_payload_with_iv)
31
- raise Ably::Exceptions::EncryptionError, "iv is missing" unless encrypted_payload_with_iv.length >= block_length*2
65
+ raise Ably::Exceptions::EncryptionError, 'iv is missing or not long enough' unless encrypted_payload_with_iv.length >= BLOCK_LENGTH*2
32
66
 
33
- iv = encrypted_payload_with_iv.slice(0..15)
34
- encrypted_payload = encrypted_payload_with_iv.slice(16..-1)
67
+ iv = encrypted_payload_with_iv.slice(0...BLOCK_LENGTH)
68
+ encrypted_payload = encrypted_payload_with_iv.slice(BLOCK_LENGTH..-1)
35
69
 
36
70
  decipher = openssl_cipher
37
71
  decipher.decrypt
38
- decipher.key = secret
72
+ decipher.key = key
39
73
  decipher.iv = iv
40
74
 
41
- unpack(decipher.update(encrypted_payload) << decipher.final)
75
+ decipher.update(encrypted_payload) << decipher.final
42
76
  end
43
77
 
78
+ # Generate a random key
79
+ # @return [String]
44
80
  def random_key
45
81
  openssl_cipher.random_key
46
82
  end
47
83
 
84
+ # Generate a random IV
85
+ # @return [String]
48
86
  def random_iv
49
87
  openssl_cipher.random_iv
50
88
  end
51
89
 
52
- private
53
- def pack(object)
54
- object.to_msgpack
55
- end
56
-
57
- def unpack(msgpack_binary)
58
- MessagePack.unpack(msgpack_binary)
59
- end
60
-
61
- def secret
62
- options[:secret]
63
- end
64
-
65
- def block_length
66
- options[:block_length]
90
+ # The Cipher algorithm string such as AES-128-CBC
91
+ # @return [String]
92
+ def cipher_type
93
+ (options[:combined] || "#{options[:algorithm]}-#{options[:key_length]}-#{options[:mode]}").to_s.upcase
67
94
  end
68
95
 
69
- def cipher_type
70
- "#{options[:algorithm]}-#{options[:key_length]}-#{options[:mode]}"
96
+ private
97
+ def key
98
+ options[:key]
71
99
  end
72
100
 
73
101
  def openssl_cipher