From 55a7562f8a1819b60b61f9ee0d92e86362df97a1 Mon Sep 17 00:00:00 2001 From: Jeff Lai Date: Fri, 26 Feb 2016 10:15:47 +0800 Subject: [PATCH] Add encryption helpers --- lib/dingtalk/pkcs7_encoder.rb | 26 ++++++++++++++++++++++++++ lib/dingtalk/prpcrypt.rb | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 0 deletions(-) create mode 100644 lib/dingtalk/pkcs7_encoder.rb create mode 100644 lib/dingtalk/prpcrypt.rb diff --git a/lib/dingtalk/pkcs7_encoder.rb b/lib/dingtalk/pkcs7_encoder.rb new file mode 100644 index 0000000..97fcf1b --- /dev/null +++ b/lib/dingtalk/pkcs7_encoder.rb @@ -0,0 +1,26 @@ +module Dingtalk + module PKCS7Encoder + extend self + + BLOCK_SIZE = 32 + + def decode(text) + pad = text[-1].ord + pad = 0 if (pad < 1 || pad > BLOCK_SIZE) + size = text.size - pad + text[0...size] + end + + # 对需要加密的明文进行填充补位 + # 返回补齐明文字符串 + def encode(text) + # 计算需要填充的位数 + amount_to_pad = BLOCK_SIZE - (text.length % BLOCK_SIZE) + amount_to_pad = BLOCK_SIZE if amount_to_pad == 0 + # 获得补位所用的字符 + pad_chr = amount_to_pad.chr + "#{text}#{pad_chr * amount_to_pad}" + end + + end +end diff --git a/lib/dingtalk/prpcrypt.rb b/lib/dingtalk/prpcrypt.rb new file mode 100644 index 0000000..aaaaa83 --- /dev/null +++ b/lib/dingtalk/prpcrypt.rb @@ -0,0 +1,46 @@ +module Dingtalk + module Prpcrypt + extend self + + # 对密文进行解密. + # text 需要解密的密文 + def decrypt(aes_key, text, corpid) + status = 200 + text = Base64.decode64(text) + text = handle_cipher(:decrypt, aes_key, text) + result = PKCS7Encoder.decode(text) + content = result[16...result.length] + len_list = content[0...4].unpack("N") + xml_len = len_list[0] + xml_content = content[4...4 + xml_len] + from_corpid = content[xml_len+4...content.size] + # TODO: refactor + if corpid != from_corpid + Rails.logger.debug("#{__FILE__}:#{__LINE__} Failure because #{corpid} != #{from_corpid}") + status = 401 + end + [xml_content, status] + end + + # 加密 + def encrypt(aes_key, text, corpid) + text = text.force_encoding("ASCII-8BIT") + random = SecureRandom.hex(8) + msg_len = [text.length].pack("N") + text = "#{random}#{msg_len}#{text}#{corpid}" + text = PKCS7Encoder.encode(text) + text = handle_cipher(:encrypt, aes_key, text) + Base64.encode64(text) + end + + private + def handle_cipher(action, aes_key, 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 + end +end -- libgit2 0.21.0