程序中SNK的原理

用来证明这个生成的程序集是你发布的;而且,如果你写的程序集要用在多个应用程序上的话,那么这个程序集必须要拥有唯一的名称,这个强名称是程序集唯一名称的一部分。

另外,只要你保护好你的snk文件不要公布出去,那么没有任何人可以假冒你发布程序集。

强名称签名的原理是不对称签名验证算法。

首先你用sn.exe命令行程序生成一个.snk的密钥文件,这个文件包括了两个部分的内容。
1   私钥,就是在vs.net编译的时候生成验证码的东西。
2   公钥,编译的时候打包到程序集元数据中PublicKey部分的内容。

而且,验证码只能通过私钥来生成,只有通过私钥生成的验证码才能通过.Net   CLR的验证。

CLR验证程序集的时候通过读取公钥来生成验证对象,生成过后对整个程序集的内容进行验证,拿这个验证码与程序集里面的验证码对比,如果吻合就通过,如果不吻合表示程序集已经被修改了,CLR将拒绝载入这个程序集并且认为需要的程序集没有找到,抛出FileNotFoundException异常。

比如说微软的.Net类库中的System.dll、System.Web.dll等,都经过了强名称验证,保证别人只能使用这些类库,而不能修改,还保证这些程序集是微软推出的。而且,这些程序集是存放在共享目录里面的,更加需要强名称了。

 

强名称是由程序集的标识加上公钥和数字签名组成的,其中,程序集的标识包括简单文本名称、版本号和区域性信息(如果提供的话)。强名称是使用相应的私钥,通过程序集文件(包含程序集清单的文件,并因而也包含构成该程序集的所有文件的名称和散列)生成的。Microsoft®   Visual   Studio   .NET®   和在   .NET   Framework   SDK   中提供的其他开发工具能够将强名称分配给一个程序集。强名称相同的程序集应该是相同的。

通过签发具有强名称的程序集,您可以确保名称的全局唯一性。强名称还特别满足以下要求:  

强名称依赖于唯一的密钥对来确保名称的唯一性。任何人都不会生成与您生成的相同的程序集名称,因为用一个私钥生成的程序集的名称与用其他私钥生成的程序集的名称不相同。  
强名称保护程序集的版本沿袭。强名称可以确保没有人能够生成您的程序集的后续版本。用户可以确信,他们所加载的程序集的版本出自创建该版本(应用程序是用该版本生成的)的同一个发行者。  
强名称提供可靠的完整性检查。通过   .NET   Framework   安全检查后,即可确信程序集的内容在生成后未被更改过。但请注意,强名称中或强名称本身并不暗含信任级别,例如由数字签名和支持证书提供的信任。  
在引用具有强名称的程序集时,您应该能够从中受益,例如版本控制和命名保护。如果此具有强名称的程序集以后引用了具有简单名称的程序集(后者没有这些好处),则您将失去使用具有强名称的程序集所带来的好处,并依旧会产生   DLL   冲突。因此,具有强名称的程序集只能引用其他具有强名称的程序集。

sn.exe是一个强名称工具,用来生成强名称,.snk就生成的强名称文件

你认真系统地地看一下.NET   Framework文档中关于程序集的内容,写的很详细,也比较好懂。


请问使用SNK文件和不使用SNK文件的区别! 问:
看到一个WEB网站的示例,里面的工程是强名的,并有一个SNK文件,在AssemblyInfo.cs文件中对其进行了引用 
请问,是不是必须要有一个SNK文件?有什么好处吗?强名是什么意思?用与不用的区别在哪里??

在线结帐
______________________________________________________________________________________________
答1:
当你把一个程序集放进GAC(全局程序集缓存)时,就要加强名(也就是签名),在GAC中的程序集可以被所有程序引用访问(相当于以前COM组件在注册表里注册一样),如果不放进GAC,刚所有使用这个程序集都要复制这个程序集(也就是私有程序集),所以用不用强名要看情况而定.
______________________________________________________________________________________________
答2:
如果不是 要把.dll共享 可以不使用强名
强名称是为了你的Dll文件的安全,一般我们的dll文件,随便在哪只要引用就可以用
但如果用了强名称的话,dll 就会有一个秘钥,其它人就不能引用了

