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 }