转:

http://network.ccidnet.com/art/1136/20030815/59697_1.html

提纲:

……………………………

一、禁止未经授权的用户

二、强名称程序集

三、测试

四、安全漏洞?

……………………………

内容:

……………………………

现在,你应该早已试着用.NET框架编写过“Hello World”程序——也许用C#,也许用VB.NET,甚至可能用托管VC++。其实对于.NET来说,用哪一种语言并不重要,因为.NET允许用一种语言编写的.NET程序方便地调用其他语言或作者写的代码。然而,既然代码共享变得如此方便,我们怎样来保证自己的代码不被未经授权的用户使用?

在宣传.NET框架时,微软提出的一个卖点是代码访问安全(CAS,Code Access Security)的概念。由CLR(Common Language Runtime,公共语言运行时环境)执行的每一段代码都在一个安全上下文内执行,代码的授权以各种标识信息为基础,这些标识信息也是程序集的强名称(Strong Name)的构成元素,包括:

▲ 文件名字:程序集的文件名称,例如MyAssembly.DLL或MyProgram.EXE等。

▲ 区域性:程序集的目标区域环境,如en、fr或fr-CA。

▲ 版本:程序集的版本号。

▲ 公用密钥:构造程序集时如果指定了RSA签名文件,绑定到程序集的公用密钥。

本文讨论的主要是最后一项——公用密钥。

一、禁止未经授权的用户

管理员可以在上述任意标识信息的基础上,执行一个安全策略,授予或取消程序集的各种执行权限。例如,管理员可以禁止某个程序集访问Internet,或禁止程序集删除本地硬盘的文件。对于管理员来说,全面地控制代码在自己的机器上可以做什么、不可以做什么无疑是很受欢迎的。但是,当开发者和管理员的出发点不同时,问题就出现了。

考虑一下这种情形:你开发了一个软件,它要读写一个加密的、格式私有的数据文件——这是该软件保持优势的关键所在。现在,随着.NET的流行,你把软件升级到了.NET平台并予以发布。假设你的软件有一个类专门负责私有数据文件的所有I/O操作,问题出现了:只要运用ILDASM.EXE之类的命令行工具和程序逻辑工具,其他人能够方便地分析程序集的原数据,获得所有方法及其参数的详细说明。对于一个有经验的程序员来说,也许只需数分钟时间就能够了解如何运用该I/O类来操作你私有的数据文件。显然,我们不希望出现这种情形。

其实,这只是一个简单的例子,促使人们设法保护自己代码的原因不可胜数。但无论出于什么原因,保护代码最好的办法就是避免未经授权的用户直接调用某些API函数和类。

二、强名称程序集

文章开头已经提到,程序集可以通过用一个RSA签名文件签名的办法实现强名称(Strong Naming)。我们创建一个公用/私有密钥对,把它保存到文件,所有用同一签名文件构造的程序集将拥有同样的公用密钥,可以相信这些程序集来自同一开发者。任何其他人都不能构造出带有同样公用密钥的签名文件,除非别人得到了你的RSA签名文件。

假设我们要为A公司创建RSA签名文件,先进入命令行环境(最好使用VS.NET提供的快捷方式,它会自动配置路径信息)。假设构造VS.NET项目的根是C:\test,转到C:\test目录,然后执行命令:SN -k SecureProducts.snk。不带参数执行SN命令可获得SN的使用帮助。

在C:\test目录下生成SecureProducts.snk签名文件后,下面我们构造一个程序集,然后用SecureProducts.snk签名文件把它签名。

启动VS.NET,创建一个C#的类库项目,将它命名为SecureAssembly。打开AssemblyInfo.cs,将版本号设置为1.0.0.0,修改AssemblyKeyFile属性,使其指向刚才创建的签名文件。这两行属性修改后应当类如:

[assembly: AssemblyVersion("1.0.0.0")][assembly: AssemblyKeyFile(@"C:\test\SecureProducts.snk")]

接下来删除项目中默认创建的Class1.cs类,另外创建一个新类SecuredClass。为SecuredClass加入一个GetTopSecretInformation 方法,代码如下:

public class SecuredClass {public SecuredClass() { }public string GetTopSecretInformation() {return "Secret Code:000111";} }

