Class: Errlog::Packager

Inherits:
Object
  • Object
show all
Defined in:
lib/errlog/packager.rb

Overview

Packager does (un)packing data to effectively and (where possible) safely transfer the report over the network. Normally you don’t use it directly.

Defined Under Namespace

Classes: Exception

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app_id, app_key, throw_errors = false) ⇒ Packager

Returns a new instance of Packager.



19
20
21
22
23
# File 'lib/errlog/packager.rb', line 19

def initialize app_id, app_key, throw_errors = false
  @appid = app_id
  @key   = app_key.length == 16 ? app_key : Base64.decode64(app_key)
  @throw_errors = throw_errors
end

Instance Attribute Details

#throw_errorsObject

Returns the value of attribute throw_errors.



15
16
17
# File 'lib/errlog/packager.rb', line 15

def throw_errors
  @throw_errors
end

Instance Method Details

#decrypt(ciphertext) ⇒ Object

AES-128 decrypt the block



35
36
37
38
39
40
41
42
43
# File 'lib/errlog/packager.rb', line 35

def decrypt ciphertext
  cipher = OpenSSL::Cipher.new('AES-128-CBC')
  cipher.decrypt
  cipher.iv    = ciphertext[0..15]
  cipher.key   = @key
  data         = cipher.update(ciphertext[16..-1]) + cipher.final
  data, digest = data[0...-16], data[-16..-1]
  digest == Digest::MD5.digest(data) ? data : nil
end

#encrypt(data) ⇒ Object

AES-128 encrypt the block



26
27
28
29
30
31
32
# File 'lib/errlog/packager.rb', line 26

def encrypt data
  cipher = OpenSSL::Cipher.new('AES-128-CBC')
  cipher.encrypt
  iv         = cipher.random_iv
  cipher.key = @key
  iv + cipher.update(data) + cipher.update(Digest::MD5.digest(data)) + cipher.final
end

#pack(payload) ⇒ binary

Returns packed payload using the default block format.

Returns:

  • (binary)

    packed payload using the default block format



46
47
48
# File 'lib/errlog/packager.rb', line 46

def pack payload
  "\x00#{encrypt(Boss.dump @appid, payload)}"
end

#unpack(block) ⇒ Hash

Note:

packager can unpack v1 (boss, encrypted) and v2 (json, unencrypted) but it does not pack to v2 as it is no secure and limited to US export laws castrated platforms like iPhone and is not recommended to be used anywhere else.

to be broken (e.g. wrong credentials used)

Returns:

  • (Hash)

    unpacked payload or nil if block format is unknown or block seems



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/errlog/packager.rb', line 56

def unpack block
  case block[0].ord
    when 0
      id, payload = Boss.load_all(decrypt(block[1..-1]))
      id == @appid ? payload : nil
    when 1
      data = block[1...-32]
      sign = block[-32..-1]
      if sign != Digest::SHA256.digest(data + @key)
        puts "Sign does not match"
        @throw_errors and raise Exception, "Wrong signature"
        nil
      else
        JSON.parse Zlib::GzipReader.new(StringIO.new(data)).read
      end
    else
      @throw_errors and raise Exception, "Unknown block type: #{block[0].ord}"
      nil
  end
rescue
  @throw_errors and raise
  nil
end