Пример #1
0
    /// <summary>
    /// 验证URL
    /// </summary>
    /// <param name="sMsgSignature">签名串,对应URL参数的msg_signature</param>
    /// <param name="sTimeStamp">时间戳,对应URL参数的timestamp</param>
    /// <param name="sNonce">随机串,对应URL参数的nonce</param>
    /// <param name="sEchoStr">经过加密的消息体,对应URL参数的encrypt</param>
    /// <param name="sReplyEchoStr"></param>
    /// <returns></returns>
    public int VerifyURL(string sMsgSignature, string sTimeStamp, string sNonce, string sEchoStr, ref string sReplyEchoStr)
    {
        int ret = 0;

        if (m_sEncodingAESKey.Length != 43)
        {
            return((int)DingTalkCryptErrorCode.AES_KEY_ILLEGAL);
        }
        ret           = VerifySignature(m_sToken, sTimeStamp, sNonce, sEchoStr, sMsgSignature);
        sReplyEchoStr = "";
        string cpid = "";

        try
        {
            sReplyEchoStr = Cryptography.AES_decrypt(sEchoStr, m_sEncodingAESKey, ref cpid); //m_sCorpID);
        }
        catch (Exception)
        {
            sReplyEchoStr = "";
            return((int)DingTalkCryptErrorCode.COMPUTE_SIGNATURE_ERROR);
        }
        if (cpid != m_sSuiteKey)
        {
            sReplyEchoStr = "";
            return((int)DingTalkCryptErrorCode.COMPUTE_DECRYPT_TEXT_SuiteKey_ERROR);
        }
        return(ret);
    }
Пример #2
0
        //验证URL
        // @param sMsgSignature: 签名串,对应URL参数的msg_signature
        // @param sTimeStamp: 时间戳,对应URL参数的timestamp
        // @param sNonce: 随机串,对应URL参数的nonce
        // @param sEchoStr: 随机串,对应URL参数的echostr
        // @param sReplyEchoStr: 解密之后的echostr,当return返回0时有效
        // @return:成功0,失败返回对应的错误码
        public int VerifyURL(string sMsgSignature, string sTimeStamp, string sNonce, string sEchoStr, ref string sReplyEchoStr)
        {
            int ret = 0;

            if (m_sEncodingAESKey.Length != 43)
            {
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey);
            }
            ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEchoStr, sMsgSignature);
            if (0 != ret)
            {
                return(ret);
            }
            sReplyEchoStr = "";
            string cpid = "";

            try
            {
                sReplyEchoStr = Cryptography.AES_decrypt(sEchoStr, m_sEncodingAESKey, ref cpid); //m_sCorpID);
            }
            catch (Exception)
            {
                sReplyEchoStr = "";
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecryptAES_Error);
            }
            if (cpid != m_sCorpID)
            {
                sReplyEchoStr = "";
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateCorpid_Error);
            }
            return(0);
        }
Пример #3
0
    /// <summary>
    /// 密文解密
    /// </summary>
    /// <param name="sMsgSignature">签名串</param>
    /// <param name="sTimeStamp">时间戳</param>
    /// <param name="sNonce">随机串</param>
    /// <param name="sPostData">密文</param>
    /// <param name="sMsg">解密后的原文,当return返回0时有效</param>
    /// <returns>成功0,失败返回对应的错误码</returns>
    public int DecryptMsg(string sMsgSignature, string sTimeStamp, string sNonce, string sPostData, ref string sMsg)
    {
        if (m_sEncodingAESKey.Length != AES_ENCODE_KEY_LENGTH)
        {
            return((int)DingTalkCryptErrorCode.AES_KEY_ILLEGAL);
        }

        string sEncryptMsg = sPostData;

        int ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sMsgSignature);

        string cpid = "";

        try
        {
            sMsg = Cryptography.AES_decrypt(sEncryptMsg, m_sEncodingAESKey, ref cpid);
        }
        catch (FormatException)
        {
            sMsg = "";
            return((int)DingTalkCryptErrorCode.COMPUTE_DECRYPT_TEXT_SuiteKey_ERROR);
        }
        catch (Exception)
        {
            sMsg = "";
            return((int)DingTalkCryptErrorCode.COMPUTE_DECRYPT_TEXT_SuiteKey_ERROR);
        }

        if (cpid != m_sSuiteKey)
        {
            return((int)DingTalkCryptErrorCode.COMPUTE_DECRYPT_TEXT_SuiteKey_ERROR);
        }

        return(ret);
    }
