.Net加密与解密——非对称加密之数字签名





  一,从非对称加密的认证模式说起



由消息的发送方发布公钥,持有私钥。

 

步骤:

1,发送方公布自己的公钥,任何人都可以获得。

2,发送方使用自己的私钥对消息进行加密,然后发送。

3,接收方使用发送方的公钥对消息进行解密。

 

 

缺点:

1,任何截获该消息的第三方都能够使用发送方公钥进行解密;

2,耗时,不适用于大数据



  二,数字签名


      过程:


1,发送方对想要传递的消息进行散列运算,得到原始消息摘要。(摘要可以代表消息本身,相当于指纹)


2,发送方使用自己的私钥只对消息摘要进行加密,该过程也称作签名。将消息和加密后的摘要发送给接收方。由于摘要非常小,因此次采用非对称加密运算速度也很快。


3,接收方使用发送方的公钥对消息摘要进行解密,确认了发送方,并得到原始消息摘要。接收方对收到的消息进行散列运算,得到一个本地消息摘要。


4,接收方对比原始的消息摘要和本地消息摘要。如果相同,说明消息没有被改动过;如果不同,说明消息已经被改动过;


  优点:

          1,解决了非对称加密中认证模式比较耗时间的问题。

       

 缺点:

  1,只对摘要进行了加密,并未对消息进行加密,一旦被截获,即可查看该消息。




三,数字签名Demo


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

namespace 数字签名
{
    class Program
    {
        static void Main(string[] args)
        {
            //发送方
            string plainTest = "hello world";
            string privateKey = "<RSAKeyValue><Modulus>qA89WuhLCmvYHJqw+mfjRZ6Ep8xuicvRkVWkuufRHBAmLgXt2lHThSSBsZhFEECHqvwGFF+OybGj1Ki72A3h056tM6yRNppJFaJGGrnsjsWPPNa14E6f+ZBvC/MZRISLGNTDxhbHuvNSMx+hLU+Skz+B75RCMoYuEOuP8GxFEqs=</Modulus><Exponent>AQAB</Exponent><P>7VxYssHAiMZtnVzgK3h3U9llNZSa5MCK4/iLvATQ5h3+yHegT0t+q2Tv844QUxcBPvkkrF+uvSb043Nw65KoTw==</P><Q>tUG739ddGWVrsBxle1ZmuABVBzeUNUiCOsbcGP/LsmbScdnk46rIfjVZ3NGlfptbAv4I7MPatr8Je1O5GL485Q==</Q><DP>ZyFXnJuYhxUILXZcJCccWb88PVKLFlceQb0NIa1KAqIHwJxReAKKT/f0VfNk3mVBclYX/Bk6uA7EGktfRcub+w==</DP><DQ>rLubBiNgBo6/hFJbZ6GcPCec4EbYB7s02DygjXZfsYEJdhQ3a7taW+QN4kEsHK6CmiRrbu7qpJMDvzK3R1wr/Q==</DQ><InverseQ>a0q3ffhjSHdaZW0QrkqZNUNSQ+j5/ltPS9zaJQiVhO2abaYaGwKaVVsbuD7cB+i4EasAw4uQHrk456Vkw/HQnw==</InverseQ><D>DyXIfvAfC2JrCTD8MKW6e2TtSf6IHA1t5y6T+XC5jVD7T/yi0qG7ce23bt1tpChc0hGDLsTqJs3HGXzX6YJez0Frz37UuNNsNyrhh3cAnxQuAwaCZMF7tPYOQbmgXP5OFpgaIjUmhMwysmm9WdrTocE6h39t5QlLy7g6xH9MJ+k=</D></RSAKeyValue>";//这里的key均由provider产生的
            string signedDigest = RSACryptoHelper.SignData(plainTest, privateKey);
            Console.Write(signedDigest);
            Console.WriteLine();


            //接收方
            string publicKey = "<RSAKeyValue><Modulus>qA89WuhLCmvYHJqw+mfjRZ6Ep8xuicvRkVWkuufRHBAmLgXt2lHThSSBsZhFEECHqvwGFF+OybGj1Ki72A3h056tM6yRNppJFaJGGrnsjsWPPNa14E6f+ZBvC/MZRISLGNTDxhbHuvNSMx+hLU+Skz+B75RCMoYuEOuP8GxFEqs=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
            bool isCorrect = RSACryptoHelper.VerifyData(plainTest, signedDigest, publicKey);
            Console.Write(isCorrect);
            Console.ReadKey();



        }
    }

