DotNet加密方法分析–数字签名

一、Application介绍

   
顿时快要过年回村里了,村里没有wifi,没有4G,没有流量,更加紧要的是过几天电脑就得卖掉换车票了,得赶紧写几篇博客。

WPF中的Application对象用来展开部分大局的行为和操作,并且每个 Domain (应用程序域)中仅且只有一个 Application 实例存在。WPF Application默认由两部分组成 : App.xaml 和 App.xaml.cs,这有点类似于 Asp.Net WebForm,将定义和行事代码相分离。

图片 1

微软把WPF中平常利用的效能都封装在 Application 类中了。 Application 类具体有以下职能: 

   
数据安全的有关技术在现在愈加变得重要,因为人们对于自身的信息都有一种尊敬的私欲,不想被人取拿到自己的私密音信,加密几乎已经是其一时代的严重性词了。在那多少个HTTPS盛行的时日,作为一个开发人员怎么可能不去精通和学习呢。这篇博文就来给我们简单介绍一个HTTPS在.NET种的运用和兑现形式。

  • 钉住应用程序的生存期并与之互相。 
  • 追寻和拍卖命令行参数。 
  • 检测和响应未经处理的这些。 
  • 共享应用程序范围的习性和资源。 
  • 管制独立应用程序中的窗口。 
  • 钉住和治本导航。 

   
数字证书和数字签名的落实重点是遵照非对称加密和数字摘要,数字签名是数字证书不可或缺的一有些。这篇博客首要讲师数字签名、数字证书,以及数字签名在.NET种的落实形式。

二、Applicaion应用

一.数字签名概述:

1、在Visual Studio 2015中开创一个“WPF应用程序”,使用App.xaml文件定义启动应用程序。

   1.数字签名的基本原理:

     
这里首先来打听部分怎么叫做数字签名,数字签名是外加在数额单元上的有些数据,或是对数码单元所做的密码变换。数字签名是对非对称加密和音讯摘要的接纳。数签名的法则:使用非对称密钥将签署函数添加到非对称算法,制造一个“签名”,另一方接受加密的信息,使用确认函数来验证签名。有如下图:

图片 2

   
 表明:用户A选取一个非对称签名算法创造一对新密钥,自己保留私钥,公钥发给B。用户B使用用户A的公钥来讲明签名。

     将散列码做为创设数字签名,有如下图:

图片 3

    将散列码作为确认一个数字签名,有如下图:

图片 4

花色中的每个WPF窗口(xaml),包含2个文件:xaml和xaml.cs

    2.数字签名的特性:

     
第三方不可能以假乱真用户A的数字签名;第三方无法再度利用用户A的数字签名;第三方不可能改变签名后的文本;用户A无法否认自己的签名文件。数字签名可以提供一种和大体签名类似的合理性编制。数字签名的安全性和加密的另外地点是同样的,他们都是依照可能的得力密钥管理的。数字签名只行使了非对称密钥加密算法,能保证发送音讯的完整性、身份表明和不可以矢口否认行,数字加密应用了对称密钥加密算法和非对称密钥加密算法相结合的章程,可以保证发送音信的保密性。

图片 5

二.数字证书概述:

   对于HTTPS(Hyper Text Transfer Protocol over Secure Socket
Layer)很多开发人士都不会陌生,尽管是普通用户也是相比的熟知。数字证书(公钥证书):用于电子音讯活动中电子公文行为主体的求证和认证,并可实现电子文件保密性和完整性的电子数码。数字证书是一个经证书认证中央批发的证件。

 
 数字证书:个人数字证书,单位数字证书、单位员工数字证书、服务器证书、VPN证书、WAP证书、代码签名证书和表单签名证书等。

 
 数字证书是一个经证书授权重心数字签名的隐含公开密钥拥有者信息以及公开密钥的文件,最简易的申明包含一个公开密钥、名称一剂证书授权中央的数字签名。

 
 数字证书的特点:音信的保密性;交易者身份的引人注目;不可否认性、不可修改性。

 
 数字证书的二种保存形式:带有私钥的证件;二进制编码的证书;Base64编码证书。

