Class: Pubnub::Crypto::CryptorHeader

Inherits:
Object
  • Object
show all
Defined in:
lib/pubnub/modules/crypto/cryptor_header.rb

Overview

Cryptor data header.

This instance used to parse header from received data and encode into binary for sending.

Defined Under Namespace

Modules: Versions

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(identifier = nil, metadata = nil) ⇒ CryptorHeader

Create cryptor header.

Parameters:

  • identifier (String) (defaults to: nil)

    Identifier of the cryptor which has been used to encrypt data.

  • metadata (String, nil) (defaults to: nil)

    Cryptor-defined information.



78
79
80
81
82
83
84
85
# File 'lib/pubnub/modules/crypto/cryptor_header.rb', line 78

def initialize(identifier = nil,  = nil)
  @data = if identifier && identifier != '\x00\x00\x00\x00'
            Versions::CryptorHeaderV1Data.new(
              identifier.to_s,
              &.length || 0
            )
          end
end

Class Method Details

.parse(data) ⇒ CryptorHeader?

Parse cryptor header data to create instance.

Parameters:

  • data (String)

    Data which may contain cryptor header information.

Returns:

  • (CryptorHeader, nil)

    Header instance or nil in case of encrypted data parse error.

Raises:

  • (ArgumentError)

    Raise an exception if data is nil or empty.

  • (UnknownCryptorError)

    Raise an exception if, during cryptor header data parsing, an unknown cryptor header version is encountered.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/pubnub/modules/crypto/cryptor_header.rb', line 98

def self.parse(data)
  if data.nil? || data.empty?
    raise ArgumentError, {
      message: '\'data\' is required and should not be empty.'
    }
  end

  # Data is too short to be encrypted. Assume legacy cryptor without
  # header.
  return CryptorHeader.new if data.length < 4 || data.unpack('A4').last != 'PNED'

  # Malformed crypto header.
  return nil if data.length < 10

  # Unpack header bytes.
  _, version, identifier, data_size = data.unpack('A4 C A4 C')

  # Check whether version is within known range.
  if version > current_version
    raise UnknownCryptorError, {
      message: 'Decrypting data created by unknown cryptor.'
    }
  end

  if data_size == 255
    data_size = data.unpack('A4 C A4 C n').last if data.length >= 12
    return CryptorHeader.new if data.length < 12
  end

  header = CryptorHeader.new
  header.send(
    :update_header_data,
    create_header_data(version.to_i, identifier.to_s, data_size.to_i)
  )
  header
end

Instance Method Details

#data_sizeInteger

Cryptor-defined information size.

Returns:

  • (Integer)

    Cryptor-defined information size.



168
169
170
# File 'lib/pubnub/modules/crypto/cryptor_header.rb', line 168

def data_size
  header_data&.data_size || 0
end

#identifierString?

Identifier of the cryptor which has been used to encrypt data.

Returns:

  • (String, nil)

    Identifier of the cryptor which has been used to encrypt data.



161
162
163
# File 'lib/pubnub/modules/crypto/cryptor_header.rb', line 161

def identifier
  header_data&.identifier || nil
end

#lengthObject

Overall header size.

Full header size which includes:

  • sentinel
  • version
  • cryptor identifier
  • cryptor data size
  • cryptor-defined fields size.


143
144
145
146
147
148
# File 'lib/pubnub/modules/crypto/cryptor_header.rb', line 143

def length
  # Legacy payload doesn't have header.
  return 0 if @data.nil?

  9 + (data_size < 255 ? 1 : 3)
end

#to_sString

Serialize cryptor header.

Returns:

  • (String)

    Cryptor header data, which is serialized as a binary string.

Raises:

  • (ArgumentError)

    Raise an exception if a cryptor identifier is not provided for a non-legacy cryptor.



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/pubnub/modules/crypto/cryptor_header.rb', line 196

def to_s
  # We don't need to serialize header for legacy cryptor.
  return '' if version.zero?

  cryptor_identifier = identifier
  if cryptor_identifier.nil? || cryptor_identifier.empty?
    raise ArgumentError, {
      message: '\'identifier\' is missing or empty.'
    }
  end

  header_bytes = ['PNED', version, cryptor_identifier]
  if data_size < 255
    header_bytes.push(data_size)
  else
    header_bytes.push(255, data_size)
  end

  header_bytes.pack(data_size < 255 ? 'A4 C A4 C' : 'A4 C A4 C n')
end

#versionInteger

Crypto header version Version module.

Returns:

  • (Integer)

    One of known versions from Version module.



153
154
155
# File 'lib/pubnub/modules/crypto/cryptor_header.rb', line 153

def version
  header_data&.version || 0
end