为了不让GetTopSecretInformation方法提供的信息落入竞争对手的手中,我们要保证只有自己的代码(带有正确公用密钥的代码)才能够创建SecuredClass类的实例并执行GetTopSecretInformation方法。

为此,我们要获得A公司完整的公用密钥。这要用到另一个命令行工具secutil,它能够从已经编译好的程序集获得安全信息。在命令行环境中,进入SecureAssembly\obj\debug目录,执行:Secutil -hex -strongname SecureAssembly.dll > secutiloutput.txt。命令执行的结果是创建一个文本文件secutiloutput.txt,内容类如:

Microsoft (R) .NET Framework SecUtil 1.0.3705.0Copyright (C) Microsoft Corporation 1998-2001. All rights reserved.Public Key =0x0024…0ACName =SecureAssemblyVersion =1.0.0.0Success

选中公用密钥(前缀0x除外,共320个字母。0x表示十六进制),将它复制到剪贴板。然后将公用密钥以属性的形式放入SecuredClass类定义的最前面,例如:

[StrongNameIdentityPermission(SecurityAction.LinkDemand,PublicKey="0024…0AC")]public class SecuredClass

这些操作的目的是:我们告诉CLR,任何试图访问该类的程序(无论是静态访问还是通过对象实例化),都必须有指定的公用密钥(LinkDemand枚举值)。如果没有,CLR将抛出异常。注意,为了让SecuredClass顺利编译,SecuredClass.cs的开头要加上using System.Security.Permissions语句。

如果没有保存在SecureProducts.snk文件中的对应的私有密钥,任何人无法构造出拥有该公用密钥的程序集。因此,一定要保证签名文件本身的安全。

三、测试

下面来测试一下这种办法是否确实有效。我们要构造一个控制台应用来引用上面的类,创建SecuredClass的实例并输出机密字符串。下面是控制台应用的主要代码:

static void Main(string[] args){SecureAssembly.SecuredClass secClass;secClass = new SecureAssembly.SecuredClass();Console.WriteLine("锦囊秘籍:{0}",secClass.GetTopSecretInformation());}

在不对该程序签名的情况下运行,输出如图一所示。可以看到,CLR拒绝执行SecuredClass类的GetTopSecretInformation方法。

图一

现在创建另外一个控制台应用(或修改原来的应用),这一次在AssemblyInfo.cs中设定:

[assembly: AssemblyVersion("1.0.0.0")][assembly: AssemblyKeyFile(@"c:\test\SecureProducts.snk")]

再编译、运行程序,得到图二的输出结果。

图二

四、安全漏洞?

还有一个必须关注的问题是:用户可能通过其他方式获得程序代码中的字符串。例如,进入命令行环境,转到SecureAssembly\obj\debug目录,执行ILDASM SecureAssembly.dll。你可以毫不费力地找到IL(中间语言)形式的方法定义,如图三。

图三

这不是太简单了吗?我们花了很大力气加以保护的机密信息竟然可以通过这种方式获得!无论是公用密钥、签名文件,都挡不住一个简单的免费工具ILDASM!

如果你确实担心有人偷看代码中的字符串,解决办法是加密字符常量,或对整个程序进行模糊处理。本文介绍的技术能够有效地防止其他人调用程序集,如果你要保护的重点是程序中的字符串而不是程序逻辑,单纯运用密钥/签名文件是不够的。

转载于:https://www.cnblogs.com/sainaxingxing/archive/2008/09/18/1293705.html

