数字签名

  转载请表明出处:http://www.cnblogs.com/oumi/p/6680520.html

  最近在项目中遇到了这样的场景,暂定2人A和B,现在A通过接口提供了服务与B.假定AB属于跨平台开发环境,为了数据顺利的实现交互,并且确保数据不被中途非法拦截篡改,现在提出了数字签名的解决方案,具体如下:

  解决方案:再次提出了数字签名的概念,所谓的数字签名在别处是怎么定义的暂且不讨论,那么在本问中将其定义为对需要的传输的数据按照某种规则转换为特定的字符串和签名密钥Key、以及身份唯一识别码进行组合产生新的字符串(此时的字符串我们称之为待签名数据)。取得待签名数据后对计算出其Hash字符串值,再将其值转换为MD5字符串。经过MD5加密后的字符串我们称之为待签名数据的数字签名。作为对接方,需要按照同样的算法将接受到的数据进行同等算法,然后与传送方传递的数字签名进行比较,比较一致我们认为数据对接放顺利并成功的取得数据,此时的数据是正确有效的,反之我们认为是无效的。具体的实现方式如下:

 /// <summary>
 /// 对象扩展
 /// </summary>
public static class ObjectExtensions
{
        #region 数据签名

        /// <summary>
        /// 数字签名
        /// </summary>
        /// <param name="input">待签名数据</param>
        /// <param name="encode">带签名数据编码格式,默认采用UTF-8</param>
        /// <returns>签名结果</returns>
        public static String DigitalSign(this string input, Encoding encode)
        {
            if (encode == null)
            {
                encode = Encoding.UTF8;
            }
            byte[] inputBytes = encode.GetBytes(input);
            return DigitalSignature(inputBytes);
        }

        /// <summary>
        /// 数字签名
        /// </summary>
        /// <param name="input">待签名数据</param>
        /// <param name="prefix">待签名前缀</param>
        /// <param name="signKey">签名加密Key</param>
        /// <param name="encode">待签名数据编码格式,默认采用UTF-8</param>
        /// <param name="suffix">待签名后缀</param>
        /// <returns>签名结果</returns>
        public static String DigitalSign(this string input, string signKey, Encoding encode, string prefix = "", string suffix = "")
        {
            var strNewUnSignStr = "";
            if (encode == null)
            {
                encode = Encoding.UTF8;
            }
            strNewUnSignStr = string.Format("{0}{1}{2}{3}", prefix ?? string.Empty, signKey, input, suffix ?? string.Empty);

            byte[] inputBytes = encode.GetBytes(strNewUnSignStr);
            return DigitalSignature(inputBytes);
        }             

        /// <summary>
        /// 二进制数字签名
        /// </summary>
        /// <param name="objectAsBytes">二进制对象</param>
        /// <returns>签名结果</returns>
        /// <remarks>
        /// 转换方式:md5
        /// 原理:把字节数组的Hash值转换为了16进制字符串</remarks>
        public static string DigitalSignature(this byte[] objectAsBytes)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] result = md5.ComputeHash(objectAsBytes);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < result.Length; i++)
            {
                sb.Append(result[i].ToString("X2"));
            }
            return sb.ToString();
        }
        #endregion

}

  使用示例:

     

        /// <summary>
        /// 测试用例
        /// </summary>
        public void DigitalSignatureTest()
        {

            //发送方:
            string unDigSign="我是需要签名的数据";
            //此处的Key对于数字签名提供方与接受方来将,只有他们二人才知道,且是不变的,别人是不知道
            //为了简化,仅仅用了一个Guid字符串来表示,实际上,可以根据自己的需要处理
            string signKey=Guid.New().ToString();
            string prefix="prefix";
            string suffix="suffix";
            string signedStr= unDigSign.DigitalSignature(signKey,Encoding.UTF8,prefix,suffix);

            //对接方
            //对接方按照本源码算法实现都等数字签名功能即可,将计算产生的数字签名进行比较便可得知是否被拦截篡改
            //如果为了数据的安全,可以对传输的字符串经常加密,然后再参与上述计算,或者先参与上述计算,再进行加密。
            //本做法可根据您具体的情况进行调整,本例不在细说。
            //若有兴趣请自行细细体会
        }

  通过上述对原理一种代码实现,就达到了数字签名。在示例中展示了具体的用法,并说明了核心思想。

  到现在,这可以顺利的实现数字签名,并防止数据被拦截篡改。

      题外:本文就是抛砖引玉,如果您有更好的方式可以留言交流。欢迎提出批评指正。

 

posted @ 2017-04-07 23:32  李文学  阅读(441)  评论(0编辑  收藏  举报