Переглянути джерело

Message decoding test done

master
Patrick Peng Sun 8 роки тому
джерело
коміт
371c2e1927
3 змінених файлів з 161 додано та 0 видалено
  1. +7
    -0
      Api_request.txt
  2. +3
    -0
      main.go
  3. +151
    -0
      messageEncrypt.go

+ 7
- 0
Api_request.txt Переглянути файл

@@ -211,4 +211,11 @@ X-Forwarded-Server: wechat.hitxy.org.au
<Content><![CDATA[songbook]]></Content>
<MsgId>6411651983041024410</MsgId>
<Encrypt><![CDATA[3muEH/vxWRf76hHB+G4WB744Ho4Fu4RmpYYwd3R0Ek//h3dZDmuzakVztD2ecG8lB0DKV9EAJHaSp/Q4nLQM36Dg9eQQb888e6Z6nyjMX/2Na8upraDHrfR2oW1Gv8AJ0bzrYKubpk7AYtvlvNpnhQ2kDKhn5v1L/Rd8CRSb5ODJ3xDhqQqYd6R4DTr4SF8ofCrqDp0taYkMt4e0eHuCDEp+/A/PLBX1PL8Xw+kv/7eW/aoJQIapXAGMgf61/Qj9RfFmNDG6hKz1bF4CU2u/y4XV63xBepDQ7ZfOmtfALa1pIQGhHzyf5jReArmkLu4yERBzQYwc8G5eDq2WDQrrwaaiaVYo1SDNk0F88zjENobf9I+9lVAFbCly4vhdtlLbRHrUomiAjgzN3nHTza9E6NdCpsJ46C8l+1u/3H7Vq0g=]]></Encrypt>
</xml>


如果纯粹加密,没有明文
<xml>
<ToUserName><![CDATA[gh_f09231355c68]]></ToUserName>
<Encrypt><![CDATA[P2DoRtilYwJ1aM+VW1sGs6p11Rhcd/TrFYtvsw53SUVw2Knh27hF5IZUBxRXbz+k87zy983ec5aOwgS+WxYoejmGubaqiYy2yfCBNyGRlWfe+iWc2TnvPIEAJebSWuNOJ7FoITeMndr4tW391XxDdMom8I/VsqKnsZZAangUsxmA1ZEnP/d4Lx8/xt3qJKrJMa4Q8s9VsOOvzLIGhL1IN5bHaXN+CwgBTAUCrHD8AneiX5MLSv/74qozg+jKBSUebZrjRYuTymQ3TBh3pQXyRBQTZNrCAe1tlcNli9e5MSUMsHFIzGw/kiu93/5VkxCYRLgRDQKl9oam4+Rpxywir7EiT7I4X343l9ogcMLWX16evkLlQHoqBhLl6ZcfW7Nmq8/Ghy8jbuwqkR/0jLJ/avtjzgJOwaxdBUz4nYZ452rLJekxIvsmV6PZgCXRrKHzmpZX+i6hIRIWiIaDeMOEsw==]]></Encrypt>
</xml>

+ 3
- 0
main.go Переглянути файл

@@ -16,6 +16,9 @@ func main() {
log.Fatal("unable to read config, program quit")
return
}

Decode("SS")
return
//setup handler
http.HandleFunc("/", webrootHandler)
http.HandleFunc("/api", apiV1Main)

+ 151
- 0
messageEncrypt.go Переглянути файл

@@ -0,0 +1,151 @@
package main

import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)

const txt = "P2DoRtilYwJ1aM+VW1sGs6p11Rhcd/TrFYtvsw53SUVw2Knh27hF5IZUBxRXbz+k87zy983ec5aOwgS+WxYoejmGubaqiYy2yfCBNyGRlWfe+iWc2TnvPIEAJebSWuNOJ7FoITeMndr4tW391XxDdMom8I/VsqKnsZZAangUsxmA1ZEnP/d4Lx8/xt3qJKrJMa4Q8s9VsOOvzLIGhL1IN5bHaXN+CwgBTAUCrHD8AneiX5MLSv/74qozg+jKBSUebZrjRYuTymQ3TBh3pQXyRBQTZNrCAe1tlcNli9e5MSUMsHFIzGw/kiu93/5VkxCYRLgRDQKl9oam4+Rpxywir7EiT7I4X343l9ogcMLWX16evkLlQHoqBhLl6ZcfW7Nmq8/Ghy8jbuwqkR/0jLJ/avtjzgJOwaxdBUz4nYZ452rLJekxIvsmV6PZgCXRrKHzmpZX+i6hIRIWiIaDeMOEsw=="

//Decode Decode encrypt string to xml context
func Decode(s string) string {

r, _ := base64.StdEncoding.DecodeString(txt)

key, _ := base64.StdEncoding.DecodeString(APIConfig.EncodingAESKey + "=")
var k [32]byte
copy(k[:], key)
random, raw, err := AESDecryptMsg([]byte(r), APIConfig.Appid, k)

fmt.Println(len(txt))
fmt.Println(random)
fmt.Println(string(raw))

bc, err := aes.NewCipher([]byte(key))
if err == nil {
fmt.Printf("The block size is %d\n", bc.BlockSize())
var decoded = make([]byte, 4096)
bc.Decrypt(decoded, r)
//AES Decode
}
fmt.Printf("%s", string(r))
return string(r)
}

// 把整数 n 格式化成 4 字节的网络字节序
func encodeNetworkBytesOrder(orderBytes []byte, n int) {
if len(orderBytes) != 4 {
panic("the length of orderBytes must be equal to 4")
}
orderBytes[0] = byte(n >> 24)
orderBytes[1] = byte(n >> 16)
orderBytes[2] = byte(n >> 8)
orderBytes[3] = byte(n)
}

// 从 4 字节的网络字节序里解析出整数
func decodeNetworkBytesOrder(orderBytes []byte) (n int) {
if len(orderBytes) != 4 {
panic("the length of orderBytes must be equal to 4")
}
n = int(orderBytes[0])<<24 |
int(orderBytes[1])<<16 |
int(orderBytes[2])<<8 |
int(orderBytes[3])
return
}

//AESEncryptMsg encryptedMsg = AES_Encrypt[random(16B) + msg_len(4B) + rawXMLMsg + AppId]
func AESEncryptMsg(random, rawXMLMsg []byte, AppId string, AESKey [32]byte) (encryptedMsg []byte) {
const BLOCK_SIZE = 32 // PKCS#7

buf := make([]byte, 20+len(rawXMLMsg)+len(AppId)+BLOCK_SIZE)
plain := buf[:20]
pad := buf[len(buf)-BLOCK_SIZE:]

// 拼接
copy(plain, random)
encodeNetworkBytesOrder(plain[16:20], len(rawXMLMsg))
plain = append(plain, rawXMLMsg...)
plain = append(plain, AppId...)

// PKCS#7 补位
amountToPad := BLOCK_SIZE - len(plain)%BLOCK_SIZE
for i := 0; i < amountToPad; i++ {
pad[i] = byte(amountToPad)
}
plain = buf[:len(plain)+amountToPad]

// 加密
block, err := aes.NewCipher(AESKey[:])
if err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, AESKey[:16])
mode.CryptBlocks(plain, plain)

encryptedMsg = plain
return
}

