转载:.Net 程序集 签名工具sn.exe 密钥对SNK文件 最基本的用法
.Net 程序集 签名工具sn.exe 密钥对SNK文件 最基本的用法
阐述签名工具这个概念之前,我先说说它不是什么:
1.它不是用于给程序集加密的工具,它与阻止Reflector或ILSpy对程序集进行反编译一毛钱关系都没有。
2.它很讨厌人们把它和加密联系在一起。
我再说说它是什么:
1.起个大名字
sn是strong name的缩写,正如其名,sn.exe的目的是给程序集起一个唯一的名字(Hash+name+version+culture),即签名,保证不会让两个不同的DLL重名(就跟身份证不能重一样)
2.让调用者识别被调用的DLL是否被篡改
这一点是我重点要说的,我们先假设一个场景。一个黑客正在用一个银行客户端程序给一个账户转账,通过反编译发现,前端主程序Bank.exe调用Transfer.dll的TransferMoney方法来进行转账操作。他自然地想到,如果我修改了TransferMoney方法,将金额参数乘以10,然后重新编译成Transfer.dll再覆盖原来的Transfer.dll,他就能成为宇宙首富!
由这个例子得知,我们亟待解决的安全问题是,让Bank.exe有能力得知其调用的Transfer.dll是不是被别人篡改过的。那么我们很自然地会想到,用信息摘要算法呗~(废话一下,不同内容摘要出来的128位字符串是绝对不一样的)
是的!sn起的这个大名字就是这个摘要信息,我们可以在Bank.exe的引用信息里存好了我应该调用Transfer.dll的摘要值OriHash,这样我们就可以在调用时先摘要一下当前的Transfer.dll得出CurHash,然后比对一下OriHash和CurHash即可!过程如下图:
2.让调用者识别被调用的DLL是否被篡改
这一点是我重点要说的,我们先假设一个场景。一个黑客正在用一个银行客户端程序给一个账户转账,通过反编译发现,前端主程序Bank.exe调用Transfer.dll的TransferMoney方法来进行转账操作。他自然地想到,如果我修改了TransferMoney方法,将金额参数乘以10,然后重新编译成Transfer.dll再覆盖原来的Transfer.dll,他就能成为宇宙首富!
由这个例子得知,我们亟待解决的安全问题是,让Bank.exe有能力得知其调用的Transfer.dll是不是被别人篡改过的。那么我们很自然地会想到,用信息摘要算法呗~(废话一下,不同内容摘要出来的128位字符串是绝对不一样的)
是的!sn起的这个大名字就是这个摘要信息,我们可以在Bank.exe的引用信息里存好了我应该调用Transfer.dll的摘要值OriHash,这样我们就可以在调用时先摘要一下当前的Transfer.dll得出CurHash,然后比对一下OriHash和CurHash即可!过程如下图:
这似乎就是正确答案了,可是...
这样做有一个问题,就是关于你预先存好的那个摘要值OriHash。有两个方面:
方面1.一旦我正常地更新了Transfer.dll, 那摘要也就变了,也就是说你要通知Bank.exe去更新OriHash。
方面2.由问题1引发的安全问题。
对于方面1,我觉得是最主要的原因,一旦Transfer.dll更新了,为了比对摘要,Bank.exe需要更新OriHash,更新100次Transfer.dll,你就要更新100次OriHash,这个做法太要命了,当然这还只是麻烦层面的问题,更严重的是,我们可以想象到由于频繁更新OriHash而引发的安全问题。
对于方面2,由于你总去更新OriHash,这个环节一旦被黑客截获,你的OriHash就不一定保证是真的了,当然我个人认为这个怀疑有点过头了,因为DLL引用信息一般都是工具自动添加的,除非你通过某种网络机制传输这个OriHash到Bank.exe所属的项目文件(如Bank.csPRoj),此时OriHash就有了更多的被黑风险,这是一个安全问题!
所以基于以上两点,.Net拿出了非对称加密算法这把利剑!(再废话一下,非对称加密即生成一对儿钥匙——私钥和公钥,明文被该私钥加密只能用该公钥解密,反之亦然,所以私钥自己要绝对保密,公钥可以给任何人)
将OriHash用私钥加密为CodedHash,并存储在Transfer.dll中。然后在Bank.exe里一次性存入这个为了调用Transfer.dll的公钥,但一定要意识到,Transfer.dll里面是绝对没有私钥的,私钥只包含在myPair.snk文件中,也只有你拿着,并配以荷枪实弹的保安们誓死保护不被别人拿走。
那么新的验证流程如下,请结合下图:
a.首先Bank.exe里含有公钥,Transfer.dll里含有CodedHash
b.Bank.exe用公钥解密CodedHash
c1.若解密成功,就证明这个CodedHash是用和我公钥配对的那个私钥加密的。
c11.对Transfer.dll进行摘要得到CurHash,将其和解密的Hash对比,如果一样则证明Transfer.dll是安全的,并且是完整的,加载即可。如果不同,则证明这个Transfer.dll是别人篡改过的,此时拒绝加载Transfer.dll
c2.若解密失败,则证明这个CodedHash是用别的私钥加密的,也就是黑客弄的,此时同样拒绝加载Transfer.dll
这样的流程解决了之前的两个问题,即当Transfer.dll正常更新时,不用再把新的Hash传给Bank.exe了,Bank.exe只需用公钥去解密CodedHash便可知晓这东西是谁发的,并通过解密了的Hash和实时计算的Transfer.dll的Hash进行对比。这里我们逻辑上有个假定,那就是Bank.exe里的那个为了调用Transfer.dll的那个公钥是真的。如果你说这个被黑了怎么办,那我只能说,他都能改你这个Bank.exe里的公钥信息了,他就想改什么改什么了,你就束手就缚吧。另外如果你说,我们既然之前说怕传给Bank.exe的OriHash有假,那你为什么不怕传给Bank.exe的公钥有假?我只能说,你的逻辑很清晰,的确,我们无法保证,但我要说的是毕竟公钥只传一次,而OriHash有可能需要多次传输,风险概率不一样,如果我们假定Transfer.dll永不改变,也就是说OriHash也只用传一次,那我可以说你用不用非对称加密算法都是一样的,因为保证第一次给的OriHash是真的和保证第一次给的公钥是真的,这俩的风险系数是一样的。不知道这么说,大家能不能明白我的意思,我也是绕了好久才捋顺的。
我们可以再假设一遍黑客可能进行的攻击方法:(注意前提是黑客不能动Bank.exe以及内部的PubKey1)
攻击1:改动并覆盖了我的Transfer.dll,但CodedHash是一模一样的
这种情况下,对Transfer.dll摘要的Hash和PubKey1对CodedHash解密的结果Hash是不一样的,成功破案!
攻击2:改动并覆盖了我的Transfer.dll,黑客自己生成了公钥私钥对,并对Transfer.dll的Hash用私钥加密成CodedHash.
这种情况下,当我们用PubKey1解密CodedHash时,由于公钥PubKey1和黑客的私钥不成对,解密时解不开的,成功破案!
攻击3:改动并覆盖了我的Transfer.dll,而Transfer.dll根本不是签名编译的。
这种情况下,结果和前面两个是一样的,成功破案!
攻击4:黑客兄由于拿不着你的私钥,表示没有其它攻击方案了,T_T。
至此,原理总算是说明白了。下面我就介绍如何利用sn.exe来办这些事儿了。
我很讨厌MS把这么多重要的任务都包装在了sn.exe里,首先我们有两个工程Bank.csproj和Transfer.csproj,我们要做的就是实现上图的流程。
1.用sn.exe生成公钥私钥对文件myPair.snk。如下图:(你要誓死保护好myPair.snk,因为里面有私钥,且这也是私钥唯一存在的地方)
2.在Transfer工程中,将myPair.snk的路径填到AssemblyInfo.cs文件中,如下图:
3.编译Transfer工程,生成Transfer.dll。此时,编译器瞬间完成了对Transfer.dll的Hash,并用myPair.snk中的私钥加密了Hash成CodedHash,并将CodedHash存入Transfer.dll中,同时公钥信息也存入了Transfer.dll中(注意绝对没有私钥)。
4.在Bank工程中,重新引用Transfer.dll文件,重新编译Bank.exe,编译时编译器将提取Transfer.dll中的公钥PubKey1,并将其写在引用Dll的描述中。当我们用反编译工具查看Bank.exe时,我们可以查看到如下信息:
// Transfer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3d5e0147c186af58
PublicKeyToken即是我们所说的公钥PubKey1。
5.此时大功告成,无论有人用自己的私钥编译篡改了的Transfer.dll或者根本就没有用私钥签名编译,运行Bank.exe时会抛出如下信息:
这便是最基本的应用了,我也是参考了不少文章,其中比较重要的是http://www.windowsdevcenter.com/pub/a/dotnet/2003/04/28/strongnaming.html,该文章还介绍了延迟签名等机制,有兴趣的朋友可以看看。
在这里再次说明,sn.exe并不能对程序集加密阻止反编译,只是让调用者知道调用对象是不是想要的,仅此而已。
另外,HTTPS也是用的类似的方案来判断对方是不是自己人的,只是多了一个用对称加密算法加密数据包这一步,其它和这个都是一样的。
祝大家在园子里一起进步!
转自:http://www.knowsky.com/604600.html
转载:.Net 程序集 签名工具sn.exe 密钥对SNK文件 最基本的用法的更多相关文章
- .Net 程序集 签名工具sn.exe 密钥对SNK文件 最基本的用法
阐述签名工具这个概念之前,我先说说它不是什么: 1.它不是用于给程序集加密的工具,它与阻止Reflector或ILSpy对程序集进行反编译一毛钱关系都没有. 2.它很讨厌人们把它和加密联系在一起. 我 ...
- 【转】.Net 程序集 签名工具sn.exe 密钥对SNK文件 最基本的用法
阐述签名工具这个概念之前,我先说说它不是什么: 1.它不是用于给程序集加密的工具,它与阻止Reflector或ILSpy对程序集进行反编译一毛钱关系都没有. 2.它很讨厌人们把它和加密联系在一起. 我 ...
- 使用sn.exe为程序集签名
前言 在写上一篇随笔时,为理解EF事务底层的原理,我去Github上把EF的源码下载放到自己项目调试,不过在编译时遇到了下面这个报错信息.经过一番查阅,了解到了程序集签名(也称强名称签名)的概念.报错 ...
- Sn.exe(强名称工具)
Sn.exe(强名称工具) .NET Framework 4.5 强名称工具 (Sn.exe) 有助于使用强名称对程序集进行签名. Sn.exe 提供了用于密钥管理.签名生成和签名验证的选项. 强 ...
- iOS包重签名工具,ipa文件重签名,快速签名,SignTool签名工具,好用的签名工具,App重签名
新工具 ProjectTool 已上线 这是一款快速写白包工具,秒级别写H5游戏壳包,可视化操作,极易使用,支持Swift.Objecive-C双语言 QQ交流群:811715780 进入 Proje ...
- 使用SN.exe对.Net生成的程序集进行签名
CLR用数字签名的方式防止程序集发布后被人篡改,也可以确定发布人,这个方法就是使用公/私钥对,然后对程序集所有模块取一个哈希生成一个数字签名放在程序集的元数据中. 1.创建公/私钥对 创建公/ ...
- SignTool.exe(签名工具)
水漂收集 -- SignTool.exe(签名工具) =============C#.Net 篇目录============== 签名工具是一个命令行工具,用于用证书对文件进行数字签名,验证文件和时间 ...
- [工具推荐]004.EXE签名工具SignTool使用教程
数字证书,真是个神奇的东西,可以保证软件不被修改,可以表明文件的发布日期,最重要的,可以很大程度的减少杀毒软件的误报,当然,这就要使用可信任的机构颁发的证书了. 现在要说的不是申请证书,而是如何制作自 ...
- Android中APK签名工具之jarsigner和apksigner详解
一.工具介绍 jarsigner是JDK提供的针对jar包签名的通用工具, 位于JDK/bin/jarsigner.exe apksigner是Google官方提供的针对Android apk签名及验 ...
随机推荐
- RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase. This probably means that you are not using fork to start your c
Error Msg: Traceback (most recent call last): File "<string>", line 1, in <module ...
- Python dict和set的实现原理
在python的dict中间进行查找某个key操作时,查找所需时间不会随着dict中键值对数量增多而变长,(时间复杂度为O(1))但是list中就会(时间复杂度为O(N)),这是因为list查询实现的 ...
- 常见的页面中两个div自适应等高CSS控制
第一种利用dispaly:table,父级div设置dispaly:table子级div设置display: table-cell; 第一种利用dispaly:flex,父级div设置dispaly: ...
- Tomcat连接 ideal
一.为了建立Servlet,我们需要先将Tomact连接到ideal! <%-- Created by IntelliJ IDEA. User: Administrator Date: 2019 ...
- P1226 【模板】快速幂||取余运算
https://www.luogu.org/problemnew/show/P1226 模板题 直接上代码吧 #include<bits/stdc++.h> using namespace ...
- Javascript初识之数据类型
一.JavaScript概述 1.ECMAScript和JavaScript的关系 1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript提交给国际标准化组 ...
- C#操作session的类实例(转)
using System.Web; namespace DotNet.Utilities { public static class SessionHelper2 { /// <summary& ...
- 使用Flink实现索引数据到Elasticsearch
使用Flink实现索引数据到Elasticsearch 2018-07-28 23:16:36 Yanjun 使用Flink处理数据时,可以基于Flink提供的批式处理(Batch Proce ...
- Go语言系列(八)- Goroute和Channel
一.Goroute 1. 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配合调度的一个独立单位 B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能 ...
- Docker:容器间互联的应用zabbix监控项目 [十]
一.docker容器间的互联 1.创建两个容器 [root@luoahong ~]# docker run -d --name luoahong httpd:latest 8f771f043391e7 ...