如何创建带有强名称的程序集
可以向程序集分配称为强名称的加密签名,它为程序集提供名称的唯一性并防止他人借用您的程序集名称(名称欺骗)。如果您正在部署一个将被同一台计算机上的多个应用程序共享的程序集,则该程序集必须有强名称。即使只在您的应用程序中使用该程序集,使用强名称也可确保加载该程序集的正确版本。

生成具有强名称的程序集的第一步是获得加密密钥对。.NET Framework SDK 包括一个可用来生成密钥对的“强名称”工具 (Sn.exe)。由“强名称”工具生成的密钥对可以保留在文件中,您也可以将它存储在本地计算机的“加密服务提供程序”(CSP) 中。下面的命令使用“强名称”工具生成一个新的密钥对并将它存储在名为 TestKey.snk 的文件中:

sn -k Testkey.snk

在获得密钥对后,需要向源文件中添加正确的自定义属性,以便编译器发出带有强名称的程序集。根据用于签名的密钥对是包含在文件中还是 CSP 内的密钥容器中,正确地选择属性。对于存储在文件中的密钥,请使用 System.Reflection.AssemblyKeyFileAttribute。对于存储在 CSP 中的密钥,请使用 System.Reflection.AssemblyKeyNameAttribute。

______________________________________________________________________________________________
答3:
讲得我还是似懂非懂
是不是用不用密钥只影响到别人能不能引用?
______________________________________________________________________________________________
答4:
(*) 如果未指定密钥,则程序集不会被签名。
//   (*) KeyName 是指已经安装在
//       计算机上的加密服务提供程序(CSP)中的密钥。KeyFile 是指包含
//       密钥的文件。
//   (*) 如果 KeyFile 和 KeyName 值都已指定,则
//       发生下面的处理:
//       (1) 如果在 CSP 中可以找到 KeyName,则使用该密钥。
//       (2) 如果 KeyName 不存在而 KeyFile 存在,则
//           KeyFile 中的密钥安装到 CSP 中并且使用该密钥。
//   (*) 要创建 KeyFile,可以使用 sn.exe(强名称)实用工具。
//        在指定 KeyFile 时,KeyFile 的位置应该
//        相对于“项目输出目录”。项目输出
//        目录的位置取决于您是在使用本地项目还是 Web 项目。
//        对于本地项目,项目输出目录定义为
//       \obj\。例如,如果 KeyFile 位于该
//       项目目录中,应将 AssemblyKeyFile
//       属性指定为 [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
//        对于 Web 项目,项目输出目录定义为
//       %HOMEPATH%\VSWebCache\\\obj\
______________________________________________________________________________________________
答5:
在编译的时候可以作为.dll文件的key,如果你用其他*.snk文件代替原来的文件,.dll是无法编译的
______________________________________________________________________________________________
答6:
http://tech.ccidnet.com/pub/disp/Article?columnID=294&articleID=34439&pageNO=1

 

生成.snk文件,VS2005生成.snk文件例子


VS2005 strong name 使用例子
先利用SN.exe这个工具生成一个密匙文件aspnetpager.snk,这个文件的英文原文叫string name key file,然后用加密的算法根据aspnetpager.snk生成一个aspnetpagerPublic.snk.最后在根据aspnetpagerPublic.snk提取一个public key token ,public key token是一个16位的数字和字母混合的数:大致流程如下:

aspnetpager.snk --根据一定的算法--> aspnetpagerPublic.snk---->public key token 所以我们只要aspnetpager.snk和public key token就可以了,aspnetpagerPublic.snk就没什么用了.因为aspnetpagerPublic.snk的贡献做完了.