项目文件(WpfApplication.csproj)中有相应的叙述节点:<Page>和<Compile>,而<ApplicationDefinition>节点有的话只可以有一个,用来定义启动项。

三.DotNet数字签名核心目的解析:

   
 在.NET中涵盖两种协助数字签名的非对称算法:RSA算法(为二种多少加密和数字签名定义了函数);DSA算法(协理数字签名,不帮忙数据加密)。在.NET中利用RSA算法举办数字签名使用RSACrypto瑟维斯(Service)(Service)Provider类,使用DSA进行数字签名的五个基本类如下图:

图片 6

 
 DSA类:数字签名算法DSA的基类;DSACryptoService(Service)Provider类:定义访问DSA算法的加密服务提供程序实现的卷入对象;DSASignatureDeformatter类:验证DSA签名;DSASignatureFormatter类:创制DSA签名;

   接下来大家具体精晓一下这多少个类:

     1.RSACryptoServiceProvider类:

       
(1).SignData()方法:使用指定的哈希算法统计指定输入流的哈希值,并对总计所得的哈希值签名。

public byte[] SignData(Stream inputStream, object halg)
    {
      int calgHash = Utils.ObjToAlgId(halg, OidGroup.HashAlgorithm);
      return this.SignHash(Utils.ObjToHashAlgorithm(halg).ComputeHash(inputStream), calgHash);
    }

   
 该措施存在五个重载方法,六个重载方法的率先个参数不同,分别是Stream、byte[]四个档次。由代码可以观望,该方法接受六个参数,inputStream是要统计其哈希值的输入数据,halg用于创制哈希值的哈希算法。SignHash()通过用私钥对其展开加密来总括指定哈希值的签约。

       
(2).VerifyData():通过使用提供的公钥确定签名中的哈希值并将其与所提供数据的哈希值进行相比印证数字签名是否可行。

 public bool VerifyData(byte[] buffer, object halg, byte[] signature)
    {
      int calgHash = Utils.ObjToAlgId(halg, OidGroup.HashAlgorithm);
      return this.VerifyHash(Utils.ObjToHashAlgorithm(halg).ComputeHash(buffer), calgHash, signature);
    }

   
该措施没有重载版本,有源码可以看出该方法接收两个参数,分别是:buffer已签约的多少,halg用于创建数量的哈希值的哈希算法名称,signature要表明的签约数据。该情势重回一个布尔类型,假如签名有效,则为
true;否则为
false。VerifyHash()通过行使提供的公钥确定签名中的哈希值并将其与提供的哈希值举办相比较来表明数字签名是否行得通。

   2.DSA类解析:

     (1).CreateSignature():创建指定数量的 Cryptography.DSA 签名。

 public abstract byte[] CreateSignature(byte[] rgbHash);

   
 该措施为一个架空方法,在派生类中重写,接受一个字节数组表示要签名的数额,重返指定数量的数字签名。在使用CreateSignature方法时,必须协调创立SHA-1散列码,重返一个用字节数组表示的DSA签名。

     (2).VerifySignature():验证指定数量的 Cryptography.DSA 签名。

public abstract bool VerifySignature(byte[] rgbHash, byte[] rgbSignature);

     该格局接受字符数组表示的SHA-1散列码和签字来申明。

    3.DSACryptoServiceProvider类解析:

     (1).ImportParameters():导入指定的
DSAParameters。该方法接受一个参数,Cryptography.DSA的参数。

   
 (2).VerifyData():通过将指定的署名数据与为指定数量统计的签署举行相比较来证实指定的签约数据。

 public bool VerifyData(byte[] rgbData, byte[] rgbSignature)
    {
      return this.VerifyHash(this._sha1.ComputeHash(rgbData), (string) null, rgbSignature);
    }

     
