package service import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/hmac" "crypto/sha1" "crypto/sha256" "encoding/base64" "encoding/binary" "encoding/hex" "main/constant" "main/mt" "sort" "strings" ) func (wp *wxpay) GenSHA256Signature(str string, key string) string { mac := hmac.New(sha256.New, []byte(key)) _, _ = mac.Write([]byte(str)) return strings.ToLower(hex.EncodeToString(mac.Sum(nil))) } func (wp *wxpay) GetPurchaseSig(gameid int64, data string, sessionkey string) (pay_sig string, signature string) { cfg := mt.Table.Wxconfig.GetById(gameid) if cfg == nil { return } pay_sig = wp.GenSHA256Signature("requestMidasPaymentGameItem&"+data, cfg.GetAppkey()) signature = wp.GenSHA256Signature(data, sessionkey) return pay_sig, signature } func (wp *wxpay) DecryptMsg(sMsgSignature string, sTimeStamp string, sNonce string, sEncryptMsg string, token string, aeskey string) (sMsg []byte, msgappid []byte) { // 2.validate signature if !wp.ValidateSignature(sMsgSignature, sTimeStamp, sNonce, sEncryptMsg, token) { return } //3.decode base64 sAesData, err := base64.StdEncoding.DecodeString(sEncryptMsg) if err != nil { return } //4.decode aes sAesKey := wp.GenAesKeyFromEncodingKey(aeskey) if len(sAesKey) == 0 { return } sNoEncryptData := wp.AES_CBCDecrypt(sAesData, sAesKey) // 5. remove kRandEncryptStrLen str if len(sNoEncryptData) <= constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN { return } netlenbyte := sNoEncryptData[constant.WX_RANDENCRYPT_STRLEN : constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN] buf := bytes.NewReader(netlenbyte) iMsgLen := int32(0) //ntohl(iNetLen); binary.Read(buf, binary.BigEndian, &iMsgLen) if len(sNoEncryptData) <= constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN+int(iMsgLen) { return } sMsg = sNoEncryptData[constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN : constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN+iMsgLen] //6. validate appid msgappid = sNoEncryptData[constant.WX_RANDENCRYPT_STRLEN+constant.WX_KMSG_LEN+iMsgLen:] return } func (wp *wxpay) ValidateSignature(sMsgSignature string, sTimeStamp string, sNonce string, sEncryptMsg string, token string) bool { sSignature := wp.ComputeSignature(token, sTimeStamp, sNonce, sEncryptMsg) if sSignature == "" { return false } return sMsgSignature == sSignature } func (wp *wxpay) ComputeSignature(sToken string, sTimeStamp string, sNonce string, sMessage string) string { if sToken == "" || sNonce == "" || sMessage == "" || sTimeStamp == "" { return "" } //sort strs := []string{} strs = append(strs, sToken) strs = append(strs, sTimeStamp) strs = append(strs, sNonce) strs = append(strs, sMessage) sort.Strings(strs) sStr := strs[0] + strs[1] + strs[2] + strs[3] //compute sha1crypto := sha1.New() _, err := sha1crypto.Write([]byte(sStr)) if err != nil { return "" } return hex.EncodeToString(sha1crypto.Sum(nil)) } func (wp *wxpay) GenAesKeyFromEncodingKey(sEncodingKey string) (aeskey []byte) { if len(sEncodingKey) != constant.WX_ENCODING_KEY_SIZE { return } sBase64 := sEncodingKey + "=" data, err := base64.StdEncoding.DecodeString(sBase64) if err != nil { return } return data } func (wp *wxpay) AES_CBCDecrypt(sSource []byte, sKey []byte) []byte { if len(sSource) < constant.WX_AESKEY_SIZE || len(sSource)%constant.WX_AESKEY_SIZE != 0 { return []byte{} } key := sKey if len(sKey) > constant.WX_AESKEY_SIZE { key = key[0:constant.WX_AESKEY_SIZE] } return aesDecryptCBC(sSource, key) } func aesDecryptCBC(encrypted []byte, key []byte) (decrypted []byte) { block, _ := aes.NewCipher(key) // 分组秘钥 blockSize := block.BlockSize() // 获取秘钥块的长度 blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) // 加密模式 decrypted = make([]byte, len(encrypted)) // 创建数组 blockMode.CryptBlocks(decrypted, encrypted) // 解密 decrypted = pkcs5UnPadding(decrypted) // 去除补全码 return decrypted } func pkcs5UnPadding(origData []byte) []byte { length := len(origData) unpadding := int(origData[length-1]) return origData[:(length - unpadding)] }