Class: Ably::Models::MessageEncoders::Cipher

Inherits:
Base
  • Object
show all
Defined in:
lib/ably/models/message_encoders/cipher.rb

Overview

Cipher Encoder & Decoder that automatically encrypts & decrypts messages using Ably::Util::Crypto when a channel has the :cipher channel option configured

Constant Summary collapse

ENCODING_ID =
'cipher'

Instance Attribute Summary

Attributes inherited from Base

#client, #options

Instance Method Summary collapse

Methods inherited from Base

#add_encoding_to_message, #current_encoding_part, #is_empty?, #strip_current_encoding_part

Constructor Details

#initialize(*args) ⇒ Cipher

Returns a new instance of Cipher.



12
13
14
15
# File 'lib/ably/models/message_encoders/cipher.rb', line 12

def initialize(*args)
  super
  @cryptos = Hash.new
end

Instance Method Details

#decode(message, channel_options) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/ably/models/message_encoders/cipher.rb', line 37

def decode(message, channel_options)
  if is_cipher_encoded?(message)
    unless channel_configured_for_encryption?(channel_options)
      raise Ably::Exceptions::CipherError.new('Message cannot be decrypted as the channel is not set up for encryption & decryption', nil, 92001)
    end

    crypto = crypto_for(channel_options)
    unless crypto.cipher_params.cipher_type == cipher_algorithm(message).upcase
      raise Ably::Exceptions::CipherError.new("Cipher algorithm #{crypto.cipher_params.cipher_type} does not match message cipher algorithm of #{cipher_algorithm(message).upcase}", nil, 92002)
    end

    message[:data] = crypto.decrypt(message[:data])
    strip_current_encoding_part message
  end
rescue OpenSSL::Cipher::CipherError => e
  raise Ably::Exceptions::CipherError.new("CipherError decrypting data, the private key may not be correct", nil, 92003)
end

#encode(message, channel_options) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/ably/models/message_encoders/cipher.rb', line 17

def encode(message, channel_options)
  return if is_empty?(message)
  return if already_encrypted?(message)

  if channel_configured_for_encryption?(channel_options)
    add_encoding_to_message 'utf-8', message unless is_binary?(message) || is_utf8_encoded?(message)
    crypto = crypto_for(channel_options)
    message[:data] = crypto.encrypt(message[:data])
    add_encoding_to_message "#{ENCODING_ID}+#{crypto.cipher_params.cipher_type.downcase}", message
  end
rescue ArgumentError => e
  raise Ably::Exceptions::CipherError.new(e.message, nil, 92005)
rescue RuntimeError => e
  if e.message.match(/unsupported cipher algorithm/i)
    raise Ably::Exceptions::CipherError.new(e.message, nil, 92004)
  else
    raise e
  end
end