该措施接受三个参数,rgbData已签署的数据;rgbSignature要阐明的签名数据,假使签名验证为使得,则为
true;否则,为
false。VerifyHash()通过将点名的签署数据与为指定哈希值总结的签约举行相比较来表明指定的签约数据,我们看一下VerifyHash()的实现代码:

 public bool VerifyHash(byte[] rgbHash, string str, byte[] rgbSignature)
    {
      if (rgbHash == null)
        throw new ArgumentNullException("rgbHash");
      if (rgbSignature == null)
        throw new ArgumentNullException("rgbSignature");
      int calgHash = X509Utils.NameOrOidToAlgId(str, OidGroup.HashAlgorithm);
      if (rgbHash.Length != this._sha1.HashSize / 8)
      {
        string key = "Cryptography_InvalidHashSize";
        object[] objArray = new object[2];
        int index1 = 0;
        string str1 = "SHA1";
        objArray[index1] = (object) str1;
        int index2 = 1;
        // ISSUE: variable of a boxed type
        __Boxed<int> local = (ValueType) (this._sha1.HashSize / 8);
        objArray[index2] = (object) local;
        throw new CryptographicException(Environment.GetResourceString(key, objArray));
      }
      this.GetKeyPair();
      return Utils.VerifySign(this._safeKeyHandle, 8704, calgHash, rgbHash, rgbSignature);
    }

   
 该方法接收多个参数,rgbHash要签署的数码的哈希值,str用于成立数量的哈希值的哈希算法名称,rgbSignature要表达的署名数据。

  <ItemGroup>
    <ApplicationDefinition Include="App.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:Compile</Generator>
    </ApplicationDefinition>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
    <Page Include="MainWindow.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
    <Compile Include="MainWindow.xaml.cs">
      <DependentUpon>MainWindow.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
  </ItemGroup>

    4.X509Certificate类解析:

       
该类在System.Security.Cryptography.X509Certificates空间下,提供救助你利用
X.509 v.3 证书的方法。

      (1).LoadCertificateFromBlob():加载证书:

private void LoadCertificateFromBlob(byte[] rawData, object password, X509KeyStorageFlags keyStorageFlags)
    {
      if (rawData == null || rawData.Length == 0)
        throw new ArgumentException(Environment.GetResourceString("Arg_EmptyOrNullArray"), "rawData");
      if (X509Utils.MapContentType(X509Utils._QueryCertBlobType(rawData)) == X509ContentType.Pfx && (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) == X509KeyStorageFlags.PersistKeySet)
        new KeyContainerPermission(KeyContainerPermissionFlags.Create).Demand();
      uint dwFlags = X509Utils.MapKeyStorageFlags(keyStorageFlags);
      IntPtr num = IntPtr.Zero;
      RuntimeHelpers.PrepareConstrainedRegions();
      try
      {
        num = X509Utils.PasswordToHGlobalUni(password);
        X509Utils._LoadCertFromBlob(rawData, num, dwFlags, (keyStorageFlags & X509KeyStorageFlags.PersistKeySet) != X509KeyStorageFlags.DefaultKeySet, ref this.m_safeCertContext);
      }
      finally
      {
        if (num != IntPtr.Zero)
          Marshal.ZeroFreeGlobalAllocUnicode(num);
      }
    }

   该措施是X509Certificate类构造函数等多少个方法加载证书的实际实现模式。

      (2).Export():使用指定的格式和密码将眼前
X509Certificate对象导出到字节数组。

 public virtual byte[] Export(X509ContentType contentType, SecureString password)
    {
      return this.ExportHelper(contentType, (object) password);
    }

        该形式接受两个参数,contentType描述如何设置输出数据格式的
X509ContentType 值之一。password访问 X.509
证书数据所需的密码。再次来到表示近日 X509Certificate 对象的字节数组。

2、也得以协调定义一个Main方法来促成WPF应用程序的起步。