实际操作如下:
1.打开SDK Command Prompt或者VS2005中的Visual Studio 2005 Command Prompt.而不是windows的cmd
2.输入sn -k aspnetpager.snk,得到的文件在命令提示符的当前文件夹下(微软叫文件夹很少叫目录,最正点是folder)
3.输入sn -p aspnetpager.snk aspnetpagerPublic.snk (从aspnetpager.snk中提取公匙存入aspnetpagerPublic.snk文件)
4.输入sn -t aspnetpagerPublic.snk 得到public key token

打开VS2005,找到项目,然后右击"项目名"找到"属性","属性"里面有个"Signing"(签名)的选项卡,然后钩上 "Sign the assembly"(为程序集签名),再Choose a strong name key file(选择强名称密钥文件).做完了操作,然后记得保存,编译 这样你的DLL才能拖到GAC,GAC就是"全局程序集缓存",这就是为什么你的你的项目的bin文件夹下没有System.Data,你都能引用的原因,因为程序会自动去找GAC,GAC的位置在win 2003中是"c:\windows\assembly".

生成.snk文件,VS2005生成.snk文件例子


petshop中.snk文件和AssemblyInfo.cs文件的作用2009-11-30 23:41snk文件在.net里面被用作存放密钥或密钥对的存储文件,生成密钥对snk文件可以用.net中的sn.exe命令,如“sn   -k   keyPair.snk”。  

snk本身只是用来存放非对称密钥的,但在各个需要用到加密、签名的地方都可以使用:  
1) 用snk文件生成强命名程序集,这样一个assembly才可以被赋予full-trust属性,也可以被添加到GAC中。在VS.NET中生成 strong-named   assembly,只需要在AssemblyInfo.cs里面添加一下代码并编译即可:  
[assembly:   AssemblyDelaySign(false)]  
[assembly:   AssemblyKeyFile("..\\..\\keyPair.snk")]  
[assembly:   AssemblyKeyName("")]  

强 命名程序集的缘由:      目前Windows中出现的DLL Hell问题(两个不同的公司可能开发处具有相同名称的程序集,如果将相同名称的程序 集放置到同一个目录下,则会出现程序集覆盖现象,最后安装的程序集会覆盖前面的程序集,从而可能导致应用序不能正常运行)。由此看来,仅靠名称来区分程序 集是不足够的。CLR采取了强命名程序集的方式来唯一的表示程序集。强命名程序集包含四个标识:名称,版本号,语言文化标识和一个共有/私有密钥对。两种 程序集/两种部署方式:.Net支持两种程序集:弱命名程序集和强命名程序集(注:.Net框架中没有弱命名程序集,只是为了和强命名程序集相对应而 已)。弱命名程序集和强命名程序集在结构上是相同的。他们都采用PE文件格式,包含PE表头,CLR表头,元数据和清单表。区别在于:强命名程序集拥有一 个发布者的公钥/私钥签名对,他们用于唯一的标识程序集的发布者。通过公钥/私钥对,我们可以对程序集进行唯一的标识,安全策略和版本策略。


AssemblyInfo.cs主要用来设定生成的有关程序集的常规信息dll文件的一些参数
请看以下具体说明:
//备注: 
[assembly:AssemblyDescription("用最强的抢劫类写成!")]
//产品名称
[assembly:AssemblyProduct("无为搜索")]
//公司
[assembly:AssemblyCompany("无为网络")]
//合法商标
[assembly:AssemblyTrademark("无为")];
//内部名称
[assembly:AssemblyCulture("")]
//设计者
[assembly:AssemblyDescription("无为类库")]
//版权
[assembly:AssemblyCopyright("")]
//配置文件
[assembly:AssemblyConfiguration("Configuration")]
//产品版品: 可指定,如下
// 程序集的版本信息由下列 4 个值组成:
//
//      主版本
//      次版本
//      内部版本号
//      修订号
//
// 您可以指定所有这些值,也可以使用“修订号”和“内部版本号”的默认值,方法是按
// 如下所示使用 '*':
[assembly:AssemblyVersion("1.0.*")]

生成dll文件以后再点击右键看看它的属性,你就为在里面看到熟悉的内容了


 


 

你可能感兴趣的:(程序中SNK的原理)