.NET中的PublicKeyToken以及强命名问题
在.NET的GAC出现之前,以前有DLL Hell的问题。这是由于当时对于共享的DLL的处理方式。是通过採用注冊表的方式实现的。当我们安装一个程序A的时候,这个程序包括一个共享的DLL,那么这个DLL就会就会写入到注冊表中,可是注意这里并没有写入版本号信息,仅仅是告诉你在哪个地方有一个叫做XX的DLL能够使用。
当安装另外的一个程序B的时候。也包括这个共享的DLL,可是是一个更加新一些的版本号,系统会发现这个DLL已经注冊存在了。就会用这个DLL去覆盖原来的DLL,可是由于注冊表中前后没有不论什么版本号的标示,所以系统还是觉得这就是一个DLL.
可是如今已经更新了DLL。A程序可能会出现使用这个DLL的时候不兼容的现象。可是此时假设你重装A程序,再把共享DLL换回去。那么B程序又可能出现不兼容的现象。这就是DLL HELL问题。引发这个问题的解决办法,还是同一个DLL不能多个版本号同一时候存在的问题。
DLL Hell 是指当多个应用程序试图共享一个公用组件(如某个动态连接库(DLL)或某个组件对象模型(COM)类)时所引发的一系列问题。
最典型的情况是,某个应用程序将要安装一个新版本号的共享组件,而该组件与机器上的现有版本号不向后兼容。尽管刚安装的应用程序执行正常。但原来依赖前一版本号共享组件的应用程序或许已无法再工作。
然后GAC的出现,攻克了这个问题。
GAC中对于能够同一时候存在同一个DLL的多个不同的版本号。假设多个程序都用到了这个DLL。那么这个程序就能够到GAC中去找对应版本号的DLL.可是在GAC中。比方说同一个Data.dll,即使有多个版本号的文件。可是其文件名称都应该全是Data.dll。并且在不同的文件夹总,其version信息不是在文件名称中体现出现了,而是在DLL的头信息中存储的。每一个程序都会有一个程序集清单。这个清单存在和程序同名的.manifest文件里。里面列出其所须要的全部依赖,这儿所列出的依赖可不是简单地靠文件明来区分的,而是依据一种叫做“强文件名称”的东西区分的。
- <?xml version='1.0' encoding='UTF-8' standalone='yes'?>
- <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
- <dependency>
- <dependentAssembly>
- <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' processorArchitecture=' x86' publicKeyToken='1fc8b3b9a1e18e3b' />
- </dependentAssembly>
- </dependency>
- </assembly>
我们发现原来这是一个XML格式的文件。当中<dependency>这一部分指明了其依赖于一个名字叫做Microsoft.VC80.CRT的库。可是我们发现,<assemblyIdentity>属性里面还有其他的东东。各自是 type系统类型,version版本号号,processorArchitecture平台环境,publicKeyToken公匙(一般用来标示一个公司)。把他们加在一起便成了“强文件名称”了,有了这样的“强文件名称”。我们就能够依据其区分不同的版本号、不同的平台。总之。有了这样的强文件名称,系统中能够有多个不同版本号的同样的库共存而不会发生冲突。
事实上PublicKeyToken就是Public Key的简单形式,我们就能够把PublicKeyToken当成PublicKey.这里说明一下PublicKeyToken的存在。
PublicKeyToken的作用就是确定要载入的DLL一定要是最初的那个DLL。事实上,这一方面也起到了安全方面的防范问题。比方说。有的程序。有人写了一个同名的DLL覆盖了你原来的DLL,程序假设不加分辨就使用这个DLL。可能就有安全问题了。那么PublicKeyToken是这么样来确保这个唯一性的呢?
这里涉及到了加密算法。最初DLL的开发人员在开发这个DLL的时候,会加密这个DLL。使用的加密方法就是公钥私钥的方法。公钥与私钥是同一时候存在而且唯一相应的。对于同一段内容,用私钥加密之后。仅仅实用公钥才干解密。
假设用其它的私钥加密的东西,用这个公钥是解不开不论什么东西的。
DLL开发人员有自己的私钥,而这个私钥别人是不知道的。是保密的,在DLL开发的时候用私钥加密。而且把公钥信息写入到程序中。
当这个程序开发完毕后。在一台计算机上执行的时候,系统会从程序的程序清单中去找用到了哪个DLL,而且去查看这个DLL的版本号,而且要用PublicKeyToken来确保这个DLL的原始性。那么是通过一个怎么样的过程来确保这个DLL的原始性呢?比方说,有一个人在你的电脑上,在你安装好这个程序后,到你程序的安装文件夹下,用一个同名的。具有相同的命名空间和类的DLL替换掉了你原来的DLL,系统是怎么可以发现的呢?程序在执行的时候。会从程序的程序清单中取看用到了哪个dll,这个dll的公钥是多少。
(我觉得这个程序清单是轻易不能被篡改的。假设这个都能篡改了,那么程序就无安全性可言了。起码我是这样觉得的。
)然后去GAC中或者程序的文件夹下寻找这个DLL。在这个DLL的头文件里有一些信息,是DLL的内容和加密后的字符串。程序会用公钥去解密这个字符串,假设解密出的内容和DLL中记录的内容一致,那么就证明这个DLL是原始的,没有被篡改过的。
以下我们考虑几种可能被篡改的情况
有人只改动了DLL的内容,并没有改动加密后的值。此时非常easy被程序发现出来。由于解密后的值和DLL内容不一致,程序会提示异常。
有人不仅改动了DLL的内容,还想改动加密后的值。可是要知道,此时的用户是没有原来的开发人员的私钥的,假设他随便用一个私钥加密,那么在程序解密的是,用那个公钥是解密不出来不论什么东西的,由于公钥私钥是相应的。此时,程序会提示异常。这篇文章比較仔细的解释了公钥私钥对于DLL加密的过程。
有时候会在Web.config文件里Runtime标签下看到一些<runtime>bindingRedirect的内容,这里涉及到了PublicKey。
这里的作用是把不同版本号的文件映射到某一个特定的版本号,即程序清单中记载的某个dll是2.0的版本号,但是程序在执行的时候在GAC中仅仅找到1.0的版本号,那么告诉程序此时不提示异常。仅仅要把这个1.0版本号当成2.0版本号就能够了。
- <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
- <dependentAssembly>
- <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
- <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
- </dependentAssembly>
- </assemblyBinding>
- </runtime>
总结:PublicKeyToken或者PublicKey不不过用于安全方面。也是用于差别同一个DLL的不同版本号方面。
事实上在一般的开发中我们用到的不多。最起码从我自己浅薄的经验来讲,接触的不多,基本上是透明的。
.NET中的PublicKeyToken以及强命名问题的更多相关文章
- .NET中查看一个强命名程序集(*****.dll)的PublicKeyToken的方法
使用命令行工具SDK Command Prompt,键入:SN -T C:\*****.dll (dll文件所在的路径) 就会显示出该dll具体的PublicKeyToken数值. 如果该程序集没有 ...
- DevExpress 重编译 替换强命名 修改源码
本文以DevExpress 11.1.8举例 必须满足几个条件 1. 必须有DXperience相应版本的全部源代码SourceCode.把全部源代码复制到X:\Program Files\DevEx ...
- CLR 关于强命名程序集 .
如何创建强命名程序集(Strong Name Assembly) 创建一个强命名程序集首先需要获得一个用强命名实用工具 (Strong Name Utility,即SN.exe,.NET ...
- C# 强命名程序集,防止dll被修改,混淆下发布
未能加载文件或程序集“Jonckers.Service.RedisCacheEngineExtend, Version=1.0.0.0, Culture=neutral, PublicKeyToken ...
- .NET程序集强命名删除与再签名技术 源代码剖析
如果你想去除一个程序集的强签名(strong name),目前为止可以有两个途径 1 反编译为IL代码,删除签名部分,再编译为程序集 2 应用Re-Sign程序,直接对一个程序集再签名 生成和读取 ...
- .net程序集强命名(签名)
要想得到强签名的dll有两种情况: 1.给项目添加强命名 在你的项目右键->属性->签名,勾选“为程序集签名”,新建 或 浏览已经新建过的.pfx文件,然后重新build项目,生成的dll ...
- membership DB生成 & dll 强命名 & 证书生成
UPD(Membership)数据库安装1.使用 Aspnet_regsql.exe 安装数据库 在 C:\WINDOWS\Microsoft.NET\Framework\\aspnet_regsql ...
- 记一次dll强命名冲突事件
一 问题的出现 现在要做一个net分布式平台,平台涉及多个服务之间调用问题,最基础的莫过于sso.由于我们的sso采用了wcf一套私有框架实现,另外一个webapi服务通过接口调用sso服务.由于s ...
- 只有ReflectionOnlyLoadFrom才可以拯救与GAC冲突的强命名程序集
先说结论,如果有两个拥有相同程序集名称的强命名程序集,一个在GAC里,一个不在.怎样动态加载那个不在GAC里的程序集?答案就是只有Assembly.ReflectionOnlyLoadFrom才可以加 ...
随机推荐
- 异步编程when.js
when.js很小,压缩后只有数kb,gzip后的大小几乎可以忽略.在Node和浏览器环境里都可以使用when.js 首先,我们看一小段代码: var getData = function(callb ...
- web pack 生成本地dist后 本地可以访问 路径由/ 改 ./
config / index.js 里面将 / 改成 ./ 有两个 都改了 反正管用 然后npm run build 如果涉及到字体 css里面不会改 需要手工改成 ../../ 反正一般用到字体也不 ...
- VC++检测硬件设备状态
首先捕捉WM_DEVICECHANGE消息,该消息在usb插拔时均有触发. MFC下 添加消息处理函数afx_msg BOOL OnDeviceChange( UINT nEventType, DWO ...
- springboot Tomcat connector configured to listen on port 8081 failed to start.
启动报 Tomcat connector configured to listen on port 8081 failed to start. The port may already be in ...
- SqlSever锁及存储过程优化
SqlSever锁及存储过程优化 SQL server的所有活动都会产生锁.锁定的单元越小,就越能提高并发处理能力,但是管理锁的开销越大.如何找到平衡点,使并发性和性能都可接受是SQL Server的 ...
- jz2440开发板烧写裸板
前提:手头没有openjtag,电脑上没有并口, 实现方法:jlink下载,nor上的uboot下载 关键点是用jlink下载uboot 1,使用jlink进行烧写,其中注意的是jlink只能烧写no ...
- 如何转成libsvm支持的数据格式并做回归分析
本次实验的数据是来自老师给的2006-2008年的日期,24小时的温度.电力负荷数据,以及2009年的日期,24小时的温度数据,目的是预测2009年每天24小时的电力负荷,实验数据本文不予给出. 用l ...
- Vertex&Frag
一.Vertex&Frag 包含Vertex&Fragment 的Shader叫做顶点&像素着色器,在Vertex的功能函数中,我们侧重于几何计算,如纹理坐标,顶点坐标等:在F ...
- C51 蜂鸣器 个人笔记
音调:频率 音量:高低电平占空比 有源:上面没有加号,只需高低电平即可发声 无源:上面有加号,不仅要电平,还要, 的频率 这里的有源不是指电源的"源",而是指有没有自带震荡电路,有 ...
- 九度oj 题目1077:最大序列和
题目1077:最大序列和 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6435 解决:1931 题目描述: 给出一个整数序列S,其中有N个数,定义其中一个非空连续子序列T中所有数的和为T ...