Module: MixinBot::API::EncryptedMessage
- Included in:
- MixinBot::API
- Defined in:
- lib/mixin_bot/api/encrypted_message.rb
Instance Method Summary collapse
-
#base_encrypted_message_params(options) ⇒ Object
base format of message params.
-
#decrypt_message(data, sk: nil, si: nil) ⇒ Object
rubocop:disable Naming/MethodParameterName.
-
#encrypt_message(data, sessions = [], sk: nil, pk: nil) ⇒ Object
rubocop:disable Naming/MethodParameterName.
- #encrypted_audio(options) ⇒ Object
- #encrypted_contact(options) ⇒ Object
- #encrypted_data(options) ⇒ Object
- #encrypted_image(options) ⇒ Object
- #encrypted_post(options) ⇒ Object
- #encrypted_sticker(options) ⇒ Object
- #encrypted_text(options) ⇒ Object
- #encrypted_video(options) ⇒ Object
- #send_encrypted_audio_message(options) ⇒ Object
- #send_encrypted_contact_message(options) ⇒ Object
- #send_encrypted_data_message(options) ⇒ Object
- #send_encrypted_image_message(options) ⇒ Object
-
#send_encrypted_message(payload) ⇒ Object
http post request.
- #send_encrypted_messages(messages) ⇒ Object
- #send_encrypted_post_message(options) ⇒ Object
- #send_encrypted_sticker_message(options) ⇒ Object
-
#send_encrypted_text_message(options) ⇒ Object
use HTTP to send message.
- #send_encrypted_video_message(options) ⇒ Object
Instance Method Details
#base_encrypted_message_params(options) ⇒ Object
base format of message params
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 80 def () data = [:data].is_a?(String) ? [:data] : [:data].to_json data_base64 = Base64.urlsafe_encode64(data, padding: false), [:sessions] session_ids = [:sessions].map(&->(s) { s['session_id'] }).sort checksum = Digest::MD5.hexdigest session_ids.join { conversation_id: [:conversation_id], recipient_id: [:recipient_id], representative_id: [:representative_id], category: [:category], quote_message_id: [:quote_message_id], message_id: [:message_id] || SecureRandom.uuid, data_base64:, checksum:, recipient_sessions: session_ids.map(&->(s) { { session_id: s } }), silent: false }.compact end |
#decrypt_message(data, sk: nil, si: nil) ⇒ Object
rubocop:disable Naming/MethodParameterName
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 156 def (data, sk: nil, si: nil) # rubocop:disable Naming/MethodParameterName bytes = Base64.urlsafe_decode64(data).bytes si ||= config.session_id sk ||= config.session_private_key[0...32] size = 16 + 48 return '' if bytes.size < 1 + 2 + 32 + size + 12 session_length = bytes[1...3].pack('v*').unpack1('C*') prefix_size = 35 + (session_length * size) i = 35 key = '' while i < prefix_size uuid = MixinBot::UUID.new(raw: bytes[i...(i + 16)].pack('C*')).unpacked if uuid == si pub = bytes[3...35] aes_key = JOSE::JWA::X25519.shared_secret( pub.pack('C*'), JOSE::JWA::Ed25519.secret_to_curve25519(sk) ) iv = bytes[(i + 16)...(i + 16 + 16)].pack('C*') encrypted_key = bytes[(i + 16 + 16)...(i + size)].pack('C*') decrypter = OpenSSL::Cipher.new('AES-256-CBC').decrypt decrypter.iv = iv decrypter.key = aes_key cipher = decrypter.update(encrypted_key) key = cipher[...16] break end i += size end return '' unless key.size == 16 decrypter = OpenSSL::Cipher.new('AES-128-GCM').decrypt decrypter.key = key decrypter.iv = bytes[prefix_size...(prefix_size + 12)].pack('C*') decrypter.auth_tag = bytes.last(16).pack('C*') decrypted = decrypter.update(bytes[(prefix_size + 12)...(bytes.size - 16)].pack('C*')) decrypter.final Base64.urlsafe_encode64 decrypted end |
#encrypt_message(data, sessions = [], sk: nil, pk: nil) ⇒ Object
rubocop:disable Naming/MethodParameterName
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 113 def (data, sessions = [], sk: nil, pk: nil) # rubocop:disable Naming/MethodParameterName raise ArgumentError, 'Wrong sessions format!' unless sessions.all?(&->(s) { s.key?('session_id') && s.key?('public_key') }) sk ||= config.session_private_key[0...32] pk ||= config.session_private_key[32...] Digest::MD5.hexdigest sessions.map(&->(s) { s['session_id'] }).sort.join encrypter = OpenSSL::Cipher.new('AES-128-GCM').encrypt key = encrypter.random_key nounce = encrypter.random_iv encrypter.key = key encrypter.iv = nounce encrypter.auth_data = '' ciphertext = encrypter.update(Base64.urlsafe_decode64(data)) + encrypter.final + encrypter.auth_tag bytes = [1] bytes += [sessions.size].pack('v*').bytes bytes += JOSE::JWA::Ed25519.pk_to_curve25519(pk).bytes sessions.each do |session| aes_key = JOSE::JWA::X25519.shared_secret( Base64.urlsafe_decode64(session['public_key']), JOSE::JWA::Ed25519.secret_to_curve25519(sk) ) padding = 16 - (key.size % 16) padtext = ([padding] * padding).pack('C*') encrypter = OpenSSL::Cipher.new('AES-256-CBC').encrypt encrypter.key = aes_key iv = encrypter.random_iv encrypter.iv = iv bytes += (MixinBot::UUID.new(hex: session['session_id']).packed + iv).bytes bytes += encrypter.update(key + padtext).bytes end bytes += nounce.bytes bytes += ciphertext.bytes Base64.urlsafe_encode64 bytes.pack('C*'), padding: false end |
#encrypted_audio(options) ⇒ Object
36 37 38 39 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 36 def encrypted_audio() .merge!(category: 'ENCRYPTED_AUDIO') () end |
#encrypted_contact(options) ⇒ Object
31 32 33 34 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 31 def encrypted_contact() .merge!(category: 'ENCRYPTED_CONTACT') () end |
#encrypted_data(options) ⇒ Object
21 22 23 24 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 21 def encrypted_data() .merge!(category: 'ENCRYPTED_DATA') () end |
#encrypted_image(options) ⇒ Object
16 17 18 19 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 16 def encrypted_image() .merge!(category: 'ENCRYPTED_IMAGE') () end |
#encrypted_post(options) ⇒ Object
11 12 13 14 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 11 def encrypted_post() .merge!(category: 'ENCRYPTED_POST') () end |
#encrypted_sticker(options) ⇒ Object
26 27 28 29 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 26 def encrypted_sticker() .merge!(category: 'ENCRYPTED_STICKER') () end |
#encrypted_text(options) ⇒ Object
6 7 8 9 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 6 def encrypted_text() .merge!(category: 'ENCRYPTED_TEXT') () end |
#encrypted_video(options) ⇒ Object
41 42 43 44 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 41 def encrypted_video() .merge!(category: 'ENCRYPTED_VIDEO') () end |
#send_encrypted_audio_message(options) ⇒ Object
71 72 73 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 71 def () encrypted_audio() end |
#send_encrypted_contact_message(options) ⇒ Object
67 68 69 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 67 def () encrypted_contact() end |
#send_encrypted_data_message(options) ⇒ Object
59 60 61 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 59 def () encrypted_data() end |
#send_encrypted_image_message(options) ⇒ Object
55 56 57 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 55 def () encrypted_image() end |
#send_encrypted_message(payload) ⇒ Object
http post request
105 106 107 108 109 110 111 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 105 def (payload) path = '/encrypted_messages' payload = [payload] if payload.is_a? Hash raise ArgumentError, 'Wrong payload format!' unless payload.is_a? Array client.post path, *payload end |
#send_encrypted_messages(messages) ⇒ Object
100 101 102 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 100 def () end |
#send_encrypted_post_message(options) ⇒ Object
51 52 53 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 51 def () encrypted_post() end |
#send_encrypted_sticker_message(options) ⇒ Object
63 64 65 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 63 def () encrypted_sticker() end |
#send_encrypted_text_message(options) ⇒ Object
use HTTP to send message
47 48 49 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 47 def () encrypted_text() end |
#send_encrypted_video_message(options) ⇒ Object
75 76 77 |
# File 'lib/mixin_bot/api/encrypted_message.rb', line 75 def () encrypted_video() end |