C#.NET XML报文签名与验签

--

MD5Util:

using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace dotNetRsa客户端
{
   public class MD5Util
    {
        /// <summary>
        /// mdh5 hash, UTF8 , 16进制表示,去除 "-" 符号,大写
        /// </summary>
        /// <param name="sArray"></param>
        /// <returns></returns>
        public static string GetMD5(string sArray,string charset)
        {

            Encoding enc = Encoding.GetEncoding(charset);

            byte[] sourceBytes = enc.GetBytes(sArray);

            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] hashedBytes = md5.ComputeHash(sourceBytes);

            string str16 = BitConverter.ToString(hashedBytes);

            string rst = str16.Replace("-", "").ToUpper();

            return rst;
        }
    }
}

--

Utils:

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace dotNetRsa客户端
{
   public class Utils
    {
        public static string UrlEncode(string temp, string charset  )
        {

            Encoding encoding = Encoding.GetEncoding(charset);
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < temp.Length; i++)
            {
                string t = temp[i].ToString();
                string k =  HttpUtility.UrlEncode(t, encoding);
                if (t == k)
                {
                    stringBuilder.Append(t);
                }
                else
                {
                    stringBuilder.Append(k.ToUpper());
                }
            }
            return stringBuilder.ToString();
        }

    }
}

--

RequestHandlerB:

--

using System;
using System.Collections;
using System.Collections.Generic;
 
using System.Text;
using System.Text.RegularExpressions;
 
using System.Web;
using System.Xml;

namespace dotNetRsa客户端
{
    /// <summary>
    /// 能处理请求报文和响应报文
    /// </summary>
    public class RequestHandlerB
    {

        /// <summary>
        /// 原始内容
        /// </summary>
        protected string content;


        public RequestHandlerB()
        {
            parameters = new Hashtable();

            // this.httpContext = httpContext;
        }

         

        /// <summary>
        /// 网关url地址
        /// </summary>
        private string gateUrl;

        /// <summary>
        /// 密钥
        /// </summary>
        private string key;

        /// <summary>
        /// 请求的参数
        /// </summary>
        protected Hashtable parameters;

        /// <summary>
        /// debug信息
        /// </summary>
        private string debugInfo;

        

        /// <summary>
        /// 初始化函数
        /// </summary>
        public virtual void init()
        {
            //nothing to do
        }

        /// <summary>
        /// 获取入口地址,不包含参数值
        /// </summary>
        /// <returns></returns>
        public String getGateUrl()
        {
            return gateUrl;
        }

        /// <summary>
        /// 设置入口地址,不包含参数值
        /// </summary>
        /// <param name="gateUrl">入口地址</param>
        public void setGateUrl(String gateUrl)
        {
            this.gateUrl = gateUrl;
        }

        /// <summary>
        /// 获取密钥
        /// </summary>
        /// <returns></returns>
        public String getKey()
        {
            return key;
        }

        /// <summary>
        /// 设置密钥
        /// </summary>
        /// <param name="key">密钥字符串</param>
        public void setKey(string key)
        {
            this.key = key;
        }

        /// <summary>
        /// 获取带参数的请求URL
        /// </summary>
        /// <returns></returns>
        public virtual string getRequestURL()
        {
            this.createSign();

            StringBuilder sb = new StringBuilder();
            ArrayList akeys = new ArrayList(parameters.Keys);
            akeys.Sort();
            foreach (string k in akeys)
            {
                string v = (string)parameters[k];
                if (null != v && "key".CompareTo(k) != 0)
                {
                    sb.Append(k + "=" + Utils.UrlEncode(v, getCharset()) + "&");
                }
            }

            //去掉最后一个&
            if (sb.Length > 0)
            {
                sb.Remove(sb.Length - 1, 1);
            }

            return this.getGateUrl() + "?" + sb.ToString();
        }

        /// <summary>
        ///创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
        /// </summary>
        public virtual void createSign()
        {
            StringBuilder sb = new StringBuilder();

            ArrayList akeys = new ArrayList(parameters.Keys);
            akeys.Sort();

            foreach (string k in akeys)
            {
                string v = (string)parameters[k];
                if (null != v && "".CompareTo(v) != 0
                    && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0)
                {
                    sb.Append(k + "=" + v + "&");
                }
            }

            sb.Append("key=" + this.getKey());

            string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToUpper();

            this.setParameter("sign", sign);

            //debug信息
            this.setDebugInfo(sb.ToString() + " => sign:" + sign);
        }

        /// <summary>
        /// 没有KEY的拼接和MD5 HASH 签名
        /// </summary>
        public virtual void createSignWithoutKey()
        {
            StringBuilder sb = new StringBuilder();

            ArrayList akeys = new ArrayList(parameters.Keys);
            akeys.Sort();

            foreach (string k in akeys)
            {
                string v = (string)parameters[k];
                if (null != v && "".CompareTo(v) != 0
                    && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0)
                {
                    sb.Append(k + "=" + v + "&");
                }
            }

            string rst = sb.ToString();
            rst = rst.TrimEnd('&');

           // sb.Append("key=" + this.getKey());

            string sign = MD5Util.GetMD5(rst, getCharset()).ToUpper();

            this.setParameter("sign", sign);

            //debug信息
            this.setDebugInfo(sb.ToString() + " => sign:" + sign);
        }