在.NET环境禁止别人调用代码相关推荐

  1. XP系统如何禁止别人在电脑上安装程序

    自已的电脑,如果自已不在电脑旁时,家人或朋友就会玩我的电脑,而且还会在电脑上安装很多软件,每次都得花很多时间去清理垃圾软件,拒绝他们动我的电脑,又觉得不太好意思,要怎样既能够让他们玩,而且又不能让他们 ...

  2. 【C++】如何阅读别人的代码?如何阅读别人的C++代码?如何高效学习他人代码

    [ C/C++ ] 程序学习--如何阅读别人的代码 ++++++++++++ 第一章: 导论 ++++++++++++ 1.要养成一个习惯, 经常花时间阅读别人编写的高品质代码. 2.要有选择地阅读代 ...

  3. 接手别人的代码,死的心有吗?

    团队里的程序员张三丰要离职,领导让你接手他的工作,叮嘱你一定要尽快掌握张三丰的代码.你的心儿扑通扑通地跳动,你的脑海里萦绕着三个选择:是拒绝呢,还是拒绝呢,还是拒绝呢?你强颜欢笑但实际上心烦意乱怨气纵 ...

  4. 使用wsdl2java命令生成webservice本地调用代码

    使用wsdl2java命令生成webservice本地调用代码 如果没有设置环境变量,就要先进入cxf的bin目录 例子: wsdl2java -d . http://localhost:7890/h ...

  5. python如何实现别人调用自己的API

    5_python如何实现别人调用自己的API(5-20181224) 参考别人的API接口的形式 参考别人的API接口的形式 https://docs.open.alipay.com/api_1/al ...

  6. html代码在线运行环境,ES5/可执行代码与执行环境

    可执行代码类型 一共有三种 ECMA 脚本可执行代码: 全局代码是指被作为 ECMAScript Eval 代码是指提供给 eval 内置函数的源代码文本.更精确地说,如果传递给 eval 内置函数的 ...

  7. ironpython使用dictionary_在C#环境中动态调用IronPython脚本(一)

    本文讲述用C#调用Ironpython运行环境,解析并运行动态pyhton脚本.这种情况应用在那些需要滞后规定行为的场合,例如,动态计算项(计算引擎),用户可以自定义计算内容.计算公式等. 本文的代码 ...

  8. Delphi环境中编写调用DLL的方法和技巧

    Delphi环境中编写调用DLL的方法和技巧 第一章 为什么要使用动态链接库(DLL) top 提起DLL您一定不会陌生,在Windows中有着大量的以DLL为后缀的文件,它们是保证Windows正常 ...

  9. 看懂别人的代码,只是成为高效程序员的第一步!

    作者 | SeattleDataGuy 译者 | 弯月,责编 | 屠敏 出品 | CSDN(ID:CSDNnews) 在为面试做准备的时候,很多软件工程师都花费了大量时间做编程题和完善简历. 最终在找 ...

最新文章

  1. java,js,jstl,EL的简单交互
  2. 5分钟带你快速了解ServiceMesh的前世今生
  3. java jvm学习笔记二(类装载器的体系结构)
  4. 奇虎360将于18日在美摘牌 进程早于外界预期
  5. 07-01-安装-Exchange Server 2019 on Win 2019 Core
  6. 增强中获取屏幕值的一句很实用代码…
  7. 里能嵌jquery吗_白芸豆里的淀粉阻断成分,能帮助减肥是真的吗?
  8. Mybatis foreach遍历
  9. 【转载】堆和栈的内存分配
  10. XTPChartAppearance.cpp错误及其解决办法
  11. cobbler的搭建
  12. Redis入门到高可用(十一)—— 慢查询
  13. 老男孩教育每日一题-第106天-MySQL如何授权用户admin:password远程访问权限
  14. Code Review 效率低?来试试智能语法服务
  15. 陶瓷封装产品的6大优点
  16. AUTOSAR--UDS诊断报文
  17. Microsoft JET Database Engine 错误 '80004005' 操作必须使用一个可更新的查询。问题解决办法
  18. PostGreSQL8.0.0中文手册
  19. Android虚拟机AVD has terminated
  20. Spring Cloud如何可用于微服务架构

热门文章

  1. PHP 使网站进行跨域访问
  2. windows访问linux下samba无需密码设置
  3. 构造函数和复制函数java_什么是Java构造函数?
  4. vco为什么低频下起振困难_为什么协作如此困难?
  5. linux管理员权限命令_每个系统管理员应该知道的20个Linux命令
  6. 未来集市广告_为什么广告的未来是开放的
  7. blender使用_DigiVita使用Blender教女孩编码
  8. 医生们团结一致,以增加对优质健康信息的访问
  9. 厉害了 | 一秒切换Hexo中英文,厉害了!!
  10. 实战 | Element UI 父子组件传值与事件绑定(正向)