在"C#程序集系列08,设置程序集版本"中体验了为程序集设置版本,但对于程序集的安全性来说,还远远不够。本篇体验程序集的签名。

□ 程序集的签名

→F盘as文件夹下有多个文件

→在程序集所在文件夹创建密匙

→打印密匙

密匙是一堆乱码,这是经过加密了。
→在密匙的基础上创建公匙Public Key

→打印公匙Public Key

注意:这里的public token是public key经过哈希算法而获得的。当程序集被引用,该程序集对外是以public token形式存在的。

→现在重新编译"C#程序集系列08,设置程序集版本"中的Cow.cs,但这次使用密匙

→重新编译"C#程序集系列08,设置程序集版本"中的MainClass.cs,引用刚创建的Farm.dll

→运行MainClass.exe

→现在模拟一个病毒程序集,首先在F盘的as文件夹中创建CowVirus.cs
→用记事本打开CowVirus.cs,编写如下,保存

using System;
using System.Reflection;

[assembly: AssemblyVersion("3.3.3.3")]

public class Cow
{
    public static void Moo()
    {
        Console.WriteLine("我是病毒");
    }
}


→编译CowVirus.cs,生成新的Farm.dll,重写原先的Farm.dll,并且在没有私匙的情况下

→再次运行MainClass.exe

可见,病毒程序虽然模拟了一个相同名称的程序集,但由于没有签名,该程序集不会得到主程序的认可。

□ Public Token

如果一个A程序集有public key,且被B程序引用,如果我们反编译B程序,在B程序的IL代码中就可以看到A程序集有一个public token,这个public token是根据A程序集的public key经哈希算法而得到的。

→再次重写Farm.dll,编译Cow.cs文件,并且使用密匙

→反编译Farm.dll

来看Farm程序集的清单部分:

.assembly Farm
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00   // .$..............
                00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00   // .$..RSA1........
                49 2C E7 BF EF 82 D2 44 A3 F4 AB 96 27 32 89 A4   // I,.....D....'2..
                77 E6 AD A6 A3 21 62 E3 0A DA 72 9D BA 0A 7C 59   // w....!b...r...|Y
                51 0C F6 63 22 ED E3 50 4B F5 61 E2 1A 7F ED 26   // Q..c"..PK.a....&
                78 BD 1B 99 E7 1C 91 7F 80 E6 3F 9B 1C F0 85 63   // x.........?....c
                58 5D 8B DC 60 41 69 2A F3 E6 EB 9B 42 4D D8 B6   // X]..`Ai*....BM..
                C5 B0 31 47 77 58 C6 53 65 2A B1 90 30 EA 24 EF   // ..1GwX.Se*..0.$.
                2A 1C 92 DD 62 D3 00 F6 F3 CA 0E 24 1C A8 F2 2E   // *...b......$....
                5D D3 06 41 A7 77 EE EB C0 2F 64 83 2A 59 00 AE ) // ]..A.w.../d.*Y..
  .hash algorithm 0x00008004
  .ver 3:3:3:3
}

以上,程序集Farm.dll中包含了public key。

→重新编译MainClass.cs,并且引用Farm.dll程序集,重新生成MainClass.exe

→运行MainClass.exe

→反编译MainClass.exe

→查看到MainClass.exe的IL代码

.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.assembly extern Farm
{
  .publickeytoken = (21 64 02 E8 98 B6 AC A9 )                         // !d......
  .ver 3:3:3:3
}
.assembly MainClass
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}

以上,在.assembly extern Farm语句块中,.publickeytoken的值,是根据Farm.dll程序集的public key哈希算法后获得的。

总结:
○ 通过给程序集签名,即给程序集加密匙,程序集就有了public key,这样会有效防止他人恶意篡改程序集
○ 程序集被A程序引用,如果反编译A程序,程序集清单中有一个public token,该值是public key经哈希算法而得到的

“C#程序集系列”包括:

C#程序集系列01,用记事本编写C#,IL代码,用DOS命令编译程序集,运行程序

C#程序集系列02,使用记事本查看可执行程序集的IL代码

C#程序集系列03,引用多个module

C#程序集系列04,在程序集包含多个module的场景下理解关键字internal

C#程序集系列05,让程序集包含多个module

C#程序集系列06,程序集清单,EXE和DLL的区别

C#程序集系列07,篡改程序集

C#程序集系列08,设置程序集版本

C#程序集系列09,程序集签名

C#程序集系列10,强名称程序集

C#程序集系列11,全局程序集缓存

C#程序集系列12,C#编译器和CLR如何找寻程序集

C#程序集系列13,如何让CLR选择不同版本的程序集

参考资料:

http://www.computersciencevideos.org/  created by Jamie King