四.DotNet数字签名实例:

    下面提供一个X509Certificate的操作方法实例:

  public void EncryptXmlDocument(string arqXmlAssinar, string tagAssinatura, string tagAtributoId, X509Certificate2 x509Cert)
        {
            StreamReader sr = null;
            try
            {
                sr = System.IO.File.OpenText(arqXmlAssinar);
                var xmlString = sr.ReadToEnd();
                sr.Close();
                sr = null;
                XmlDocument doc = new XmlDocument { PreserveWhitespace = false };
                doc.LoadXml(xmlString);
                if (doc.GetElementsByTagName(tagAssinatura).Count == 0)
                {
                    throw new Exception(tagAssinatura.Trim());
                }
                if (doc.GetElementsByTagName(tagAtributoId).Count == 0)
                {
                    throw new Exception(tagAtributoId.Trim());
                }
                XmlNodeList lists = doc.GetElementsByTagName(tagAssinatura);
                foreach (XmlNode nodes in lists)
                {
                    foreach (XmlNode childNodes in nodes.ChildNodes)
                    {
                        if (!childNodes.Name.Equals(tagAtributoId))
                            continue;
                        if (childNodes.NextSibling != null && childNodes.NextSibling.Name.Equals("Signature"))
                            continue;
                        Reference reference = new Reference { Uri = "" };                                 
                        XmlElement childElemen = (XmlElement)childNodes;
                        if (childElemen.GetAttributeNode("Id") != null)
                        {
                            var attributeNode = childElemen.GetAttributeNode("Id");
                            if (attributeNode != null)
                                reference.Uri = "#" + attributeNode.Value;
                        }
                        else if (childElemen.GetAttributeNode("id") != null)
                        {
                            var attributeNode = childElemen.GetAttributeNode("id");
                            if (attributeNode != null)
                                reference.Uri = "#" + attributeNode.Value;
                        }
                        XmlDocument documentoNovo = new XmlDocument();
                        documentoNovo.LoadXml(nodes.OuterXml);
                        SignedXml signedXml = new SignedXml(documentoNovo) { SigningKey = x509Cert.PrivateKey };
                        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
                        reference.AddTransform(env);
                        XmlDsigC14NTransform c14 = new XmlDsigC14NTransform();
                        reference.AddTransform(c14);
                        signedXml.AddReference(reference);
                        KeyInfo keyInfo = new KeyInfo();
                        keyInfo.AddClause(new KeyInfoX509Data(x509Cert));
                        signedXml.KeyInfo = keyInfo;
                        signedXml.ComputeSignature();
                        XmlElement xmlDigitalSignature = signedXml.GetXml();
nodes.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
                    }
                }
                var xmlDoc = doc;
                var stringXmlAssinado = xmlDoc.OuterXml;
                StreamWriter sw2 = System.IO.File.CreateText(arqXmlAssinar);
                sw2.Write(stringXmlAssinado);
                sw2.Close();
            }
            catch (CryptographicException ex)
            {
                throw new CryptographicException(ex.Message);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
            finally
            {
                if (sr != null) sr.Close();
            }
        }

第一步:在“解决方案资源管理器”中选中App.xaml文件,右键“从类别中消除”。

五.总结:

 
 下边是有关.NET数字证书的简约介绍,如有写的非正常的地点还望多多原谅,在博文中有些类和办法没有较多的罗列出来,有趣味的可以协调去深刻的打听。咱们上学一个知识时,已经从知识的社团了然初阶,这样便于我们站在大局思考问题。

 

此时,Visual Studio自动会改变WPF项目文件(WpfApplication.csproj),去掉了<ItemGroup>中的<ApplicationDefinition>节点和<Compile>节点

加密算法体系:

     
 DotNet加密方法分析–散列加密:http://www.cnblogs.com/pengze0902/p/6268700.html

     
 DotNet加密方法分析–对称加密:http://www.cnblogs.com/pengze0902/p/6268702.html

     
 DotNet加密方法分析–数字签名:http://www.cnblogs.com/pengze0902/p/6268709.html

     
 DotNet加密方法分析–非对称加密:http://www.cnblogs.com/pengze0902/p/6268705.html

<ItemGroup>
    <ApplicationDefinition Include="App.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:Compile</Generator>
    </ApplicationDefinition>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
      <SubType>Code</SubType>
    </Compile>
</ItemGroup>

若前面又要将App.xaml文件“包括在品种中”来作为WPF应用启动,F5周转时会报错误“不分包适合于入口点的静态‘Main’方法”。这多少个错误是出于Visual
Studio把品种文件(*.csproj)中原发源动生成的app.xaml相关的定义举行了改动(下边已证实)。

添加App.xaml进来后,项目文件(*.csproj)自动会转移如下代码:

  <ItemGroup>
    <Page Include="App.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:Compile</Generator>
    </Page>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
    </Compile>
  </ItemGroup>

先是段代码中App.xaml在类型文件之中用ApplicationDefinition标签定义。第二段代码中App.xaml在项目文件之中用Page标签定义,这种概念是指App.xaml只是一个页面而已。由此,只需要把品种文件准将App.xaml的安排由Page修改成ApplicationDefinition即可。

第二步:现在中添加一个新类,类名为App.cs。

可以写入以下二种办法启动WPF。 

    class App
    {
        [STAThread]
        static void Main()
        {
            f1();
        }
        static void f1()
        {
            // 定义Application对象作为整个应用程序入口
            Application app = new Application();
            MainWindow win = new MainWindow();
            //ShutdownMode选项,注意这个设置必须要写在app.Run()方法之前
            app.ShutdownMode = ShutdownMode.OnMainWindowClose; //非必须
            //调用Run方法
            app.Run(win);
        }
        static void f2()
        {
            // 定义Application对象作为整个应用程序入口  
            Application app = new Application();
            MainWindow win = new MainWindow();
            //是必须的,否则无法显示窗体  
            win.Show();
            //指定Application对象的MainWindow属性为启动窗体,然后调用无参数的Run方法  
            app.MainWindow = win;
            app.Run();
        }
        static void f3()
        {
            // 定义Application对象作为整个应用程序入口  
            Application app = new Application();
            // 通过Url的方式启动
            app.StartupUri = new Uri("MainWindow.xaml", UriKind.Relative);
            app.Run();
        }
    }

三、WPF应用程序的闭馆

WPF应用程序的关门只有在应用程序的 Shutdown
方法被调用时,应用程序才告一段落运作。 ShutDown
是隐式或显式暴发,可以通过点名 ShutdownMode 的属性值来进展设置。

主意一:如下边写在代码里

方式二:写在App.xaml里

<Application x:Class="WpfApplication1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication1"
             StartupUri="MainWindow.xaml" ShutdownMode="OnExplicitShutdown">
    <Application.Resources>

    </Application.Resources>
</Application>

四、Application对象事件

1、第一种艺术,在App.xaml文件添加事件,如Activated事件(当应用程序成为前台应用程序时接触)

此办法也得以在Visual Studio(ide)中的App.xaml属性窗口(按F4)中设置。

<Application x:Class="WpfApplication1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication1"
             StartupUri="MainWindow.xaml" ShutdownMode="OnExplicitShutdown" Activated="Application_Activated">
    <Application.Resources>

    </Application.Resources>
</Application>

在App.xaml.cs文件的代码如下:

namespace WpfApplication1
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
        private void Application_Activated(object sender, EventArgs e)
        {

        }
    }
}

2、第三种艺术,定义一个App类写Main方法和此外事件等。

namespace WpfApplication1
{
    class App
    {
        [STAThread]
        static void Main()
        {
            f1();
        }
        static void f1()
        {
            // 定义Application对象作为整个应用程序入口
            Application app = new Application();
            MainWindow win = new MainWindow();
            //ShutdownMode选项,注意这个设置必须要写在app.Run()方法之前
            app.ShutdownMode = ShutdownMode.OnMainWindowClose;
            //调用Run方法
            app.Run(win);
            app.Activated += App_Activated;
        }
        static void App_Activated(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }
    }
}

五、WPF应用程序生存周期

WPF应用程序的生命周期与履行顺序,用MSDN上的一张图纸举办求证。

图片 7

Continue…

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注