欢迎来到 无奈人生 安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

如何安全的给.net程序签名

来源: 作者: 时间:2019-02-24 21:26 点击: 我要投稿
广告位API接口通信错误,查看德得广告获取帮助

“TestLib,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = 769a8f10a7f072b4”
如果你能看懂上面这行的意思,那你很可能是一个.NET开发人员,同时你也可能知道结束处的十六进制字符串表示的是一个公钥标记。
不错,上面的字符串就是一组.net程序集强名称签名。
但你知道如何计算这个令牌吗?你知道强名称签名的结构吗?在这篇文章中,我们将详细介绍强名称的工作原理及其优缺点。
强名称是由程序集的标记加上公钥和数字签名组成的。其中,程序集的标记包括简单文本名称、版本号和区域性信息(如果提供的话)。也就是说,一个完整的强名称字符串包含4部分:
1.程序集的文件名;
2.程序集的版本号;
3.程序集的区域性信息;
4.一个公钥以及一个数字签名;
其中前3部分信息会存储在程序集的清单(manifest)中。清单包含了程序集的元数据,并嵌入在程序集的某个文件中。它使用相应私钥从程序集文件生成。
具有强名称的程序集只能使用其他具有强名称的程序集的类型。 否则,将会危害具有强名称的程序集的安全性。
在.NET框架中强名称程序集是通过公钥和私钥加密来产生这个唯一标记的。
因为强命名程序集使用公钥/私钥对来进行唯一性签名,不同的公司公钥/私钥对不可能相同,所以所生成的程序也不相同,这就解决了以前老出现的DLL Hell问题(两个不同的公司可能开发处具有相同名称的程序集,如果将相同名称的程序集放置到同一个目录下,则会出现程序集覆盖现象,最后安装的程序集会覆盖前面的程序集,从而可能导致应用序不能正常运行)。任何两个强命名的程序集,就算名称一模一样,Windows也知道他们是两个不同的版本,因为他们的唯一标记不一样。并且你可以通过配置文件控制应用程序去正确的加载你想要加载的那个dll。
所以强名称签名还能唯一标记程序集所使用的组件,所以强名称的作用主要有三个:
1.区分不同的程序集;
2.确保代码没有被篡改过;
3.在.NET中,只有强名称签名的程序集才能放到全局程序集缓存中。
公钥标记和强名称签名
公钥是包含在程序集元数据中的#Blob流的一部分,下图就是dnSpy窗口的一部分,dnSpy是一款开源的基于ILSpy发展而来的.net程序集的编辑,反编译,调试神器:

下图列出了构建公钥模块的元素:


上图中记录有公钥标记,开发人员和最终用户看到的也是公钥标记,而不是公钥。
公钥和公钥标记有什么区别呢?
公钥总共占160字节,有32个字节装的是头信息,另外有128个字节装的是数据。公钥对程序开发者来说是可见的。因为公钥占160字节,一个程序集可能会引用很多其他的程序集,所以在最终生成的文件中会有很大一部分空间被公钥占用,在使用的时候不太方便,于是人们提出了一个公钥标记的概念,公钥标记只占8个字节。公钥标记是把公钥进行哈希处理(使用SHA1算法),把哈希处理的结果的后面8个字节进行逆转,得到的就是公钥标记,
本文的测试中所用的公钥标记为:
769a8f10a7f072b4 (SHA-1(00 24 00 00 0c 80 … c8 8a c1 b1) = 9aa4de0a96ada8d83d6d7678b472f0a7108f9a76
怎样对程序集进行RSA签名
1.对PE文件内容进行哈希处理,然后把哈希处理后的值,用私钥进行RSA签名,把签名后的值加入到PE文件的CLR头中去。同时也会把公钥加入到程序集的元数据中去。
2.在生成元数据表FileRef时,CLR会把程序集里面的文件也进行哈希处理,得到一个哈希值,把文件和对应的哈希值同时加到FileRef元数据表中,

为了计算RSA签名,我们需要拥有与公钥相对应的私钥。如果你想看到实现验证的C#代码,请查看dnLib库中的StrongNameSigner.cs文件。
在研究了强名称签名结构之后,让我们来了解一下可以用来创建强名称签名的工具。我们发现生成的.snk文件会存储RSA密钥详细信息(如果你对.snk文件格式的详细信息感兴趣,请查看010编辑器模板):

然后我们可以使用C#编译器(csc.exe)或组装链接器(al.exe),这两个两者都可以被注入/ keyfile参数,在这里我们提供了刚生成的.snk文件的路径,如下图:

此命令将基于文件内容的SHA-1算法生成签名。不过现在,SHA-1已经不是一种安全的算法了,强烈建议使用SHA-2算法。
如果要使用SHA-2算法对我们的程序集进行签名,我们首先需要提取.snk文件的公钥部分:

然后延迟私钥签名(强名称签名块将被清0,强名称签名标志不会被置位)。 csc.exe和al.exe都会被注入/ delaysign +参数用于延迟私钥签名:
csc.exe /keyfile:TestLibPubKey.snk /delaysign+ /t:library TestLib.cs
什么是延迟签名?
如果要生成一个强命名的程序集,那么每次生成都需要进行签名,在开发的时候就会频繁的访问私钥文件,而私钥文件一般都是非常保密的,想要频繁使用可能有些费事。所以就有了延迟签名的机制。延迟签名的意思就是在开发阶段,只把公钥提供给开发人员,只有公钥对程序集进行签名,在最后打包发布的时候,才使用私钥来进行签名。

[1] [2]  下一页

“TestLib,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = 769a8f10a7f072b4”
如果你能看懂上面这行的意思,那你很可能是一个.NET开发人员,同时你也可能知道结束处的十六进制字符串表示的是一个公钥标记。
不错,上面的字符串就是一组.net程序集强名称签名。
但你知道如何计算这个令牌吗?你知道强名称签名的结构吗?在这篇文章中,我们将详细介绍强名称的工作原理及其优缺点。
强名称是由程序集的标记加上公钥和数字签名组成的。其中,程序集的标记包括简单文本名称、版本号和区域性信息(如果提供的话)。也就是说,一个完整的强名称字符串包含4部分:
1.程序集的文件名;
2.程序集的版本号;
3.程序集的区域性信息;
4.一个公钥以及一个数字签名;
其中前3部分信息会存储在程序集的清单(manifest)中。清单包含了程序集的元数据,并嵌入在程序集的某个文件中。它使用相应私钥从程序集文件生成。
具有强名称的程序集只能使用其他具有强名称的程序集的类型。 否则,将会危害具有强名称的程序集的安全性。
在.NET框架中强名称程序集是通过公钥和私钥加密来产生这个唯一标记的。

内容来自无奈安全网


因为强命名程序集使用公钥/私钥对来进行唯一性签名,不同的公司公钥/私钥对不可能相同,所以所生成的程序也不相同,这就解决了以前老出现的DLL Hell问题(两个不同的公司可能开发处具有相同名称的程序集,如果将相同名称的程序集放置到同一个目录下,则会出现程序集覆盖现象,最后安装的程序集会覆盖前面的程序集,从而可能导致应用序不能正常运行)。任何两个强命名的程序集,就算名称一模一样,Windows也知道他们是两个不同的版本,因为他们的唯一标记不一样。并且你可以通过配置文件控制应用程序去正确的加载你想要加载的那个dll。
所以强名称签名还能唯一标记程序集所使用的组件,所以强名称的作用主要有三个:
1.区分不同的程序集;
2.确保代码没有被篡改过;
3.在.NET中,只有强名称签名的程序集才能放到全局程序集缓存中。
公钥标记和强名称签名
公钥是包含在程序集元数据中的#Blob流的一部分,下图就是dnSpy窗口的一部分,dnSpy是一款开源的基于ILSpy发展而来的.net程序集的编辑,反编译,调试神器:
本文来自无奈人生安全网

下图列出了构建公钥模块的元素:


上图中记录有公钥标记,开发人员和最终用户看到的也是公钥标记,而不是公钥。
公钥和公钥标记有什么区别呢?
公钥总共占160字节,有32个字节装的是头信息,另外有128个字节装的是数据。公钥对程序开发者来说是可见的。因为公钥占160字节,一个程序集可能会引用很多其他的程序集,所以在最终生成的文件中会有很大一部分空间被公钥占用,在使用的时候不太方便,于是人们提出了一个公钥标记的概念,公钥标记只占8个字节。公钥标记是把公钥进行哈希处理(使用SHA1算法),把哈希处理的结果的后面8个字节进行逆转,得到的就是公钥标记,
本文的测试中所用的公钥标记为:
769a8f10a7f072b4 (SHA-1(00 24 00 00 0c 80 … c8 8a c1 b1) = 9aa4de0a96ada8d83d6d7678b472f0a7108f9a76 www.wnhack.com
怎样对程序集进行RSA签名
1.对PE文件内容进行哈希处理,然后把哈希处理后的值,用私钥进行RSA签名,把签名后的值加入到PE文件的CLR头中去。同时也会把公钥加入到程序集的元数据中去。
2.在生成元数据表FileRef时,CLR会把程序集里面的文件也进行哈希处理,得到一个哈希值,把文件和对应的哈希值同时加到FileRef元数据表中,

为了计算RSA签名,我们需要拥有与公钥相对应的私钥。如果你想看到实现验证的C#代码,请查看dnLib库中的StrongNameSigner.cs文件。
在研究了强名称签名结构之后,让我们来了解一下可以用来创建强名称签名的工具。我们发现生成的.snk文件会存储RSA密钥详细信息(如果你对.snk文件格式的详细信息感兴趣,请查看010编辑器模板):

然后我们可以使用C#编译器(csc.exe)或组装链接器(al.exe),这两个两者都可以被注入/ keyfile参数,在这里我们提供了刚生成的.snk文件的路径,如下图: copyright 无奈人生

此命令将基于文件内容的SHA-1算法生成签名。不过现在,SHA-1已经不是一种安全的算法了,强烈建议使用SHA-2算法。
如果要使用SHA-2算法对我们的程序集进行签名,我们首先需要提取.snk文件的公钥部分:

然后延迟私钥签名(强名称签名块将被清0,强名称签名标志不会被置位)。 csc.exe和al.exe都会被注入/ delaysign +参数用于延迟私钥签名:
csc.exe /keyfile:TestLibPubKey.snk /delaysign+ /t:library TestLib.cs
什么是延迟签名?
如果要生成一个强命名的程序集,那么每次生成都需要进行签名,在开发的时候就会频繁的访问私钥文件,而私钥文件一般都是非常保密的,想要频繁使用可能有些费事。所以就有了延迟签名的机制。延迟签名的意思就是在开发阶段,只把公钥提供给开发人员,只有公钥对程序集进行签名,在最后打包发布的时候,才使用私钥来进行签名。 无奈人生安全网
copyright 无奈人生

[1] [2]  下一页 www.wnhack.com

。 (责任编辑:admin)
【声明】:无奈人生安全网(http://www.wnhack.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱472701013@qq.com,我们会在最短的时间内进行处理。