C#程序集系列09,程序集签名的更多相关文章

  1. C#程序集系列13,如何让CLR选择不同版本的程序集

    本篇主要体验,在存在多个版本程序集的情况下,如何让CLR选择哪个版本程序集运行,以及程序集版本的切换. 分别生成非强名称程序集不同版本 □ 生成某个版本的程序集 →清理F盘as文件夹,剩下如下文件 → ...

  2. C#程序集系列12,C#编译器和CLR如何找寻程序集

    本篇体验C#编译器和CLR运行时如何查找程序集,并自定义CLR运行时查找程序集的方式. □ C#编译器和CLR运行时如何查找程序集 C#编译器在哪里?--在C:\Windows\Microsoft.N ...

  3. C#程序集系列11,全局程序集缓存

    全局程序集缓存(GAC:Global Assembly Cache)用来存放可能被多次使用的强名称程序集.当主程序需要加载程序集的时候,优先选择到全局程序集缓存中去找寻需要的程序集. 为什么需要全局程 ...

  4. C#程序集系列10,强名称程序集

    当一个程序集的名称,版本,文化,Public Key都做了设置,就可以把这个程序集叫做"强名称程序集".强名称程序集可以防止被仿冒或篡改.本篇首先创建一个强名称程序集,接着模拟篡改 ...

  5. C#程序集系列08,设置程序集版本

    区别一个程序集,不仅仅是程序集名称,还包括程序集版本.程序集公匙.程序集文化等,本篇体验通过界面和编码设置程序集版本. □ 通过Visual Studio设置程序集版本 →右键项目,选择"属 ...

  6. C#程序集系列07,篡改程序集

    以下几个方面用来区分不同的程序集:○ 程序集名称:Name○ 程序集版本:Version○ 程序集公匙: Public Token○ 程序集文化:Culture 如果没有很严格地按照上面的几个方面来创 ...

  7. C#程序集系列06,程序集清单,EXE和DLL的区别

    CLR在加载程序集的时候会查看程序集清单,程序集清单包含哪些内容呢?可执行文件和程序集有什么区别/ 程序集清单 □ 查看程序集清单 →清空F盘as文件夹中的所有内容→创建MainClass.cs文件→ ...

  8. C#程序集系列05,让程序集包含多个module

    本篇体验在一个程序集中包含多个module. □ 创建3个module →删除F盘as文件夹中的一些文件,只剩下如下3个文件→用记事本打开MyFirstModule.cs文件,修改如下,并保存 usi ...

  9. C#程序集系列04,在程序集包含多个module的场景下理解关键字internal

    本篇在一个程序集包含多个module的场景下体验internal的含义. →查看F盘as文件夹下的文件→删除MainClass.exe→把MyFirstModule和MySecondModule组装到 ...

随机推荐

  1. conding.net或github,readme.md添加图片

    原因:    将图片放在仓库里面,在文件里链接它,最后 push 到 github 上.github 图片链接格式:(http://github.com/yourname/your-repositor ...

  2. Oracle学习笔记:decode函数

    decode函数主要作用:将查询结果翻译成其他值(即以其他形式变现出来) 使用方法: SELECT DECODE(colunm_name,值1,翻译值1,值2,翻译值2……值n,翻译值n,缺省值) F ...

  3. MySQL学习笔记:生成一个时间序列

    今天遇到一个需求是生成以下表格的数据,一整天24小时,每秒一行数据. 寻找颇旧,找到另外两个实现的例子,暂且学习一翻.另一个见另外一篇. DAY) AS DATE FROM ( ) AS tmp, ( ...

  4. Retrofit + RxJava + OkHttp 让网络请求变的简单-基础篇

    https://www.jianshu.com/p/5bc866b9cbb9 最近因为手头上的工作做完了,比较闲,想着做一些优化.看到以前用的那一套网络框架添加一个请求比较麻烦,并且比较难用,所以想改 ...

  5. vuejs学习--递归组件(树型表格分享)

    前言 学习vue有一段时间了,最近使用vue做了一套后台管理系统,其中使用最多就是递归组件,也因为自己对官方文档的不熟悉使得自己踩了不少坑,今天写出来和大家一起分享. 递归组件 组件在它的模板内可以递 ...

  6. phpstorm 输入法中文不同步 phpstorm 输入法不跟随光标解决办法

    win7系统新安装的phpstorm2017.2版本,试了很多输入法,要么是不显示候选次,要么是输入法候选词总是在屏幕右下角,没有跟随光标移动.百度很久,重要找到解决方案. 就是替换phpstorm安 ...

  7. Just a Hook (线段树)

    给你n个数(初始时每个数的值为1),m个操作,每个操作把区间[l,r]里的数更新为c,问最后这n个数的和是多少. 区域更新用懒惰标记 #include<bits/stdc++.h> usi ...

  8. thinkphp3.2中开启静态缓存后对404页面的处理方法

    静态缓存很实用但是有时有些不需要静态缓存,如404页面,第一次访问返回404页面并缓存,第二次换回的状态就是200,属于正常访问,虽然人眼可以看出是404页面,但是搜索引擎不会的,而是把这个页面当成正 ...

  9. 2017-2018-1 20179202《Linux内核原理与分析》第十周作业

    一.设备与模块 1.设备类型 块设备:随机访问设备中的内容,通过块设备结点访问,通常被挂载为文件系统 字符设备:不可寻址,仅提供数据的流式访问,通过字符设备结点访问,应用程序通过直接访问设备节点与字符 ...

  10. 迭代器模式 与 C# IEnumerator/IEnumerable

    Part1 迭代器模式 与 接口 IEnumerable IEnumerator interface IEnumerable { IEnumerator GetEnumerator(); } // 泛 ...