zoukankan      html  css  js  c++  java
  • 强命名程序集,签名,延迟签名

    强命名程序集

           如果一个程序集有一个唯一的标记,那么这个程序集就可以叫做强命名程序集。在.NET框架中是通过公钥/私钥加密来产生这个唯一标记的。一个强命名程序集包含四个唯一标志程序集的特性:文件名(没有扩展名),版本号,语言文化信息(如果有的话),公有秘钥。 这些信息存储在程序集的清单(manifest)中。清单包含了程序集的元数据,并嵌入在程序集的某个文件中。下面的字符串标识了二个不同的程序集文件:

    “MyType, Version=1.0.1.0,Culture=neutral, PublicKeyToken=bf5779af662fc055”

    “MyType, Version=1.0.1.0,Culture=en-us, PublicKeyToken=bf5779af662fc055”

    弱命名程序集

          其实根本就没有弱命名程序集这个名称,只是为了和强命名程序集对应而产生的一个概念。弱命名程序集就是没有一个唯一标记的程序集,其实强程序集和弱程序集的结构是一模一样的,就是一个有唯一的标识符,而后者没有。它们之间的一个区别就是,强命名程序集有一个发布者的公钥/私钥签名对,它们可以唯一的标识程序集的发布者

    强命名的好处

          因为强命名程序集使用公钥/私钥对来进行唯一性签名,不同的公司公钥/私钥对不可能相同,所以所生成的程序也不相同,这就解决了以前老出现的DLL Hell问题(两个不同的公司可能开发处具有相同名称的程序集,如果将相同名称的程序 集放置到同一个目录下,则会出现程序集覆盖现象,最后安装的程序集会覆盖前面的程序集,从而可能导致应用序不能正常运行)。任何两个强命名的程序集,就算名称一模一样,Windows也知道他们是两个不同的版本,因为他们的唯一标记不一样。并且你可以通过配置文件控制应用程序去正确的加载你想要加载的那个dll。

         强命名带来的一个不好的地方就是部署的问题,强命名程序集如果以全局的方式部署安装到GAC中去了,那么如果想要部署到另外一台电脑上,就不能直接以XCopy的方式部署了,还必须把这个强命名程序集拷贝到另外一台电脑上的GAC中去。

    公钥,公钥标记,私钥

         公钥总共占160字节,有32个字节装的是头信息,另外有128个字节装的是数据。公钥对程序开发者来说是可见的。因为公钥占160字节,一个程序集可能会引用很多其他的程序集,所以在最终生成的文件中会有很大一部分空间被公钥占用,在使用的时候不太方便,于是人们提出了一个公钥标记的概念,公钥标记只占8个字节。公钥标记是把公钥进行哈希处理(使用SHA1算法),把哈希处理的结果的后面8个字节进行逆转,得到的就是公钥标记,具体参见:由Public key生成Public key token。AssemblyRef表中记录的是公钥标记,开发人员和最终用户看到的也是公钥标记,而不是公钥。不过在生成的程序集清单中,AssemblyDef记录的还是整个公钥,而不是占8个字节的公钥标记。CLR在做出安全或者信任决策时,永远不会使用公钥标记,因为几个公钥在经过哈希处理后,可能得到相同的公钥标记。私钥来说对于一般人都是不可见的。

        可以直接使用vs自带的命令行工具,运行sn –T来查看程序集的公钥,注意这里的T要大写,如果是小写的话就会报错“未能将密钥转换为标记 -- 程序集“(null)”的公钥无效”。 Sn工具的所有命令都是区分大小写的

    签名的原理

    clip_image001

        主要的原理是:(图及文字参考《CLR via C#的第三章》)

    1. 对PE文件内容进行哈希处理,然后把哈希处理后的值,用私钥进行RSA签名,把签名后的值加入到PE文件的CLR头中去。同时也会把公钥加入到程序集的元数据中去。

    2. 在生成元数据表FileRef时,CLR会把程序集里面的文件也进行哈希处理,得到一个哈希值,把文件和对应的哈希值同时加到FileRef元数据表中,

    验证时:

          当在其他用户上加载这个dll的时候,对PE文件进行哈希处理,得到一个哈希值,然后用公钥对RSA数字签名值解除签名,得到一个值,如果这两个相等,代表文件的内容没有被篡改。除此之外,系统还会对程序集里的文件内容进行哈希处理,并将哈希处理的值与清单文件的FileDef表中存储的哈希值进行比较。任何一个哈希值不相同,表明程序集至少有一个文件被篡改,程序集无法安装到GAC。

         注意:在对文件进行哈希处理的时候,可以选择不同的哈希算法,默认是SHA1,但对PE文件内容进行哈希处理的时候,哈希算法只能是SHA1,不能修改。

    怎样对程序集进行签名

        在vs中有两种方式可以对程序集进行签名,一种是通过项目属性,另外一种是通过添加AssemblyKeyFile,使用AssemblyKeyFile如下:

    clip_image002

        使用这种方式,vs有个警告,提示用其他的方式是实现签名,可见微软是不推荐以这种方式进行的。

        另外一种方式就是通过项目属性

    clip_image004

       在签名选项卡中,勾选“为程序集签名”,并且选择相应的密钥文件。

       这两种签名方式都需要事先生成好密钥文件,密钥文件可以用sn.exe这个工具生成,具体的请参见:.NET工具篇(四)—SN.EXE

       当然在使用第二种方式的时候,也可以通过vs的界面来生成密钥,如:

    clip_image006

        在下拉框中选择新建,就可以新生成一个密钥文件。

    延迟签名

          如果要生成一个强命名的程序集,那么每次生成都需要进行签名,在开发的时候就会频繁的访问私钥文件,而私钥文件一般都是非常保密的,想要频繁使用可能有些费事。所以就有了延迟签名的机制。延迟签名的意思就是在开发阶段,只把公钥提供给开发人员,只有公钥对程序集进行签名,在最后打包发布的时候,才使用私钥来进行签名。可以使用工具sn.exe从一个密钥文件中提取出公钥来。同时想要延迟签名,还需要告诉编译器知道你想进行延迟签名。如果使用C#编译器,可以在项目属性里面设置延迟签名。

         编译器一旦检测到需要进行延迟签名,在生成清单项的时候,它会在AssemblyDef记录程序集的公钥,在生成程序集的时候,生成的PE文件会为RSA数字签名预留空间。文件内容不会在这个时候进行哈希处理。

         在安装到GAC中时,因为没有用私钥进行签名,就会报错。想要安装成功,就必须取消系统的验证。在正式签名后,必须重新启动系统的验证。对程序集进行延迟签名,有以下几步:

    1. 用sn.exe生成一个密钥文件,并使用相关命令导出公钥文件;

    2. 设置项目属性,勾选“延迟签名”选项,并选择相应的公钥文件对项目进行延迟签名;

    3. 使用SN的-Vr开关,告诉系统不要对这个程序集进行验证;

    4. 程序集可以顺利的安装到GAC中,并且可以被其他程序集引用。(但此时程序集还没有真正的签名,任何一个同名的程序集都可以覆盖它)。

    5. 在打包发布的时候,使用SN.exe –R命令,用私钥文件对程序集进行正式的签名;

    6. 使用SN –Vu命令重新启动对这个程序集的验证;

    7. 程序集可以顺利的安装到GAC中

  • 相关阅读:
    npm版本管理
    spring框架学习笔记5:SpringAOP示例
    spring框架学习笔记4:SpringAOP实现原理
    spring框架学习笔记3:使用注解代替配置文件
    spring框架学习笔记2:配置详解
    spring框架学习笔记1:搭建测试
    struts2框架学习笔记7:struts2标签
    struts2框架学习笔记6:拦截器
    struts2框架学习笔记5:OGNL表达式
    struts2框架学习笔记4:获取参数
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/4735578.html
Copyright © 2011-2022 走看看