ably 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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