forked from ridewindx/wechat
/
msgcrypto.go
82 lines (68 loc) · 1.91 KB
/
msgcrypto.go
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
package mp
import (
"crypto/aes"
"crypto/cipher"
"encoding/binary"
"fmt"
)
const BLOCK_SIZE = 32
func encryptMsg(random, msg, appId, aesKey []byte) []byte {
msgLen := len(msg)
textLen := 20+msgLen+len(appId)
padNum := BLOCK_SIZE - (textLen % BLOCK_SIZE)
if padNum == 0 {
padNum = BLOCK_SIZE
}
textLen += padNum
text := make([]byte, textLen)
copy(text[:16], random)
binary.BigEndian.PutUint32(text[16:20], uint32(msgLen))
copy(text[20:], msg)
copy(text[20+msgLen:], appId)
pad := byte(padNum)
for i := textLen-padNum; i < textLen; i++ {
text[i] = pad
}
block, err := aes.NewCipher(aesKey)
if err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, aesKey[:16])
mode.CryptBlocks(text, text)
return text
}
func decryptMsg(ciphertext, aesKey []byte) (random, msg, appId []byte, err error) {
if len(ciphertext) < BLOCK_SIZE {
err = fmt.Errorf("ciphertext length is too short: %d", len(ciphertext))
return
}
if len(ciphertext) % BLOCK_SIZE != 0 {
err = fmt.Errorf("ciphertext length is invalid: %d", len(ciphertext))
return
}
text := make([]byte, len(ciphertext))
block, err := aes.NewCipher(aesKey)
if err != nil {
panic(err)
}
mode := cipher.NewCBCDecrypter(block, aesKey[:16])
mode.CryptBlocks(text, ciphertext)
padNum := int(text[len(text)-1])
if padNum < 1 || padNum > BLOCK_SIZE {
err = fmt.Errorf("incorrect pad bytes num: %d", padNum)
return
}
text = text[:len(text)-padNum]
if len(text) < 20 {
err = fmt.Errorf("")
}
random = text[:16]
msgLen := int(binary.BigEndian.Uint32(text[16:20]))
if len(text) <= 20+msgLen {
err = fmt.Errorf("incorrect msg length: %d", msgLen)
return
}
msg = text[20:20+msgLen]
appId = text[20+msgLen:]
return
}