Commit 55a7562f8a1819b60b61f9ee0d92e86362df97a1
1 parent
526b4bcc
Exists in
master
Add encryption helpers
Showing
2 changed files
with
72 additions
and
0 deletions
Show diff stats
... | ... | @@ -0,0 +1,26 @@ |
1 | +module Dingtalk | |
2 | + module PKCS7Encoder | |
3 | + extend self | |
4 | + | |
5 | + BLOCK_SIZE = 32 | |
6 | + | |
7 | + def decode(text) | |
8 | + pad = text[-1].ord | |
9 | + pad = 0 if (pad < 1 || pad > BLOCK_SIZE) | |
10 | + size = text.size - pad | |
11 | + text[0...size] | |
12 | + end | |
13 | + | |
14 | + # 对需要加密的明文进行填充补位 | |
15 | + # 返回补齐明文字符串 | |
16 | + def encode(text) | |
17 | + # 计算需要填充的位数 | |
18 | + amount_to_pad = BLOCK_SIZE - (text.length % BLOCK_SIZE) | |
19 | + amount_to_pad = BLOCK_SIZE if amount_to_pad == 0 | |
20 | + # 获得补位所用的字符 | |
21 | + pad_chr = amount_to_pad.chr | |
22 | + "#{text}#{pad_chr * amount_to_pad}" | |
23 | + end | |
24 | + | |
25 | + end | |
26 | +end | ... | ... |
... | ... | @@ -0,0 +1,46 @@ |
1 | +module Dingtalk | |
2 | + module Prpcrypt | |
3 | + extend self | |
4 | + | |
5 | + # 对密文进行解密. | |
6 | + # text 需要解密的密文 | |
7 | + def decrypt(aes_key, text, corpid) | |
8 | + status = 200 | |
9 | + text = Base64.decode64(text) | |
10 | + text = handle_cipher(:decrypt, aes_key, text) | |
11 | + result = PKCS7Encoder.decode(text) | |
12 | + content = result[16...result.length] | |
13 | + len_list = content[0...4].unpack("N") | |
14 | + xml_len = len_list[0] | |
15 | + xml_content = content[4...4 + xml_len] | |
16 | + from_corpid = content[xml_len+4...content.size] | |
17 | + # TODO: refactor | |
18 | + if corpid != from_corpid | |
19 | + Rails.logger.debug("#{__FILE__}:#{__LINE__} Failure because #{corpid} != #{from_corpid}") | |
20 | + status = 401 | |
21 | + end | |
22 | + [xml_content, status] | |
23 | + end | |
24 | + | |
25 | + # 加密 | |
26 | + def encrypt(aes_key, text, corpid) | |
27 | + text = text.force_encoding("ASCII-8BIT") | |
28 | + random = SecureRandom.hex(8) | |
29 | + msg_len = [text.length].pack("N") | |
30 | + text = "#{random}#{msg_len}#{text}#{corpid}" | |
31 | + text = PKCS7Encoder.encode(text) | |
32 | + text = handle_cipher(:encrypt, aes_key, text) | |
33 | + Base64.encode64(text) | |
34 | + end | |
35 | + | |
36 | + private | |
37 | + def handle_cipher(action, aes_key, text) | |
38 | + cipher = OpenSSL::Cipher.new('AES-256-CBC') | |
39 | + cipher.send(action) | |
40 | + cipher.padding = 0 | |
41 | + cipher.key = aes_key | |
42 | + cipher.iv = aes_key[0...16] | |
43 | + cipher.update(text) + cipher.final | |
44 | + end | |
45 | + end | |
46 | +end | ... | ... |