    /// <summary>
    /// Class RSACryptoHelper
    /// </summary>
    /// <remarks>Editor:v-liuhch CreateTime:2015/5/17 19:15:42</remarks>
    public class RSACryptoHelper {

        /*
         RSACryptoServiceProvider
         
         */
        /// <summary>
        /// 运算摘要,并对摘要进行签名
        /// </summary>
        /// <param name="plainText">明文</param>
        /// <param name="privateKeyXml">私钥.</param>
        /// <returns>System.String.</returns>
        /// <remarks>Editor:v-liuhch CreateTime:2015/5/17 19:11:41</remarks>
        public static string SignData(string plainText, string privateKeyXml) {

            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            provider.FromXmlString(privateKeyXml);

            byte[] plainData = Encoding.Default.GetBytes(plainText);

            //设置获取摘要的算法
            HashAlgorithm shal = HashAlgorithm.Create("SHA1");

            //获得签名的过的摘要
            byte[] signedDigest = provider.SignData(plainData, shal);//运算摘要,并对摘要进行签名,并返回签名后的摘要
            return Convert.ToBase64String(signedDigest);

        }

        /// <summary>
        /// Verifies the data.
        /// </summary>
        /// <param name="plainText">明文</param>
        /// <param name="signature">要验证的签名数据.</param>
        /// <param name="publicKeyXml">发送方公钥</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        /// <remarks>Editor:v-liuhch CreateTime:2015/5/17 18:44:36</remarks>
        public static bool VerifyData(string plainText, string signature, string publicKeyXml) {

            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            provider.FromXmlString(publicKeyXml);

            byte[] plainData = Encoding.Default.GetBytes(plainText);
            byte[] signedDigest = Convert.FromBase64String(signature);

            HashAlgorithm shal = HashAlgorithm.Create("SHA1");

            /*
                 摘要:
            //     通过将指定的签名数据与为指定数据计算的签名进行比较来验证指定的签名数据。
            //
            // 参数:
            //   buffer:
            //     已签名的数据。
            //
            //   halg:
            //     用于创建数据的哈希值的哈希算法名称。
            //
            //   signature:
            //     要验证的签名数据。
            //
            // 返回结果:
            //     如果签名验证为有效,则为 true;否则,为 false。
             */
            bool isDataIntact = provider.VerifyData(plainData, shal, signedDigest);//用于重新运算消息,得出本地摘要,并解密传递进来的原始摘要,最后对本地摘要和原始摘要进行对比,并返回bool型的结果

            return isDataIntact;


        }

        /// <summary>
        /// Signs the data2.
        /// </summary>
        /// <param name="plainText">The plain text.</param>
        /// <param name="privateKeyXml">The private key XML.</param>
        /// <returns>System.String.</returns>
        /// <remarks>Editor:v-liuhch CreateTime:2015/5/17 19:15:36</remarks>
        public static string SignData2(string plainText, string privateKeyXml) {

            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            provider.FromXmlString(privateKeyXml);

            byte[] plainData = Encoding.Default.GetBytes(plainText);

            //设置获取摘要的算法
            HashAlgorithm shal = HashAlgorithm.Create("SHA1");
            //获取原始摘要
            byte[] digestData = shal.ComputeHash(plainData);
            //对原始摘要签名
            byte[] signedDigest = provider.SignHash(digestData, "SHA1");
            return Convert.ToBase64String(signedDigest);

        }

        /// <summary>
        /// Verifies the data2.
        /// </summary>
        /// <param name="plainText">The plain text.</param>
        /// <param name="signedDigest">The signed digest.</param>
        /// <param name="publicKeyXml">The public key XML.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
        /// <remarks>Editor:v-liuhch CreateTime:2015/5/17 19:15:33</remarks>
        public static bool VerifyData2(string plainText, string signedDigest, string publicKeyXml) {


            RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
            provider.FromXmlString(publicKeyXml);

            byte[] plainData = Encoding.Default.GetBytes(plainText);
            byte[] signedDigestData = Convert.FromBase64String(signedDigest);

            //获得本地摘要
            HashAlgorithm shal = HashAlgorithm.Create("SHA1");
            byte[] digest = shal.ComputeHash(plainData);

            //解密签名,并判断摘要是否一致
            bool isDataIntact = provider.VerifyHash(digest, "SHA1", signedDigestData);
            return isDataIntact;



        
        }
    }

}



         
















上一篇:为你的APK进行数字签名


下一篇:Lucene.Net 入门---介绍篇