Class: MTProto::Message

Inherits:
Object
  • Object
show all
Extended by:
Binary
Includes:
Binary
Defined in:
lib/mtproto/message/message.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Binary

b_u32, b_u64, u32_b, u64_b

Constructor Details

#initialize(body, msg_id: self.class.generate_msg_id, auth_key_id: 0) ⇒ Message

Returns a new instance of Message.



12
13
14
15
16
# File 'lib/mtproto/message/message.rb', line 12

def initialize(body, msg_id: self.class.generate_msg_id, auth_key_id: 0)
  @auth_key_id = auth_key_id
  @msg_id = msg_id
  @body = body
end

Instance Attribute Details

#auth_key_idObject (readonly)

Returns the value of attribute auth_key_id.



8
9
10
# File 'lib/mtproto/message/message.rb', line 8

def auth_key_id
  @auth_key_id
end

#bodyObject (readonly)

Returns the value of attribute body.



8
9
10
# File 'lib/mtproto/message/message.rb', line 8

def body
  @body
end

#encrypted_dataObject (readonly)

Returns the value of attribute encrypted_data.



8
9
10
# File 'lib/mtproto/message/message.rb', line 8

def encrypted_data
  @encrypted_data
end

#msg_idObject (readonly)

Returns the value of attribute msg_id.



8
9
10
# File 'lib/mtproto/message/message.rb', line 8

def msg_id
  @msg_id
end

#msg_keyObject (readonly)

Returns the value of attribute msg_key.



8
9
10
# File 'lib/mtproto/message/message.rb', line 8

def msg_key
  @msg_key
end

#seq_noObject (readonly)

Returns the value of attribute seq_no.



8
9
10
# File 'lib/mtproto/message/message.rb', line 8

def seq_no
  @seq_no
end

#server_saltObject (readonly)

Returns the value of attribute server_salt.



8
9
10
# File 'lib/mtproto/message/message.rb', line 8

def server_salt
  @server_salt
end

#session_idObject (readonly)

Returns the value of attribute session_id.



8
9
10
# File 'lib/mtproto/message/message.rb', line 8

def session_id
  @session_id
end

Class Method Details

.generate_msg_idObject



65
66
67
# File 'lib/mtproto/message/message.rb', line 65

def self.generate_msg_id
  (Time.now.to_f * (2**32)).to_i & ~3
end

.parse(packet) ⇒ Object



18
19
20
21
22
23
24
25
26
27
# File 'lib/mtproto/message/message.rb', line 18

def self.parse(packet)
  data = packet.data
  auth_key_id = b_u64(data[0, 8])

  if auth_key_id.zero?
    parse_unencrypted(data)
  else
    parse_encrypted(data, auth_key_id)
  end
end

Instance Method Details

#bytesObject



58
59
60
61
62
63
# File 'lib/mtproto/message/message.rb', line 58

def bytes
  u64_b(@auth_key_id) +
    u64_b(@msg_id) +
    u32_b(@body.length) +
    @body
end

#decrypt(auth_key:, sender: :server) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/mtproto/message/message.rb', line 33

def decrypt(auth_key:, sender: :server)
  raise 'Message is not encrypted' unless encrypted?

  keys = Crypto::MessageKey.derive_aes_key_iv(auth_key, @msg_key, sender: sender)
  plaintext = Crypto::AES_IGE.decrypt_ige(@encrypted_data, keys[:aes_key], keys[:aes_iv])

  expected_msg_key = Crypto::MessageKey.generate_msg_key(auth_key, plaintext, sender: sender)
  raise 'msg_key mismatch!' unless @msg_key == expected_msg_key

  offset = 0
  @server_salt = plaintext[offset, 8].unpack1('Q<')
  offset += 8
  @session_id = plaintext[offset, 8].unpack1('Q<')
  offset += 8
  @msg_id = plaintext[offset, 8].unpack1('Q<')
  offset += 8
  @seq_no = plaintext[offset, 4].unpack1('L<')
  offset += 4
  body_length = plaintext[offset, 4].unpack1('L<')
  offset += 4
  @body = plaintext[offset, body_length].bytes

  self
end

#encrypted?Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/mtproto/message/message.rb', line 29

def encrypted?
  !@auth_key_id.zero?
end