        /// <summary>
        /// 获取参数值
        /// </summary>
        /// <param name="parameter">参数名</param>
        /// <returns></returns>
        public string getParameter(string parameter)
        {
            string s = (string)parameters[parameter];
            return (null == s) ? "" : s;
        }

        /// <summary>
        /// 设置参数值
        /// </summary>
        /// <param name="parameter">参数名</param>
        /// <param name="parameterValue">参数值</param>
        public void setParameter(string parameter, string parameterValue)
        {
            if (parameter != null && parameter != "")
            {
                if (parameters.Contains(parameter))
                {
                    parameters.Remove(parameter);
                }

                parameters.Add(parameter, parameterValue);
            }
        }

         

        /// <summary>
        /// 获取debug信息
        /// </summary>
        /// <returns></returns>
        public String getDebugInfo()
        {
            return debugInfo;
        }

        /// <summary>
        /// 设置debug信息
        /// </summary>
        /// <param name="debugInfo"></param>
        public void setDebugInfo(String debugInfo)
        {
            this.debugInfo = debugInfo;
        }

        /// <summary>
        /// 获取所有参数
        /// </summary>
        /// <returns></returns>
        public Hashtable getAllParameters()
        {
            return this.parameters;
        }

        /// <summary>
        /// 获取编码
        /// </summary>
        /// <returns></returns>
        protected virtual string getCharset()
        {
            //return this.httpContext.Request.ContentEncoding.BodyName;
            return "utf-8";
        }

         

        public virtual void createSignMCH()
        {

            /*
             1.进件接口用 用的是dataSign,不是sign
             2.拼接key时,不需要&key=
             */

            StringBuilder sb = new StringBuilder();

            ArrayList akeys = new ArrayList(parameters.Keys);
            akeys.Sort();

            foreach (string k in akeys)
            {
                string v = (string)parameters[k];
                if (null != v && "".CompareTo(v) != 0
                    && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0)
                {
                    sb.Append(k + "=" + v + "&");
                }
            }

            string sighStr = sb.ToString();
            sighStr = sighStr.TrimEnd('&');
            sighStr += this.getKey();//和支付接口不同

            string sign = MD5Util.GetMD5(sighStr, getCharset()).ToLower();

            this.setParameter("dataSign", sign);

            //debug信息
            this.setDebugInfo(sb.ToString() + " => dataSign:" + sign);
        }


        //创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。

        //public string createSign2()
        //{
        //    StringBuilder sb = new StringBuilder();

        //    ArrayList akeys = new ArrayList(parameters.Keys);
        //    akeys.Sort();

        //    foreach (string k in akeys)
        //    {
        //        string v = (string)parameters[k];
        //        if (null != v && "".CompareTo(v) != 0
        //            && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0)
        //        {
        //            sb.Append(k + "=" + v + "&");
        //        }
        //    }

        //    sb.Append("key=" + this.getKey());
        //    string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToUpper();

        //    this.setParameter("sign", sign);

        //    return sign;
        //}

        //输出XML
        public string parseXML()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<xml>");
            foreach (string k in parameters.Keys)
            {
                string v = (string)parameters[k];
                if (Regex.IsMatch(v, @"^[0-9.]$"))
                {

                    sb.Append("<" + k + ">" + v + "</" + k + ">");
                }
                else
                {
                    sb.Append("<" + k + "><![CDATA[" + v + "]]></" + k + ">");
                }

            }
            sb.Append("</xml>");
            return sb.ToString();
        }

        /// <summary>
        /// 设置返回内容
        /// </summary>
        /// <param name="content">XML内容</param>
        public virtual void setContent(string content)
        {
            this.content = content;
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.XmlResolver = null;//2018-12-3
            xmlDoc.LoadXml(content);
            XmlNode root = xmlDoc.SelectSingleNode("xml");
            XmlNodeList xnl = root.ChildNodes;

            foreach (XmlNode xnf in xnl)
            {
                this.setParameter(xnf.Name, xnf.InnerText);
            }
        }


        /// <summary>
        /// 是否平台签名,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
        /// </summary>
        /// <returns></returns>
        public virtual Boolean isTenpaySign()
        {
            StringBuilder sb = new StringBuilder();

            ArrayList akeys = new ArrayList(parameters.Keys);
            akeys.Sort();

            foreach (string k in akeys)
            {
                string v = (string)parameters[k];
                if (null != v && "".CompareTo(v) != 0
                    && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0)
                {
                    sb.Append(k + "=" + v + "&");
                }
            }

            sb.Append("key=" + this.getKey());
            string sign = MD5Util.GetMD5(sb.ToString(), getCharset()).ToUpper();

            //debug信息
            this.setDebugInfo(sb.ToString() + " => sign:" + sign);
            return getParameter("sign").Equals(sign);
        }


    }
}

--

xml root 为"xml"。

使用,签名:

 RequestHandlerB rb = new RequestHandlerB();
                rb.setKey("1111111111111111XXXXXXXXXXXXX"); //设置KEY                
                rb.setParameter("custno", "11111");
                rb.setParameter("shopname", "2222");
                rb.setParameter("type", "333");
                rb.setParameter("serialno", "141111");
                rb.createSign(); //签名
                string xmlb = rb.parseXML();  // 转XML

验证签名

 RequestHandlerB rb2 = new RequestHandlerB();
                rb2.setKey("1111111111111111XXXXXXXXXXXXX");
                rb2.setContent(xmlb);
                bool isvalid = rb2.isTenpaySign();

--

原文地址:https://www.cnblogs.com/runliuv/p/10736755.html