Пример #4
0
        /// <summary>
        /// 接收推送消息
        /// </summary>
        /// <param name="xml">请求消息</param>
        /// <param name="configData">configData</param>
        /// <returns>处理结果</returns>
        public static PushResult ReceivePushMessage(string xml, ConfigData configData)
        {
            PushRequest pushRequest = new PushRequest
            {
                Xml                   = xml,
                EncodingAESKey        = configData.EncodingAESKey,
                ComponentVerifyTicket = configData.component_verify_ticket_key,
                ValidityTime          = DateTime.Now.AddDays(1)
            };
            XElement   doc            = XElement.Parse(pushRequest.Xml);
            var        encry          = doc.Element("Encrypt").GetString();
            string     encodingAESKey = pushRequest.EncodingAESKey;
            string     appid          = string.Empty;
            var        xmlContent     = Cryptography.AES_decrypt(encry, encodingAESKey, ref appid);
            PushResult pushResult     = TenpayUtil.ConvertToPushRequest(xmlContent);

            if (pushResult.InfoType == "component_verify_ticket")
            {
                // 写入缓存
                //Redis.SetRedis(pushRequest.ComponentVerifyTicket, pushResult.ComponentVerifyTicket, pushRequest.ValidityTime);
                pushResult.IsSucceed = !string.IsNullOrEmpty(pushRequest.ComponentVerifyTicket);
            }
            else
            {
                pushResult.IsSucceed = false;
                pushResult.Message   = $"暂不处理类型{pushResult.InfoType}";
            }
            return(pushResult);
        }
Пример #5
0
        /// <summary>
        /// 消息解密
        /// </summary>
        /// <param name="post_xml">微信推送的加密事件或消息</param>
        /// <param name="decrypt_key">第三方平台的解密key</param>
        /// <param name="appid">公众号appid</param>
        /// <returns>解密后的xml字符串</returns>
        public static string MessageDecrypt(string post_xml, string decrypt_key, string appid)
        {
            XmlDocument xmldoc = new XmlDocument();

            xmldoc.LoadXml(post_xml);
            XmlElement rootNode    = xmldoc.DocumentElement;
            string     sDecryptXml = Cryptography.AES_decrypt(rootNode.SelectSingleNode("Encrypt").InnerText, decrypt_key, ref appid);

            return(sDecryptXml);
        }
Пример #6
0
        // 检验消息的真实性,并且获取解密后的明文
        // @param sMsgSignature: 签名串,对应URL参数的msg_signature
        // @param sTimeStamp: 时间戳,对应URL参数的timestamp
        // @param sNonce: 随机串,对应URL参数的nonce
        // @param sPostData: 密文,对应POST请求的数据
        // @param sMsg: 解密后的原文,当return返回0时有效
        // @return: 成功0,失败返回对应的错误码
        public int DecryptMsg(string sMsgSignature, string sTimeStamp, string sNonce, string sPostData, ref string sMsg)
        {
            if (m_sEncodingAESKey.Length != 43)
            {
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey);
            }
            XmlDocument doc = new XmlDocument();
            XmlNode     root;
            string      sEncryptMsg;

            try
            {
                doc.LoadXml(sPostData);
                root        = doc.FirstChild;
                sEncryptMsg = root["Encrypt"].InnerText;
            }
            catch (Exception)
            {
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ParseXml_Error);
            }
            //verify signature
            int ret = 0;

            ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sMsgSignature);
            if (ret != 0)
            {
                return(ret);
            }
            //decrypt
            string cpid = "";

            try
            {
                sMsg = Cryptography.AES_decrypt(sEncryptMsg, m_sEncodingAESKey, ref cpid);
            }
            catch (FormatException)
            {
                sMsg = "";
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecodeBase64_Error);
            }
            catch (Exception)
            {
                sMsg = "";
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecryptAES_Error);
            }
            if (cpid != m_sCorpID)
            {
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateCorpid_Error);
            }
            return(0);
        }
Пример #7
0
 /// <summary>
 /// 开启微信回调模式
 /// </summary>
 /// <returns></returns>
 public string OpenWeChatCallbackMode(U_WeChatCallbackParameter wcp)
 {
     //数据不为空,表示验证开启微信回调模式
     //数据为空,表示微信数据正常回调
     if (!string.IsNullOrEmpty(wcp.echostr))
     {
         string corpid  = "";
         string echostr = Cryptography.AES_decrypt(wcp.echostr, ConfigSugar.GetAppString("WeChatCallbackEncodingAESKey"), ref corpid);
         return(echostr);
     }
     else
     {
         WeChatHandle wch = WeChatEventFactory.GetWeChatHandle(wcp, Request.InputStream);
         return(wch.ExecuteEventHandle());
     }
 }
