class WeixinMessageEncryptor
Constants
- BLOCK_SIZE
- VERSION
Attributes
app_id[R]
encoding_aes_key[R]
sign_token[R]
Public Class Methods
new(encoding_aes_key: nil, sign_token: nil, app_id: nil)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 13 def initialize(encoding_aes_key: nil, sign_token: nil, app_id: nil) @encoding_aes_key = encoding_aes_key @sign_token = sign_token @app_id = app_id end
Public Instance Methods
decrypt(payload)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 43 def decrypt(payload) encrypted_payload = payload['echostr'] || payload['xml']['Encrypt'] sign = generate_signature encrypted_payload, payload['timestamp'], payload['nonce'] message, app_id = decrypt_payload encrypted_payload return message, app_id, sign end
encrypt(payload)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 19 def encrypt(payload) aes_encrypt(payload).delete("\n") end
encrypt_to_xml(payload)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 31 def encrypt_to_xml(payload) encrypted_payload, timestamp, nonce, signature = encrypt_with_signature(payload) <<XML <xml> <Encrypt><![CDATA[#{encrypted_payload}]]></Encrypt> <MsgSignature><![CDATA[#{signature}]]></MsgSignature> <TimeStamp>#{timestamp}</TimeStamp> <Nonce><![CDATA[#{nonce}]]></Nonce> </xml> XML end
encrypt_with_signature(payload)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 23 def encrypt_with_signature(payload) encrypted_payload = encrypt(payload) timestamp = Time.now.to_i.to_s nonce = SecureRandom.hex(8) signature = generate_signature(encrypted_payload, timestamp, nonce) return [encrypted_payload, timestamp, nonce, signature] end
Private Instance Methods
aes_encrypt(text)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 73 def aes_encrypt(text) text = text.force_encoding('ASCII-8BIT') random = SecureRandom.hex(8) msg_len = [text.length].pack('N') text = "#{random}#{msg_len}#{text}#{app_id}" text = encode(text) text = handle_cipher(:encrypt, text) Base64.encode64(text) end
aes_key()
click to toggle source
# File lib/weixin_message_encryptor.rb, line 52 def aes_key @aes_key ||= Base64.decode64 encoding_aes_key + '=' end
decrypt_payload(encrypted_payload)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 56 def decrypt_payload(encrypted_payload) text = Base64.decode64 encrypted_payload text = handle_cipher(:decrypt, text) result = pkcs7_decode(text) content = result[16...result.length] len_list = content[0...4].unpack('N') xml_len = len_list[0] payload = content[4...4 + xml_len] app_id = content[xml_len+4...content.size] return payload, app_id end
encode(text)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 99 def encode(text) amount_to_pad = BLOCK_SIZE - (text.length % BLOCK_SIZE) amount_to_pad = BLOCK_SIZE if amount_to_pad.zero? pad_chr = amount_to_pad.chr "#{text}#{pad_chr * amount_to_pad}" end
generate_signature(message, timestamp, nonce)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 68 def generate_signature(message, timestamp, nonce) sorted_params = [message, sign_token, timestamp, nonce].sort.join Digest::SHA1.hexdigest(sorted_params) end
handle_cipher(action, text)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 83 def handle_cipher(action, text) cipher = OpenSSL::Cipher.new('AES-256-CBC') cipher.send(action) cipher.padding = 0 cipher.key = aes_key cipher.iv = aes_key[0...16] cipher.update(text) + cipher.final end
pkcs7_decode(text)
click to toggle source
# File lib/weixin_message_encryptor.rb, line 92 def pkcs7_decode(text) pad = text[-1].ord pad = 0 if pad < 1 || pad > BLOCK_SIZE size = text.size - pad text[0...size] end