class MideaAirCondition::Security

Class to manage encryptions/decryptions/sign/etc

Attributes

access_token[RW]
app_key[RW]

Public Class Methods

new(app_key:, access_token: '') click to toggle source
# File lib/security.rb, line 10
def initialize(app_key:, access_token: '')
  @app_key      = app_key
  @access_token = access_token

  @crc8_854_table = Base64.decode64(
    'AF684mE/3YPCnH4go/0fQZ3DIX/8okAeXwHjvT5ggtwjfZ/BQhz+oOG/XQOA' \
    '3jxivuACXN+BYz18IsCeHUOh/0YY+qQneZvFhNo4ZuW7WQfbhWc5uuQGWBlH' \
    'pft4JsSaZTvZhwRauOan+RtFxph6JPimRBqZxyV7OmSG2FsF57mM0jBu7bNR' \
    'D04Q8qwvcZPNEU+t83AuzJLTjW8xsuwOUK/xE03OkHIsbTPRjwxSsO4ybI7Q' \
    'Uw3vsfCuTBKRzy1zypR2KKv1F0kIVrTqaTfVi1cJ67U2aIrUlcspd/SqSBbp' \
    't1ULiNY0ait1l8lKFPaodCrIlhVLqfe26ApU14lrNQ=='
  ).unpack('C*')
end

Public Instance Methods

aes_decrypt(data, key) click to toggle source

rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength

# File lib/security.rb, line 67
def aes_decrypt(data, key)
  aes = OpenSSL::Cipher.new('aes128')
  aes.decrypt
  aes.padding = 0
  aes.key = key

  data = [data].pack('H*')

  blocks = data.chars.each_slice(16).map(&:join)

  final = ''
  blocks.each do |b|
    aes.reset
    final += aes.update(b) + aes.final
  end

  pad = final[final.length - 1].ord

  final[0...(final.length - pad)]
end
aes_encrypt(data, key) click to toggle source
# File lib/security.rb, line 88
def aes_encrypt(data, key)
  aes = OpenSSL::Cipher.new('aes128')
  aes.encrypt
  aes.padding = 0
  aes.key = key

  blocks = data.chars.each_slice(16).map(&:join)
  if blocks.last.length < 16
    pad = 16 - blocks.last.length
    blocks[blocks.length - 1] = blocks.last + pad.chr * pad
  else
    pad = 16
    blocks << pad.chr * pad
  end

  final = ''
  blocks.each do |b|
    aes.reset
    final += aes.update(b) + aes.final
  end

  unpacked = final.unpack('H*')
  unpacked.first
end
checksum(data) click to toggle source
# File lib/security.rb, line 60
def checksum(data)
  sum_value = data.inject(&:+)
  255 - sum_value % 256 + 1
end
crc8(data) click to toggle source
# File lib/security.rb, line 48
def crc8(data)
  crc_value = 0
  data.each do |m|
    k = crc_value ^ m
    k -= 256 if k > 256
    k += 256 if k.negative?
    crc_value = @crc8_854_table[k]
  end

  crc_value
end
data_key() click to toggle source
# File lib/security.rb, line 35
def data_key
  aes_decrypt(
    @access_token,
    (::Digest::MD5.new << @app_key).to_s[0...16]
  )
end
encrypt_password(password, login_id) click to toggle source
# File lib/security.rb, line 30
def encrypt_password(password, login_id)
  pass = (::Digest::SHA2.new << password).to_s
  (::Digest::SHA2.new << "#{login_id}#{pass}#{@app_key}").to_s
end
sign(path, args) click to toggle source
# File lib/security.rb, line 24
def sign(path, args)
  query = args.map { |k, v| "#{k}=#{v}" }.to_a.sort.join('&')
  content = "#{path}#{query}#{@app_key}"
  (::Digest::SHA2.new << content).to_s
end
transcode(data) click to toggle source
# File lib/security.rb, line 42
def transcode(data)
  data.map do |d|
    (d >= 128 ? d - 256 : d)
  end
end