Пример #8
0
        /// <summary>
        /// 返回验证内容
        /// </summary>
        /// <param name="msg_signature"></param>
        /// <param name="timestamp"></param>
        /// <param name="nonce"></param>
        /// <param name="echostr"></param>
        /// <returns></returns>
        public string ReplyVerify(string echostr)
        {
            string rEchoStr = "";
            int    ret      = 0;

            try
            {
                if (EncodingAESKey.Length != 43)
                {
                    ret = (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey;
                }
                ret = VerifySignature(Token, _timestamp, _nonce, _signature, echostr);
                if (ret == 0)
                {
                    rEchoStr = "";
                    string cpid = "";
                    try
                    {
                        rEchoStr = Cryptography.AES_decrypt(echostr, EncodingAESKey, ref cpid); //CorpID);
                    }
                    catch (Exception)
                    {
                        rEchoStr = "";
                        ret      = (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecryptAES_Error;
                    }
                    if (cpid != WeiXinID)
                    {
                        rEchoStr = "";
                        ret      = (int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateCorpid_Error;
                    }
                }
            }
            catch
            {
            }
            if (ret != 0)
            {
                rEchoStr = "ERR: VerifyURL fail, ret: " + ret + "  echostr:" + echostr;
            }
            return(rEchoStr);
        }
Пример #9
0
        /// <summary>
        ///  检验消息的真实性,并且获取解密后的明文
        /// </summary>
        /// <param name="sMsgSignature">签名串,对应URL参数的msg_signature</param>
        /// <param name="sTimeStamp">时间戳,对应URL参数的timestamp</param>
        /// <param name="sNonce">随机串,对应URL参数的nonce</param>
        /// <param name="sPostData">密文,对应POST请求的数据</param>
        /// <param name="sMsg">解密后的原文,当return返回0时有效</param>
        /// <returns> 成功0,失败返回对应的错误码</returns>
        public int DecryptMsg(string sMsgSignature, string sTimeStamp, string sNonce, string sEncryptMsg, ref string sMsg)
        {
            if (m_sEncodingAESKey == null || m_sEncodingAESKey.Length != 43)
            {
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_IllegalAesKey);
            }
            XmlDocument doc = new XmlDocument();
            XmlNode     root;
            //检验签名
            int ret = 0;

            ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sMsgSignature);
            if (ret != 0)
            {
                return(ret);
            }
            //解密
            string cpid = "";

            try
            {
                sMsg = Cryptography.AES_decrypt(sEncryptMsg, m_sEncodingAESKey, ref cpid);
            }
            catch (FormatException)
            {
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecodeBase64_Error);
            }
            catch (Exception)
            {
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_DecryptAES_Error);
            }
            if (cpid != m_sAppID)
            {
                return((int)WXBizMsgCryptErrorCode.WXBizMsgCrypt_ValidateAppid_Error);
            }
            return(0);
        }