// encryptedMsg = AES_Encrypt[random(16B) + msg_len(4B) + rawXMLMsg + AppId]
func AESDecryptMsg(encryptedMsg []byte, AppId string, AESKey [32]byte) (random, rawXMLMsg []byte, err error) {
const BLOCK_SIZE = 32 // PKCS#7

if len(encryptedMsg) < BLOCK_SIZE {
err = fmt.Errorf("the length of encryptedMsg too short: %d", len(encryptedMsg))
return
}
if len(encryptedMsg)%BLOCK_SIZE != 0 {
err = fmt.Errorf("encryptedMsg is not a multiple of the block size, the length is %d", len(encryptedMsg))
return
}

plain := make([]byte, len(encryptedMsg)) // len(plain) >= BLOCK_SIZE

// 解密
block, err := aes.NewCipher(AESKey[:])
if err != nil {
panic(err)
}
mode := cipher.NewCBCDecrypter(block, AESKey[:16])
mode.CryptBlocks(plain, encryptedMsg)

// PKCS#7 去除补位
amountToPad := int(plain[len(plain)-1])
if amountToPad < 1 || amountToPad > BLOCK_SIZE {
err = fmt.Errorf("the amount to pad is invalid: %d", amountToPad)
return
}
plain = plain[:len(plain)-amountToPad]

// 反拼装
// len(plain) == 16+4+len(rawXMLMsg)+len(AppId)
// len(AppId) > 0
if len(plain) <= 20 {
err = fmt.Errorf("plain msg too short, the length is %d", len(plain))
return
}
msgLen := decodeNetworkBytesOrder(plain[16:20])
if msgLen < 0 {
err = fmt.Errorf("invalid msg length: %d", msgLen)
return
}
msgEnd := 20 + msgLen
if len(plain) <= msgEnd {
err = fmt.Errorf("msg length too large: %d", msgLen)
return
}

AppIdHave := string(plain[msgEnd:])
if AppIdHave != AppId { // crypto/subtle.ConstantTimeCompare ???
err = fmt.Errorf("AppId mismatch, have: %s, want: %s", AppIdHave, AppId)
return
}

random = plain[:16:16]
rawXMLMsg = plain[20:msgEnd]
return
}

Завантаження…
Відмінити
Зберегти