Module: MTProto::Crypto::RSA_PAD

Defined in:
lib/mtproto/crypto/rsa_pad.rb

Class Method Summary collapse

Class Method Details

.encrypt(data, rsa_key) ⇒ Object

Raises:

  • (ArgumentError)


12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/mtproto/crypto/rsa_pad.rb', line 12

def encrypt(data, rsa_key)
  raise ArgumentError, 'Data too large' if data.bytesize > 144

  loop do
    result = perform_encryption(data)
    result_bn = OpenSSL::BN.new(result, 2)

    return rsa_key.key.public_encrypt(result, OpenSSL::PKey::RSA::NO_PADDING) if result_bn < rsa_key.key.n

    # If result >= modulus, retry with new random data
  end
end

.pad_to_192(data) ⇒ Object

Raises:

  • (ArgumentError)


42
43
44
45
46
47
# File 'lib/mtproto/crypto/rsa_pad.rb', line 42

def pad_to_192(data)
  padding_length = 192 - data.bytesize
  raise ArgumentError, 'Data too large for RSA_PAD' if padding_length < 0

  data + SecureRandom.random_bytes(padding_length)
end

.perform_encryption(data) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/mtproto/crypto/rsa_pad.rb', line 25

def perform_encryption(data)
  data_with_padding = pad_to_192(data)
  data_reversed = data_with_padding.reverse
  temp_key = SecureRandom.random_bytes(32)
  data_hash = Digest::SHA256.digest(temp_key + data_with_padding)
  to_encrypt = data_reversed + data_hash

  aes_key = temp_key
  aes_iv = "\x00" * 32
  encrypted = AES_IGE.encrypt_ige(to_encrypt, aes_key, aes_iv)

  encrypted_hash = Digest::SHA256.digest(encrypted)
  temp_key_xor = xor_bytes(temp_key, encrypted_hash)

  temp_key_xor + encrypted
end

.xor_bytes(bytes1, bytes2) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/mtproto/crypto/rsa_pad.rb', line 49

def xor_bytes(bytes1, bytes2)
  length = [bytes1.bytesize, bytes2.bytesize].min
  result = String.new(capacity: length)
  length.times do |i|
    result << (bytes1.getbyte(i) ^ bytes2.getbyte(i))
  end
  result
end