Пример #10
0
        public async Task InvokeAsync(HttpContext context)
        {
            var request = context.Request;

            if (request.Path.Value.Contains(_options.Value.LazyWechatListener))
            {
                bool validation = Validate(out string signature, out string timestamp, out string nonce, out string echostr);

                var info = "signature:{0},timestamp:{1},nonce:{2},echostr:{3} received from wechat at {4}";
                _logger.LogInformation(info, signature, timestamp, nonce, echostr, DateTime.Now);

                var weChatMessager = new WeChatMessager
                {
                    signature  = signature,
                    timestamp  = timestamp,
                    nonce      = nonce,
                    echostr    = echostr,
                    validation = validation,
                    type       = _options.Value.Type,
                    method     = context.Request.Method
                };

                #region 以stream的方式获取微信post到监听程序的数据:数据类型为XML
                var inputContent = "";
                using (StreamReader stream = new StreamReader(request.Body, Encoding.UTF8))
                {
                    inputContent = await stream.ReadToEndAsync();
                }
                #endregion

                info = "inputXml:'{0}' received from wechat at {1}";
                _logger.LogInformation(info, inputContent, DateTime.Now);

                var encrypted = false;

                if (!string.IsNullOrEmpty(inputContent))
                {
                    dynamic messageBody = new ExpandoObject();
                    messageBody           = ParseMessage(inputContent, out MessageFormat format);
                    weChatMessager.format = format;

                    if (UtilRepository.IsPropertyExist(messageBody, "Encrypt"))
                    {
                        string decryptedMessage = Cryptography.AES_decrypt(messageBody.Encrypt, _options.Value.EncodingAESKey);
                        messageBody = ParseMessage(decryptedMessage, out _);
                        encrypted   = true;
                    }

                    weChatMessager.messageBody = messageBody;

                    if (UtilRepository.IsPropertyExist(messageBody, "FromUserName"))
                    {
                        _onMessageReceived?.Invoke(weChatMessager);
                    }

                    var json = JsonConvert.SerializeObject(weChatMessager);
                    _ = _messageQueue.Push(json);

                    info = "json format of message:'{0}' has been pushed into queue at {1}";
                    _logger.LogInformation(info, json, DateTime.Now);
                }

                var message = weChatMessager.message;

                if (encrypted && message.ToLower() != "success")
                {
                    var encryptMessage    = Cryptography.AES_encrypt(weChatMessager.message, _options.Value.EncodingAESKey, _options.Value.AppID);
                    var signatureResponse = generateSignature(timestamp, nonce, encryptMessage);
                    message = string.Format(MessageTemplateFactory.CreateInstance(weChatMessager.format == MessageFormat.Xml ? MessageType.Encrypt : MessageType.EncryptJson), encryptMessage, signatureResponse, timestamp, nonce);
                }

                info = "sent message:'{0}' has been logged at {1}";
                _logger.LogInformation(info, message, DateTime.Now);

                await context.Response.WriteAsync(message);
            }
            else
            {
                await _next(context);
            }

            bool Validate(out string signature, out string timestamp, out string nonce, out string echostr)
            {
                #region 微信在向监听程序发送数据的时候会同时发送signature,timestamp,nonce以及echostr供用户判断该请求是否来自微信端
                signature = string.IsNullOrEmpty(request.Query["signature"]) ? "" : request.Query["signature"].ToString();

                timestamp = string.IsNullOrEmpty(request.Query["timestamp"]) ? "" : request.Query["timestamp"].ToString();

                nonce = string.IsNullOrEmpty(request.Query["nonce"]) ? "" : request.Query["nonce"].ToString();

                echostr = string.IsNullOrEmpty(request.Query["echostr"]) ? "" : request.Query["echostr"].ToString();

                #endregion

                List <string> lstSort = new List <string> {
                    _options.Value.Token, timestamp, nonce
                };
                lstSort.Sort();
                var sha1 = string.Join(string.Empty, lstSort).SHA1();

                var validation = (sha1.ToUpper() == signature.ToUpper());
                return(validation);
            }

            string generateSignature(string timestamp, string nonce, string encryptMessage)
            {
                ArrayList AL = new ArrayList();

                AL.Add(_options.Value.Token);
                AL.Add(timestamp);
                AL.Add(nonce);
                AL.Add(encryptMessage);
                AL.Sort(new DictionarySort());
                string raw = "";

                for (int i = 0; i < AL.Count; ++i)
                {
                    raw += AL[i];
                }

                SHA1          sha;
                ASCIIEncoding enc;
                string        hash = "";

                sha = new SHA1CryptoServiceProvider();
                enc = new ASCIIEncoding();
                byte[] dataToHash = enc.GetBytes(raw);
                byte[] dataHashed = sha.ComputeHash(dataToHash);
                hash = BitConverter.ToString(dataHashed).Replace("-", "");
                hash = hash.ToLower();

                return(hash);
            }

            dynamic ParseMessage(string inputContent, out MessageFormat format)
            {
                inputContent = inputContent.Trim().Replace("\n", "");
                dynamic messageBody = new ExpandoObject();

                if (inputContent.StartsWith("<") && inputContent.EndsWith(">"))
                {
                    messageBody = UtilRepository.ParseAPIResult(JsonConvert.SerializeObject(inputContent.FromXml()));
                    format      = MessageFormat.Xml;
                }
                else if (inputContent.StartsWith("{") && inputContent.EndsWith("}"))
                {
                    messageBody = UtilRepository.ParseAPIResult(inputContent);
                    format      = MessageFormat.Json;
                }
                else
                {
                    throw new ArgumentException(nameof(inputContent));
                }
                return(messageBody);
            }
        }