推送事件加解密
# 推送事件加解密
由于数据在公开的因特网上传输,消息内容是可被截获的;如果内容未加密,则截获者可以直接阅读数据内容,存在着数据泄漏或者数据被抓包破解的风险。

# 推送事件至第三方平台
假设开发者接收推送数据的URL设置为:http://api.3rd.com/receive (opens new window)
当用户触发回调行为时,熵基智联会发送回调消息到填写的URL。
请求内容规范如下:
请求方式: POST
请求地址: http://api.3rdcom/receive?sign=XXXXXXXX×tamp=XXXXXXXX&nonce=XXXXXXXX
接收数据格式 :
{
"event":"XXXXXXXXXXXXXXXXXXXXXXXX",
"unitId": "XXXXXXXXXXXXXXXXXXXXXXX",
"data": "XXXXXXXXXXXXXXXXXXXXXXX"
}
1
2
3
4
5
2
3
4
5
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| sign | String | 加密签名,token为开发者应用回调配置,sign = MD5-32 (token+timestamp+nonce),MD5加密。32位小写。 |
| timestamp | Long | 当前Unix时间戳(毫秒),用于防止请求重放攻击(时间戳有效期为5分钟)。 |
| nonce | String | 随机数。与timestamp结合使用,用于防止请求重放攻击。 |
| unitId | String | 主体Id。 |
| event | String | 回调事件id,唯一不重复。 |
| data | String | 事件消息体加密后的字符串。 |
# AES加密参数说明及各开发语言Demo
sSrc: 需要加密的字串
cKey: AppKey
cIv: AppSecret
1
2
3
4
5
2
3
4
5
# Java
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AES
{
public static void main(String args[]) throws Exception {
// appKey
String cKey = "DBC3KLPYUBC3KLPJ";
// 需要加密的字串
String cSrc = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
// appSecret;
String cIv = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
System.out.println(cSrc);
// 加密
long lStart = System.currentTimeMillis();
String enString = AES.Encrypt(cSrc, cKey, cIv);
System.out.println("加密后的字串是:" + enString);
long lUseTime = System.currentTimeMillis() - lStart;
System.out.println("加密耗时:" + lUseTime + "毫秒");
// 解密
lStart = System.currentTimeMillis();
String DeString = AES.Decrypt(enString, cKey, cIv);
System.out.println("解密后的字串是:" + DeString);
lUseTime = System.currentTimeMillis() - lStart;
System.out.println("解密耗时:" + lUseTime + "毫秒");
}
public static String Encrypt(String sSrc, String sKey, String sIv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();
byte[] dataBytes = sSrc.getBytes();
int plaintextLength = dataBytes.length;
if (plaintextLength % blockSize != 0) {
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
}
byte[] plaintext = new byte[plaintextLength];
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
SecretKeySpec keyspec = new SecretKeySpec(sKey.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(sIv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
return byte2hex(encrypted).toLowerCase();
}
public static String Decrypt(String sSrc, String sKey, String sIv) throws Exception {
byte[] encrypted1 = hex2byte(sSrc);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keyspec = new SecretKeySpec(sKey.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(sIv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] original = cipher.doFinal(encrypted1);
// 去除填充
String originalString = new String(original).replaceAll("\\u0000","");
return originalString;
}
public static byte[] hex2byte(String strhex) {
if (strhex == null) {
return null;
}
int l = strhex.length();
if (l % 2 == 1) {
return null;
}
byte[] b = new byte[l / 2];
for (int i = 0; i != l / 2; i++) {
b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2),
16);
}
return b;
}
public static String byte2hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
return hs.toUpperCase();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# Python
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
import binascii
class AESCipher(object):
def __init__(self):
self.bs = 16
self.iv = '0123456789123456'
self.key = '1234567890123456'
def encrypt(self, raw):
raw = self._pad(raw)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
return binascii.hexlify(cipher.encrypt(raw))
def decrypt(self, enc):
enc = binascii.unhexlify(enc)
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
return cipher.decrypt(enc).decode('utf-8').rstrip("\0")
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * '\0'
crypt = AESCipher()
print crypt.encrypt('12345')
print crypt.decrypt('90b2c15e84cb78e5161f42867807c4bc')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Goland
// AesEncrypt 加密函数
func AesEncrypt(text []byte, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
fmt.Println(err)
}
// 填充
blockSize := block.BlockSize()
paddText := ZeroPadding(text)
blockMode := cipher.NewCBCEncrypter(block, iv[:blockSize])
// 加密
result := make([]byte, len(paddText))
blockMode.CryptBlocks(result, paddText)
// 返回密文
return result, nil
}
// AesDecrypt 解密函数
func AesDecrypt(encrypter []byte, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
fmt.Println(err)
}
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, iv[:blockSize])
result := make([]byte, len(encrypter))
blockMode.CryptBlocks(result, encrypter)
// 去除填充
result = NullUnPadding(result)
return result, nil
}
func ZeroPadding(in []byte) []byte {
length := len(in)
if length%16 == 0 {
return in
} else {
blockCount := length / 16
out := make([]byte, (blockCount+1)*16)
var i int
for i = 0; i < length; i++ {
out[i] = in[i]
}
return out
}
}
func NullUnPadding(in []byte) []byte {
return bytes.TrimRight(in, string([]byte{0}))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51