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 @@ | @@ -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 @@ | @@ -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 |